diff --git a/.github/ISSUE_TEMPLATE/bug-report.md b/.github/ISSUE_TEMPLATE/bug-report.md index 6313c4cf055..999c3a6628b 100644 --- a/.github/ISSUE_TEMPLATE/bug-report.md +++ b/.github/ISSUE_TEMPLATE/bug-report.md @@ -1,6 +1,7 @@ --- name: Bug Report about: Report a bug encountered while operating Kubernetes +labels: kind/bug --- @@ -22,6 +23,3 @@ about: Report a bug encountered while operating Kubernetes - Kernel (e.g. `uname -a`): - Install tools: - Others: - - -/kind bug \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/enhancement.md b/.github/ISSUE_TEMPLATE/enhancement.md index 54f21fda5f2..f04c3d34350 100644 --- a/.github/ISSUE_TEMPLATE/enhancement.md +++ b/.github/ISSUE_TEMPLATE/enhancement.md @@ -1,6 +1,7 @@ --- name: Enhancement Request about: Suggest an enhancement to the Kubernetes project +labels: kind/feature --- @@ -8,6 +9,3 @@ about: Suggest an enhancement to the Kubernetes project **What would you like to be added**: **Why is this needed**: - - -/kind feature \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/failing-test.md b/.github/ISSUE_TEMPLATE/failing-test.md index 5da4006fe29..ca843e19537 100644 --- a/.github/ISSUE_TEMPLATE/failing-test.md +++ b/.github/ISSUE_TEMPLATE/failing-test.md @@ -1,6 +1,7 @@ --- name: Failing Test about: Report test failures in Kubernetes CI jobs +labels: kind/failing-test --- @@ -17,6 +18,3 @@ about: Report test failures in Kubernetes CI jobs **Reason for failure**: **Anything else we need to know**: - - -/kind failing-test \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/support.md b/.github/ISSUE_TEMPLATE/support.md index 28a1100eb35..173f5f183b4 100644 --- a/.github/ISSUE_TEMPLATE/support.md +++ b/.github/ISSUE_TEMPLATE/support.md @@ -1,6 +1,7 @@ --- name: Support Request about: Support request or question relating to Kubernetes +labels: triage/support --- @@ -15,8 +16,3 @@ You can also post your question on the [Kubernetes Slack](http://slack.k8s.io/) If the matter is security related, please disclose it privately via https://kubernetes.io/security/. --> - - - -/triage support - diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index a588771a581..ff71abd6682 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,5 +1,6 @@ **What type of PR is this?** -> Uncomment only one, leave it on its own line: +> Uncomment only one ` /kind <>` line, hit enter to put that in a new line, and remove leading whitespaces from that line: > > /kind api-change > /kind bug @@ -22,17 +23,21 @@ https://git.k8s.io/community/contributors/devel/release.md#issue-kind-label **What this PR does / why we need it**: -**Which issue(s) this PR fixes** *(optional, in `fixes #(, fixes #, ...)` format, will close the issue(s) when PR gets merged)*: +**Which issue(s) this PR fixes**: + Fixes # **Special notes for your reviewer**: **Does this PR introduce a user-facing change?**: ```release-note diff --git a/CHANGELOG-1.10.md b/CHANGELOG-1.10.md index 851da9c32bd..feed7dfd93b 100644 --- a/CHANGELOG-1.10.md +++ b/CHANGELOG-1.10.md @@ -1,89 +1,96 @@ -- [v1.10.11](#v11011) - - [Downloads for v1.10.11](#downloads-for-v11011) +- [v1.10.12](#v11012) + - [Downloads for v1.10.12](#downloads-for-v11012) - [Client Binaries](#client-binaries) - [Server Binaries](#server-binaries) - [Node Binaries](#node-binaries) - - [Changelog since v1.10.10](#changelog-since-v11010) + - [Changelog since v1.10.11](#changelog-since-v11011) - [Other notable changes](#other-notable-changes) -- [v1.10.10](#v11010) - - [Downloads for v1.10.10](#downloads-for-v11010) +- [v1.10.11](#v11011) + - [Downloads for v1.10.11](#downloads-for-v11011) - [Client Binaries](#client-binaries-1) - [Server Binaries](#server-binaries-1) - [Node Binaries](#node-binaries-1) - - [Changelog since v1.10.9](#changelog-since-v1109) + - [Changelog since v1.10.10](#changelog-since-v11010) - [Other notable changes](#other-notable-changes-1) -- [v1.10.9](#v1109) - - [Downloads for v1.10.9](#downloads-for-v1109) +- [v1.10.10](#v11010) + - [Downloads for v1.10.10](#downloads-for-v11010) - [Client Binaries](#client-binaries-2) - [Server Binaries](#server-binaries-2) - [Node Binaries](#node-binaries-2) - - [Changelog since v1.10.8](#changelog-since-v1108) + - [Changelog since v1.10.9](#changelog-since-v1109) - [Other notable changes](#other-notable-changes-2) -- [v1.10.8](#v1108) - - [Downloads for v1.10.8](#downloads-for-v1108) +- [v1.10.9](#v1109) + - [Downloads for v1.10.9](#downloads-for-v1109) - [Client Binaries](#client-binaries-3) - [Server Binaries](#server-binaries-3) - [Node Binaries](#node-binaries-3) - - [Changelog since v1.10.7](#changelog-since-v1107) + - [Changelog since v1.10.8](#changelog-since-v1108) - [Other notable changes](#other-notable-changes-3) -- [v1.10.7](#v1107) - - [Downloads for v1.10.7](#downloads-for-v1107) +- [v1.10.8](#v1108) + - [Downloads for v1.10.8](#downloads-for-v1108) - [Client Binaries](#client-binaries-4) - [Server Binaries](#server-binaries-4) - [Node Binaries](#node-binaries-4) - - [Changelog since v1.10.6](#changelog-since-v1106) - - [Action Required](#action-required) + - [Changelog since v1.10.7](#changelog-since-v1107) - [Other notable changes](#other-notable-changes-4) -- [v1.10.6](#v1106) - - [Downloads for v1.10.6](#downloads-for-v1106) +- [v1.10.7](#v1107) + - [Downloads for v1.10.7](#downloads-for-v1107) - [Client Binaries](#client-binaries-5) - [Server Binaries](#server-binaries-5) - [Node Binaries](#node-binaries-5) - - [Changelog since v1.10.5](#changelog-since-v1105) - - [Action Required](#action-required-1) + - [Changelog since v1.10.6](#changelog-since-v1106) + - [Action Required](#action-required) - [Other notable changes](#other-notable-changes-5) -- [v1.10.5](#v1105) - - [Downloads for v1.10.5](#downloads-for-v1105) +- [v1.10.6](#v1106) + - [Downloads for v1.10.6](#downloads-for-v1106) - [Client Binaries](#client-binaries-6) - [Server Binaries](#server-binaries-6) - [Node Binaries](#node-binaries-6) - - [Changelog since v1.10.4](#changelog-since-v1104) - - [Action Required](#action-required-2) + - [Changelog since v1.10.5](#changelog-since-v1105) + - [Action Required](#action-required-1) - [Other notable changes](#other-notable-changes-6) -- [v1.10.4](#v1104) - - [Downloads for v1.10.4](#downloads-for-v1104) +- [v1.10.5](#v1105) + - [Downloads for v1.10.5](#downloads-for-v1105) - [Client Binaries](#client-binaries-7) - [Server Binaries](#server-binaries-7) - [Node Binaries](#node-binaries-7) - - [Changelog since v1.10.3](#changelog-since-v1103) + - [Changelog since v1.10.4](#changelog-since-v1104) + - [Action Required](#action-required-2) - [Other notable changes](#other-notable-changes-7) -- [v1.10.3](#v1103) - - [Downloads for v1.10.3](#downloads-for-v1103) +- [v1.10.4](#v1104) + - [Downloads for v1.10.4](#downloads-for-v1104) - [Client Binaries](#client-binaries-8) - [Server Binaries](#server-binaries-8) - [Node Binaries](#node-binaries-8) - - [Changelog since v1.10.2](#changelog-since-v1102) + - [Changelog since v1.10.3](#changelog-since-v1103) - [Other notable changes](#other-notable-changes-8) -- [v1.10.2](#v1102) - - [Downloads for v1.10.2](#downloads-for-v1102) +- [v1.10.3](#v1103) + - [Downloads for v1.10.3](#downloads-for-v1103) - [Client Binaries](#client-binaries-9) - [Server Binaries](#server-binaries-9) - [Node Binaries](#node-binaries-9) - - [Changelog since v1.10.1](#changelog-since-v1101) + - [Changelog since v1.10.2](#changelog-since-v1102) - [Other notable changes](#other-notable-changes-9) -- [v1.10.1](#v1101) - - [Downloads for v1.10.1](#downloads-for-v1101) +- [v1.10.2](#v1102) + - [Downloads for v1.10.2](#downloads-for-v1102) - [Client Binaries](#client-binaries-10) - [Server Binaries](#server-binaries-10) - [Node Binaries](#node-binaries-10) - - [Changelog since v1.10.0](#changelog-since-v1100) + - [Changelog since v1.10.1](#changelog-since-v1101) - [Other notable changes](#other-notable-changes-10) -- [v1.10.0](#v1100) - - [Downloads for v1.10.0](#downloads-for-v1100) +- [v1.10.1](#v1101) + - [Downloads for v1.10.1](#downloads-for-v1101) - [Client Binaries](#client-binaries-11) - [Server Binaries](#server-binaries-11) - [Node Binaries](#node-binaries-11) + - [Changelog since v1.10.0](#changelog-since-v1100) + - [Other notable changes](#other-notable-changes-11) +- [v1.10.0](#v1100) + - [Downloads for v1.10.0](#downloads-for-v1100) + - [Client Binaries](#client-binaries-12) + - [Server Binaries](#server-binaries-12) + - [Node Binaries](#node-binaries-12) - [Major Themes](#major-themes) - [Node](#node) - [Storage](#storage) @@ -97,7 +104,7 @@ - [Before Upgrading](#before-upgrading) - [Known Issues](#known-issues) - [Deprecations](#deprecations) - - [Other Notable Changes](#other-notable-changes-11) + - [Other Notable Changes](#other-notable-changes-12) - [Apps](#apps) - [AWS](#aws) - [Auth](#auth-1) @@ -120,69 +127,139 @@ - [External Dependencies](#external-dependencies) - [v1.10.0-rc.1](#v1100-rc1) - [Downloads for v1.10.0-rc.1](#downloads-for-v1100-rc1) - - [Client Binaries](#client-binaries-12) - - [Server Binaries](#server-binaries-12) - - [Node Binaries](#node-binaries-12) - - [Changelog since v1.10.0-beta.4](#changelog-since-v1100-beta4) - - [Other notable changes](#other-notable-changes-12) -- [v1.10.0-beta.4](#v1100-beta4) - - [Downloads for v1.10.0-beta.4](#downloads-for-v1100-beta4) - [Client Binaries](#client-binaries-13) - [Server Binaries](#server-binaries-13) - [Node Binaries](#node-binaries-13) - - [Changelog since v1.10.0-beta.3](#changelog-since-v1100-beta3) + - [Changelog since v1.10.0-beta.4](#changelog-since-v1100-beta4) - [Other notable changes](#other-notable-changes-13) -- [v1.10.0-beta.3](#v1100-beta3) - - [Downloads for v1.10.0-beta.3](#downloads-for-v1100-beta3) +- [v1.10.0-beta.4](#v1100-beta4) + - [Downloads for v1.10.0-beta.4](#downloads-for-v1100-beta4) - [Client Binaries](#client-binaries-14) - [Server Binaries](#server-binaries-14) - [Node Binaries](#node-binaries-14) - - [Changelog since v1.10.0-beta.2](#changelog-since-v1100-beta2) + - [Changelog since v1.10.0-beta.3](#changelog-since-v1100-beta3) - [Other notable changes](#other-notable-changes-14) -- [v1.10.0-beta.2](#v1100-beta2) - - [Downloads for v1.10.0-beta.2](#downloads-for-v1100-beta2) +- [v1.10.0-beta.3](#v1100-beta3) + - [Downloads for v1.10.0-beta.3](#downloads-for-v1100-beta3) - [Client Binaries](#client-binaries-15) - [Server Binaries](#server-binaries-15) - [Node Binaries](#node-binaries-15) - - [Changelog since v1.10.0-beta.1](#changelog-since-v1100-beta1) - - [Action Required](#action-required-3) + - [Changelog since v1.10.0-beta.2](#changelog-since-v1100-beta2) - [Other notable changes](#other-notable-changes-15) -- [v1.10.0-beta.1](#v1100-beta1) - - [Downloads for v1.10.0-beta.1](#downloads-for-v1100-beta1) +- [v1.10.0-beta.2](#v1100-beta2) + - [Downloads for v1.10.0-beta.2](#downloads-for-v1100-beta2) - [Client Binaries](#client-binaries-16) - [Server Binaries](#server-binaries-16) - [Node Binaries](#node-binaries-16) - - [Changelog since v1.10.0-alpha.3](#changelog-since-v1100-alpha3) - - [Action Required](#action-required-4) + - [Changelog since v1.10.0-beta.1](#changelog-since-v1100-beta1) + - [Action Required](#action-required-3) - [Other notable changes](#other-notable-changes-16) -- [v1.10.0-alpha.3](#v1100-alpha3) - - [Downloads for v1.10.0-alpha.3](#downloads-for-v1100-alpha3) +- [v1.10.0-beta.1](#v1100-beta1) + - [Downloads for v1.10.0-beta.1](#downloads-for-v1100-beta1) - [Client Binaries](#client-binaries-17) - [Server Binaries](#server-binaries-17) - [Node Binaries](#node-binaries-17) - - [Changelog since v1.10.0-alpha.2](#changelog-since-v1100-alpha2) + - [Changelog since v1.10.0-alpha.3](#changelog-since-v1100-alpha3) + - [Action Required](#action-required-4) - [Other notable changes](#other-notable-changes-17) -- [v1.10.0-alpha.2](#v1100-alpha2) - - [Downloads for v1.10.0-alpha.2](#downloads-for-v1100-alpha2) +- [v1.10.0-alpha.3](#v1100-alpha3) + - [Downloads for v1.10.0-alpha.3](#downloads-for-v1100-alpha3) - [Client Binaries](#client-binaries-18) - [Server Binaries](#server-binaries-18) - [Node Binaries](#node-binaries-18) - - [Changelog since v1.10.0-alpha.1](#changelog-since-v1100-alpha1) - - [Action Required](#action-required-5) + - [Changelog since v1.10.0-alpha.2](#changelog-since-v1100-alpha2) - [Other notable changes](#other-notable-changes-18) -- [v1.10.0-alpha.1](#v1100-alpha1) - - [Downloads for v1.10.0-alpha.1](#downloads-for-v1100-alpha1) +- [v1.10.0-alpha.2](#v1100-alpha2) + - [Downloads for v1.10.0-alpha.2](#downloads-for-v1100-alpha2) - [Client Binaries](#client-binaries-19) - [Server Binaries](#server-binaries-19) - [Node Binaries](#node-binaries-19) + - [Changelog since v1.10.0-alpha.1](#changelog-since-v1100-alpha1) + - [Action Required](#action-required-5) + - [Other notable changes](#other-notable-changes-19) +- [v1.10.0-alpha.1](#v1100-alpha1) + - [Downloads for v1.10.0-alpha.1](#downloads-for-v1100-alpha1) + - [Client Binaries](#client-binaries-20) + - [Server Binaries](#server-binaries-20) + - [Node Binaries](#node-binaries-20) - [Changelog since v1.9.0](#changelog-since-v190) - [Action Required](#action-required-6) - - [Other notable changes](#other-notable-changes-19) + - [Other notable changes](#other-notable-changes-20) +# v1.10.12 + +[Documentation](https://docs.k8s.io) + +## Downloads for v1.10.12 + + +filename | sha512 hash +-------- | ----------- +[kubernetes.tar.gz](https://dl.k8s.io/v1.10.12/kubernetes.tar.gz) | `be4d23a65d8aacd28355941f82a3b3668b4763ea37dc5caca9b556c5e8922133e91c13b48e14b4c337af61ae7d7d20c662b7a8439efff2626328beb569d1ad94` +[kubernetes-src.tar.gz](https://dl.k8s.io/v1.10.12/kubernetes-src.tar.gz) | `048ae3196924cb4fc78c9fbf9b816df6e65ded80f651a7fcb3cbabb531dd55adab30db579a0ed5f9b161066611658da68bf7963d7f0e78fbff9525e504911abe` + +### Client Binaries + +filename | sha512 hash +-------- | ----------- +[kubernetes-client-darwin-386.tar.gz](https://dl.k8s.io/v1.10.12/kubernetes-client-darwin-386.tar.gz) | `7b9d52fdd81efad548c0860f273a9a4b05dee7e8d8a7508f859e72af299bd5e8d29d7f449689c97f9673a86ecb3968fccede6e24672b45d645ed7355f80a9127` +[kubernetes-client-darwin-amd64.tar.gz](https://dl.k8s.io/v1.10.12/kubernetes-client-darwin-amd64.tar.gz) | `e1cc1bd0f9c00899cd1ded8b87e3ca49ac698459c7c4c55d370f31ad675a8d9d44380d004111ccd39c164ac954c9fb63b476a2d476dec3425fe3b3f64273684b` +[kubernetes-client-linux-386.tar.gz](https://dl.k8s.io/v1.10.12/kubernetes-client-linux-386.tar.gz) | `8ddf167501e2bbd9fa6923abb4027d866d7ea9a5b743c4f42c520c86ba5f9f3e9bf84c5ebf7e694aa1cfcd6a23c65fa39c00f4c53ffd268f1ab0f353a23d6cc5` +[kubernetes-client-linux-amd64.tar.gz](https://dl.k8s.io/v1.10.12/kubernetes-client-linux-amd64.tar.gz) | `1772c0d5328113884916e5564ed010612599d8e22eea9bea01175ddf17e1e292220cd3915b0dba746b42eaa1bd2a051c235dc2de12579b35270a2868cfe25a4c` +[kubernetes-client-linux-arm.tar.gz](https://dl.k8s.io/v1.10.12/kubernetes-client-linux-arm.tar.gz) | `3710487740cf8bef6aa26e8dcee9e1b0346e32ca5d389de8edc0a1925764dbacadf186779752b7b511a5290b59aaa4da70f9289aa6a7756160d7878ddd3a80aa` +[kubernetes-client-linux-arm64.tar.gz](https://dl.k8s.io/v1.10.12/kubernetes-client-linux-arm64.tar.gz) | `b12fc191da4753873ce08f4e3182b03d8af418434da9eea9346382ce2c3907f5d0cf1c2f3c7bba279713142acbb6bbaffbf38451ea86be1e1eda35e08cc21ef5` +[kubernetes-client-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.10.12/kubernetes-client-linux-ppc64le.tar.gz) | `22c1e26c4f2acb749ea2e6735767b494e8d5deb1d39afcf3c3f52550a524c23464ae7d54b8ecececfa808e97201f4fcec8051165cb87490be2f379535b20c3f1` +[kubernetes-client-linux-s390x.tar.gz](https://dl.k8s.io/v1.10.12/kubernetes-client-linux-s390x.tar.gz) | `d4039f0d3df66c57b840c82c17cfe221a0d9db39ebdc3194f58b92542dd483b0861538b977c389f7cb07faa4a910ceb48775793633a90d53f91677159361a023` +[kubernetes-client-windows-386.tar.gz](https://dl.k8s.io/v1.10.12/kubernetes-client-windows-386.tar.gz) | `950b45edc202acd61ec21642abeb5f17f95e54708cdb3564dcc7dc19a40184373c3e9b8d032b285b860d5748ec3e151ab766bfee3bab7e406187eab88471d159` +[kubernetes-client-windows-amd64.tar.gz](https://dl.k8s.io/v1.10.12/kubernetes-client-windows-amd64.tar.gz) | `20fa2a817fa17ffd0f79fe5549f5ad0baf60536ed9c00cdb16ae0afb7950b21f6152aead5bd92fc89bceeeeee54954f9e0d12dec516408703f957488c7c0a5c9` + +### Server Binaries + +filename | sha512 hash +-------- | ----------- +[kubernetes-server-linux-amd64.tar.gz](https://dl.k8s.io/v1.10.12/kubernetes-server-linux-amd64.tar.gz) | `b802cd244d6c727938dca27c24f6b83e7edce23cfeb5ec8cd91c0d5a28ef23d6fc7222617d574fe3ea1429b2618c0ffce8b42bc3fe4867e8f54a4f6a395e5887` +[kubernetes-server-linux-arm.tar.gz](https://dl.k8s.io/v1.10.12/kubernetes-server-linux-arm.tar.gz) | `a39bc970133cd519f9dc99377fc83ef3472246ba334ea3e6060c001748c6fffd6fb27bff94b9bc18b6e1ea7d0da1c3160eb4b1f8fb58a3eed9bcce4aa464092b` +[kubernetes-server-linux-arm64.tar.gz](https://dl.k8s.io/v1.10.12/kubernetes-server-linux-arm64.tar.gz) | `e9ecb2eac0c887b6659cbf35c0753b8783ca9316ad7c4517f55f2bdc2dde1a5d49d54e34312c025c4492cda2ef40f229be37772477e82098fc7dedbe0c53dcd2` +[kubernetes-server-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.10.12/kubernetes-server-linux-ppc64le.tar.gz) | `6a06b7ceb02e6ce1cf0f8f5bb326fb88441b022f2e87a44125e971365b8cd0dcfa4b1fd5dcfcbeb659950c32f460e26d4600e693cdee54da640beee11e05ed27` +[kubernetes-server-linux-s390x.tar.gz](https://dl.k8s.io/v1.10.12/kubernetes-server-linux-s390x.tar.gz) | `46902169b2fa7be5db76384b851dcd15f20581e7cdc7a69102a8d654269626e19953cb2728014c3c03bdfc4a0ae78afca182dfb4b280177d135ed1fac34b8c1c` + +### Node Binaries + +filename | sha512 hash +-------- | ----------- +[kubernetes-node-linux-amd64.tar.gz](https://dl.k8s.io/v1.10.12/kubernetes-node-linux-amd64.tar.gz) | `066a9268fc2539176232dbf643d2fce09ff8d9d7968c28181d7215455f5019e9abdfc7e2668ab0bb582e249016bfb59add635c2645746f603b6cd0204d6e427f` +[kubernetes-node-linux-arm.tar.gz](https://dl.k8s.io/v1.10.12/kubernetes-node-linux-arm.tar.gz) | `26cede0b12af44a1b43eb0d529ba9e2ae483fb3729a6c70b6bf34110be33260169871005616f736ecb2b87faeb1d10e7e472d7f8baef2a6f36b773d0c005357a` +[kubernetes-node-linux-arm64.tar.gz](https://dl.k8s.io/v1.10.12/kubernetes-node-linux-arm64.tar.gz) | `b98d6fe3bce97f59271eda3ff1dd2674c345f0db3cd5a196922edf67ffcbe4f4428ceb951c69309c20c0641267d2ace39ee697d5cd2fe6891f6ad18e51423179` +[kubernetes-node-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.10.12/kubernetes-node-linux-ppc64le.tar.gz) | `9e7113cf792fa8cfe0bd07ae0c9ec25bb51f9b92bf2ed2724910c0cf935200dd6c5cce03243a2e1788588d550851bf71af796746f38c13176b7311c5b7b9abae` +[kubernetes-node-linux-s390x.tar.gz](https://dl.k8s.io/v1.10.12/kubernetes-node-linux-s390x.tar.gz) | `f083646dc9cc8518b3ccdf0dc5a6dce1cc583236ab31cf9e79a803c7b3c0028ea1daaf4175a95ba0012c407f6d39ea9eab478c9e71a12308021fbfaf2eab933a` +[kubernetes-node-windows-amd64.tar.gz](https://dl.k8s.io/v1.10.12/kubernetes-node-windows-amd64.tar.gz) | `0b01cb827874b641dc51a91c033d6c53d13dac8926e5065d783689c313b2af50176cdb82cc1e65c3660a54f07e104390d02f6b47ecbe49d7e6f1b20ae90bb4d8` + +## Changelog since v1.10.11 + +### Other notable changes + +* Updates defaultbackend to 1.5 ([#69381](https://github.com/kubernetes/kubernetes/pull/69381), [@bowei](https://github.com/bowei)) +* Immediately close the other side of the connection when proxying. ([#67288](https://github.com/kubernetes/kubernetes/pull/67288), [@MHBauer](https://github.com/MHBauer)) +* Disable proxy to loopback and linklocal ([#71980](https://github.com/kubernetes/kubernetes/pull/71980), [@micahhausler](https://github.com/micahhausler)) +* Do not detach volume if mount in progress ([#71145](https://github.com/kubernetes/kubernetes/pull/71145), [@gnufied](https://github.com/gnufied)) +* Only use the first IP address got from instance metadata. This is because Azure CNI would set up a list of IP addresses in instance metadata, while only the first one is the Node's IP. ([#71736](https://github.com/kubernetes/kubernetes/pull/71736), [@feiskyer](https://github.com/feiskyer)) +* fix detach azure disk issue due to dirty cache ([#71495](https://github.com/kubernetes/kubernetes/pull/71495), [@andyzhangx](https://github.com/andyzhangx)) +* Fixes issue where an apiserver on 1.9 and controller-manager on 1.10 can cause volume provisioning and binding to fail. ([#71286](https://github.com/kubernetes/kubernetes/pull/71286), [@msau42](https://github.com/msau42)) +* On GCI, NPD starts to monitor kubelet, docker, containerd crashlooping, read-only filesystem and corrupt docker overlay2 issues. ([#71522](https://github.com/kubernetes/kubernetes/pull/71522), [@wangzhen127](https://github.com/wangzhen127)) +* Allows changing nodeName in endpoint update. ([#68575](https://github.com/kubernetes/kubernetes/pull/68575), [@prameshj](https://github.com/prameshj)) +* Upgrade Stackdriver Logging Agent addon image to 0.6-1.6.0-1 to use Fluentd v1.2. This provides nanoseconds timestamp granularity for logs. ([#70954](https://github.com/kubernetes/kubernetes/pull/70954), [@qingling128](https://github.com/qingling128)) +* apiserver: fixes handling and logging of panics in REST handlers to prevent crashes ([#71076](https://github.com/kubernetes/kubernetes/pull/71076), [@liggitt](https://github.com/liggitt)) +* Fixes ability for admin/edit/view users to see controller revisions, needed for kubectl rollout commands ([#70699](https://github.com/kubernetes/kubernetes/pull/70699), [@liggitt](https://github.com/liggitt)) +* fix azure disk attach/detach failed forever issue ([#71377](https://github.com/kubernetes/kubernetes/pull/71377), [@andyzhangx](https://github.com/andyzhangx)) +* Fixes an issue with stuck connections handling error responses ([#71419](https://github.com/kubernetes/kubernetes/pull/71419), [@liggitt](https://github.com/liggitt)) +* Add tolerations for Stackdriver Logging and Metadata Agents. ([#69737](https://github.com/kubernetes/kubernetes/pull/69737), [@qingling128](https://github.com/qingling128)) + + + # v1.10.11 [Documentation](https://docs.k8s.io) @@ -235,7 +312,7 @@ filename | sha512 hash ### Other notable changes -* Fixes an issue with stuck connections handling error responses ([#71415](https://github.com/kubernetes/kubernetes/pull/71415), [@liggitt](https://github.com/liggitt)) +* CVE-2018-1002105: Fix critical security issue in kube-apiserver upgrade request proxy handler ([#71411](https://github.com/kubernetes/kubernetes/issues/71411), [@liggitt](https://github.com/liggitt)) @@ -1083,17 +1160,17 @@ filename | sha256 hash ### Node -Many of the changes within SIG-Node revolve around control. With the beta release of the `kubelet.config.k8s.io` API group, a significant subset of Kubelet configuration can now be [configured via a versioned config file](https://kubernetes.io/docs/tasks/administer-cluster/kubelet-config-file/). Kubernetes v1.10 adds alpha support for the ability to [configure whether containers in a pod should share a single process namespace](https://github.com/kubernetes/features/issues/495), and the CRI has been upgraded to v1alpha2, which adds [support for Windows Container Configuration](https://github.com/kubernetes/features/issues/547). Kubernetes v1.10 also ships with the beta release of the [CRI validation test suite](https://github.com/kubernetes/features/issues/292). +Many of the changes within SIG-Node revolve around control. With the beta release of the `kubelet.config.k8s.io` API group, a significant subset of Kubelet configuration can now be [configured via a versioned config file](https://kubernetes.io/docs/tasks/administer-cluster/kubelet-config-file/). Kubernetes v1.10 adds alpha support for the ability to [configure whether containers in a pod should share a single process namespace](https://github.com/kubernetes/enhancements/issues/495), and the CRI has been upgraded to v1alpha2, which adds [support for Windows Container Configuration](https://github.com/kubernetes/enhancements/issues/547). Kubernetes v1.10 also ships with the beta release of the [CRI validation test suite](https://github.com/kubernetes/enhancements/issues/292). The Resource Management Working Group graduated three features to beta in the 1.10 release. First, [CPU Manager](https://kubernetes.io/docs/tasks/administer-cluster/cpu-management-policies/), which allows users to request exclusive CPU cores. This helps performance in a variety of use-cases, including network latency sensitive applications, as well as applications that benefit from CPU cache residency. Next, [Huge Pages](https://kubernetes.io/docs/tasks/manage-hugepages/scheduling-hugepages/), which allows pods to consume either 2Mi or 1Gi Huge Pages. This benefits applications that consume large amounts of memory. Use of Huge Pages is a common tuning recommendation for databases and JVMs. Finally, the [Device Plugin](https://kubernetes.io/docs/concepts/cluster-administration/device-plugins/) feature, which provides a framework for vendors to advertise their resources to the Kubelet without changing Kubernetes core code. Targeted devices include GPUs, High-performance NICs, FPGAs, InfiniBand, and other similar computing resources that may require vendor specific initialization and setup. ### Storage -This release brings additional power to both local storage and Persistent Volumes. [Mount namespace propagation](https://github.com/kubernetes/features/issues/432) allows a container to mount a volume as rslave so that host mounts can be seen inside the container, or as rshared so that mounts made inside a container can be seen by the host. (Note that this is [not supported on Windows](https://github.com/kubernetes/kubernetes/pull/60275).) [Local Ephemeral Storage Capacity Isolation](https://github.com/kubernetes/features/issues/361) makes it possible to set requests and limits on ephemeral local storage resources. In addition, you can now create [Local Persistent Storage](https://github.com/kubernetes/features/issues/121), which enables PersistentVolumes to be created with locally attached disks, and not just network volumes. +This release brings additional power to both local storage and Persistent Volumes. [Mount namespace propagation](https://github.com/kubernetes/enhancements/issues/432) allows a container to mount a volume as rslave so that host mounts can be seen inside the container, or as rshared so that mounts made inside a container can be seen by the host. (Note that this is [not supported on Windows](https://github.com/kubernetes/kubernetes/pull/60275).) [Local Ephemeral Storage Capacity Isolation](https://github.com/kubernetes/enhancements/issues/361) makes it possible to set requests and limits on ephemeral local storage resources. In addition, you can now create [Local Persistent Storage](https://github.com/kubernetes/enhancements/issues/121), which enables PersistentVolumes to be created with locally attached disks, and not just network volumes. -On the Persistent Volumes side, this release [Prevents deletion of Persistent Volume Claims that are used by a pod](https://github.com/kubernetes/features/issues/498) and [Persistent Volumes that are bound to a Persistent Volume Claim](https://github.com/kubernetes/features/issues/499), making it impossible to delete storage that is in use by a pod. +On the Persistent Volumes side, this release [Prevents deletion of Persistent Volume Claims that are used by a pod](https://github.com/kubernetes/enhancements/issues/498) and [Persistent Volumes that are bound to a Persistent Volume Claim](https://github.com/kubernetes/enhancements/issues/499), making it impossible to delete storage that is in use by a pod. -This release also includes [Topology Aware Volume Scheduling](https://github.com/kubernetes/features/issues/490) for local persistent volumes, the stable release of [Detailed storage metrics of internal state](https://github.com/kubernetes/features/issues/496), and beta support for [Out-of-tree CSI Volume Plugins](https://github.com/kubernetes/features/issues/178). +This release also includes [Topology Aware Volume Scheduling](https://github.com/kubernetes/enhancements/issues/490) for local persistent volumes, the stable release of [Detailed storage metrics of internal state](https://github.com/kubernetes/enhancements/issues/496), and beta support for [Out-of-tree CSI Volume Plugins](https://github.com/kubernetes/enhancements/issues/178). ### Windows @@ -1105,23 +1182,23 @@ SIG-OpenStack updated the OpenStack provider to use newer APIs, consolidated com ### API-machinery -[API Aggregation](https://github.com/kubernetes/features/issues/263) has been upgraded to "stable" in Kubernetes 1.10, so you can use it in production. Webhooks have seen numerous improvements, including alpha [Support for self-hosting authorizer webhooks](https://github.com/kubernetes/features/issues/516). +[API Aggregation](https://github.com/kubernetes/enhancements/issues/263) has been upgraded to "stable" in Kubernetes 1.10, so you can use it in production. Webhooks have seen numerous improvements, including alpha [Support for self-hosting authorizer webhooks](https://github.com/kubernetes/enhancements/issues/516). ### Auth -This release lays the groundwork for new authentication methods, including the alpha release of [External client-go credential providers](https://github.com/kubernetes/features/issues/541) and the [TokenRequest API](https://github.com/kubernetes/features/issues/542). In addition, [Pod Security Policy](https://github.com/kubernetes/features/issues/5) now lets administrators decide what contexts pods can run in, and gives administrators the ability to [limit node access to the API](https://github.com/kubernetes/features/issues/279). +This release lays the groundwork for new authentication methods, including the alpha release of [External client-go credential providers](https://github.com/kubernetes/enhancements/issues/541) and the [TokenRequest API](https://github.com/kubernetes/enhancements/issues/542). In addition, [Pod Security Policy](https://github.com/kubernetes/enhancements/issues/5) now lets administrators decide what contexts pods can run in, and gives administrators the ability to [limit node access to the API](https://github.com/kubernetes/enhancements/issues/279). ### Azure -Kubernetes 1.10 includes alpha [Azure support for cluster-autoscaler](https://github.com/kubernetes/features/issues/514), as well as [support for Azure Virtual Machine Scale Sets](https://github.com/kubernetes/features/issues/513). +Kubernetes 1.10 includes alpha [Azure support for cluster-autoscaler](https://github.com/kubernetes/enhancements/issues/514), as well as [support for Azure Virtual Machine Scale Sets](https://github.com/kubernetes/enhancements/issues/513). ### CLI -This release includes a change to [kubectl get and describe to work better with extensions](https://github.com/kubernetes/features/issues/515), as the server, rather than the client, returns this information for a smoother user experience. +This release includes a change to [kubectl get and describe to work better with extensions](https://github.com/kubernetes/enhancements/issues/515), as the server, rather than the client, returns this information for a smoother user experience. ### Network -In terms of networking, Kubernetes 1.10 is about control. Users now have beta support for the ability to [configure a pod's resolv.conf](https://github.com/kubernetes/features/issues/504), rather than relying on the cluster DNS, as well as [configuring the NodePort IP address](https://github.com/kubernetes/features/issues/539). You can also [switch the default DNS plugin to CoreDNS](https://github.com/kubernetes/features/issues/427) (beta). +In terms of networking, Kubernetes 1.10 is about control. Users now have beta support for the ability to [configure a pod's resolv.conf](https://github.com/kubernetes/enhancements/issues/504), rather than relying on the cluster DNS, as well as [configuring the NodePort IP address](https://github.com/kubernetes/enhancements/issues/539). You can also [switch the default DNS plugin to CoreDNS](https://github.com/kubernetes/enhancements/issues/427) (beta). ## Before Upgrading @@ -1267,7 +1344,7 @@ If no featureGates was specified in `kubeadm-config`, just change `featureGates: * VolumeScheduling and LocalPersistentVolume features are beta and enabled by default. The PersistentVolume NodeAffinity alpha annotation is deprecated and will be removed in a future release. ([#59391](https://github.com/kubernetes/kubernetes/pull/59391), [@msau42](https://github.com/msau42)) -* The alpha Accelerators feature gate is deprecated and will be removed in v1.11. Please use device plugins ([https://github.com/kubernetes/features/issues/368](https://github.com/kubernetes/features/issues/368)) instead. They can be enabled using the DevicePlugins feature gate. ([#57384](https://github.com/kubernetes/kubernetes/pull/57384), [@mindprince](https://github.com/mindprince)) +* The alpha Accelerators feature gate is deprecated and will be removed in v1.11. Please use device plugins ([https://github.com/kubernetes/enhancements/issues/368](https://github.com/kubernetes/enhancements/issues/368)) instead. They can be enabled using the DevicePlugins feature gate. ([#57384](https://github.com/kubernetes/kubernetes/pull/57384), [@mindprince](https://github.com/mindprince)) * The ability to use kubectl scale jobs is deprecated. All other scale operations remain in place, but the ability to scale jobs will be removed in a future release. ([#60139](https://github.com/kubernetes/kubernetes/pull/60139), [@soltysh](https://github.com/soltysh)) @@ -1397,7 +1474,7 @@ Accept: application/com.github.proto-openapi.spec.v2@v1.0+protobuf Accept-Encodi * Fix RBAC role for certificate controller to allow cleaning up of Certificate Signing Requests that are Approved and issued or Denied. ([#59375](https://github.com/kubernetes/kubernetes/pull/59375), [@mikedanese](https://github.com/mikedanese)) -* kube-apiserver: Use of the `--admission-control-config-file` with a file containing an AdmissionConfiguration apiserver.k8s.io/v1alpha1 config object no longer leads to an error when launching kube-apiserver. ([#58439]([https://github.com/kubernetes/kubernetes/pull/58439](https://github.com/kubernetes/kubernetes/pull/58439)) [@liggitt](https://github.com/liggitt)) +* kube-apiserver: Use of the `--admission-control-config-file` with a file containing an AdmissionConfiguration apiserver.k8s.io/v1alpha1 config object no longer leads to an error when launching kube-apiserver. ([#58439](https://github.com/kubernetes/kubernetes/pull/58439) [@liggitt](https://github.com/liggitt)) * Default enabled admission plugins are now `NamespaceLifecycle,LimitRanger,ServiceAccount,PersistentVolumeLabel,DefaultStorageClass,DefaultTolerationSeconds,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota`. Please note that if you previously had not set the `--admission-control` flag, your cluster behavior may change (to be more standard). ([#58684](https://github.com/kubernetes/kubernetes/pull/58684), [@hzxuzhonghu](https://github.com/hzxuzhonghu)) @@ -1700,7 +1777,7 @@ And point to the file using the --config flag, as in * Kubernetes now uses the more reliable GlobalMemoryStatusEx to get total physical memory on windows nodes. ([#57124](https://github.com/kubernetes/kubernetes/pull/57124), [@JiangtianLi](https://github.com/JiangtianLi)) -* Windows containers now support experimental Hyper-V isolation by setting annotation `experimental.windows.kubernetes.io/isolation-type=hyperv` and feature gates HyperVContainer. At the moment this function only supports one container per pod. ([#58751]([https://github.com/kubernetes/kubernetes/pull/58751](https://github.com/kubernetes/kubernetes/pull/58751)), [@feiskyer](https://github.com/feiskyer)) +* Windows containers now support experimental Hyper-V isolation by setting annotation `experimental.windows.kubernetes.io/isolation-type=hyperv` and feature gates HyperVContainer. At the moment this function only supports one container per pod. ([#58751](https://github.com/kubernetes/kubernetes/pull/58751), [@feiskyer](https://github.com/feiskyer)) * Get windows kernel version directly from registry rather than windows.getVersion(). ([#58498](https://github.com/kubernetes/kubernetes/pull/58498), [@feiskyer](https://github.com/feiskyer)) @@ -1801,7 +1878,7 @@ And point to the file using the --config flag, as in * Fixed race condition issue when detaching azure disk, preventing `Multi-Attach error`s when scheduling one pod from one node to another. ([#60183](https://github.com/kubernetes/kubernetes/pull/60183), [@andyzhangx](https://github.com/andyzhangx)) -* Add AzureDisk support for vmss nodes. ([#59716]([https://github.com/kubernetes/kubernetes/pull/59716](https://github.com/kubernetes/kubernetes/pull/59716)), [@feiskyer](https://github.com/feiskyer)) +* Add AzureDisk support for vmss nodes. ([#59716](https://github.com/kubernetes/kubernetes/pull/59716), [@feiskyer](https://github.com/feiskyer)) * Map correct vmset name for Azure internal load balancers. ([#59747](https://github.com/kubernetes/kubernetes/pull/59747), [@feiskyer](https://github.com/feiskyer)) @@ -1926,7 +2003,7 @@ parameters: * Increase timeout of integration tests ([#60458](https://github.com/kubernetes/kubernetes/pull/60458), [@jennybuckley](https://github.com/jennybuckley)) -* force node name lowercase on static pod name generating ([#59849](https://github.com/kubernetes/kubernetes/pull/59849), [@yue9944882]([https://github.com/yue9944882](https://github.com/yue9944882)) +* force node name lowercase on static pod name generating ([#59849](https://github.com/kubernetes/kubernetes/pull/59849), [@yue9944882](https://github.com/yue9944882) * fix device name change issue for azure disk ([#60346](https://github.com/kubernetes/kubernetes/pull/60346), [@andyzhangx](https://github.com/andyzhangx)) diff --git a/CHANGELOG-1.11.md b/CHANGELOG-1.11.md index 803ef6450dd..6a3dc843fc1 100644 --- a/CHANGELOG-1.11.md +++ b/CHANGELOG-1.11.md @@ -1,47 +1,54 @@ -- [v1.11.5](#v1115) - - [Downloads for v1.11.5](#downloads-for-v1115) +- [v1.11.6](#v1116) + - [Downloads for v1.11.6](#downloads-for-v1116) - [Client Binaries](#client-binaries) - [Server Binaries](#server-binaries) - [Node Binaries](#node-binaries) - - [Changelog since v1.11.4](#changelog-since-v1114) + - [Changelog since v1.11.5](#changelog-since-v1115) - [Other notable changes](#other-notable-changes) -- [v1.11.4](#v1114) - - [Downloads for v1.11.4](#downloads-for-v1114) +- [v1.11.5](#v1115) + - [Downloads for v1.11.5](#downloads-for-v1115) - [Client Binaries](#client-binaries-1) - [Server Binaries](#server-binaries-1) - [Node Binaries](#node-binaries-1) - - [Changelog since v1.11.3](#changelog-since-v1113) + - [Changelog since v1.11.4](#changelog-since-v1114) - [Other notable changes](#other-notable-changes-1) -- [v1.11.3](#v1113) - - [Downloads for v1.11.3](#downloads-for-v1113) +- [v1.11.4](#v1114) + - [Downloads for v1.11.4](#downloads-for-v1114) - [Client Binaries](#client-binaries-2) - [Server Binaries](#server-binaries-2) - [Node Binaries](#node-binaries-2) - - [Changelog since v1.11.2](#changelog-since-v1112) - - [Action Required](#action-required) + - [Changelog since v1.11.3](#changelog-since-v1113) - [Other notable changes](#other-notable-changes-2) -- [v1.11.2](#v1112) - - [Downloads for v1.11.2](#downloads-for-v1112) +- [v1.11.3](#v1113) + - [Downloads for v1.11.3](#downloads-for-v1113) - [Client Binaries](#client-binaries-3) - [Server Binaries](#server-binaries-3) - [Node Binaries](#node-binaries-3) - - [Changelog since v1.11.1](#changelog-since-v1111) - - [Action Required](#action-required-1) + - [Changelog since v1.11.2](#changelog-since-v1112) + - [Action Required](#action-required) - [Other notable changes](#other-notable-changes-3) -- [v1.11.1](#v1111) - - [Downloads for v1.11.1](#downloads-for-v1111) +- [v1.11.2](#v1112) + - [Downloads for v1.11.2](#downloads-for-v1112) - [Client Binaries](#client-binaries-4) - [Server Binaries](#server-binaries-4) - [Node Binaries](#node-binaries-4) - - [Changelog since v1.11.0](#changelog-since-v1110) - - [Action Required](#action-required-2) + - [Changelog since v1.11.1](#changelog-since-v1111) + - [Action Required](#action-required-1) - [Other notable changes](#other-notable-changes-4) -- [v1.11.0](#v1110) - - [Downloads for v1.11.0](#downloads-for-v1110) +- [v1.11.1](#v1111) + - [Downloads for v1.11.1](#downloads-for-v1111) - [Client Binaries](#client-binaries-5) - [Server Binaries](#server-binaries-5) - [Node Binaries](#node-binaries-5) + - [Changelog since v1.11.0](#changelog-since-v1110) + - [Action Required](#action-required-2) + - [Other notable changes](#other-notable-changes-5) +- [v1.11.0](#v1110) + - [Downloads for v1.11.0](#downloads-for-v1110) + - [Client Binaries](#client-binaries-6) + - [Server Binaries](#server-binaries-6) + - [Node Binaries](#node-binaries-6) - [Kubernetes 1.11 Release Notes](#kubernetes-111-release-notes) - [Urgent Upgrade Notes](#urgent-upgrade-notes) - [(No, really, you MUST do this before you upgrade)](#no-really-you-must-do-this-before-you-upgrade) @@ -64,7 +71,7 @@ - [Graduated to Stable/GA](#graduated-to-stablega) - [Graduated to Beta](#graduated-to-beta) - [New alpha features](#new-alpha-features) - - [Other Notable Changes](#other-notable-changes-5) + - [Other Notable Changes](#other-notable-changes-6) - [SIG API Machinery](#sig-api-machinery-1) - [SIG Apps](#sig-apps) - [SIG Auth](#sig-auth-1) @@ -88,62 +95,141 @@ - [Non-user-facing changes](#non-user-facing-changes) - [v1.11.0-rc.3](#v1110-rc3) - [Downloads for v1.11.0-rc.3](#downloads-for-v1110-rc3) - - [Client Binaries](#client-binaries-6) - - [Server Binaries](#server-binaries-6) - - [Node Binaries](#node-binaries-6) - - [Changelog since v1.11.0-rc.2](#changelog-since-v1110-rc2) - - [Other notable changes](#other-notable-changes-6) -- [v1.11.0-rc.2](#v1110-rc2) - - [Downloads for v1.11.0-rc.2](#downloads-for-v1110-rc2) - [Client Binaries](#client-binaries-7) - [Server Binaries](#server-binaries-7) - [Node Binaries](#node-binaries-7) - - [Changelog since v1.11.0-rc.1](#changelog-since-v1110-rc1) + - [Changelog since v1.11.0-rc.2](#changelog-since-v1110-rc2) - [Other notable changes](#other-notable-changes-7) -- [v1.11.0-rc.1](#v1110-rc1) - - [Downloads for v1.11.0-rc.1](#downloads-for-v1110-rc1) +- [v1.11.0-rc.2](#v1110-rc2) + - [Downloads for v1.11.0-rc.2](#downloads-for-v1110-rc2) - [Client Binaries](#client-binaries-8) - [Server Binaries](#server-binaries-8) - [Node Binaries](#node-binaries-8) - - [Changelog since v1.11.0-beta.2](#changelog-since-v1110-beta2) - - [Action Required](#action-required-3) + - [Changelog since v1.11.0-rc.1](#changelog-since-v1110-rc1) - [Other notable changes](#other-notable-changes-8) -- [v1.11.0-beta.2](#v1110-beta2) - - [Downloads for v1.11.0-beta.2](#downloads-for-v1110-beta2) +- [v1.11.0-rc.1](#v1110-rc1) + - [Downloads for v1.11.0-rc.1](#downloads-for-v1110-rc1) - [Client Binaries](#client-binaries-9) - [Server Binaries](#server-binaries-9) - [Node Binaries](#node-binaries-9) - - [Changelog since v1.11.0-beta.1](#changelog-since-v1110-beta1) - - [Action Required](#action-required-4) + - [Changelog since v1.11.0-beta.2](#changelog-since-v1110-beta2) + - [Action Required](#action-required-3) - [Other notable changes](#other-notable-changes-9) -- [v1.11.0-beta.1](#v1110-beta1) - - [Downloads for v1.11.0-beta.1](#downloads-for-v1110-beta1) +- [v1.11.0-beta.2](#v1110-beta2) + - [Downloads for v1.11.0-beta.2](#downloads-for-v1110-beta2) - [Client Binaries](#client-binaries-10) - [Server Binaries](#server-binaries-10) - [Node Binaries](#node-binaries-10) - - [Changelog since v1.11.0-alpha.2](#changelog-since-v1110-alpha2) - - [Action Required](#action-required-5) + - [Changelog since v1.11.0-beta.1](#changelog-since-v1110-beta1) + - [Action Required](#action-required-4) - [Other notable changes](#other-notable-changes-10) -- [v1.11.0-alpha.2](#v1110-alpha2) - - [Downloads for v1.11.0-alpha.2](#downloads-for-v1110-alpha2) +- [v1.11.0-beta.1](#v1110-beta1) + - [Downloads for v1.11.0-beta.1](#downloads-for-v1110-beta1) - [Client Binaries](#client-binaries-11) - [Server Binaries](#server-binaries-11) - [Node Binaries](#node-binaries-11) - - [Changelog since v1.11.0-alpha.1](#changelog-since-v1110-alpha1) + - [Changelog since v1.11.0-alpha.2](#changelog-since-v1110-alpha2) + - [Action Required](#action-required-5) - [Other notable changes](#other-notable-changes-11) -- [v1.11.0-alpha.1](#v1110-alpha1) - - [Downloads for v1.11.0-alpha.1](#downloads-for-v1110-alpha1) +- [v1.11.0-alpha.2](#v1110-alpha2) + - [Downloads for v1.11.0-alpha.2](#downloads-for-v1110-alpha2) - [Client Binaries](#client-binaries-12) - [Server Binaries](#server-binaries-12) - [Node Binaries](#node-binaries-12) + - [Changelog since v1.11.0-alpha.1](#changelog-since-v1110-alpha1) + - [Other notable changes](#other-notable-changes-12) +- [v1.11.0-alpha.1](#v1110-alpha1) + - [Downloads for v1.11.0-alpha.1](#downloads-for-v1110-alpha1) + - [Client Binaries](#client-binaries-13) + - [Server Binaries](#server-binaries-13) + - [Node Binaries](#node-binaries-13) - [Changelog since v1.10.0](#changelog-since-v1100) - [Action Required](#action-required-6) - - [Other notable changes](#other-notable-changes-12) + - [Other notable changes](#other-notable-changes-13) +# v1.11.6 + +[Documentation](https://docs.k8s.io) + +## Downloads for v1.11.6 + + +filename | sha512 hash +-------- | ----------- +[kubernetes.tar.gz](https://dl.k8s.io/v1.11.6/kubernetes.tar.gz) | `78e865de9aa6065a48027fc2c9c5e9e957c36dd69d1859e29db283875562cf11d54cb50910151e320f08554a5a530f9af83e8c437bd78e8feef038514be303a9` +[kubernetes-src.tar.gz](https://dl.k8s.io/v1.11.6/kubernetes-src.tar.gz) | `e9309ebcc5ca68c86ff623c45af0a91c4d9b11d4a39df6f6df98101aea22422ada4e4be243eabf8e7134fe38ff899da9f504c7abed6d482d0222ada0e0b65d81` + +### Client Binaries + +filename | sha512 hash +-------- | ----------- +[kubernetes-client-darwin-386.tar.gz](https://dl.k8s.io/v1.11.6/kubernetes-client-darwin-386.tar.gz) | `b5b3bcf9aab8694647bb03d13c83fdc5250d29f52cdf3ff9e52147f8be5fad9713242ad6996a84bcb6aaa76739abc392a8774b14c12d6896923ec0671eda84d9` +[kubernetes-client-darwin-amd64.tar.gz](https://dl.k8s.io/v1.11.6/kubernetes-client-darwin-amd64.tar.gz) | `dc25f6121501d79c3871848dc91a4528e24031ef7c7c52f85e1706e5d83b41ae1aabb33824ddbb456283f204d61853cf2daed6dd433dbb2ed16f67f7b32c8e52` +[kubernetes-client-linux-386.tar.gz](https://dl.k8s.io/v1.11.6/kubernetes-client-linux-386.tar.gz) | `8e8e22e03126c8de297ca45b7e1b292ac1c0fd1e5cc119964de2332457c63df16a2aa43fd3dcef6cff4224324dddcc497932533c3fed5c55a0d097bb364dc8e9` +[kubernetes-client-linux-amd64.tar.gz](https://dl.k8s.io/v1.11.6/kubernetes-client-linux-amd64.tar.gz) | `6048e7ccb5c084f7582511cba3bd0db2c8ccb237d409956d08cb3c20735e076b52bc3a0aa3d7cce8d1d8d980e5e3bb72ebe25107f17c1ec86a1841cfadd7dbc7` +[kubernetes-client-linux-arm.tar.gz](https://dl.k8s.io/v1.11.6/kubernetes-client-linux-arm.tar.gz) | `3fcc09d617949c09fc0a470633460b534092f45e47b74365bbed243f582817f0a63a73ff39c90e298894334085ec3c32d8a75b1c742ac782beff4f5ed36fb070` +[kubernetes-client-linux-arm64.tar.gz](https://dl.k8s.io/v1.11.6/kubernetes-client-linux-arm64.tar.gz) | `5fc0c5d1f1580080ac383cdef61ce11d21845a84e2f196ccbc826ec565ad34755ec746be741ed46de93d782d1e5f1ea9991a8583cbe6f34222d56ff4f7aef67a` +[kubernetes-client-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.11.6/kubernetes-client-linux-ppc64le.tar.gz) | `95f986284501b681ba45158383248dacdb42b95445776509844a34e7939116c61db3c7b37fb0b390a8ff5d0a5354ec5e9e98048117f2e716c28e87bcef9e19d7` +[kubernetes-client-linux-s390x.tar.gz](https://dl.k8s.io/v1.11.6/kubernetes-client-linux-s390x.tar.gz) | `a83f75d6698b8586c7974d2fb67b7f25aaf591ee6b17381b0d415a170941969c65e97df679b4efc6df7ea4f1424339ceb210b5e64c12bee923988cd5a24761e7` +[kubernetes-client-windows-386.tar.gz](https://dl.k8s.io/v1.11.6/kubernetes-client-windows-386.tar.gz) | `f083073409ef17c29a4791163d6ca0cbb19d61dbd79f8057c2e7056951638d6600b7047b7638394d1f1847179897c30e3c5666665d937fca50f2221fbfa43cef` +[kubernetes-client-windows-amd64.tar.gz](https://dl.k8s.io/v1.11.6/kubernetes-client-windows-amd64.tar.gz) | `3a8198a787c2efc74e40e7eaa2c66ff76b3ae13656ba49382de0fbda6ff21bbe17b5b8cf7672b2e538e017a9773ad172df3cbdb4e1c800b535cb84e5f66078ea` + +### Server Binaries + +filename | sha512 hash +-------- | ----------- +[kubernetes-server-linux-amd64.tar.gz](https://dl.k8s.io/v1.11.6/kubernetes-server-linux-amd64.tar.gz) | `4aa44b92ecaed54ff3535687729d8a3e4421a9c3772937b7a26bb813d1cce06785ad4a746c40654bf3b3f57b1ece1691a244220693ed0db402b2430bd94119af` +[kubernetes-server-linux-arm.tar.gz](https://dl.k8s.io/v1.11.6/kubernetes-server-linux-arm.tar.gz) | `56f2b429e48858bbac7a28a46c4a59b942fbcad14da8c89d997f87b84268a7f5e8e7b591f326b3e51cdac2ec86ed4bb20eb1de62fdc595f1cea6acbc9117c8e1` +[kubernetes-server-linux-arm64.tar.gz](https://dl.k8s.io/v1.11.6/kubernetes-server-linux-arm64.tar.gz) | `afd2aa213c6485591faf734d58415aef44f887bd4da4a895f37f091665c372ebeecc8c3daeafc47864ae376b457a6d134d535d021f5601a7e8dddbbe2c8f7ac1` +[kubernetes-server-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.11.6/kubernetes-server-linux-ppc64le.tar.gz) | `0ecf8feafb05746a43fc8e9cd822dbee294f9e02323851b3b9cdf27eba0f40dcbf5a047a54f09f248496191688fe1f8422dc9a02973644bf8853427e589b2707` +[kubernetes-server-linux-s390x.tar.gz](https://dl.k8s.io/v1.11.6/kubernetes-server-linux-s390x.tar.gz) | `88a450b30aa213b30092447761eadd6c8440a406a10819400f365edde42f3ddfb39dd330981fd5d5f6a1d5c15a623ef9e89e97f8571a5762a8b7e5b5b4db9a82` + +### Node Binaries + +filename | sha512 hash +-------- | ----------- +[kubernetes-node-linux-amd64.tar.gz](https://dl.k8s.io/v1.11.6/kubernetes-node-linux-amd64.tar.gz) | `5627a6382277e34ad5240b41740b5bb300dd86cbceb9fe8967da07650939b1a5e899dbb2da63bba6202e2ca95dbdd9492b8ce9285a5e57ddbf3b6b52f8f8a8f8` +[kubernetes-node-linux-arm.tar.gz](https://dl.k8s.io/v1.11.6/kubernetes-node-linux-arm.tar.gz) | `d6d497bd02eb7b749663f600b11ce5364d79e1a2e7229c9ed9abaf25d99de20f41caa88b1358940986faacdfe4c110afe3f8e63f102fb26b11166611cbe43b89` +[kubernetes-node-linux-arm64.tar.gz](https://dl.k8s.io/v1.11.6/kubernetes-node-linux-arm64.tar.gz) | `bd23aced861869fb857bf36754882274f3c7353eccdbc9fc7f1b3e24ab80254efb0de6d79783e2438a1eda12d51b807786507c000d5752001b605efac0607a6d` +[kubernetes-node-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.11.6/kubernetes-node-linux-ppc64le.tar.gz) | `fb78c12993b800b235fe31a0d21172aeb207b2d2d78bb84a6e4cb1b8536bf3e55b2c139d4f17c3967ebbcb8c296dca5b931b7dcff28a04fa49e71a2e9604be05` +[kubernetes-node-linux-s390x.tar.gz](https://dl.k8s.io/v1.11.6/kubernetes-node-linux-s390x.tar.gz) | `15945c55c3665d9694b0a6476e53af5a372742ef59c49a8678141a545db0491f52cd1cc2bc9a9d1a9b3f8f6ad51228651e59bc4a9703e8f8c90d05409e3a92a0` +[kubernetes-node-windows-amd64.tar.gz](https://dl.k8s.io/v1.11.6/kubernetes-node-windows-amd64.tar.gz) | `3bf95932081fe7f62741f0ad652d0bef94aa61961a6af4b097b0a92a80deffa2c24b3a8e4a14a881c4474b84af46b6212b1ea5377cba125c7c9eb242adf2cc92` + +## Changelog since v1.11.5 + +### Other notable changes + +* Scheduler only activates unschedulable pods if node's scheduling related properties change. ([#71551](https://github.com/kubernetes/kubernetes/pull/71551), [@mlmhl](https://github.com/mlmhl)) +* Disable proxy to loopback and linklocal ([#71980](https://github.com/kubernetes/kubernetes/pull/71980), [@micahhausler](https://github.com/micahhausler)) +* Scheduler only activates unschedulable pods if node's scheduling related properties change. ([#71551](https://github.com/kubernetes/kubernetes/pull/71551), [@mlmhl](https://github.com/mlmhl)) +* fix issue: vm sku restriction policy does not work in azure disk attach/detach ([#71941](https://github.com/kubernetes/kubernetes/pull/71941), [@andyzhangx](https://github.com/andyzhangx)) +* Include CRD for BGPConfigurations, needed for calico 2.x to 3.x upgrade. ([#71868](https://github.com/kubernetes/kubernetes/pull/71868), [@satyasm](https://github.com/satyasm)) +* On GCI, NPD starts to monitor kubelet, docker, containerd crashlooping, read-only filesystem and corrupt docker overlay2 issues. ([#71522](https://github.com/kubernetes/kubernetes/pull/71522), [@wangzhen127](https://github.com/wangzhen127)) +* UDP connections now support graceful termination in IPVS mode ([#71515](https://github.com/kubernetes/kubernetes/pull/71515), [@lbernail](https://github.com/lbernail)) +* Fix a potential bug that scheduler preempts unnecessary pods. ([#70898](https://github.com/kubernetes/kubernetes/pull/70898), [@Huang-Wei](https://github.com/Huang-Wei)) +* Only use the first IP address got from instance metadata. This is because Azure CNI would set up a list of IP addresses in instance metadata, while only the first one is the Node's IP. ([#71736](https://github.com/kubernetes/kubernetes/pull/71736), [@feiskyer](https://github.com/feiskyer)) +* Fix scheduling starvation of pods in cluster with large number of unschedulable pods. ([#71488](https://github.com/kubernetes/kubernetes/pull/71488), [@bsalamat](https://github.com/bsalamat)) +* Fixes an issue with stuck connections handling error responses ([#71419](https://github.com/kubernetes/kubernetes/pull/71419), [@liggitt](https://github.com/liggitt)) +* Ensure orphan public IPs on Azure deleted when service recreated with the same name. ([#70463](https://github.com/kubernetes/kubernetes/pull/70463), [@feiskyer](https://github.com/feiskyer)) +* Upgrade Stackdriver Logging Agent addon image to 0.6-1.6.0-1 to use Fluentd v1.2. This provides nanoseconds timestamp granularity for logs. ([#70954](https://github.com/kubernetes/kubernetes/pull/70954), [@qingling128](https://github.com/qingling128)) +* [GCE] Filter out spammy audit logs from cluster autoscaler. ([#70696](https://github.com/kubernetes/kubernetes/pull/70696), [@loburm](https://github.com/loburm)) +* Fix a scheduler panic due to internal cache inconsistency ([#71063](https://github.com/kubernetes/kubernetes/pull/71063), [@Huang-Wei](https://github.com/Huang-Wei)) +* apiserver: fixes handling and logging of panics in REST handlers to prevent crashes ([#71076](https://github.com/kubernetes/kubernetes/pull/71076), [@liggitt](https://github.com/liggitt)) +* Upgrade golang.org/x/net image to release-branch.go1.10 ([#70663](https://github.com/kubernetes/kubernetes/pull/70663), [@wenjiaswe](https://github.com/wenjiaswe)) +* Fixes a bug in previous releases where a pod could be placed inside another pod's cgroup when specifying --cgroup-root ([#70678](https://github.com/kubernetes/kubernetes/pull/70678), [@dashpole](https://github.com/dashpole)) +* Fixes ability for admin/edit/view users to see controller revisions, needed for kubectl rollout commands ([#70699](https://github.com/kubernetes/kubernetes/pull/70699), [@liggitt](https://github.com/liggitt)) +* remove retry operation on attach/detach azure disk ([#70568](https://github.com/kubernetes/kubernetes/pull/70568), [@andyzhangx](https://github.com/andyzhangx)) +* Fix cloud-controller-manager crash when using OpenStack provider and PersistentVolume initializing controller ([#70459](https://github.com/kubernetes/kubernetes/pull/70459), [@mvladev](https://github.com/mvladev)) +* Update defaultbackend to 1.5: move /metrics to a private endpoint (:10254). ([#69383](https://github.com/kubernetes/kubernetes/pull/69383), [@bowei](https://github.com/bowei)) +* Allows changing nodeName in endpoint update. ([#68575](https://github.com/kubernetes/kubernetes/pull/68575), [@prameshj](https://github.com/prameshj)) +* Improve Azure instance metadata handling by adding caches. ([#70353](https://github.com/kubernetes/kubernetes/pull/70353), [@feiskyer](https://github.com/feiskyer)) + + + # v1.11.5 [Documentation](https://docs.k8s.io) @@ -196,7 +282,7 @@ filename | sha512 hash ### Other notable changes -* Fixes an issue with stuck connections handling error responses ([#71414](https://github.com/kubernetes/kubernetes/pull/71414), [@liggitt](https://github.com/liggitt)) +* CVE-2018-1002105: Fix critical security issue in kube-apiserver upgrade request proxy handler ([#71411](https://github.com/kubernetes/kubernetes/issues/71411), [@liggitt](https://github.com/liggitt)) * IPVS proxier mode now support connection based graceful termination. ([#66012](https://github.com/kubernetes/kubernetes/pull/66012), [@Lion-Wei](https://github.com/Lion-Wei)) * Update Cluster Autoscaler to 1.3.4 ([#70285](https://github.com/kubernetes/kubernetes/pull/70285), [@losipiuk](https://github.com/losipiuk)) * Fix cluster autoscaler addon permissions so it can access batch/job. ([#69858](https://github.com/kubernetes/kubernetes/pull/69858), [@losipiuk](https://github.com/losipiuk)) @@ -806,30 +892,30 @@ controllerManagerExtraVolumes: * Support for the `alpha.kubernetes.io/nvidia-gpu` resource, which was deprecated in 1.10, has been removed. Please use the resource exposed by DevicePlugins instead (`nvidia.com/gpu`). ([#61498](https://github.com/kubernetes/kubernetes/pull/61498), [@mindprince](https://github.com/mindprince)) * The `kube-cloud-controller-manager` flag `--service-account-private-key-file` has been removed. Use `--use-service-account-credentials` instead. ([#60875](https://github.com/kubernetes/kubernetes/pull/60875), [@charrywanganthony](https://github.com/charrywanganthony)) * The rknetes code, which was deprecated in 1.10, has been removed. Use rktlet and CRI instead. ([#61432](https://github.com/kubernetes/kubernetes/pull/61432), [@filbranden](https://github.com/filbranden)) -* DaemonSet scheduling associated with the alpha ScheduleDaemonSetPods feature flag has been emoved. See https://github.com/kubernetes/features/issues/548 for feature status. ([#61411](https://github.com/kubernetes/kubernetes/pull/61411), [@liggitt](https://github.com/liggitt)) +* DaemonSet scheduling associated with the alpha ScheduleDaemonSetPods feature flag has been emoved. See https://github.com/kubernetes/enhancements/issues/548 for feature status. ([#61411](https://github.com/kubernetes/kubernetes/pull/61411), [@liggitt](https://github.com/liggitt)) * The `METADATA_AGENT_VERSION` configuration option has been removed to keep metadata agent version consistent across Kubernetes deployments. ([#63000](https://github.com/kubernetes/kubernetes/pull/63000), [@kawych](https://github.com/kawych)) * The deprecated `--service-account-private-key-file` flag has been removed from the cloud-controller-manager. The flag is still present and supported in the kube-controller-manager. ([#65182](https://github.com/kubernetes/kubernetes/pull/65182), [@liggitt](https://github.com/liggitt)) * Removed alpha functionality that allowed the controller manager to approve kubelet server certificates. This functionality should be replaced by automating validation and approval of node server certificate signing requests. ([#62471](https://github.com/kubernetes/kubernetes/pull/62471), [@mikedanese](https://github.com/mikedanese)) #### Graduated to Stable/GA -* IPVS-based in-cluster load balancing is now GA ([ref](https://github.com/kubernetes/features/issues/265)) -* Enable CoreDNS as a DNS plugin for Kubernetes ([ref](https://github.com/kubernetes/features/issues/427)) +* IPVS-based in-cluster load balancing is now GA ([ref](https://github.com/kubernetes/enhancements/issues/265)) +* Enable CoreDNS as a DNS plugin for Kubernetes ([ref](https://github.com/kubernetes/enhancements/issues/427)) * Azure Go SDK is now GA ([#63063](https://github.com/kubernetes/kubernetes/pull/63063), [@feiskyer](https://github.com/feiskyer)) -* ClusterRole aggregation is now GA ([ref](https://github.com/kubernetes/features/issues/502)) -* CRI validation test suite is now GA ([ref](https://github.com/kubernetes/features/issues/292)) -* StorageObjectInUseProtection is now GA ([ref](https://github.com/kubernetes/features/issues/498)) and ([ref](https://github.com/kubernetes/features/issues/499)) +* ClusterRole aggregation is now GA ([ref](https://github.com/kubernetes/enhancements/issues/502)) +* CRI validation test suite is now GA ([ref](https://github.com/kubernetes/enhancements/issues/292)) +* StorageObjectInUseProtection is now GA ([ref](https://github.com/kubernetes/enhancements/issues/498)) and ([ref](https://github.com/kubernetes/enhancements/issues/499)) #### Graduated to Beta -* Supporting out-of-tree/external cloud providers is now considered beta ([ref](https://github.com/kubernetes/features/issues/88)) -* Resizing PersistentVolumes after pod restart is now considered beta. ([ref](https://github.com/kubernetes/features/issues/284)) -* sysctl support is now considered beta ([ref](https://github.com/kubernetes/features/issues/34)) -* Support for Azure Virtual Machine Scale Sets is now considered beta. ([ref](https://github.com/kubernetes/features/issues/513)) -* Azure support for Cluster Autoscaler is now considered beta. ([ref](https://github.com/kubernetes/features/issues/514)) -* The ability to limit a node's access to the API is now considered beta. ([ref](https://github.com/kubernetes/features/issues/279)) -* CustomResource versioning is now considered beta. ([ref](https://github.com/kubernetes/features/issues/544)) -* Windows container configuration in CRI is now considered beta ([ref](https://github.com/kubernetes/features/issues/547)) -* CRI logging and stats are now considered beta ([ref](https://github.com/kubernetes/features/issues/552)) +* Supporting out-of-tree/external cloud providers is now considered beta ([ref](https://github.com/kubernetes/enhancements/issues/88)) +* Resizing PersistentVolumes after pod restart is now considered beta. ([ref](https://github.com/kubernetes/enhancements/issues/284)) +* sysctl support is now considered beta ([ref](https://github.com/kubernetes/enhancements/issues/34)) +* Support for Azure Virtual Machine Scale Sets is now considered beta. ([ref](https://github.com/kubernetes/enhancements/issues/513)) +* Azure support for Cluster Autoscaler is now considered beta. ([ref](https://github.com/kubernetes/enhancements/issues/514)) +* The ability to limit a node's access to the API is now considered beta. ([ref](https://github.com/kubernetes/enhancements/issues/279)) +* CustomResource versioning is now considered beta. ([ref](https://github.com/kubernetes/enhancements/issues/544)) +* Windows container configuration in CRI is now considered beta ([ref](https://github.com/kubernetes/enhancements/issues/547)) +* CRI logging and stats are now considered beta ([ref](https://github.com/kubernetes/enhancements/issues/552)) * The dynamic Kubelet config feature is now beta, and the DynamicKubeletConfig feature gate is on by default. In order to use dynamic Kubelet config, ensure that the Kubelet's --dynamic-config-dir option is set. ([#64275](https://github.com/kubernetes/kubernetes/pull/64275), [@mtaufen](https://github.com/mtaufen)) * The Sysctls experimental feature has been promoted to beta (enabled by default via the `Sysctls` feature flag). PodSecurityPolicy and Pod objects now have fields for specifying and controlling sysctls. Alpha sysctl annotations will be ignored by 1.11+ kubelets. All alpha sysctl annotations in existing deployments must be converted to API fields to be effective. ([#6371](https://github.com/kubernetes/kubernetes/pull/63717), [@ingvagabund](https://github.com/ingvagabund)) * Volume expansion is now considered Beta. ([#64288](https://github.com/kubernetes/kubernetes/pull/64288), [@gnufied](https://github.com/gnufied)) @@ -841,12 +927,12 @@ controllerManagerExtraVolumes: ### New alpha features -* kube-scheduler can now schedule DaemonSet pods ([ref](https://github.com/kubernetes/features/issues/548)) -* You can now resize PersistentVolumes without taking them offline ([ref](https://github.com/kubernetes/features/issues/531)) -* You can now set a maximum volume count ([ref](https://github.com/kubernetes/features/issues/554)) -* You can now do environment variable expansion in a subpath mount. ([ref](https://github.com/kubernetes/features/issues/559)) -* You can now run containers in a pod as a particular group. ([ref](https://github.com/kubernetes/features/issues/213)) -You can now bind tokens to service requests. ([ref](https://github.com/kubernetes/features/issues/542)) +* kube-scheduler can now schedule DaemonSet pods ([ref](https://github.com/kubernetes/enhancements/issues/548)) +* You can now resize PersistentVolumes without taking them offline ([ref](https://github.com/kubernetes/enhancements/issues/531)) +* You can now set a maximum volume count ([ref](https://github.com/kubernetes/enhancements/issues/554)) +* You can now do environment variable expansion in a subpath mount. ([ref](https://github.com/kubernetes/enhancements/issues/559)) +* You can now run containers in a pod as a particular group. ([ref](https://github.com/kubernetes/enhancements/issues/213)) +You can now bind tokens to service requests. ([ref](https://github.com/kubernetes/enhancements/issues/542)) * The --experimental-qos-reserve kubelet flags has been replaced by the alpha level --qos-reserved flag or the QOSReserved field in the kubeletconfig, and requires the QOSReserved feature gate to be enabled. ([#62509](https://github.com/kubernetes/kubernetes/pull/62509), [@sjenning](https://github.com/sjenning)) ## Other Notable Changes @@ -2018,7 +2104,7 @@ filename | sha256 hash * NONE ([#62643](https://github.com/kubernetes/kubernetes/pull/62643), [@xiangpengzhao](https://github.com/xiangpengzhao)) * ACTION REQUIRED: Alpha annotation for PersistentVolume node affinity has been removed. Update your PersistentVolumes to use the beta PersistentVolume.nodeAffinity field before upgrading to this release ([#61816](https://github.com/kubernetes/kubernetes/pull/61816), [@wackxu](https://github.com/wackxu)) -* ACTION REQUIRED: In-place node upgrades to this release from versions 1.7.14, 1.8.9, and 1.9.4 are not supported if using subpath volumes with PVCs. Such pods should be drained from the node first. ([#61373](https://github.com/kubernetes/kubernetes/pull/61373), [@msau42](https://github.com/msau42)) +* ACTION REQUIRED: In-place node upgrades to this release from versions 1.7.14+, 1.8.9+, and 1.9.4+ are not supported if using subpath volumes with PVCs. Such pods should be drained from the node first. ([#61373](https://github.com/kubernetes/kubernetes/pull/61373), [@msau42](https://github.com/msau42)) ### Other notable changes @@ -2182,7 +2268,7 @@ filename | sha256 hash * Implement preemption for extender with a verb and new interface ([#58717](https://github.com/kubernetes/kubernetes/pull/58717), [@resouer](https://github.com/resouer)) * `kube-cloud-controller-manager` flag `--service-account-private-key-file` is removed in v1.11 ([#60875](https://github.com/kubernetes/kubernetes/pull/60875), [@charrywanganthony](https://github.com/charrywanganthony)) * kubeadm: Add the writable boolean option to kubeadm config. The option works on a per-volume basis for *ExtraVolumes config keys. ([#60428](https://github.com/kubernetes/kubernetes/pull/60428), [@rosti](https://github.com/rosti)) -* DaemonSet scheduling associated with the alpha ScheduleDaemonSetPods feature flag has been removed from the 1.10 release. See https://github.com/kubernetes/features/issues/548 for feature status. ([#61411](https://github.com/kubernetes/kubernetes/pull/61411), [@liggitt](https://github.com/liggitt)) +* DaemonSet scheduling associated with the alpha ScheduleDaemonSetPods feature flag has been removed from the 1.10 release. See https://github.com/kubernetes/enhancements/issues/548 for feature status. ([#61411](https://github.com/kubernetes/kubernetes/pull/61411), [@liggitt](https://github.com/liggitt)) * Bugfix for erroneous upgrade needed messaging in kubernetes worker charm. ([#60873](https://github.com/kubernetes/kubernetes/pull/60873), [@wwwtyro](https://github.com/wwwtyro)) * Fix data race in node lifecycle controller ([#60831](https://github.com/kubernetes/kubernetes/pull/60831), [@resouer](https://github.com/resouer)) * Nodes are not deleted from kubernetes anymore if node is shutdown in Openstack. ([#59931](https://github.com/kubernetes/kubernetes/pull/59931), [@zetaab](https://github.com/zetaab)) diff --git a/CHANGELOG-1.12.md b/CHANGELOG-1.12.md index 442e28d7831..f9a56437215 100644 --- a/CHANGELOG-1.12.md +++ b/CHANGELOG-1.12.md @@ -1,30 +1,38 @@ -- [v1.12.3](#v1123) - - [Downloads for v1.12.3](#downloads-for-v1123) +- [v1.12.4](#v1124) + - [Downloads for v1.12.4](#downloads-for-v1124) - [Client Binaries](#client-binaries) - [Server Binaries](#server-binaries) - [Node Binaries](#node-binaries) - - [Changelog since v1.12.2](#changelog-since-v1122) + - [Changelog since v1.12.3](#changelog-since-v1123) + - [Action Required](#action-required) - [Other notable changes](#other-notable-changes) -- [v1.12.2](#v1122) - - [Downloads for v1.12.2](#downloads-for-v1122) +- [v1.12.3](#v1123) + - [Downloads for v1.12.3](#downloads-for-v1123) - [Client Binaries](#client-binaries-1) - [Server Binaries](#server-binaries-1) - [Node Binaries](#node-binaries-1) - - [Changelog since v1.12.1](#changelog-since-v1121) + - [Changelog since v1.12.2](#changelog-since-v1122) - [Other notable changes](#other-notable-changes-1) -- [v1.12.1](#v1121) - - [Downloads for v1.12.1](#downloads-for-v1121) +- [v1.12.2](#v1122) + - [Downloads for v1.12.2](#downloads-for-v1122) - [Client Binaries](#client-binaries-2) - [Server Binaries](#server-binaries-2) - [Node Binaries](#node-binaries-2) - - [Changelog since v1.12.0](#changelog-since-v1120) + - [Changelog since v1.12.1](#changelog-since-v1121) - [Other notable changes](#other-notable-changes-2) -- [v1.12.0](#v1120) - - [Downloads for v1.12.0](#downloads-for-v1120) +- [v1.12.1](#v1121) + - [Downloads for v1.12.1](#downloads-for-v1121) - [Client Binaries](#client-binaries-3) - [Server Binaries](#server-binaries-3) - [Node Binaries](#node-binaries-3) + - [Changelog since v1.12.0](#changelog-since-v1120) + - [Other notable changes](#other-notable-changes-3) +- [v1.12.0](#v1120) + - [Downloads for v1.12.0](#downloads-for-v1120) + - [Client Binaries](#client-binaries-4) + - [Server Binaries](#server-binaries-4) + - [Node Binaries](#node-binaries-4) - [Known Issues](#known-issues) - [Major Themes](#major-themes) - [SIG API Machinery](#sig-api-machinery) @@ -42,11 +50,11 @@ - [SIG-storage](#sig-storage) - [SIG-vmware](#sig-vmware) - [SIG-windows](#sig-windows) - - [Action Required](#action-required) + - [Action Required](#action-required-1) - [Deprecations and removals](#deprecations-and-removals) - [New Features](#new-features) - [API Changes](#api-changes) - - [Other Notable Changes](#other-notable-changes-3) + - [Other Notable Changes](#other-notable-changes-4) - [SIG API Machinery](#sig-api-machinery-1) - [SIG Apps](#sig-apps) - [SIG Auth](#sig-auth) @@ -65,54 +73,137 @@ - [SIG Storage](#sig-storage-1) - [SIG VMWare](#sig-vmware-1) - [SIG Windows](#sig-windows-1) - - [Other Notable Changes](#other-notable-changes-4) + - [Other Notable Changes](#other-notable-changes-5) - [Bug Fixes](#bug-fixes) - [Not Very Notable (that is, non-user-facing)](#not-very-notable-that-is-non-user-facing) - [External Dependencies](#external-dependencies) - [v1.12.0-rc.2](#v1120-rc2) - [Downloads for v1.12.0-rc.2](#downloads-for-v1120-rc2) - - [Client Binaries](#client-binaries-4) - - [Server Binaries](#server-binaries-4) - - [Node Binaries](#node-binaries-4) - - [Changelog since v1.12.0-rc.1](#changelog-since-v1120-rc1) - - [Other notable changes](#other-notable-changes-5) -- [v1.12.0-rc.1](#v1120-rc1) - - [Downloads for v1.12.0-rc.1](#downloads-for-v1120-rc1) - [Client Binaries](#client-binaries-5) - [Server Binaries](#server-binaries-5) - [Node Binaries](#node-binaries-5) - - [Changelog since v1.12.0-beta.2](#changelog-since-v1120-beta2) - - [Action Required](#action-required-1) + - [Changelog since v1.12.0-rc.1](#changelog-since-v1120-rc1) - [Other notable changes](#other-notable-changes-6) -- [v1.12.0-beta.2](#v1120-beta2) - - [Downloads for v1.12.0-beta.2](#downloads-for-v1120-beta2) +- [v1.12.0-rc.1](#v1120-rc1) + - [Downloads for v1.12.0-rc.1](#downloads-for-v1120-rc1) - [Client Binaries](#client-binaries-6) - [Server Binaries](#server-binaries-6) - [Node Binaries](#node-binaries-6) - - [Changelog since v1.12.0-beta.1](#changelog-since-v1120-beta1) + - [Changelog since v1.12.0-beta.2](#changelog-since-v1120-beta2) - [Action Required](#action-required-2) - [Other notable changes](#other-notable-changes-7) -- [v1.12.0-beta.1](#v1120-beta1) - - [Downloads for v1.12.0-beta.1](#downloads-for-v1120-beta1) +- [v1.12.0-beta.2](#v1120-beta2) + - [Downloads for v1.12.0-beta.2](#downloads-for-v1120-beta2) - [Client Binaries](#client-binaries-7) - [Server Binaries](#server-binaries-7) - [Node Binaries](#node-binaries-7) - - [Changelog since v1.12.0-alpha.1](#changelog-since-v1120-alpha1) + - [Changelog since v1.12.0-beta.1](#changelog-since-v1120-beta1) - [Action Required](#action-required-3) - [Other notable changes](#other-notable-changes-8) -- [v1.12.0-alpha.1](#v1120-alpha1) - - [Downloads for v1.12.0-alpha.1](#downloads-for-v1120-alpha1) +- [v1.12.0-beta.1](#v1120-beta1) + - [Downloads for v1.12.0-beta.1](#downloads-for-v1120-beta1) - [Client Binaries](#client-binaries-8) - [Server Binaries](#server-binaries-8) - [Node Binaries](#node-binaries-8) - - [Changelog since v1.11.0](#changelog-since-v1110) + - [Changelog since v1.12.0-alpha.1](#changelog-since-v1120-alpha1) - [Action Required](#action-required-4) - [Other notable changes](#other-notable-changes-9) +- [v1.12.0-alpha.1](#v1120-alpha1) + - [Downloads for v1.12.0-alpha.1](#downloads-for-v1120-alpha1) + - [Client Binaries](#client-binaries-9) + - [Server Binaries](#server-binaries-9) + - [Node Binaries](#node-binaries-9) + - [Changelog since v1.11.0](#changelog-since-v1110) + - [Action Required](#action-required-5) + - [Other notable changes](#other-notable-changes-10) +# v1.12.4 + +[Documentation](https://docs.k8s.io) + +## Downloads for v1.12.4 + + +filename | sha512 hash +-------- | ----------- +[kubernetes.tar.gz](https://dl.k8s.io/v1.12.4/kubernetes.tar.gz) | `35fd7a207cf3b6a5d569b1aad2fbccaf82ae394e6c91d3b1861b9e73b5069ca83aee8d5cdaa2e65f727579124d94ca9e886d0f4439f37b3204a1ac51db930cb0` +[kubernetes-src.tar.gz](https://dl.k8s.io/v1.12.4/kubernetes-src.tar.gz) | `ec7a67dfd82b0e8dd5020ebd3f059c38bb751bbb868b91410516cdde260f5a768ce4237a272c78f8a6b3fab6e1f4d13a7d3b88da7cdd81cc93abfcf8f5da6121` + +### Client Binaries + +filename | sha512 hash +-------- | ----------- +[kubernetes-client-darwin-386.tar.gz](https://dl.k8s.io/v1.12.4/kubernetes-client-darwin-386.tar.gz) | `96568f7d8f9583565345841b56c14ede552028d43b9425ed59bac343fab54e4a522d435b31e62e7cfa877e323b78c54a161b6f9ecd5ba200887a0ab7bafe472d` +[kubernetes-client-darwin-amd64.tar.gz](https://dl.k8s.io/v1.12.4/kubernetes-client-darwin-amd64.tar.gz) | `ba9c3d8186da6c4d41e1cfd19b0b9e317bba9b41124a46d6fb6820bd564059bca5d480639e3b2c415dd0d40817e56a050db8949ffeaf23e1a79a62ab4b907eeb` +[kubernetes-client-linux-386.tar.gz](https://dl.k8s.io/v1.12.4/kubernetes-client-linux-386.tar.gz) | `4c90bf1f267545ae835d2c098829b15a4b093be8b6212bd30e4f9eade6bd25334ec54638f5b8917a19543438ccce55a211adec47ed7f3d779092ab2de5c5633e` +[kubernetes-client-linux-amd64.tar.gz](https://dl.k8s.io/v1.12.4/kubernetes-client-linux-amd64.tar.gz) | `68edc349340f94d30c44f190eaf894d0df5dc6cda6e875335d7b34ea02febe05efaf8239cbf3a3153914ad9cc3c771a94aec521c75b1b5665bdd3d7741977ab3` +[kubernetes-client-linux-arm.tar.gz](https://dl.k8s.io/v1.12.4/kubernetes-client-linux-arm.tar.gz) | `a18faf32226c95dc864b5f4d728eb1d9bf84ee972fd690555c63c92f56f42c6e0dc65d60b4d59f9d549b3176af6ad3eece478d999dd2a6a64f116c12c3ae018c` +[kubernetes-client-linux-arm64.tar.gz](https://dl.k8s.io/v1.12.4/kubernetes-client-linux-arm64.tar.gz) | `ca70191ee9801de4721a367a7bf751b6b3b0347c48d8fddc1c898a87ed345c7bf32d3237123a4ab3776b619a383e7cd534b9a8a02be4bb00da781bb3272b5713` +[kubernetes-client-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.12.4/kubernetes-client-linux-ppc64le.tar.gz) | `4a9c55bc8c63a0a4ee606dcc80736af8504f194a92a737684cb8f8c65cf9d7ca3663b0dccb934ff48a7f7fa98c0d3225eb85930d09e089122a64bc81a221a46d` +[kubernetes-client-linux-s390x.tar.gz](https://dl.k8s.io/v1.12.4/kubernetes-client-linux-s390x.tar.gz) | `088f9cee592db55de3cc7c382dca7eb118670952a68d5f91e7722e1c4a3f81e7c5b0cb800f805ba15d0d444864f4b8c9788d5b98f4ab94c7c53a065296d09182` +[kubernetes-client-windows-386.tar.gz](https://dl.k8s.io/v1.12.4/kubernetes-client-windows-386.tar.gz) | `56f52a924d212e01c04ebf57163c8cb709e65d87cce5131bb2766f876f5cd82ab757108e75d8ac7c64fb0b088d86feb8fbdc5da42fc47a2fe06ee9f42c276631` +[kubernetes-client-windows-amd64.tar.gz](https://dl.k8s.io/v1.12.4/kubernetes-client-windows-amd64.tar.gz) | `d2e3f2976cce4779539ea5ce09a3745293cfa63b872d449ae49a0b811b202a7223223d9fa16f91dc5901aab0a84ac3dd1eb05beb632000833aa7c612e243f3cd` + +### Server Binaries + +filename | sha512 hash +-------- | ----------- +[kubernetes-server-linux-amd64.tar.gz](https://dl.k8s.io/v1.12.4/kubernetes-server-linux-amd64.tar.gz) | `d5b4a448c03800c146a8abe924349fa5bb3ee4b1215f2c154171812325d056f488269bd29a8ff25dd3a16ca7a1f8804f5dcea141d82e7a1d991b778f84fa5bc5` +[kubernetes-server-linux-arm.tar.gz](https://dl.k8s.io/v1.12.4/kubernetes-server-linux-arm.tar.gz) | `e1a3f1e6d8b20482a1bfd37081f45758022930e13bf13f8a06e4f65fb9fc01d138511e5a4368bbdef342744f9d9db4e892149f94ad9481ee147e98a319e26acc` +[kubernetes-server-linux-arm64.tar.gz](https://dl.k8s.io/v1.12.4/kubernetes-server-linux-arm64.tar.gz) | `d10b4b6e4ccb6652a6b64b0b32751a7ed151baf8054fcad8c9ff8e477d0c4a4a8386f2d433462570f78b5750ef0c3e641896cd542391d6928566958a12f6d0c7` +[kubernetes-server-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.12.4/kubernetes-server-linux-ppc64le.tar.gz) | `7076feb091b9b9c01af7bb3a23cdd8b7a4716c7da454029551dc6d2862813b4b5460ea70e4ba0a604ede3ea2f4fa012e12f97adbaf31938e74d063e797aaff0a` +[kubernetes-server-linux-s390x.tar.gz](https://dl.k8s.io/v1.12.4/kubernetes-server-linux-s390x.tar.gz) | `5d2faa0309f0d6ed88f242ce621588cd6fb3c2c7e87230b5452cda8c86b649407c0dc7ef2ad0ef78f63aade7054edaac4656ee31560a0feceeca5991e44a11b4` + +### Node Binaries + +filename | sha512 hash +-------- | ----------- +[kubernetes-node-linux-amd64.tar.gz](https://dl.k8s.io/v1.12.4/kubernetes-node-linux-amd64.tar.gz) | `060304784430f3200c337edbd63dd46e04b2fa32cbb82a3f39e020ce157b6c3634e2ca5817f8e4f26c7f498086e20e173625a73093ee6f0262d36dfb19238eb9` +[kubernetes-node-linux-arm.tar.gz](https://dl.k8s.io/v1.12.4/kubernetes-node-linux-arm.tar.gz) | `a4bb2548075a04decec14d672921ac99ff90afbae3bc74ccdc778fdb15087ceef3b9a691871fccda36aae078181fd13f9dce1c8d82e1f40991354266006d37ee` +[kubernetes-node-linux-arm64.tar.gz](https://dl.k8s.io/v1.12.4/kubernetes-node-linux-arm64.tar.gz) | `a9e8d364f55d63c3b42f3441b64a1995d5820886d0963389fa086b5083db30a0bd7412e12ce49d6d777587a983d6acd2b66888bd202228fef8b7efb4a4b9da9c` +[kubernetes-node-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.12.4/kubernetes-node-linux-ppc64le.tar.gz) | `4aed63ade9f735439a11e87ffeadd2bb41302d07fe4e5168cb2fb2b241b2cf51a9015ad181426ca8b94fcda3878a7a896f23f6c8468cc645828c00f1f81aa5e0` +[kubernetes-node-linux-s390x.tar.gz](https://dl.k8s.io/v1.12.4/kubernetes-node-linux-s390x.tar.gz) | `bd64af61473b1e1cee99df44455ee588a5fbb5a1348d3e17af60673024d5591dece97fde5c546fdd58222888665d0d6fb2a22cd56d8bf8ca371a6aa6780583c1` +[kubernetes-node-windows-amd64.tar.gz](https://dl.k8s.io/v1.12.4/kubernetes-node-windows-amd64.tar.gz) | `5944e1fcf835464d1efb1c7e21b11c1701a4b236cd2be176139d5cadfbaf91840de674c5e40470ceb3c82139950b4dccb95cd39abae89deaa9d8ab96d696d8b0` + +## Changelog since v1.12.3 + +### Action Required + +* ACTION REQUIRED: The Node.Status.Volumes.Attached.DevicePath fields is deprecated for CSI volumes and will be unset in a future release ([#71095](https://github.com/kubernetes/kubernetes/pull/71095), [@msau42](https://github.com/msau42)) + +### Other notable changes + +* fix kubelet log flushing issue in azure disk ([#71990](https://github.com/kubernetes/kubernetes/pull/71990), [@andyzhangx](https://github.com/andyzhangx)) +* Disable proxy to loopback and linklocal ([#71980](https://github.com/kubernetes/kubernetes/pull/71980), [@micahhausler](https://github.com/micahhausler)) +* fix issue: vm sku restriction policy does not work in azure disk attach/detach ([#71941](https://github.com/kubernetes/kubernetes/pull/71941), [@andyzhangx](https://github.com/andyzhangx)) +* Scheduler only activates unschedulable pods if node's scheduling related properties change. ([#71551](https://github.com/kubernetes/kubernetes/pull/71551), [@mlmhl](https://github.com/mlmhl)) +* UDP connections now support graceful termination in IPVS mode ([#71515](https://github.com/kubernetes/kubernetes/pull/71515), [@lbernail](https://github.com/lbernail)) +* Fixes an issue where Azure VMSS instances not existing in Azure were not being deleted by the Cloud Controller Manager. ([#71597](https://github.com/kubernetes/kubernetes/pull/71597), [@marc-sensenich](https://github.com/marc-sensenich)) +* Include CRD for BGPConfigurations, needed for calico 2.x to 3.x upgrade. ([#71868](https://github.com/kubernetes/kubernetes/pull/71868), [@satyasm](https://github.com/satyasm)) +* On GCI, NPD starts to monitor kubelet, docker, containerd crashlooping, read-only filesystem and corrupt docker overlay2 issues. ([#71522](https://github.com/kubernetes/kubernetes/pull/71522), [@wangzhen127](https://github.com/wangzhen127)) +* Only use the first IP address got from instance metadata. This is because Azure CNI would set up a list of IP addresses in instance metadata, while only the first one is the Node's IP. ([#71736](https://github.com/kubernetes/kubernetes/pull/71736), [@feiskyer](https://github.com/feiskyer)) +* kube-controller-manager: fixed issue display help for the deprecated insecure --port flag ([#71601](https://github.com/kubernetes/kubernetes/pull/71601), [@liggitt](https://github.com/liggitt)) +* Fixes apiserver nil pointer panics when requesting v2beta1 autoscaling object metrics ([#71744](https://github.com/kubernetes/kubernetes/pull/71744), [@yue9944882](https://github.com/yue9944882)) +* Fix a potential bug that scheduler preempts unnecessary pods. ([#70898](https://github.com/kubernetes/kubernetes/pull/70898), [@Huang-Wei](https://github.com/Huang-Wei)) +* The kube-apiserver's healthz now takes in an optional query parameter which allows you to disable health checks from causing healthz failures. ([#70676](https://github.com/kubernetes/kubernetes/pull/70676), [@logicalhan](https://github.com/logicalhan)) +* Fix scheduling starvation of pods in cluster with large number of unschedulable pods. ([#71488](https://github.com/kubernetes/kubernetes/pull/71488), [@bsalamat](https://github.com/bsalamat)) +* Upgrade Stackdriver Logging Agent addon image to 0.6-1.6.0-1 to use Fluentd v1.2. This provides nanoseconds timestamp granularity for logs. ([#70954](https://github.com/kubernetes/kubernetes/pull/70954), [@qingling128](https://github.com/qingling128)) +* fix detach azure disk issue due to dirty cache ([#71495](https://github.com/kubernetes/kubernetes/pull/71495), [@andyzhangx](https://github.com/andyzhangx)) +* Fixes ability for admin/edit/view users to see controller revisions, needed for kubectl rollout commands ([#70699](https://github.com/kubernetes/kubernetes/pull/70699), [@liggitt](https://github.com/liggitt)) +* Upgrade golang.org/x/net image to release-branch.go1.10 ([#70663](https://github.com/kubernetes/kubernetes/pull/70663), [@wenjiaswe](https://github.com/wenjiaswe)) +* [GCE] Filter out spammy audit logs from cluster autoscaler. ([#70696](https://github.com/kubernetes/kubernetes/pull/70696), [@loburm](https://github.com/loburm)) +* Correctly default Audience in the kubelet for TokenRequestProjections. ([#71007](https://github.com/kubernetes/kubernetes/pull/71007), [@mikedanese](https://github.com/mikedanese)) +* fix azure disk attach/detach failed forever issue ([#71377](https://github.com/kubernetes/kubernetes/pull/71377), [@andyzhangx](https://github.com/andyzhangx)) +* Fix a scheduler panic due to internal cache inconsistency ([#71063](https://github.com/kubernetes/kubernetes/pull/71063), [@Huang-Wei](https://github.com/Huang-Wei)) +* apiserver: fixes handling and logging of panics in REST handlers to prevent crashes ([#71076](https://github.com/kubernetes/kubernetes/pull/71076), [@liggitt](https://github.com/liggitt)) +* Fixes an issue with stuck connections handling error responses ([#71419](https://github.com/kubernetes/kubernetes/pull/71419), [@liggitt](https://github.com/liggitt)) + + + # v1.12.3 [Documentation](https://docs.k8s.io) @@ -165,7 +256,7 @@ filename | sha512 hash ### Other notable changes -* Fixes an issue with stuck connections handling error responses ([#71413](https://github.com/kubernetes/kubernetes/pull/71413), [@liggitt](https://github.com/liggitt)) +* CVE-2018-1002105: Fix critical security issue in kube-apiserver upgrade request proxy handler ([#71411](https://github.com/kubernetes/kubernetes/issues/71411), [@liggitt](https://github.com/liggitt)) * remove retry operation on attach/detach azure disk ([#70568](https://github.com/kubernetes/kubernetes/pull/70568), [@andyzhangx](https://github.com/andyzhangx)) * Fix CSI volume limits not showing up in node's capacity and allocatable ([#70540](https://github.com/kubernetes/kubernetes/pull/70540), [@gnufied](https://github.com/gnufied)) * kubeadm: fix a panic when calling "alpha phase certs renew all --use-api=false" ([#70768](https://github.com/kubernetes/kubernetes/pull/70768), [@neolit123](https://github.com/neolit123)) @@ -380,7 +471,7 @@ filename | sha512 hash ## Known Issues -- Feature [#566](https://github.com/kubernetes/kubernetes/issues/566) enabling CoreDNS as the default for kube-up deployments was dropped from the release due to a scalability memory resource consumption issue observed. If a cluster operator is considering using CoreDNS on a cluster greater than 2000 nodes, it may be necessary to give more consideration to CoreDNS pod memory resource limits and experimentally measure that memory usage versus cluster resource availability. +- Feature [#566](https://github.com/kubernetes/enhancements/issues/566) enabling CoreDNS as the default for kube-up deployments was dropped from the release due to a scalability memory resource consumption issue observed. If a cluster operator is considering using CoreDNS on a cluster greater than 2000 nodes, it may be necessary to give more consideration to CoreDNS pod memory resource limits and experimentally measure that memory usage versus cluster resource availability. - kube-controller-manager currently needs a writable `--cert-dir` (default is `/var/run/kubernetes`) for generating self-signed certificates, when no `--tls-cert-file` or `--tls-private-key-file` are provided. - The `system:kube-controller-manager` ClusterRole lacks permission to `get` the `configmap` extension-apiserver-authentication. kube-controller-manager errors if run with a service account bound to the clusterrole. - Runtime handler and Windows npipe protocol are not supported yet in crictl v1.11.x. Those features will be supported in crictl [v1.12.0](https://github.com/kubernetes-sigs/cri-tools/releases/tag/v1.12.0), together with Kubernetes v1.12.1. @@ -518,13 +609,13 @@ SIG Scheduling development efforts have been primarily focused on improving perf ### SIG-storage -SIG Storage promoted the [Kubernetes volume topology feature](https://github.com/kubernetes/features/issues/490) to beta. This enables Kubernetes to understand and act intelligently on volume accessibility information (such as the “zone” a cloud volume is provisioned in, the “rack” that a SAN array is accessible from, and so on). +SIG Storage promoted the [Kubernetes volume topology feature](https://github.com/kubernetes/enhancements/issues/490) to beta. This enables Kubernetes to understand and act intelligently on volume accessibility information (such as the “zone” a cloud volume is provisioned in, the “rack” that a SAN array is accessible from, and so on). -The [dynamic maximum volume count](https://github.com/kubernetes/features/issues/554) feature was also moved to beta. This enables a volume plugin to specify the maximum number of a given volume type per node as a function of the node characteristics (for example, a larger limit for larger nodes, a smaller limit for smaller nodes). +The [dynamic maximum volume count](https://github.com/kubernetes/enhancements/issues/554) feature was also moved to beta. This enables a volume plugin to specify the maximum number of a given volume type per node as a function of the node characteristics (for example, a larger limit for larger nodes, a smaller limit for smaller nodes). -SIG Storage also worked on a number of [Container Storage Interface (CSI) features](https://github.com/kubernetes/features/issues/178) this quarter in anticipation of moving support for CSI from beta to GA in the next Kubernetes release. This includes graduating the dependent “mount namespace propagation” feature to GA, moving the Kubelet plugin registration mechanism to beta, adding alpha support for a new CSI driver registry as well as for topology, and adding a number of alpha features to support the use of CSI for “local ephemeral volumes” (that is, volumes that exist for the lifecycle of a pod and contain some injected information, like a token or secret). +SIG Storage also worked on a number of [Container Storage Interface (CSI) features](https://github.com/kubernetes/enhancements/issues/178) this quarter in anticipation of moving support for CSI from beta to GA in the next Kubernetes release. This includes graduating the dependent “mount namespace propagation” feature to GA, moving the Kubelet plugin registration mechanism to beta, adding alpha support for a new CSI driver registry as well as for topology, and adding a number of alpha features to support the use of CSI for “local ephemeral volumes” (that is, volumes that exist for the lifecycle of a pod and contain some injected information, like a token or secret). -With Kubernetes v1.12, SIG Storage also introduced alpha support for [volume snapshotting](https://github.com/kubernetes/features/issues/177). This feature introduces the ability to create/delete volume snapshots and create new volumes from a snapshot using the Kubernetes API. +With Kubernetes v1.12, SIG Storage also introduced alpha support for [volume snapshotting](https://github.com/kubernetes/enhancements/issues/177). This feature introduces the ability to create/delete volume snapshots and create new volumes from a snapshot using the Kubernetes API. ### SIG-vmware @@ -1588,7 +1679,7 @@ filename | sha256 hash * The `system-node-critical` and `system-cluster-critical` priority classes are now limited to the `kube-system` namespace by the `PodPriority` admission plugin. ([#65593](https://github.com/kubernetes/kubernetes/pull/65593), [@bsalamat](https://github.com/bsalamat)) * kubernetes-worker juju charm: Added support for setting the --enable-ssl-chain-completion option on the ingress proxy. "action required": if your installation relies on supplying incomplete certificate chains and using OCSP to fill them in, you must set "ingress-ssl-chain-completion" to "true" in your juju configuration. ([#63845](https://github.com/kubernetes/kubernetes/pull/63845), [@paulgear](https://github.com/paulgear)) * In anticipation of CSI 1.0 in the next release, Kubernetes 1.12 calls the CSI `NodeGetInfo` RPC instead of `NodeGetId` RPC. Ensure your CSI Driver implements `NodeGetInfo(...)` before upgrading to 1.12. [@saad-ali](https://github.com/kubernetes/kubernetes/issues/68688) -* Kubernetes 1.12 also enables [Kubelet device plugin registration](https://github.com/kubernetes/features/issues/595) feature by default. Before upgrading to 1.12, ensure the `driver-registrar` CSI sidecar container for your CSI driver is configured to handle plugin registration (set the `--kubelet-registration-path` parameter on `driver-registrar` to expose a new unix domain socket to handle Kubelet Plugin Registration). +* Kubernetes 1.12 also enables [Kubelet device plugin registration](https://github.com/kubernetes/enhancements/issues/595) feature by default. Before upgrading to 1.12, ensure the `driver-registrar` CSI sidecar container for your CSI driver is configured to handle plugin registration (set the `--kubelet-registration-path` parameter on `driver-registrar` to expose a new unix domain socket to handle Kubelet Plugin Registration). ### Other notable changes @@ -1754,7 +1845,7 @@ filename | sha256 hash * Added block volume support to Cinder volume plugin. ([#64879](https://github.com/kubernetes/kubernetes/pull/64879), [@bertinatto](https://github.com/bertinatto)) * fixed incorrect OpenAPI schema for CustomResourceDefinition objects ([#65256](https://github.com/kubernetes/kubernetes/pull/65256), [@liggitt](https://github.com/liggitt)) * ignore not found file error when watching manifests ([#64880](https://github.com/kubernetes/kubernetes/pull/64880), [@dixudx](https://github.com/dixudx)) -* add port-forward examples for sevice ([#64773](https://github.com/kubernetes/kubernetes/pull/64773), [@MasayaAoyama](https://github.com/MasayaAoyama)) +* add port-forward examples for service ([#64773](https://github.com/kubernetes/kubernetes/pull/64773), [@MasayaAoyama](https://github.com/MasayaAoyama)) * Fix issues for block device not mapped to container. ([#64555](https://github.com/kubernetes/kubernetes/pull/64555), [@wenlxie](https://github.com/wenlxie)) * Update crictl on GCE to v1.11.0. ([#65254](https://github.com/kubernetes/kubernetes/pull/65254), [@Random-Liu](https://github.com/Random-Liu)) * Fixes missing nodes lines when kubectl top nodes ([#64389](https://github.com/kubernetes/kubernetes/pull/64389), [@yue9944882](https://github.com/yue9944882)) diff --git a/CHANGELOG-1.13.md b/CHANGELOG-1.13.md index 433fc1bcdaa..900c86e4034 100644 --- a/CHANGELOG-1.13.md +++ b/CHANGELOG-1.13.md @@ -1,53 +1,757 @@ -- [v1.13.0-rc.1](#v1130-rc1) - - [Downloads for v1.13.0-rc.1](#downloads-for-v1130-rc1) +- [v1.13.1](#v1131) + - [Downloads for v1.13.1](#downloads-for-v1131) - [Client Binaries](#client-binaries) - [Server Binaries](#server-binaries) - [Node Binaries](#node-binaries) - - [Changelog since v1.13.0-beta.2](#changelog-since-v1130-beta2) + - [Changelog since v1.13.0](#changelog-since-v1130) - [Other notable changes](#other-notable-changes) -- [v1.13.0-beta.2](#v1130-beta2) - - [Downloads for v1.13.0-beta.2](#downloads-for-v1130-beta2) +- [v1.13.0](#v1130) + - [Downloads for v1.13.0](#downloads-for-v1130) - [Client Binaries](#client-binaries-1) - [Server Binaries](#server-binaries-1) - [Node Binaries](#node-binaries-1) - - [Changelog since v1.13.0-beta.1](#changelog-since-v1130-beta1) - - [Other notable changes](#other-notable-changes-1) -- [v1.13.0-beta.1](#v1130-beta1) - - [Downloads for v1.13.0-beta.1](#downloads-for-v1130-beta1) +- [Kubernetes 1.13 Release Notes](#kubernetes-113-release-notes) + - [Security Content](#security-content) + - [Urgent Upgrade Notes](#urgent-upgrade-notes) + - [(No, really, you MUST do this before you upgrade)](#no-really-you-must-do-this-before-you-upgrade) + - [Known Issues](#known-issues) + - [Deprecations](#deprecations) + - [Major Themes](#major-themes) + - [SIG API Machinery](#sig-api-machinery) + - [SIG Auth](#sig-auth) + - [SIG AWS](#sig-aws) + - [SIG Azure](#sig-azure) + - [SIG Big Data](#sig-big-data) + - [SIG CLI](#sig-cli) + - [SIG Cloud Provider](#sig-cloud-provider) + - [SIG Cluster Lifecycle](#sig-cluster-lifecycle) + - [SIG IBM Cloud](#sig-ibm-cloud) + - [SIG Multicluster](#sig-multicluster) + - [SIG Network](#sig-network) + - [SIG Node](#sig-node) + - [SIG Openstack](#sig-openstack) + - [SIG Scalability](#sig-scalability) + - [SIG Scheduling](#sig-scheduling) + - [SIG Service Catalog](#sig-service-catalog) + - [SIG Storage](#sig-storage) + - [SIG UI](#sig-ui) + - [SIG VMWare](#sig-vmware) + - [SIG Windows](#sig-windows) + - [New Features](#new-features) + - [Release Notes From SIGs](#release-notes-from-sigs) + - [SIG API Machinery](#sig-api-machinery-1) + - [SIG Auth](#sig-auth-1) + - [SIG Autoscaling](#sig-autoscaling) + - [SIG AWS](#sig-aws-1) + - [SIG Azure](#sig-azure-1) + - [SIG CLI](#sig-cli-1) + - [SIG Cloud Provider](#sig-cloud-provider-1) + - [SIG Cluster Lifecycle](#sig-cluster-lifecycle-1) + - [SIG GCP](#sig-gcp) + - [SIG Network](#sig-network-1) + - [SIG Node](#sig-node-1) + - [SIG OpenStack](#sig-openstack-1) + - [SIG Release](#sig-release) + - [SIG Scheduling](#sig-scheduling-1) + - [SIG Storage](#sig-storage-1) + - [SIG Windows](#sig-windows-1) + - [External Dependencies](#external-dependencies) +- [v1.13.0-rc.2](#v1130-rc2) + - [Downloads for v1.13.0-rc.2](#downloads-for-v1130-rc2) - [Client Binaries](#client-binaries-2) - [Server Binaries](#server-binaries-2) - [Node Binaries](#node-binaries-2) - - [Changelog since v1.13.0-alpha.3](#changelog-since-v1130-alpha3) - - [Action Required](#action-required) - - [Other notable changes](#other-notable-changes-2) -- [v1.13.0-alpha.3](#v1130-alpha3) - - [Downloads for v1.13.0-alpha.3](#downloads-for-v1130-alpha3) + - [Changelog since v1.13.0-rc.1](#changelog-since-v1130-rc1) + - [Other notable changes](#other-notable-changes-1) +- [v1.13.0-rc.1](#v1130-rc1) + - [Downloads for v1.13.0-rc.1](#downloads-for-v1130-rc1) - [Client Binaries](#client-binaries-3) - [Server Binaries](#server-binaries-3) - [Node Binaries](#node-binaries-3) - - [Changelog since v1.13.0-alpha.2](#changelog-since-v1130-alpha2) - - [Other notable changes](#other-notable-changes-3) -- [v1.13.0-alpha.2](#v1130-alpha2) - - [Downloads for v1.13.0-alpha.2](#downloads-for-v1130-alpha2) + - [Changelog since v1.13.0-beta.2](#changelog-since-v1130-beta2) + - [Other notable changes](#other-notable-changes-2) +- [v1.13.0-beta.2](#v1130-beta2) + - [Downloads for v1.13.0-beta.2](#downloads-for-v1130-beta2) - [Client Binaries](#client-binaries-4) - [Server Binaries](#server-binaries-4) - [Node Binaries](#node-binaries-4) - - [Changelog since v1.13.0-alpha.1](#changelog-since-v1130-alpha1) - - [Other notable changes](#other-notable-changes-4) -- [v1.13.0-alpha.1](#v1130-alpha1) - - [Downloads for v1.13.0-alpha.1](#downloads-for-v1130-alpha1) + - [Changelog since v1.13.0-beta.1](#changelog-since-v1130-beta1) + - [Other notable changes](#other-notable-changes-3) +- [v1.13.0-beta.1](#v1130-beta1) + - [Downloads for v1.13.0-beta.1](#downloads-for-v1130-beta1) - [Client Binaries](#client-binaries-5) - [Server Binaries](#server-binaries-5) - [Node Binaries](#node-binaries-5) + - [Changelog since v1.13.0-alpha.3](#changelog-since-v1130-alpha3) + - [Action Required](#action-required) + - [Other notable changes](#other-notable-changes-4) +- [v1.13.0-alpha.3](#v1130-alpha3) + - [Downloads for v1.13.0-alpha.3](#downloads-for-v1130-alpha3) + - [Client Binaries](#client-binaries-6) + - [Server Binaries](#server-binaries-6) + - [Node Binaries](#node-binaries-6) + - [Changelog since v1.13.0-alpha.2](#changelog-since-v1130-alpha2) + - [Other notable changes](#other-notable-changes-5) +- [v1.13.0-alpha.2](#v1130-alpha2) + - [Downloads for v1.13.0-alpha.2](#downloads-for-v1130-alpha2) + - [Client Binaries](#client-binaries-7) + - [Server Binaries](#server-binaries-7) + - [Node Binaries](#node-binaries-7) + - [Changelog since v1.13.0-alpha.1](#changelog-since-v1130-alpha1) + - [Other notable changes](#other-notable-changes-6) +- [v1.13.0-alpha.1](#v1130-alpha1) + - [Downloads for v1.13.0-alpha.1](#downloads-for-v1130-alpha1) + - [Client Binaries](#client-binaries-8) + - [Server Binaries](#server-binaries-8) + - [Node Binaries](#node-binaries-8) - [Changelog since v1.12.0](#changelog-since-v1120) - [Action Required](#action-required-1) - - [Other notable changes](#other-notable-changes-5) + - [Other notable changes](#other-notable-changes-7) +# v1.13.1 + +[Documentation](https://docs.k8s.io) + +## Downloads for v1.13.1 + + +filename | sha512 hash +-------- | ----------- +[kubernetes.tar.gz](https://dl.k8s.io/v1.13.1/kubernetes.tar.gz) | `de3858357b2b4444bccc0599c7d0edd3e6ec1a80267ef96883ebcfb06c518ce467dd8720b48084644677a42b8e3ffad9a7d4745b40170ce9dfe5b43310979be1` +[kubernetes-src.tar.gz](https://dl.k8s.io/v1.13.1/kubernetes-src.tar.gz) | `7f0a8dbd3c7397cc5a5bc0297eb24b8e734c3c7b78e48fc794c525377c3895f4fd84fd0a2fa70c5513cc47ee5a174c22bab54796abc5a8f2b30687642c819a68` + +### Client Binaries + +filename | sha512 hash +-------- | ----------- +[kubernetes-client-darwin-386.tar.gz](https://dl.k8s.io/v1.13.1/kubernetes-client-darwin-386.tar.gz) | `371028dba7a28ec3c8f10b861448cb1574dce25d32d847af254b76b7f158aa4fcda695972e2a08440faa4e16077f8021b07115d0da897bef79c33e702f3be95e` +[kubernetes-client-darwin-amd64.tar.gz](https://dl.k8s.io/v1.13.1/kubernetes-client-darwin-amd64.tar.gz) | `6aa7025308e9fb1eb4415e504e8aa9c7a0a20b09c500cb48df82bbd04443101664b2614fb284875b9670d4bb11e8f1a10190eaf1d54f81f3a9526053958b0802` +[kubernetes-client-linux-386.tar.gz](https://dl.k8s.io/v1.13.1/kubernetes-client-linux-386.tar.gz) | `6453670bb61b4f5f7fe8ae78804864ecd52682b32592f6956faf3d2220884a64fb22ae2e668b63f28ea8fd354c50aa90ce61c60be327fb0b5fcfe2c7835ef559` +[kubernetes-client-linux-amd64.tar.gz](https://dl.k8s.io/v1.13.1/kubernetes-client-linux-amd64.tar.gz) | `ca00442f50b5d5627357dce97c90c17cb0126d746b887afdab2d4db9e0826532469fd1ee62f40eb6923761618f46752d10993578ca19c8b92c3a2aeb5102a318` +[kubernetes-client-linux-arm.tar.gz](https://dl.k8s.io/v1.13.1/kubernetes-client-linux-arm.tar.gz) | `5fa170cbe56b8f5d103f520e2493f911c5eb59b51a6afdbaa9c08196943f1235e533f0384ce7c01c73a020c6889cf8f03cc3642912d0953c74d1098e4b21f3a0` +[kubernetes-client-linux-arm64.tar.gz](https://dl.k8s.io/v1.13.1/kubernetes-client-linux-arm64.tar.gz) | `710343ad067f0d642c43cd26871828275645b08b4f4c86bd555865318d8fe08b7f0a720174c04d58acffcb26faf563636dc13eef66a2813eac68bb8b994908f4` +[kubernetes-client-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.13.1/kubernetes-client-linux-ppc64le.tar.gz) | `0fa7ab255f0cba3adc754337c6184e6ec464aa5a4d6dd4d38aad8a0e2430a0044f4ed1ffcd7cc7c863190d3cda6b84abd12ca7536139d665ad61fe7704e63d30` +[kubernetes-client-linux-s390x.tar.gz](https://dl.k8s.io/v1.13.1/kubernetes-client-linux-s390x.tar.gz) | `749a8dce5b81e2edbd315841acac64a0e5d17bb1ead8173560b6a4ccc28604bc8254051297ab51cb5df845495bd75a45137827b3386e3962295fec8601563eaa` +[kubernetes-client-windows-386.tar.gz](https://dl.k8s.io/v1.13.1/kubernetes-client-windows-386.tar.gz) | `cd4732fbe569009c426f963318d05ddcc7c63dc27ec9d2bf9c60d716195e3676aa5b0e6ccbde6298f621450d365d41a910ce3ced89bf2ae6d3e81ee2fed0bb16` +[kubernetes-client-windows-amd64.tar.gz](https://dl.k8s.io/v1.13.1/kubernetes-client-windows-amd64.tar.gz) | `40f5b5d221b3a611511690d316539dc8fb3f4513e4f9eb141bffa17c9ddeee875a462f5bd45e62ce7c7535310fc3e48e3441614700ee9877584c5948ddbef19f` + +### Server Binaries + +filename | sha512 hash +-------- | ----------- +[kubernetes-server-linux-amd64.tar.gz](https://dl.k8s.io/v1.13.1/kubernetes-server-linux-amd64.tar.gz) | `e0e48825c5fe33a3f82b1b74847d9bfb8c5716c4313c5e4e6f46be0580e20a1e396a669b8ca446cfa581e3eb75698813249bbfcfc79c8a90793880eb5c177921` +[kubernetes-server-linux-arm.tar.gz](https://dl.k8s.io/v1.13.1/kubernetes-server-linux-arm.tar.gz) | `7ff4856e7959cf14eba0e1ab274c0bf0d3193391e7034a936697f0c4813e81d8dda4a019d3185677bee9d1345a6433db3fd6e55f644a0f73d076e0b2014ed172` +[kubernetes-server-linux-arm64.tar.gz](https://dl.k8s.io/v1.13.1/kubernetes-server-linux-arm64.tar.gz) | `b8c2356002e675bd3de5ee9c2337a12e2a1bbfa2478f8e3b91065a578dfa8d50f596fd606d9f0232b06b8263867a7ca5cc7c04150718b8e40b49ae7d46001c30` +[kubernetes-server-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.13.1/kubernetes-server-linux-ppc64le.tar.gz) | `5d3a15b1241d849d8954894aa7f3fb12606f9966f73fc36aa15152038fc385153b0f0e967cc0bf410a5d5894d0269e54eac581d8e79003904d7bc29b33e98684` +[kubernetes-server-linux-s390x.tar.gz](https://dl.k8s.io/v1.13.1/kubernetes-server-linux-s390x.tar.gz) | `78a9cccaf9d737b519db0866c2e80c472c7136bc723910d08649ece1c420ae7f6e56e610d65c436c56ccef8360c4da0f70e75d0cf47c0c8e739f5138cdc7b0d2` + +### Node Binaries + +filename | sha512 hash +-------- | ----------- +[kubernetes-node-linux-amd64.tar.gz](https://dl.k8s.io/v1.13.1/kubernetes-node-linux-amd64.tar.gz) | `3a7881a52885bebe5958f02dc54194cc8c330576b7cf5935189df4f0b754b958917b104e1d3358c0bc9277f13a8eef2176284548d664f27a36baa389fbcc7bea` +[kubernetes-node-linux-arm.tar.gz](https://dl.k8s.io/v1.13.1/kubernetes-node-linux-arm.tar.gz) | `d0bfcff3ef7c0aa36005e7b111685438ebd0ea61d48dc68a7bd06eea3782b6eb224f9b651d80c955afa162f766c8b682976db43238562c293d6552cdadf9e934` +[kubernetes-node-linux-arm64.tar.gz](https://dl.k8s.io/v1.13.1/kubernetes-node-linux-arm64.tar.gz) | `2e23bd00661aceb30fa37e24ab71315755bd93dfcc5ff361d78445a8e9ff99e7b3a56641112af3184e8b107545fba6573a6368a82bd0ce475c81cb53fd44da3b` +[kubernetes-node-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.13.1/kubernetes-node-linux-ppc64le.tar.gz) | `8d0fdb743c700d662886636fe67b52202cf9e6e57c2d7de5961b8189d8c03c91fda1d68c47033286efcc582e78be40846e2b1f5c589a0b94794fa2ce3c1ebfee` +[kubernetes-node-linux-s390x.tar.gz](https://dl.k8s.io/v1.13.1/kubernetes-node-linux-s390x.tar.gz) | `70445038b4db62c3fc99540f5ddbb881387018244242f182332b8eaa7159ce1aa8929145010ab2befd4e101d39c24c61e430928235434c7d7eb54f113860a83a` +[kubernetes-node-windows-amd64.tar.gz](https://dl.k8s.io/v1.13.1/kubernetes-node-windows-amd64.tar.gz) | `a87ad43f5a6b8f66d1bbd64f9c91e8bcbdf4adc8de0ec3cd559adaa8c14a6fe078ffdf090e52627c0522b79209fcc37bf822b323895dd47b18c20026cb25e9f5` + +## Changelog since v1.13.0 + +### Other notable changes + +* Fix overlapping filenames in diff if multiple resources have the same name. ([#71923](https://github.com/kubernetes/kubernetes/pull/71923), [@apelisse](https://github.com/apelisse)) +* Disable proxy to loopback and linklocal ([#71980](https://github.com/kubernetes/kubernetes/pull/71980), [@micahhausler](https://github.com/micahhausler)) +* kube-scheduler: restores ability to run without authentication configuration lookup permissions ([#71755](https://github.com/kubernetes/kubernetes/pull/71755), [@liggitt](https://github.com/liggitt)) +* client-go: restores behavior of populating the BearerToken field in rest.Config objects constructed from kubeconfig files containing tokenFile config, or from in-cluster configuration. An additional BearerTokenFile field is now populated to enable constructed clients to periodically refresh tokens. ([#71713](https://github.com/kubernetes/kubernetes/pull/71713), [@liggitt](https://github.com/liggitt)) +* apply: fix detection of non-dry-run enabled servers ([#71854](https://github.com/kubernetes/kubernetes/pull/71854), [@apelisse](https://github.com/apelisse)) +* Scheduler only activates unschedulable pods if node's scheduling related properties change. ([#71551](https://github.com/kubernetes/kubernetes/pull/71551), [@mlmhl](https://github.com/mlmhl)) +* Fixes pod deletion when cleaning old cronjobs ([#71802](https://github.com/kubernetes/kubernetes/pull/71802), [@soltysh](https://github.com/soltysh)) +* fix issue: vm sku restriction policy does not work in azure disk attach/detach ([#71941](https://github.com/kubernetes/kubernetes/pull/71941), [@andyzhangx](https://github.com/andyzhangx)) +* Include CRD for BGPConfigurations, needed for calico 2.x to 3.x upgrade. ([#71868](https://github.com/kubernetes/kubernetes/pull/71868), [@satyasm](https://github.com/satyasm)) +* UDP connections now support graceful termination in IPVS mode ([#71515](https://github.com/kubernetes/kubernetes/pull/71515), [@lbernail](https://github.com/lbernail)) +* kubeadm: use kubeconfig flag instead of kubeconfig-dir on init phase bootstrap-token ([#71803](https://github.com/kubernetes/kubernetes/pull/71803), [@yagonobre](https://github.com/yagonobre)) +* On GCI, NPD starts to monitor kubelet, docker, containerd crashlooping, read-only filesystem and corrupt docker overlay2 issues. ([#71522](https://github.com/kubernetes/kubernetes/pull/71522), [@wangzhen127](https://github.com/wangzhen127)) +* Fixes an issue where Portworx volumes cannot be mounted if 9001 port is already in use on the host and users remap 9001 to another port. ([#70392](https://github.com/kubernetes/kubernetes/pull/70392), [@harsh-px](https://github.com/harsh-px)) +* Only use the first IP address got from instance metadata. This is because Azure CNI would set up a list of IP addresses in instance metadata, while only the first one is the Node's IP. ([#71736](https://github.com/kubernetes/kubernetes/pull/71736), [@feiskyer](https://github.com/feiskyer)) +* kube-controller-manager: fixed issue display help for the deprecated insecure --port flag ([#71601](https://github.com/kubernetes/kubernetes/pull/71601), [@liggitt](https://github.com/liggitt)) +* Update Cluster Autoscaler version in gce manifests to 1.13.1 (https://github.com/kubernetes/autoscaler/releases/tag/cluster-autoscaler-1.13.1) ([#71842](https://github.com/kubernetes/kubernetes/pull/71842), [@losipiuk](https://github.com/losipiuk)) +* kubectl: fixes regression in --sort-by behavior ([#71805](https://github.com/kubernetes/kubernetes/pull/71805), [@liggitt](https://github.com/liggitt)) +* Fixes apiserver nil pointer panics when requesting v2beta1 autoscaling object metrics ([#71744](https://github.com/kubernetes/kubernetes/pull/71744), [@yue9944882](https://github.com/yue9944882)) +* Fix scheduling starvation of pods in cluster with large number of unschedulable pods. ([#71488](https://github.com/kubernetes/kubernetes/pull/71488), [@bsalamat](https://github.com/bsalamat)) + + + +# v1.13.0 + +[Documentation](https://docs.k8s.io) + +## Downloads for v1.13.0 + + +filename | sha512 hash +-------- | ----------- +[kubernetes.tar.gz](https://dl.k8s.io/v1.13.0/kubernetes.tar.gz) | `7b6a81c9f1b852b1e889c1b62281569a4b8853c79e5675b0910d941dfa7863c97f244f6d607aae3faf60bccd596dedb9d136b7fffeae199876e780904fd9f31e` +[kubernetes-src.tar.gz](https://dl.k8s.io/v1.13.0/kubernetes-src.tar.gz) | `844b9fbba21374dd190c8f12dd0e5b3303dd2cd7ad25f241d6f7e46f74adf6987afad021553521d4f479c19d87aa8d4d5be77ac7a6715d31a9187a5bab3b397b` + +### Client Binaries + +filename | sha512 hash +-------- | ----------- +[kubernetes-client-darwin-386.tar.gz](https://dl.k8s.io/v1.13.0/kubernetes-client-darwin-386.tar.gz) | `0c010351acb660a75122feb876c9887d46ec2cb466872dd073b7f5b26fdadd96888a350e01606f2ae43606a5a4ab2d9309441f4357cee924b19688f9b02c55dc` +[kubernetes-client-darwin-amd64.tar.gz](https://dl.k8s.io/v1.13.0/kubernetes-client-darwin-amd64.tar.gz) | `c2c40bd202900124f4e9458b067a1e1fc040030dc84ce9bcc6a5beb263de05892c16f3bdafb8d854e343e71f086207f390fd0b60f6e32e770c73294b053da6e4` +[kubernetes-client-linux-386.tar.gz](https://dl.k8s.io/v1.13.0/kubernetes-client-linux-386.tar.gz) | `5f5449be103b103d72a4e2b1028ab014cf7f74781166327f2ae284e4f5ecb539f6b60f36b8f7c7be0ae43dfb30661b2672dd93a1fa7e26d6c67498672674bf12` +[kubernetes-client-linux-amd64.tar.gz](https://dl.k8s.io/v1.13.0/kubernetes-client-linux-amd64.tar.gz) | `61a6cd3b1fb34507e0b762a45da09d88e34921985970a2ba594e0e5af737d94c966434b4e9f8e84fb73a0aeb5fa3e557344cd2eb902bf73c67d4b4bff33c6831` +[kubernetes-client-linux-arm.tar.gz](https://dl.k8s.io/v1.13.0/kubernetes-client-linux-arm.tar.gz) | `dd5591e2b88c347759a138c4d2436a0f5252341d0e8c9fbab16b8f151e2744cbdd0c8583555a451425bc471f11b688ce568d9245caf8a278cbac2b343fdead89` +[kubernetes-client-linux-arm64.tar.gz](https://dl.k8s.io/v1.13.0/kubernetes-client-linux-arm64.tar.gz) | `894ed30261598ebf3485f3575e95f85e3c353f4d834bf9a6ea53b265427704b43fba5403fbc4d522b3f02afb08e6afaae200af1fe57996291a7c74398ec2fe17` +[kubernetes-client-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.13.0/kubernetes-client-linux-ppc64le.tar.gz) | `6c26c807fc730ea736fda75dc57ac73395ba78bb828fffeee18b385be550d8f3ba2bbc27a52a8f15bcbbe68218c7945d9fb725e6759c117422bc0a632c110670` +[kubernetes-client-linux-s390x.tar.gz](https://dl.k8s.io/v1.13.0/kubernetes-client-linux-s390x.tar.gz) | `41e6e972de77c0bde22fdd779ea64e731b60f32e97e78a024f33fc3e33a3b364b7f77ece7d3c64ad85b7f8fe7c8fc6d6892098a3362d1fe01ebf3d551fe2bf37` +[kubernetes-client-windows-386.tar.gz](https://dl.k8s.io/v1.13.0/kubernetes-client-windows-386.tar.gz) | `442229e5030452901b924a94e7a879d4085597a4f201a5b3fc5ac9806cab5830c836cfa7a33e8f1693fe2e8badc4047bf227d7fb00c537fb1fb4cb7639de5455` +[kubernetes-client-windows-amd64.tar.gz](https://dl.k8s.io/v1.13.0/kubernetes-client-windows-amd64.tar.gz) | `a11a8e8e732e7292781b9cb1de6e3e41683f95fb3fefc2b1a7b5fb1f064a0d80c0833876d931675135778457d81de9ed2e81caee4b3eb27d9f23c7b722b17442` + +### Server Binaries + +filename | sha512 hash +-------- | ----------- +[kubernetes-server-linux-amd64.tar.gz](https://dl.k8s.io/v1.13.0/kubernetes-server-linux-amd64.tar.gz) | `a8e3d457e5bcc1c09eeb66111e8dd049d6ba048c3c0fa90a61814291afdcde93f1c6dbb07beef090d1d8a9958402ff843e9af23ae9f069c17c0a7c6ce4034686` +[kubernetes-server-linux-arm.tar.gz](https://dl.k8s.io/v1.13.0/kubernetes-server-linux-arm.tar.gz) | `4e17494767000256775e4dd33c0a9b2d152bd4b5fba9f343b6dfeb5746ff34e400a8e0aaf2153476453225ef57e4bb1ae3635416ab18f9e4dabf4e5cc82f8aaa` +[kubernetes-server-linux-arm64.tar.gz](https://dl.k8s.io/v1.13.0/kubernetes-server-linux-arm64.tar.gz) | `0ddd0cf0ff56cebfa89efb1972cc2bc6916e824c2af56cfd330ac5638c8918eaf3c60d05714b220dbf4f896160eded123beeba42f5be55fe434a43d04508d86a` +[kubernetes-server-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.13.0/kubernetes-server-linux-ppc64le.tar.gz) | `b93828560224e812ed21b57fea5458fa8560745cfec96fc1677b258393c00e208ad9b99467b575e74e01699ffd75f03f5793675032e7306cba7208c1afb53c8d` +[kubernetes-server-linux-s390x.tar.gz](https://dl.k8s.io/v1.13.0/kubernetes-server-linux-s390x.tar.gz) | `154d565329d5ba52cdb7c3d43d8854b7a9b8e34803c4df6b3e6ae74c1a6e255c78e6559b7546b9158df0e3f7931bbdaf43407d95cd875c79f5cce960bb9882dd` + +### Node Binaries + +filename | sha512 hash +-------- | ----------- +[kubernetes-node-linux-amd64.tar.gz](https://dl.k8s.io/v1.13.0/kubernetes-node-linux-amd64.tar.gz) | `9d18ba5f0c3b09edcf29397a496a1e908f4906087be3792989285630d7bcbaf6cd3bdd7b07dace439823885acc808637190f5eaa240b7b4580acf277b67bb553` +[kubernetes-node-linux-arm.tar.gz](https://dl.k8s.io/v1.13.0/kubernetes-node-linux-arm.tar.gz) | `959b04ff7b8690413e01bffeabaab2119794dedf06b7aae1743e49988f797cb7e6ff12e1a91af2d4c5f664414f3aa4bd9020521c6a21c1196c194d12a6f7fe08` +[kubernetes-node-linux-arm64.tar.gz](https://dl.k8s.io/v1.13.0/kubernetes-node-linux-arm64.tar.gz) | `b5c18e8c9e28cf276067c871446720d86b6f162e22c3a5e9343cdbc6857baa6961d09a6908b6acd1bbd132c2e2e526377676babf77b8d3bfb36f8711827c105a` +[kubernetes-node-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.13.0/kubernetes-node-linux-ppc64le.tar.gz) | `63e3504d3b115fdf3396968afafd1107b98e5a1a15b7c042a87f5a9cffbdc274f7b06b07ce90eb51876cfffd57cf7f20180bad7e9f9762af577e51f4f13d2f7a` +[kubernetes-node-linux-s390x.tar.gz](https://dl.k8s.io/v1.13.0/kubernetes-node-linux-s390x.tar.gz) | `21c5c2721febf7fddeada9569f3ecbd059267e5d2cc325d98fb74faf1ae9e9e15899750225a1fc7c25feef96e7705b1456cb489f4882b9eb10e78bd0f590d019` +[kubernetes-node-windows-amd64.tar.gz](https://dl.k8s.io/v1.13.0/kubernetes-node-windows-amd64.tar.gz) | `3e73d3ecff14b4c85a71bb6cf91b1ab7d9c3075c64bd5ce6863562ab17bf808b0cbc33ddd25346d25040649c1ad89745796afd218190886b54f1d8acc17896e4` + +# Kubernetes 1.13 Release Notes + +## Security Content + +- CVE-2018-1002105, a critical security issue in the Kubernetes API Server, is resolved in v1.13.0 (and in [v1.10.11](https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG-1.10.md/#v11011), [v1.11.5](https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG-1.11.md/#v1115), and [v1.12.3](https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG-1.12.md/#v1123)). We recommend all clusters running previous versions update to one of these releases immediately. See issue [#71411](https://github.com/kubernetes/kubernetes/issues/71411) for details. + +## Urgent Upgrade Notes + +### (No, really, you MUST do this before you upgrade) + +Before upgrading to Kubernetes 1.13, you must keep the following in mind: + +- kube-apiserver + - The deprecated `etcd2` storage backend has been removed. Before upgrading a kube-apiserver using `--storage-backend=etcd2`, etcd v2 data must be migrated to the v3 storage backend, and kube-apiserver invocations changed to use `--storage-backend=etcd3`. Please consult the installation procedure used to set up etcd for specific migration instructions. Backups prior to upgrade are always a good practice, but since the etcd2 to etcd3 migration is not reversible, an etcd backup prior to migration is essential. + - The deprecated `--etcd-quorum-read` flag has been removed. Quorum reads are now always enabled when fetching data from etcd. Remove the `--etcd-quorum-read` flag from kube-apiserver invocations before upgrading. +- kube-controller-manager + - The deprecated `--insecure-experimental-approve-all-kubelet-csrs-for-group` flag has been removed. +- kubelet + - The deprecated `--google-json-key` flag has been removed. Remove the `--google-json-key` flag from kubelet invocations before upgrading. ([#69354](https://github.com/kubernetes/kubernetes/pull/69354), [@yujuhong](https://github.com/yujuhong)) + - DaemonSet pods now make use of scheduling features that require kubelets to be at 1.11 or above. Ensure all kubelets in the cluster are at 1.11 or above before upgrading kube-controller-manager to 1.13. + - The schema for the alpha `CSINodeInfo` CRD has been split into `spec` and `status` fields, and new fields `status.available` and `status.volumePluginMechanism` added. Clusters using the previous alpha schema must delete and recreate the CRD using the new schema. ([#70515](https://github.com/kubernetes/kubernetes/pull/70515), [@davidz627](https://github.com/davidz627)) +- kube-scheduler dropped support for configuration files with apiVersion `componentconfig/v1alpha1`. Ensure kube-scheduler is configured using command-line flags or a configuration file with apiVersion `kubescheduler.config.k8s.io/v1alpha1` before upgrading to 1.13. +- kubectl + - The deprecated command `run-container` has been removed. Invocations should use `kubectl run` instead ([#70728](https://github.com/kubernetes/kubernetes/pull/70728), [@Pingan2017](https://github.com/Pingan2017)) +- client-go releases will no longer have bootstrap (k8s.io/client-go/tools/bootstrap) related code. Any reference to it will break. Please redirect all references to k8s.io/bootstrap instead. ([#67356](https://github.com/kubernetes/kubernetes/pull/67356), [@yliaog](https://github.com/yliaog)) +- Kubernetes cannot distinguish between GCE Zonal PDs and Regional PDs with the same name. To workaround this issue, precreate PDs with unique names. PDs that are dynamically provisioned do not encounter this issue. ([#70716](https://github.com/kubernetes/kubernetes/pull/70716), [@msau42](https://github.com/msau42)) + +## Known Issues + +- If kubelet plugin registration for a driver fails, kubelet will not retry. The driver must delete and recreate the driver registration socket in order to force kubelet to attempt registration again. Restarting only the driver container may not be sufficient to trigger recreation of the socket, instead a pod restart may be required. ([#71487](https://github.com/kubernetes/kubernetes/issues/71487)) +- In some cases, a Flex volume resize may leave a PVC with erroneous Resizing condition even after volume has been successfully expanded. Users may choose to delete the condition, but it is not required. ([#71470](https://github.com/kubernetes/kubernetes/issues/71470)) +- The CSI driver-registrar external sidecar container v1.0.0-rc2 is known to take up to 1 minute to start in some cases. We expect this issue to be resolved in a future release of the sidecar container. For verification, please see the release notes of future releases of the external sidecar container. ([#76](https://github.com/kubernetes-csi/driver-registrar/issues/76)) +- When using IPV6-only, be sure to use `proxy-mode=iptables` as `proxy-mode=ipvs` is known to not work. ([#68437](https://github.com/kubernetes/kubernetes/issues/68437)) + +## Deprecations + +- kube-apiserver + - The `--service-account-api-audiences` flag is deprecated in favor of `--api-audiences`. The old flag is accepted with a warning but will be removed in a future release. ([#70105](https://github.com/kubernetes/kubernetes/pull/70105), [@mikedanese](https://github.com/mikedanese)) + - The `--experimental-encryption-provider-config` flag is deprecated in favor of `--encryption-provider-config`. The old flag is accepted with a warning but will be removed in 1.14. ([#71206](https://github.com/kubernetes/kubernetes/pull/71206), [@stlaz](https://github.com/stlaz)) + - As part of graduating the etcd encryption feature to beta, the configuration file referenced by `--encryption-provider-config` now uses `kind: EncryptionConfiguration` and `apiVersion: apiserver.config.k8s.io/v1`. Support for `kind: EncryptionConfig` and `apiVersion: v1` is deprecated and will be removed in a future release. ([#67383](https://github.com/kubernetes/kubernetes/pull/67383), [@stlaz](https://github.com/stlaz)) + - The `--deserialization-cache-size` flag is deprecated, and will be removed in a future release. The flag is inactive since the etcd2 storage backend was removed. ([#69842](https://github.com/kubernetes/kubernetes/pull/69842), [@liggitt](https://github.com/liggitt)) + - The `Node` authorization mode no longer allows kubelets to delete their Node API objects (prior to 1.11, in rare circumstances related to cloudprovider node ID changes, kubelets would attempt to delete/recreate their Node object at startup) ([#71021](https://github.com/kubernetes/kubernetes/pull/71021), [@liggitt](https://github.com/liggitt)) + - The built-in `system:csi-external-provisioner` and `system:csi-external-attacher` cluster roles are deprecated and will not be auto-created in a future release. CSI deployments should provide their own RBAC role definitions with required permissions. ([#69868](https://github.com/kubernetes/kubernetes/pull/69868), [@pohly]( https://github.com/pohly)) + - The built-in `system:aws-cloud-provider` cluster role is deprecated and will not be auto-created in a future release. Deployments using the AWS cloud provider should grant required permissions to the `aws-cloud-provider` service account in the `kube-system` namespace as part of deployment. ([#66635](https://github.com/kubernetes/kubernetes/pull/66635), [@wgliang](https://github.com/wgliang)) +- kubelet + - Use of the beta plugin registration directory `{kubelet_root_dir}/plugins/` for registration of external drivers via the kubelet plugin registration protocol is deprecated in favor of `{kubelet_root_dir}/plugins_registry/`. Support for the old directory is planned to be removed in v1.15. Device plugin and CSI storage drivers should switch to the new directory prior to v1.15. Only CSI storage drivers that support 0.x versions of the CSI API are allowed in the old directory. ([#70494](https://github.com/kubernetes/kubernetes/pull/70494) by [@RenaudWasTaken](https://github.com/RenaudWasTaken) and [#71314](https://github.com/kubernetes/kubernetes/pull/71314) by [@saad-ali](https://github.com/saad-ali)) + - With the release of the CSI 1.0 API, support for CSI drivers using 0.3 and older releases of the CSI API is deprecated, and is planned to be removed in Kubernetes v1.15. CSI drivers should be updated to support the CSI 1.0 API, and deployed in the new kubelet plugin registration directory (`{kubelet_root_dir}/plugins_registry/`) once all nodes in the cluster are at 1.13 or higher ([#71020](https://github.com/kubernetes/kubernetes/pull/71020) and [#71314](https://github.com/kubernetes/kubernetes/pull/71314), both by [@saad-ali](https://github.com/saad-ali)) + - Use of the `--node-labels` flag to set labels under the `kubernetes.io/` and `k8s.io/` prefix will be subject to restriction by the `NodeRestriction` admission plugin in future releases. [See admission plugin documentation](https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#noderestriction) for allowed labels. ([#68267](https://github.com/kubernetes/kubernetes/pull/68267), [@liggitt](https://github.com/liggitt)) +- kube-scheduler + - The alpha critical pod annotation (`scheduler.alpha.kubernetes.io/critical-pod`) is deprecated. Pod priority should be used instead to mark pods as critical. ([#70298](https://github.com/kubernetes/kubernetes/pull/70298), [@bsalamat](https://github.com/bsalamat)) +- The following features are now GA, and the associated feature gates are deprecated and will be removed in a future release: + - CSIPersistentVolume + - GCERegionalPersistentDisk + - KubeletPluginsWatcher + - VolumeScheduling +- kubeadm + - The DynamicKubeletConfig feature gate is deprecated. The functionality is still accessible by using the kubeadm alpha kubelet enable-dynamic command. + - The command `kubeadm config print-defaults` is deprecated in favor of `kubeadm config print init-defaults` and `kubeadm config print join-defaults` ([#69617](https://github.com/kubernetes/kubernetes/pull/69617), [@rosti](https://github.com/rosti)) + - support for the `v1alpha3` configuration file format is deprecated and will be removed in 1.14. Use `kubeadm config migrate` to migrate `v1alpha3` configuration files to `v1beta1`, which provides improvements in image repository management, addons configuration, and other areas. The documentation for `v1beta1` can be found here: https://godoc.org/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta1 +- The `node.status.volumes.attached.devicePath` field is deprecated for CSI volumes and will not be set in future releases ([#71095](https://github.com/kubernetes/kubernetes/pull/71095), [@msau42](https://github.com/msau42)) +- kubectl + - The `kubectl convert` command is deprecated and will be removed in a future release ([#70820](https://github.com/kubernetes/kubernetes/pull/70820), [@seans3](https://github.com/seans3)) +- Support for passing unknown provider names to the E2E test binaries is deprecated and will be removed in a future release. Use `--provider=skeleton` (no ssh access) or `--provider=local` (local cluster with ssh) instead. ([#70141](https://github.com/kubernetes/kubernetes/pull/70141), [@pohly](https://github.com/pohly)) + +## Major Themes + +### SIG API Machinery + +For the 1.13 release, SIG API Machinery is happy to announce that the [dry-run functionality](https://kubernetes.io/docs/reference/using-api/api-concepts/#dry-run) is now beta. + +### SIG Auth + +With this release we've made several important enhancements to core SIG Auth areas. In the authorization category, we've further reduced Kubelet privileges by [restricting node self-updates of labels to a whitelisted selection and by disallowing kubelets from deleting their Node API object](https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#noderestriction). In authentication, we added alpha-level support for automounting improved service account tokens through projected volumes. We also enabled [audience validation in TokenReview](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.13/#tokenreview-v1-authentication-k8s-io) for the new tokens for improved scoping. Under audit logging, the new alpha-level "dynamic audit configuration" adds support for [dynamically registering webhooks to receive a stream of audit events](https://kubernetes.io/docs/tasks/debug-application-cluster/audit/#dynamic-backend). Finally, we've enhanced secrets protection by graduating [etcd encryption](https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/) out of experimental. + +### SIG AWS + +In v1.13 we worked on tighter integrations of Kubernetes API objects with AWS services. These include three out-of-tree alpha feature releases: + +1) Alpha for AWS ALB (Application Load Balancer) integration to Kubernetes Ingress resources. +2) Alpha for CSI specification 0.3 integration to AWS EBS (Elastic Block Store) +3) Alpha for the cloudprovider-aws cloud controller manager binary. Additionally we added [aws-k8s-tester](https://github.com/kubernetes/test-infra/issues/9814), deployer interface for kubetest, to the test-infra repository. This plugin allowed us to integrate Prow to the 3 subprojects defined above in order to provide CI signal for all 3 features. The CI signal is visible [here](https://testgrid.k8s.io/) under SIG-AWS. + +For detailed release notes on the three alpha features from SIG AWS, please refer to the following Changelogs: + +- [aws-alb-ingress-controller v1.0.0](https://github.com/kubernetes-sigs/aws-alb-ingress-controller/releases/tag/v1.0.0) +- [aws-ebs-csi-driver v0.1](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/blob/master/CHANGELOG-0.1.md) +- [cloudprovider-aws external v0.1.0](https://github.com/kubernetes/cloud-provider-aws/blob/master/changelogs/CHANGELOG-0.1.md) + +### SIG Azure + +For 1.13 SIG Azure was focused on adding additional Azure Disk support for Ultra SSD, Standard SSD, and Premium Azure Files. Azure Availability Zones and cross resource group nodes were also moved from Alpha to Beta in 1.13. + +### SIG Big Data + +During the 1.13 release cycle, SIG Big Data has been focused on community engagements relating to 3rd-party project integrations with Kubernetes. There have been no impacts on the 1.13 release. + +### SIG CLI + +Over the course of 1.13 release SIG CLI mostly focused on stabilizing the items we’ve been working on over the past releases such as server-side printing and its support in kubectl, as well as finishing [kubectl diff which is based on server-side dry-run feature](https://kubernetes.io/docs/concepts/overview/object-management-kubectl/#how-to-create-objects). We’ve continued separating kubectl code to prepare for extraction out of main repository. Finally, thanks to the awesome support and feedback from community we’ve managed to promote the new [plugin mechanism to Beta](https://kubernetes.io/docs/tasks/extend-kubectl/kubectl-plugins/). + +### SIG Cloud Provider + +For v1.13, SIG Cloud Provider has been focused on stabilizing the common APIs and interfaces consumed by cloud providers today. This involved auditing the cloud provider APIs for anything that should be deprecated as well as adding changes where necessary. In addition, SIG Cloud Provider has begun exploratory work around having a “cloud provider” e2e test suite which can be used to test common cloud provider functionalities with resources such as nodes and load balancers. + +We are also continuing our long running effort to extract all the existing cloud providers that live in k8s.io/kubernetes into their own respective repos. Along with this migration, we are slowly transitioning users to use the cloud-controller-manager for any cloud provider features instead of the kube-controller-manager. + +### SIG Cluster Lifecycle + +For 1.13 SIG Cluster Lifecycle is pleased to announce the long awaited promotion of kubeadm to stable GA, and the promotion of kubeadm’s configuration API to `v1beta1`. +In this release the SIG again focused on further improving the user experience on cluster creation and also fixing a number of bugs and other assorted improvements. + +Some notable changes in kubeadm since Kubernetes 1.12: + +- kubeadm’s configuration API is now `v1beta1`. The new configuration format provides improvements in - image repository management, addons configuration, and other areas. We encourage `v1alpha3` users to migrate to this configuration API using `kubeadm config migrate`, as `v1alpha3` will be removed in 1.14. The documentation for `v1beta1` can be found here: https://godoc.org/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta1 +- kubeadm has graduated `kubeadm alpha phase` commands to `kubeadm init phase`. This means that the phases of creating a control-plane node are now tightly integrated as part of the `init` command. Alpha features, not yet ready for GA are still kept under `kubeadm alpha` and we appreciate feedback on them. +- `kubeadm init` and `kubeadm init phase` now have a `--image-repository` flag, improving support for environments with limited access to official kubernetes repository. +- The DynamicKubeletConfig and SelfHosting functionality was moved outside of `kubeadm init` and feature gates and is now exposed under `kubeadm alpha`. +- Kubeadm init phase certs now support the `--csr-only` option, simplifying custom CA creation. +- `kubeadm join --experimental-control-plane` now automatically adds a new etcd member for `local etcd` mode, further simplifying required tasks for HA clusters setup. +- Improvements were made to `kubeadm reset` related to cleaning etcd and notifying the user about the state of iptables. +- kubeadm commands now print warnings if input YAML documents contain unknown or duplicate fields. +- kubeadm now properly recognizes Docker 18.09.0 and newer, but still treats 18.06 as the default supported version. +- kubeadm now automatically sets the `--pod-infra-container-image` flag when starting the kubelet. + +### SIG IBM Cloud + +The IBM Cloud SIG was focused on defining its charter and working towards moving its cloud provider code to an external repository with a goal to have this work done by the end of Kubernetes 1.14 release cycle. In the SIG meetings, we also made sure to share updates on the latest Kubernetes developments in the IBM Cloud like the availability of Kubernetes v1.12.2 in the IBM Cloud Kubernetes Service (IKS). The SIG updates were provided in the Kubernetes community weekly call and at the KubeCon China 2018. + +### SIG Multicluster + +Moving Federation v2 from Alpha towards Beta has been the focus of our effort over the past quarter. To this end we engaged with end users, and successfully enlisted additional contributors from companies including IBM, Amadeus, Cisco and others. Federation v2 provides a suite of decoupled API’s and re-usable components for building multi-cluster control planes. We plan to start releasing Beta components in late 2018. In addition, more minor updates were made to our cluster-registry and multi-cluster ingress sub-projects. + +### SIG Network + +For 1.13, the areas of focus were in IPv6, DNS improvements and some smaller items: +CoreDNS is now the default cluster DNS passing all of the scale/resource usage tests +Node-local DNS cache feature is available in Alpha. This feature deploys a lightweight DNS caching Daemonset that avoids the conntrack and converts queries from UDP to more reliable TCP. +PodReady++ feature now has `kubectl` CLI support. + +Progress was made towards finalizing the IPv6 dual stack support KEP and support for topological routing of services. + +### SIG Node + +SIG Node focused on stability and performance improvements in the 1.13 release. A new alpha feature is introduced to improve the mechanism that nodes heartbeat back to the control plane. The `NodeLease` feature results in the node using a `Lease` resource in the `kube-node-lease` namespace that is renewed periodically. The `NodeStatus` that was used previously to heartbeat back to the control plane is only updated when it changes. This reduces load on the control plane for large clusters. The Kubelet plugin registration mechanism, which enables automatic discovery of external plugins (including CSI and device plugins) has been promoted to stable in this release (introduced as alpha in 1.11 and promoted to beta in 1.12). + +### SIG Openstack + +The major theme for the SIG OpenStack release is the work-in-progress for removing the in-tree provider. This work, being done in conjunction with SIG Cloud Provider, is focusing on moving internal APIs that the OpenStack (and other providers) depends upon to staging to guarantee API stability. This work also included abstracting the in-tree Cinder API and refactoring code to the external Cinder provider to remove additional Cinder volume provider code. + +Additional work was also done to implement an OpenStack driver for the Cluster API effort lead by SIG Cluster Lifecycle. For the external Cloud-Provider-OpenStack code, the SIG largely focused on bug fixes and updates to match K8s 1.13 development. + +### SIG Scalability + +SIG Scalability has mostly focused on stability and deflaking our tests, investing into framework for writing scalability tests (ClusterLoader v2) with a goal to migrate all tests to it by the end of 2018 and on the work towards extending definition of Kubernetes scalability by providing more/better user-friendly SLIs/SLOs. + +### SIG Scheduling + +SIG Scheduling has mostly focused on stability in 1.13 and has postponed some of the major features to the next versions. There are still two notable changes: 1. TaintBasedEviction is moved to Beta and will be enabled by default. With this feature enabled, condition taints are automatically added to the nodes and pods can add tolerations for them if needed. 2. Pod critical annotation is deprecated. Pods should use pod priority instead of the annotation. + +It is worth noting again that kube-scheduler will use apiVersion `kubescheduler.config.k8s.io/v1alpha1` instead of `componentconfig/v1alpha1` in its configuration files in 1.13. + +### SIG Service Catalog + +The Service Plan Defaults feature is still under active development. +We continue to improve the UX for the svcat CLI, specifically filling in gaps for the new Namespaced Service Broker feature. + +### SIG Storage + +Over the last year, SIG Storage has been focused on adding support for the Container Storage Interface (CSI) to Kubernetes. The specification recently moved to 1.0, and on the heels of this achievement, Kubernetes v1.13 moves CSI support for PersistentVolumes to GA. + +With CSI the Kubernetes volume layer becomes truly extensible, allowing third party storage developers to write drivers making their storage systems available in Kubernetes without having to touch the core code. + +CSI was first introduction as alpha in Kubernetes v1.9 and moved to beta in Kubernetes v1.10. + +You can find a list of sample and production drivers in the [CSI Documentation](https://kubernetes.io/docs/concepts/storage/volumes/#csi). + +SIG Storage also moves support for Block Volumes to beta (introduced as alpha in v1.9) and support for Topology Aware Volume Scheduling to stable (introduced as alpha in v1.9 and promoted to beta in 1.10). + +### SIG UI + +The migration to the newest version of Angular is still under active development as it is most important thing on the roadmap at the moment. We are getting closer to to the new release. We continue fixing bugs and adding other improvements. + +### SIG VMWare + +Major focus for SIG VMware for this release is the work on moving internal APIs that the vSphere provider depends upon to staging to guarantee API stability. This work is being done in conjunction with SIG Cloud Provider and includes the creation of a brand new vsphere-csi plugin to replace the current volume functionalities in-tree. + +Additional work was also done to implement a vSphere provider for the Cluster API effort lead by SIG Cluster Lifecycle. For the out-of-tree vSphere cloud provider, the SIG largely focused on bug fixes and updates to match K8s 1.13 development. + +### SIG Windows + +SIG Windows focused on improving reliability for Windows and Kubernetes support + +## New Features + +- kubelet: When node lease feature is enabled, kubelet reports node status to api server only if there is some change or it didn't report over last report interval. ([#69753](https://github.com/kubernetes/kubernetes/pull/69753), [@wangzhen127](https://github.com/wangzhen127)) +- vSphereVolume implements Raw Block Volume Support ([#68761](https://github.com/kubernetes/kubernetes/pull/68761), [@fanzhangio](https://github.com/fanzhangio)) +- CRD supports multi-version Schema, Subresources and AdditionalPrintColumns (NOTE that CRDs created prior to 1.13 populated the top-level additionalPrinterColumns field by default. To apply an updated that changes to per-version additionalPrinterColumns, the top-level additionalPrinterColumns field must be explicitly set to null). ([#70211](https://github.com/kubernetes/kubernetes/pull/70211), [@roycaihw](https://github.com/roycaihw)) +- New addon in addon manager that automatically installs CSI CRDs if CSIDriverRegistry or CSINodeInfo feature gates are true. ([#70193](https://github.com/kubernetes/kubernetes/pull/70193), [@saad-ali](https://github.com/saad-ali)) +- Delegated authorization can now allow unrestricted access for `system:masters` like the main kube-apiserver ([#70671](https://github.com/kubernetes/kubernetes/pull/70671), [@deads2k](https://github.com/deads2k)) +- Added dns capabilities for Windows CNI plugins: ([#67435](https://github.com/kubernetes/kubernetes/pull/67435), [@feiskyer](https://github.com/feiskyer)) +- kube-apiserver: `--audit-webhook-version` and `--audit-log-version` now default to `audit.k8s.io/v1` if unspecified ([#70476](https://github.com/kubernetes/kubernetes/pull/70476), [@charrywanganthony](https://github.com/charrywanganthony)) +- kubeadm: timeoutForControlPlane is introduced as part of the API Server config, that controls the timeout for the wait for control plane to be up. Default value is 4 minutes. ([#70480](https://github.com/kubernetes/kubernetes/pull/70480), [@rosti](https://github.com/rosti)) +- `--api-audiences` now defaults to the `--service-account-issuer` if the issuer is provided but the API audience is not. ([#70308](https://github.com/kubernetes/kubernetes/pull/70308), [@mikedanese](https://github.com/mikedanese)) +- Added support for projected volume in describe function ([#70158](https://github.com/kubernetes/kubernetes/pull/70158), [@WanLinghao](https://github.com/WanLinghao)) +- kubeadm now automatically creates a new stacked etcd member when joining a new control plane node (does not applies to external etcd) ([#69486](https://github.com/kubernetes/kubernetes/pull/69486), [@fabriziopandini](https://github.com/fabriziopandini)) +- Display the usage of ephemeral-storage when using `kubectl describe node` ([#70268](https://github.com/kubernetes/kubernetes/pull/70268), [@Pingan2017](https://github.com/Pingan2017)) +- Added functionality to enable br_netfilter and ip_forward for debian packages to improve kubeadm support for CRI runtime besides Docker. ([#70152](https://github.com/kubernetes/kubernetes/pull/70152), [@ashwanikhemani](https://github.com/ashwanikhemani)) +- Added regions ap-northeast-3 and eu-west-3 to the list of well known AWS regions. ([#70252](https://github.com/kubernetes/kubernetes/pull/70252), [@nckturner](https://github.com/nckturner)) +- kubeadm: Implemented preflight check to ensure that number of CPUs ([#70048](https://github.com/kubernetes/kubernetes/pull/70048), [@bart0sh](https://github.com/bart0sh)) +- CoreDNS is now the default DNS server in kube-up deployments. ([#69883](https://github.com/kubernetes/kubernetes/pull/69883), [@chrisohaver](https://github.com/chrisohaver)) +- Opt out of chowning and chmoding from kubectl cp. ([#69573](https://github.com/kubernetes/kubernetes/pull/69573), [@bjhaid](https://github.com/bjhaid)) +- Failed to provision volume with StorageClass "azurefile-premium": failed to create share andy-mg1121-dynamic-pvc-1a7b2813-d1b7-11e8-9e96-000d3a03e16b in account f7228f99bcde411e8ba4900: failed to create file share, err: storage: service returned error: StatusCode=400, ErrorCode=InvalidHeaderValue, ErrorMessage=The value for one of the HTTP headers is not in the correct format. ([#69718](https://github.com/kubernetes/kubernetes/pull/69718), [@andyzhangx](https://github.com/andyzhangx)) +- `TaintBasedEvictions` feature is promoted to beta. ([#69824](https://github.com/kubernetes/kubernetes/pull/69824), [@Huang-Wei](https://github.com/Huang-Wei)) +- Fixed https://github.com/kubernetes/client-go/issues/478 by adding support for JSON Patch in client-go/dynamic/fake ([#69330](https://github.com/kubernetes/kubernetes/pull/69330), [@vaikas-google](https://github.com/vaikas-google)) +- Dry-run is promoted to Beta and will be enabled by default. ([#69644](https://github.com/kubernetes/kubernetes/pull/69644), [@apelisse](https://github.com/apelisse)) +- `kubectl get priorityclass` now prints value column by default. ([#69431](https://github.com/kubernetes/kubernetes/pull/69431), [@Huang-Wei](https://github.com/Huang-Wei)) +- Added a new container based image for running e2e tests ([#69368](https://github.com/kubernetes/kubernetes/pull/69368), [@dims](https://github.com/dims)) +- The `LC_ALL` and `LC_MESSAGES` env vars can now be used to set desired locale for `kubectl` while keeping `LANG` unchanged. ([#69500](https://github.com/kubernetes/kubernetes/pull/69500), [@m1kola](https://github.com/m1kola)) +- NodeLifecycleController: Now node lease renewal is treated as the heartbeat signal from the node, in addition to NodeStatus Update. ([#69241](https://github.com/kubernetes/kubernetes/pull/69241), [@wangzhen127](https://github.com/wangzhen127)) +- Added dynamic shared informers to write generic, non-generated controllers ([#69308](https://github.com/kubernetes/kubernetes/pull/69308), [@p0lyn0mial](https://github.com/p0lyn0mial)) +- Upgraded to etcd 3.3 client ([#69322](https://github.com/kubernetes/kubernetes/pull/69322), [@jpbetz](https://github.com/jpbetz)) +- It is now possible to use named ports in the `kubectl port-forward` command ([#69477](https://github.com/kubernetes/kubernetes/pull/69477), [@m1kola](https://github.com/m1kola)) +- `kubectl wait` now supports condition value checks other than true using `--for condition=available=false` ([#69295](https://github.com/kubernetes/kubernetes/pull/69295), [@deads2k](https://github.com/deads2k)) +- Updated defaultbackend image to 1.5. Users should concentrate on updating scripts to the new version. ([#69120](https://github.com/kubernetes/kubernetes/pull/69120), [@aledbf](https://github.com/aledbf)) +- Bumped Dashboard version to v1.10.0 ([#68450](https://github.com/kubernetes/kubernetes/pull/68450), [@jeefy](https://github.com/jeefy)) +- Added env variables to control CPU requests of kube-controller-manager and kube-scheduler. ([#68823](https://github.com/kubernetes/kubernetes/pull/68823), [@loburm](https://github.com/loburm)) +- PodSecurityPolicy objects now support a `MayRunAs` rule for `fsGroup` and `supplementalGroups` options. This allows specifying ranges of allowed GIDs for pods/containers without forcing a default GID the way `MustRunAs` does. This means that a container to which such a policy applies to won't use any fsGroup/supplementalGroup GID if not explicitly specified, yet a specified GID must still fall in the GID range according to the policy. ([#65135](https://github.com/kubernetes/kubernetes/pull/65135), [@stlaz](https://github.com/stlaz)) +- Upgrade Stackdriver Logging Agent addon image to 0.6-1.6.0-1 to use Fluentd v1.2. This provides nanoseconds timestamp granularity for logs. ([#70954](https://github.com/kubernetes/kubernetes/pull/70954), [@qingling128](https://github.com/qingling128)) +- When the BoundServiceAccountTokenVolumes Alpha feature is enabled, ServiceAccount volumes now use a projected volume source and their names have the prefix "kube-api-access". ([#69848](https://github.com/kubernetes/kubernetes/pull/69848), [@mikedanese](https://github.com/mikedanese)) +- Raw block volume support is promoted to beta, and enabled by default. This is accessible via the `volumeDevices` container field in pod specs, and the `volumeMode` field in persistent volume and persistent volume claims definitions. ([#71167](https://github.com/kubernetes/kubernetes/pull/71167), [@msau42](https://github.com/msau42)) +- TokenReview now supports audience validation of tokens with audiences other than the kube-apiserver. ([#62692](https://github.com/kubernetes/kubernetes/pull/62692), [@mikedanese](https://github.com/mikedanese)) +- StatefulSet is supported in `kubectl autoscale` command ([#71103](https://github.com/kubernetes/kubernetes/pull/71103), [@Pingan2017](https://github.com/Pingan2017)) +- Kubernetes v1.13 moves support for Container Storage Interface to GA. As part of this move Kubernetes now supports CSI v1.0.0 and deprecates support for CSI 0.3 and older releases. Older CSI drivers must be updated to CSI 1.0 and moved to the new kubelet plugin registration directory in order to work with Kubernetes 1.15+. ([#71020](https://github.com/kubernetes/kubernetes/pull/71020), [@saad-ali](https://github.com/saad-ali)) +- Added option to create CSRs instead of certificates for kubeadm init phase certs and kubeadm alpha certs renew ([#70809](https://github.com/kubernetes/kubernetes/pull/70809), [@liztio](https://github.com/liztio)) +- Added a kubelet socket which serves an grpc service containing the devices used by containers on the node. ([#70508](https://github.com/kubernetes/kubernetes/pull/70508), [@dashpole](https://github.com/dashpole)) +- Added DynamicAuditing feature which allows for the configuration of audit webhooks through the use of an AuditSink API object. ([#67257](https://github.com/kubernetes/kubernetes/pull/67257), [@pbarker](https://github.com/pbarker)) +- The kube-apiserver's healthz now takes in an optional query parameter which allows you to disable health checks from causing healthz failures. ([#70676](https://github.com/kubernetes/kubernetes/pull/70676), [@logicalhan](https://github.com/logicalhan)) +- Introduced support for running a nodelocal dns cache. It is disabled by default, can be enabled by setting KUBE_ENABLE_NODELOCAL_DNS=true ([#70555](https://github.com/kubernetes/kubernetes/pull/70555), [@prameshj](https://github.com/prameshj)) +- Added readiness gates in extended output for pods ([#70775](https://github.com/kubernetes/kubernetes/pull/70775), [@freehan](https://github.com/freehan)) +- Added `Ready` column and improve human-readable output of Deployments and StatefulSets ([#70466](https://github.com/kubernetes/kubernetes/pull/70466), [@Pingan2017](https://github.com/Pingan2017)) +- Added `kubelet_container_log_size_bytes` metric representing the log file size of a container. ([#70749](https://github.com/kubernetes/kubernetes/pull/70749), [@brancz](https://github.com/brancz)) +- NodeLifecycleController: When node lease feature is enabled, node lease will be deleted when the corresponding node is deleted. ([#70034](https://github.com/kubernetes/kubernetes/pull/70034), [@wangzhen127](https://github.com/wangzhen127)) +- GCERegionalPersistentDisk feature is GA now! ([#70716](https://github.com/kubernetes/kubernetes/pull/70716), [@jingxu97](https://github.com/jingxu97)) +- Added secure port 10259 to the kube-scheduler (enabled by default) and deprecate old insecure port 10251. Without further flags self-signed certs are created on startup in memory. ([#69663](https://github.com/kubernetes/kubernetes/pull/69663), [@sttts](https://github.com/sttts)) + +## Release Notes From SIGs + +### SIG API Machinery + +- The OwnerReferencesPermissionEnforcement admission plugin now checks authorization for the correct scope (namespaced or cluster-scoped) of the owner resource type. Previously, it always checked permissions at the same scope as the child resource. ([#70389](https://github.com/kubernetes/kubernetes/pull/70389), [@caesarxuchao](https://github.com/caesarxuchao)) +- OpenAPI spec now correctly marks delete request's body parameter as optional ([#70032](https://github.com/kubernetes/kubernetes/pull/70032), [@iamneha](https://github.com/iamneha)) +- The rules for incrementing `metadata.generation` of custom resources changed: ([#69059](https://github.com/kubernetes/kubernetes/pull/69059), [@caesarxuchao](https://github.com/caesarxuchao)) + - If the custom resource participates the spec/status convention, the metadata.generation of the CR increments when there is any change, except for the changes to the metadata or the changes to the status. + - If the custom resource does not participate the spec/status convention, the metadata.generation of the CR increments when there is any change to the CR, except for changes to the metadata. + - A custom resource is considered to participate the spec/status convention if and only if the "CustomResourceSubresources" feature gate is turned on and the CRD has `.spec.subresources.status={}`. +- Fixed patch/update operations on multi-version custom resources ([#70087](https://github.com/kubernetes/kubernetes/pull/70087), [@liggitt](https://github.com/liggitt)) +- Reduced memory utilization of admission webhook metrics by removing resource related labels. ([#69895](https://github.com/kubernetes/kubernetes/pull/69895), [@jpbetz](https://github.com/jpbetz)) +- Kubelet can now parse PEM file containing both TLS certificate and key in arbitrary order. Previously key was always required to be first. ([#69536](https://github.com/kubernetes/kubernetes/pull/69536), [@awly](https://github.com/awly)) +- Code-gen: Removed lowercasing for project imports ([#68484](https://github.com/kubernetes/kubernetes/pull/68484), [@jsturtevant](https://github.com/jsturtevant)) +- Fixed client cert setup in delegating authentication logic ([#69430](https://github.com/kubernetes/kubernetes/pull/69430), [@DirectXMan12](https://github.com/DirectXMan12)) +- OpenAPI spec and API reference now reflect dryRun query parameter for POST/PUT/PATCH operations ([#69359](https://github.com/kubernetes/kubernetes/pull/69359), [@roycaihw](https://github.com/roycaihw)) +- Fixed the sample-apiserver so that its BanFlunder admission plugin can be used. ([#68417](https://github.com/kubernetes/kubernetes/pull/68417), [@MikeSpreitzer](https://github.com/MikeSpreitzer)) +- APIService availability related to networking glitches are corrected faster ([#68678](https://github.com/kubernetes/kubernetes/pull/68678), [@deads2k](https://github.com/deads2k)) +- Fixed an issue with stuck connections handling error responses ([#71412](https://github.com/kubernetes/kubernetes/pull/71412), [@liggitt](https://github.com/liggitt)) +- apiserver: fixed handling and logging of panics in REST handlers ([#71076](https://github.com/kubernetes/kubernetes/pull/71076), [@liggitt](https://github.com/liggitt)) +- kube-controller-manager no longer removes ownerReferences from ResourceQuota objects ([#70035](https://github.com/kubernetes/kubernetes/pull/70035), [@liggitt](https://github.com/liggitt)) +- "unfinished_work_microseconds" is added to the workqueue metrics; it can be used to detect stuck worker threads. (kube-controller-manager runs many workqueues.) ([#70884](https://github.com/kubernetes/kubernetes/pull/70884), [@lavalamp](https://github.com/lavalamp)) +- Timeouts set in ListOptions for clients are also be respected locally ([#70998](https://github.com/kubernetes/kubernetes/pull/70998), [@deads2k](https://github.com/deads2k)) +- Added support for CRD conversion webhook ([#67006](https://github.com/kubernetes/kubernetes/pull/67006), [@mbohlool](https://github.com/mbohlool)) +- client-go: fixed sending oversized data frames to spdystreams in remotecommand.NewSPDYExecutor ([#70999](https://github.com/kubernetes/kubernetes/pull/70999), [@liggitt](https://github.com/liggitt)) +- Fixed missing flags in `-controller-manager --help`. ([#71298](https://github.com/kubernetes/kubernetes/pull/71298), [@stewart-yu](https://github.com/stewart-yu)) +- Fixed missing flags in `kube-apiserver --help`. ([#70204](https://github.com/kubernetes/kubernetes/pull/70204), [@imjching](https://github.com/imjching)) +- The caBundle and service fields in admission webhook API objects now correctly indicate they are optional ([#70138](https://github.com/kubernetes/kubernetes/pull/70138), [@liggitt](https://github.com/liggitt)) +- Fixed an issue with stuck connections handling error responses ([#71419](https://github.com/kubernetes/kubernetes/pull/71419), [@liggitt](https://github.com/liggitt)) +- kube-controller-manager and cloud-controller-manager now hold generated serving certificates in-memory unless a writeable location is specified with --cert-dir ([#69884](https://github.com/kubernetes/kubernetes/pull/69884), [@liggitt](https://github.com/liggitt)) +- CCM server will not listen insecurely if secure port is specified ([#68982](https://github.com/kubernetes/kubernetes/pull/68982), [@aruneli](https://github.com/aruneli)) +- List operations against the API now return internal server errors instead of partially complete lists when a value cannot be transformed from storage. The updated behavior is consistent with all other operations that require transforming data from storage such as watch and get. ([#69399](https://github.com/kubernetes/kubernetes/pull/69399), [@mikedanese](https://github.com/mikedanese)) + +### SIG Auth + +- API Server can be configured to reject requests that cannot be audit-logged. ([#65763](https://github.com/kubernetes/kubernetes/pull/65763), [@x13n](https://github.com/x13n)) +- Go clients created from a kubeconfig that specifies a TokenFile now periodically reload the token from the specified file. ([#70606](https://github.com/kubernetes/kubernetes/pull/70606), [@mikedanese](https://github.com/mikedanese)) +- When `--rotate-server-certificates` is enabled, kubelet will no longer request a new certificate on startup if the current certificate on disk is satisfactory. ([#69991](https://github.com/kubernetes/kubernetes/pull/69991), [@agunnerson-ibm](https://github.com/agunnerson-ibm)) +- Added dynamic audit configuration api ([#67547](https://github.com/kubernetes/kubernetes/pull/67547), [@pbarker](https://github.com/pbarker)) +- Added ability to control primary GID of containers through Pod Spec and PodSecurityPolicy ([#67802](https://github.com/kubernetes/kubernetes/pull/67802), [@krmayankk](https://github.com/krmayankk)) +- kube-apiserver: the `NodeRestriction` admission plugin now prevents kubelets from modifying `Node` labels prefixed with `node-restriction.kubernetes.io/`. The `node-restriction.kubernetes.io/` label prefix is reserved for cluster administrators to use for labeling `Node` objects to target workloads to nodes in a way that kubelets cannot modify or spoof. ([#68267](https://github.com/kubernetes/kubernetes/pull/68267), [@liggitt](https://github.com/liggitt)) + +### SIG Autoscaling + +- Updated Cluster Autoscaler version to 1.13.0. See the [Release Notes](https://github.com/kubernetes/autoscaler/releases/tag/cluster-autoscaler-1.13.0) for more information. ([#71513](https://github.com/kubernetes/kubernetes/pull/71513), [@losipiuk](https://github.com/losipiuk)) + +### SIG AWS + +- `service.beta.kubernetes.io/aws-load-balancer-internal` now supports true and false values, previously it only supported non-empty strings ([#69436](https://github.com/kubernetes/kubernetes/pull/69436), [@mcrute](https://github.com/mcrute)) +- Added `service.beta.kubernetes.io/aws-load-balancer-security-groups` annotation to set the security groups to the AWS ELB to be the only ones specified in the annotation in case this is present (does not add `0.0.0.0/0`). ([#62774](https://github.com/kubernetes/kubernetes/pull/62774), [@Raffo](https://github.com/Raffo)) + +### SIG Azure + +- Ensured orphan public IPs on Azure deleted when service recreated with the same name. ([#70463](https://github.com/kubernetes/kubernetes/pull/70463), [@feiskyer](https://github.com/feiskyer)) +- Improved Azure instance metadata handling by adding caches. ([#70353](https://github.com/kubernetes/kubernetes/pull/70353), [@feiskyer](https://github.com/feiskyer)) +- Corrected check for non-Azure managed nodes with the Azure cloud provider ([#70135](https://github.com/kubernetes/kubernetes/pull/70135), [@marc-sensenich](https://github.com/marc-sensenich)) +- Fixed azure disk attach/detach failed forever issue ([#71377](https://github.com/kubernetes/kubernetes/pull/71377), [@andyzhangx](https://github.com/andyzhangx)) +- DisksAreAttached --> getNodeDataDisks--> GetDataDisks --> getVirtualMachine --> vmCache.Get ([#71495](https://github.com/kubernetes/kubernetes/pull/71495), [@andyzhangx](https://github.com/andyzhangx)) + +### SIG CLI + +- `kubectl apply` can now change a deployment strategy from rollout to recreate without explicitly clearing the rollout-related fields ([#70436](https://github.com/kubernetes/kubernetes/pull/70436), [@liggitt](https://github.com/liggitt)) +- The `kubectl plugin list` command now displays discovered plugin paths in the same order as they are found in a user's PATH variable. ([#70443](https://github.com/kubernetes/kubernetes/pull/70443), [@juanvallejo](https://github.com/juanvallejo)) +- `kubectl get` no longer exits before printing all of its results if an error is found ([#70311](https://github.com/kubernetes/kubernetes/pull/70311), [@juanvallejo](https://github.com/juanvallejo)) +- Fixed a runtime error occuring when sorting the output of `kubectl get` with empty results ([#70740](https://github.com/kubernetes/kubernetes/pull/70740), [@mfpierre](https://github.com/mfpierre)) +- kubectl: support multiple arguments for cordon/uncordon and drain ([#68655](https://github.com/kubernetes/kubernetes/pull/68655), [@goodluckbot](https://github.com/goodluckbot)) +- Fixed ability for admin/edit/view users to see controller revisions, needed for kubectl rollout commands ([#70699](https://github.com/kubernetes/kubernetes/pull/70699), [@liggitt](https://github.com/liggitt)) +- `kubectl rollout undo` now returns errors when attempting to rollback a deployment to a non-existent revision ([#70039](https://github.com/kubernetes/kubernetes/pull/70039), [@liggitt](https://github.com/liggitt)) +- kubectl run now generates apps/v1 deployments by default ([#71006](https://github.com/kubernetes/kubernetes/pull/71006), [@liggitt](https://github.com/liggitt)) +- The "kubectl cp" command now supports path shortcuts (../) in remote paths. ([#65189](https://github.com/kubernetes/kubernetes/pull/65189), [@juanvallejo](https://github.com/juanvallejo)) +- Fixed dry-run output in kubectl apply --prune ([#69344](https://github.com/kubernetes/kubernetes/pull/69344), [@zegl](https://github.com/zegl)) +- The kubectl wait command must handle when a watch returns an error vs closing by printing out the error and retrying the watch. ([#69389](https://github.com/kubernetes/kubernetes/pull/69389), [@smarterclayton](https://github.com/smarterclayton)) +- kubectl: support multiple arguments for cordon/uncordon and drain ([#68655](https://github.com/kubernetes/kubernetes/pull/68655), [@goodluckbot](https://github.com/goodluckbot)) + +### SIG Cloud Provider + +- Added deprecation warning for all cloud providers ([#69171](https://github.com/kubernetes/kubernetes/pull/69171), [@andrewsykim](https://github.com/andrewsykim)) + +### SIG Cluster Lifecycle + +- kubeadm: Updates version of CoreDNS to 1.2.6 ([#70796](https://github.com/kubernetes/kubernetes/pull/70796), [@detiber](https://github.com/detiber)) +- kubeadm: Validate kubeconfig files in case of external CA mode. ([#70537](https://github.com/kubernetes/kubernetes/pull/70537), [@yagonobre](https://github.com/yagonobre)) +- kubeadm: The writable config file option for extra volumes is renamed to readOnly with a reversed meaning. With readOnly defaulted to false (as in pod specs). ([#70495](https://github.com/kubernetes/kubernetes/pull/70495), [@rosti](https://github.com/rosti)) +- kubeadm: Multiple API server endpoints support upon join is removed as it is now redundant. ([#69812](https://github.com/kubernetes/kubernetes/pull/69812), [@rosti](https://github.com/rosti)) +- `kubeadm reset` now cleans up custom etcd data path ([#70003](https://github.com/kubernetes/kubernetes/pull/70003), [@yagonobre](https://github.com/yagonobre)) +- kubeadm: Fixed unnecessary upgrades caused by undefined order of Volumes and VolumeMounts in manifests ([#70027](https://github.com/kubernetes/kubernetes/pull/70027), [@bart0sh](https://github.com/bart0sh)) +- kubeadm: Fixed node join taints. ([#69846](https://github.com/kubernetes/kubernetes/pull/69846), [@andrewrynhard](https://github.com/andrewrynhard)) +- Fixed cluster autoscaler addon permissions so it can access batch/job. ([#69858](https://github.com/kubernetes/kubernetes/pull/69858), [@losipiuk](https://github.com/losipiuk)) +- kubeadm: JoinConfiguration now houses the discovery options in a nested Discovery structure, which in turn has a couple of other nested structures to house more specific options (BootstrapTokenDiscovery and FileDiscovery) ([#67763](https://github.com/kubernetes/kubernetes/pull/67763), [@rosti](https://github.com/rosti)) +- kubeadm: Fixed a possible scenario where kubeadm can pull much newer control-plane images ([#69301](https://github.com/kubernetes/kubernetes/pull/69301), [@neolit123](https://github.com/neolit123)) +- kubeadm now allows mixing of init/cluster and join configuration in a single YAML file (although a warning gets printed in this case). ([#69426](https://github.com/kubernetes/kubernetes/pull/69426), [@rosti](https://github.com/rosti)) +- kubeadm: Added a `v1beta1` API. ([#69289](https://github.com/kubernetes/kubernetes/pull/69289), [@fabriziopandini](https://github.com/fabriziopandini)) +- kubeadm init correctly uses `--node-name` and `--cri-socket` when `--config` option is also used ([#71323](https://github.com/kubernetes/kubernetes/pull/71323), [@bart0sh](https://github.com/bart0sh)) +- kubeadm: Always pass spec.nodeName as `--hostname-override` for kube-proxy ([#71283](https://github.com/kubernetes/kubernetes/pull/71283), [@Klaven](https://github.com/Klaven)) +- `kubeadm join` correctly uses `--node-name` and `--cri-socket` when `--config` option is also used ([#71270](https://github.com/kubernetes/kubernetes/pull/71270), [@bart0sh](https://github.com/bart0sh)) +- kubeadm now supports the `--image-repository` flag for customizing what registry to pull images from ([#71135](https://github.com/kubernetes/kubernetes/pull/71135), [@luxas](https://github.com/luxas)) +- kubeadm: The writable config file option for extra volumes is renamed to readOnly with a reversed meaning. With readOnly defaulted to false (as in pod specs). ([#70495](https://github.com/kubernetes/kubernetes/pull/70495), [@rosti](https://github.com/rosti)) +- kubeadm: Multiple API server endpoints support upon join is removed as it is now redundant. ([#69812](https://github.com/kubernetes/kubernetes/pull/69812), [@rosti](https://github.com/rosti)) +- kubeadm: JoinConfiguration now houses the discovery options in a nested Discovery structure, which in turn has a couple of other nested structures to house more specific options (BootstrapTokenDiscovery and FileDiscovery) ([#67763](https://github.com/kubernetes/kubernetes/pull/67763), [@rosti](https://github.com/rosti)) +- kubeadm: Added a `v1beta1` API. ([#69289](https://github.com/kubernetes/kubernetes/pull/69289), [@fabriziopandini](https://github.com/fabriziopandini)) +- kubeadm: Use `advertise-client-urls` instead of `listen-client-urls` as and `etcd-servers` options for apiserver. ([#69827](https://github.com/kubernetes/kubernetes/pull/69827), [@tomkukral](https://github.com/tomkukral)) +- Kubeadm now respects the custom image registry configuration across joins and upgrades. Kubeadm passes the custom registry to the kubelet for a custom pause container. ([#70603](https://github.com/kubernetes/kubernetes/pull/70603), [@chuckha](https://github.com/chuckha)) +- `kubeadm reset` now outputs instructions about manual iptables rules cleanup. ([#70874](https://github.com/kubernetes/kubernetes/pull/70874), [@rdodev](https://github.com/rdodev)) +- kubeadm: remove the AuditPolicyConfiguration feature gate ([#70807](https://github.com/kubernetes/kubernetes/pull/70807), [@Klaven](https://github.com/Klaven)) +- kubeadm pre-pulls Etcd image only if external Etcd is not used and ([#70743](https://github.com/kubernetes/kubernetes/pull/70743), [@bart0sh](https://github.com/bart0sh)) +- kubeadm: UnifiedControlPlaneImage is replaced by UseHyperKubeImage boolean value. ([#70793](https://github.com/kubernetes/kubernetes/pull/70793), [@rosti](https://github.com/rosti)) +- For kube-up and derived configurations, CoreDNS will honor master taints, for consistency with kube-dns behavior. ([#70868](https://github.com/kubernetes/kubernetes/pull/70868), [@justinsb](https://github.com/justinsb)) +- Recognize newer docker versions without -ce/-ee suffix: 18.09.0 ([#71001](https://github.com/kubernetes/kubernetes/pull/71001), [@thomas-riccardi](https://github.com/thomas-riccardi)) +- Any external provider should be aware the cloud-provider interface should be imported from :- ([#68310](https://github.com/kubernetes/kubernetes/pull/68310), [@cheftako](https://github.com/cheftako)) +- Fixed 'kubeadm upgrade' infinite loop waiting for pod restart ([#69886](https://github.com/kubernetes/kubernetes/pull/69886), [@bart0sh](https://github.com/bart0sh)) +- Bumped addon-manager to v8.8 ([#69337](https://github.com/kubernetes/kubernetes/pull/69337), [@MrHohn](https://github.com/MrHohn)) +- GCE: Filter out spammy audit logs from cluster autoscaler. ([#70696](https://github.com/kubernetes/kubernetes/pull/70696), [@loburm](https://github.com/loburm)) +- GCE: Enable by default audit logging truncating backend. ([#68288](https://github.com/kubernetes/kubernetes/pull/68288), [@loburm](https://github.com/loburm)) +- Bumped cluster-proportional-autoscaler to 1.3.0 ([#69338](https://github.com/kubernetes/kubernetes/pull/69338), [@MrHohn](https://github.com/MrHohn)) +- Updated defaultbackend to v1.5 ([#69334](https://github.com/kubernetes/kubernetes/pull/69334), [@bowei](https://github.com/bowei)) + +### SIG GCP + +- Added tolerations for Stackdriver Logging and Metadata Agents. ([#69737](https://github.com/kubernetes/kubernetes/pull/69737), [@qingling128](https://github.com/qingling128)) +- Enabled insertId generation, and updated Stackdriver Logging Agent image to 0.5-1.5.36-1-k8s. This help reduce log duplication and guarantee log order. ([#68920](https://github.com/kubernetes/kubernetes/pull/68920), [@qingling128](https://github.com/qingling128)) +- Updated crictl to v1.12.0 ([#69033](https://github.com/kubernetes/kubernetes/pull/69033), [@feiskyer](https://github.com/feiskyer)) + +### SIG Network + +- Corrected family type (inet6) for ipsets in ipv6-only clusters ([#68436](https://github.com/kubernetes/kubernetes/pull/68436), [@uablrek](https://github.com/uablrek)) +- kube-proxy argument `hostname-override` can be used to override hostname defined in the configuration file ([#69340](https://github.com/kubernetes/kubernetes/pull/69340), [@stevesloka](https://github.com/stevesloka)) +- CoreDNS correctly implements DNS spec for Services with externalNames that look like IP addresses. Kube-dns does not follow the spec for the same case, resulting in a behavior change when moving from Kube-dns to CoreDNS. See: [coredns/coredns#2324](https://github.com/coredns/coredns/issues/2324) +- IPVS proxier now set net/ipv4/vs/conn_reuse_mode to 0 by default, which will highly improve IPVS proxier performance. ([#71114](https://github.com/kubernetes/kubernetes/pull/71114), [@Lion-Wei](https://github.com/Lion-Wei)) +- CoreDNS is now version 1.2.6 ([#70799](https://github.com/kubernetes/kubernetes/pull/70799), [@rajansandeep](https://github.com/rajansandeep)) +- Addon configuration is introduced in the kubeadm config API, while feature flag CoreDNS is now deprecated. ([#70024](https://github.com/kubernetes/kubernetes/pull/70024), [@fabriziopandini](https://github.com/fabriziopandini)) + +### SIG Node + +- Fixed a bug in previous releases where a pod could be placed inside another pod's cgroup when specifying --cgroup-root ([#70678](https://github.com/kubernetes/kubernetes/pull/70678), [@dashpole](https://github.com/dashpole)) +- Optimized calculating stats when only CPU and Memory stats are returned from Kubelet stats/summary http endpoint. ([#68841](https://github.com/kubernetes/kubernetes/pull/68841), [@krzysztof-jastrzebski](https://github.com/krzysztof-jastrzebski)) +- kubelet now supports `log-file` option to write logs directly to a specific file ([#70917](https://github.com/kubernetes/kubernetes/pull/70917), [@dims](https://github.com/dims)) +- Do not detach volume if mount in progress ([#71145](https://github.com/kubernetes/kubernetes/pull/71145), [@gnufied](https://github.com/gnufied)) +- The runtimeHandler field on the RuntimeClass resource now accepts the empty string. ([#69550](https://github.com/kubernetes/kubernetes/pull/69550), [@tallclair](https://github.com/tallclair)) +- kube-apiserver: fixes `procMount` field incorrectly being marked as required in openapi schema ([#69694](https://github.com/kubernetes/kubernetes/pull/69694), [@jessfraz](https://github.com/jessfraz)) + +### SIG OpenStack + +- Fixed cloud-controller-manager crash when using OpenStack provider and PersistentVolume initializing controller ([#70459](https://github.com/kubernetes/kubernetes/pull/70459), [@mvladev](https://github.com/mvladev)) + +### SIG Release + +- Use debian-base instead of busybox as base image for server images ([#70245](https://github.com/kubernetes/kubernetes/pull/70245), [@ixdy](https://github.com/ixdy)) +- Images for cloud-controller-manager, kube-apiserver, kube-controller-manager, and kube-scheduler now contain a minimal /etc/nsswitch.conf and should respect /etc/hosts for lookups ([#69238](https://github.com/kubernetes/kubernetes/pull/69238), [@BenTheElder](https://github.com/BenTheElder)) + +### SIG Scheduling + +- Added metrics for volume scheduling operations ([#59529](https://github.com/kubernetes/kubernetes/pull/59529), [@wackxu](https://github.com/wackxu)) +- Improved memory use and performance when processing large numbers of pods containing tolerations ([#65350](https://github.com/kubernetes/kubernetes/pull/65350), [@liggitt](https://github.com/liggitt)) +- Fixed a bug in the scheduler that could cause the scheduler to go to an infinite loop when all nodes in a zone are removed. ([#69758](https://github.com/kubernetes/kubernetes/pull/69758), [@bsalamat](https://github.com/bsalamat)) +- Clear pod binding cache on bind error to make sure stale pod binding cache will not be used. ([#71212](https://github.com/kubernetes/kubernetes/pull/71212), [@cofyc](https://github.com/cofyc)) +- Fixed a scheduler panic due to internal cache inconsistency ([#71063](https://github.com/kubernetes/kubernetes/pull/71063), [@Huang-Wei](https://github.com/Huang-Wei)) +- Report kube-scheduler unhealthy if leader election is deadlocked. ([#71085](https://github.com/kubernetes/kubernetes/pull/71085), [@bsalamat](https://github.com/bsalamat)) +- Fixed a potential bug that scheduler preempts unnecessary pods. ([#70898](https://github.com/kubernetes/kubernetes/pull/70898), [@Huang-Wei](https://github.com/Huang-Wei)) + +### SIG Storage + +- Fixed CSI volume limits not showing up in node's capacity and allocatable ([#70540](https://github.com/kubernetes/kubernetes/pull/70540), [@gnufied](https://github.com/gnufied)) +- CSI drivers now have access to mountOptions defined on the storage class when attaching volumes. ([#67898](https://github.com/kubernetes/kubernetes/pull/67898), [@bswartz](https://github.com/bswartz)) +- change default azure file mount permission to 0777 ([#69854](https://github.com/kubernetes/kubernetes/pull/69854), [@andyzhangx](https://github.com/andyzhangx)) +- Fixed subpath in containerized kubelet. ([#69565](https://github.com/kubernetes/kubernetes/pull/69565), [@jsafrane](https://github.com/jsafrane)) +- Fixed panic on iSCSI volume tear down. ([#69140](https://github.com/kubernetes/kubernetes/pull/69140), [@jsafrane](https://github.com/jsafrane)) +- CSIPersistentVolume feature, i.e. PersistentVolumes with CSIPersistentVolumeSource, is GA. ([#69929](https://github.com/kubernetes/kubernetes/pull/69929), [@jsafrane](https://github.com/jsafrane)) +- Fixed CSIDriver API object to allow missing fields. ([#69331](https://github.com/kubernetes/kubernetes/pull/69331), [@jsafrane](https://github.com/jsafrane)) +- Flex volume plugins now support expandvolume (to increase underlying volume capacity) and expanfs (resize filesystem) commands that Flex plugin authors can implement to support expanding in use Flex PersistentVolumes ([#67851](https://github.com/kubernetes/kubernetes/pull/67851), [@aniket-s-kulkarni](https://github.com/aniket-s-kulkarni)) +- Enabled AttachVolumeLimit feature ([#69225](https://github.com/kubernetes/kubernetes/pull/69225), [@gnufied](https://github.com/gnufied)) +- The default storage class annotation for the storage addons has been changed to use the GA variant ([#68345](https://github.com/kubernetes/kubernetes/pull/68345), [@smelchior](https://github.com/smelchior)) +- GlusterFS PersistentVolumes sources can now reference endpoints in any namespace using the `spec.glusterfs.endpointsNamespace` field. Ensure all kubelets are upgraded to 1.13+ before using this capability. ([#60195](https://github.com/kubernetes/kubernetes/pull/60195), [@humblec](https://github.com/humblec)) +- Fixed GetVolumeLimits log flushing issue ([#69558](https://github.com/kubernetes/kubernetes/pull/69558), [@andyzhangx](https://github.com/andyzhangx)) +- The `MountPropagation` feature is unconditionally enabled in v1.13, and can no longer be disabled. ([#68230](https://github.com/kubernetes/kubernetes/pull/68230), [@bertinatto](https://github.com/bertinatto)) + +### SIG Windows + +- `kubelet --system-reserved` and `--kube-reserved` are supported now on Windows nodes ([#69960](https://github.com/kubernetes/kubernetes/pull/69960), [@feiskyer](https://github.com/feiskyer)) +- Windows runtime endpoints is now switched to `npipe:////./pipe/dockershim` from `tcp://localhost:3735`. ([#69516](https://github.com/kubernetes/kubernetes/pull/69516), [@feiskyer](https://github.com/feiskyer)) +- Fixed service issues with named targetPort for Windows ([#70076](https://github.com/kubernetes/kubernetes/pull/70076), [@feiskyer](https://github.com/feiskyer)) +- Handle Windows named pipes in host mounts. ([#69484](https://github.com/kubernetes/kubernetes/pull/69484), [@ddebroy](https://github.com/ddebroy)) +- Fixed inconsistency in windows kernel proxy when updating HNS policy. ([#68923](https://github.com/kubernetes/kubernetes/pull/68923), [@delulu](https://github.com/delulu)) + +## External Dependencies + +- Default etcd server is unchanged at v3.2.24 since Kubernetes 1.12. ([#68318](https://github.com/kubernetes/kubernetes/pull/68318)) +- The list of validated docker versions remain unchanged at 1.11.1, 1.12.1, 1.13.1, 17.03, 17.06, 17.09, 18.06 since Kubernetes 1.12. ([#68495](https://github.com/kubernetes/kubernetes/pull/68495)) +- The default Go version was updated to 1.11.2. ([#70665](https://github.com/kubernetes/kubernetes/pull/70665)) +- The minimum supported Go version was updated to 1.11.2 ([#69386](https://github.com/kubernetes/kubernetes/pull/69386)) +- CNI is unchanged at v0.6.0 since Kubernetes 1.10 ([#51250](https://github.com/kubernetes/kubernetes/pull/51250)) +- CSI is updated to 1.0.0. Pre-1.0.0 API support is now deprecated. ([#71020](https://github.com/kubernetes/kubernetes/pull/71020)]) +- The dashboard add-on has been updated to v1.10.0. ([#68450](https://github.com/kubernetes/kubernetes/pull/68450)) +- Heapster remains at v1.6.0-beta, but is now retired in Kubernetes 1.13 ([#67074](https://github.com/kubernetes/kubernetes/pull/67074)) +- Cluster Autoscaler has been upgraded to v1.13.0 ([#71513](https://github.com/kubernetes/kubernetes/pull/71513)) +- kube-dns is unchanged at v1.14.13 since Kubernetes 1.12 ([#68900](https://github.com/kubernetes/kubernetes/pull/68900)) +- Influxdb is unchanged at v1.3.3 since Kubernetes 1.10 ([#53319](https://github.com/kubernetes/kubernetes/pull/53319)) +- Grafana is unchanged at v4.4.3 since Kubernetes 1.10 ([#53319](https://github.com/kubernetes/kubernetes/pull/53319)) +- Kibana has been upgraded to v6.3.2. ([#67582](https://github.com/kubernetes/kubernetes/pull/67582)) +- CAdvisor has been updated to v0.32.0 ([#70964](https://github.com/kubernetes/kubernetes/pull/70964)) +- fluentd-gcp-scaler has been updated to v0.5.0 ([#68837](https://github.com/kubernetes/kubernetes/pull/68837)) +- Fluentd in fluentd-elasticsearch is unchanged at v1.2.4 since Kubernetes 1.11 ([#67434](https://github.com/kubernetes/kubernetes/pull/67434)) +- fluentd-elasticsearch has been updated to v2.2.1 ([#68012](https://github.com/kubernetes/kubernetes/pull/68012)) +- The fluent-plugin-kubernetes_metadata_filter plugin in fluentd-elasticsearch is unchanged at 2.0.0 since Kubernetes 1.12 ([#67544](https://github.com/kubernetes/kubernetes/pull/67544)) +- fluentd-gcp has been updated to v3.2.0 ([#70954](https://github.com/kubernetes/kubernetes/pull/70954)) +- OIDC authentication is unchanged at coreos/go-oidc v2 since Kubernetes 1.10 ([#58544](https://github.com/kubernetes/kubernetes/pull/58544)) +- Calico was updated to v3.3.1 ([#70932](https://github.com/kubernetes/kubernetes/pull/70932)) +- Upgraded crictl on GCE to v1.12.0 ([#69033](https://github.com/kubernetes/kubernetes/pull/69033)) +- CoreDNS has been updated to v1.2.6 ([#70799](https://github.com/kubernetes/kubernetes/pull/70799)) +- event-exporter has been updated to v0.2.3 ([#67691](https://github.com/kubernetes/kubernetes/pull/67691)) +- Es-image remains unchanged at Elasticsearch 6.3.2 since Kubernetes 1.12 ([#67484](https://github.com/kubernetes/kubernetes/pull/67484)) +- metrics-server remains unchanged at v0.3.1 since Kubernetes 1.12 ([#68746](https://github.com/kubernetes/kubernetes/pull/68746)) +- GLBC remains unchanged at v1.2.3 since Kubernetes 1.12 ([#66793](https://github.com/kubernetes/kubernetes/pull/66793)) +- Ingress-gce remains unchanged at v1.2.3 since Kubernetes 1.12 ([#66793](https://github.com/kubernetes/kubernetes/pull/66793)) +- ip-masq-agen remains unchanged at v2.1.1 since Kubernetes 1.12 ([#67916](https://github.com/kubernetes/kubernetes/pull/67916)) + +# v1.13.0-rc.2 + +[Documentation](https://docs.k8s.io) + +## Downloads for v1.13.0-rc.2 + + +filename | sha512 hash +-------- | ----------- +[kubernetes.tar.gz](https://dl.k8s.io/v1.13.0-rc.2/kubernetes.tar.gz) | `12fbaf943ae72711cd93c9955719ec1773a229dbb8f86a44fcda179229beb82add4dc1a54ceb50b9f48fde48e2464ed0cd4b2e57d9689a7ae784cb052beb6751` +[kubernetes-src.tar.gz](https://dl.k8s.io/v1.13.0-rc.2/kubernetes-src.tar.gz) | `8e94f0fe73909610e85c201bb1ba4f66fd55ca2b4ded77217a4dfad2874d402cc1cc94203ecc195f909126c186701e5e1e62890ad288895493a1759f88a190d0` + +### Client Binaries + +filename | sha512 hash +-------- | ----------- +[kubernetes-client-darwin-386.tar.gz](https://dl.k8s.io/v1.13.0-rc.2/kubernetes-client-darwin-386.tar.gz) | `ac555f5d1e6b88fa4de1e06e0a1ebd372582f97c526c938334a8c63fbf17545607efbba9975d1767e147113e551e986d6523f6985ea41236cfbf7949df31f016` +[kubernetes-client-darwin-amd64.tar.gz](https://dl.k8s.io/v1.13.0-rc.2/kubernetes-client-darwin-amd64.tar.gz) | `2eae428a0e4bcb2237343d7ac1e431ccfc1f7037622bb3131ad8d48a3af6f5ed34be899ec1ec32af7eb7d411cb0cda02a2413405479722ab868cdc816726c9df` +[kubernetes-client-linux-386.tar.gz](https://dl.k8s.io/v1.13.0-rc.2/kubernetes-client-linux-386.tar.gz) | `89e671679b4516f184f7fd5ea0fe2a9ab0245fab34447625786bf55841223124527d3aa2ee6fa2474333f37eea4e9a5ba6f3f4dc3698907fd24bedf522f53b40` +[kubernetes-client-linux-amd64.tar.gz](https://dl.k8s.io/v1.13.0-rc.2/kubernetes-client-linux-amd64.tar.gz) | `61f6513722e9c485300b822d6fc5998927bbffa18862d2d3f177a7c7cc0ee56c51ec169e3c8239e352c022094bb02124ed060d7d5c3cec9b67aae20ffd42f387` +[kubernetes-client-linux-arm.tar.gz](https://dl.k8s.io/v1.13.0-rc.2/kubernetes-client-linux-arm.tar.gz) | `ef0e5fd4bf2074dfd3cf54d45307550273695906baca3533a9d23424e7b693d706f6d1d3a09a34e2d1f84d9eddc6b62d96e5190b8c7145919e93f0ae75ec4d06` +[kubernetes-client-linux-arm64.tar.gz](https://dl.k8s.io/v1.13.0-rc.2/kubernetes-client-linux-arm64.tar.gz) | `d34bb9ce9bfe2a5375fd58920e63b4eef818348719dba460f35838433af57a1a23fa659e53de52c8174fa212c94c4196ac5a02ce02ef714860488c77563b5821` +[kubernetes-client-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.13.0-rc.2/kubernetes-client-linux-ppc64le.tar.gz) | `4dc4e4a5e166e63360ba86e1278bbe75212ac7c3f60ba30425a1c5654bf5a9b1164543fdc23d7dfd9d3aea7be38544c8dc535459e96c062db631e58c5c628762` +[kubernetes-client-linux-s390x.tar.gz](https://dl.k8s.io/v1.13.0-rc.2/kubernetes-client-linux-s390x.tar.gz) | `d27675f4753469cd5e31faed13a1ea9654c25d38b0d96c1340215fd231050ffc66dc40c5103f8377339bacf00f1c99d386fe9c21fc68c5a21c10667f773d9d4b` +[kubernetes-client-windows-386.tar.gz](https://dl.k8s.io/v1.13.0-rc.2/kubernetes-client-windows-386.tar.gz) | `9d6e6de2d4a55eaeebd7fa6b861548e0768381d50838430722b56636428a3417b8f2bbc953bc365294a857d8f5b51d90807e5eafe874f37d9b726f48b5d04197` +[kubernetes-client-windows-amd64.tar.gz](https://dl.k8s.io/v1.13.0-rc.2/kubernetes-client-windows-amd64.tar.gz) | `30b2da5c015ef88b9efcf90bffe0498d367df7c126b65f2e878af263c5d62b8c93792dbf20511d0ff034c7a9e2c3fc93931860e1254ed158eddec34f407b9005` + +### Server Binaries + +filename | sha512 hash +-------- | ----------- +[kubernetes-server-linux-amd64.tar.gz](https://dl.k8s.io/v1.13.0-rc.2/kubernetes-server-linux-amd64.tar.gz) | `8180f2b788249fe65f7f1d3ee431ac758ede29a6349db312afbee080ff2c24586fc468f11a9cbcb8d22842739974f29e10793778f5fd5c55d10129e97a1efce3` +[kubernetes-server-linux-arm.tar.gz](https://dl.k8s.io/v1.13.0-rc.2/kubernetes-server-linux-arm.tar.gz) | `e9165284a0b82a9ab88dad05f43bfe1bebecad3bb1c7118475c3426e0b6f9f91d340e1e6223d81df9337ab4cc9a96708443c025030127acf88437f0c327b750b` +[kubernetes-server-linux-arm64.tar.gz](https://dl.k8s.io/v1.13.0-rc.2/kubernetes-server-linux-arm64.tar.gz) | `03797c021ebed3b08835e72eed405c57aaacce972bbbbf88bf49310efbf8c7242f2f223d73b5d2ed4c21e5196e6e5fb7b2b811f08607db6dbe98f869bf28bedb` +[kubernetes-server-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.13.0-rc.2/kubernetes-server-linux-ppc64le.tar.gz) | `ceb49af22e3b518f3ba27c1e7de28e577e2735175e84a6d203f1f8766eceaa7c0424746ff71498d7847e98f538af5663b16cc306cb0adbb006d5d869766dfb9b` +[kubernetes-server-linux-s390x.tar.gz](https://dl.k8s.io/v1.13.0-rc.2/kubernetes-server-linux-s390x.tar.gz) | `bee4752e8a52e217ae1ffcfbc263453c724de684b4d463d5ddb24a3a30a67fc8f78e6c0a8154c6b6581d17f1e168903bc18d0e56f02fce5933f673bb4c74a8cf` + +### Node Binaries + +filename | sha512 hash +-------- | ----------- +[kubernetes-node-linux-amd64.tar.gz](https://dl.k8s.io/v1.13.0-rc.2/kubernetes-node-linux-amd64.tar.gz) | `b368989bbb8ab4d29b51d5d4d71d073b0ceb39614c944859dcd14c3303c31475850f7012deaa8d5ba9c17edd728bce536fbd523ae7defc74a30f0878f05497bf` +[kubernetes-node-linux-arm.tar.gz](https://dl.k8s.io/v1.13.0-rc.2/kubernetes-node-linux-arm.tar.gz) | `404b7b74a1e0d0fed9088a7e9461e02cfd9a6992c554baa125b7a361a6baa03d1e4622fbc4ec51836f00a7ac4f90167f345307678527f5781e06acdf526b9a45` +[kubernetes-node-linux-arm64.tar.gz](https://dl.k8s.io/v1.13.0-rc.2/kubernetes-node-linux-arm64.tar.gz) | `fa531b1675a778c572a2175fb1bed00e78dc589f638f2096b3b5c9d3d691a5668787a43d69898678abd70c7b949e05cfebfb0783c0144a66bdff61fed6094582` +[kubernetes-node-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.13.0-rc.2/kubernetes-node-linux-ppc64le.tar.gz) | `a7ecc1f63e632c1b4f9b312babd6882ec966420bf4f8346edf80495fcf860d912729072c79d23cc071a07239783409b02c1f4a716a24e2597f2b490c9b3bb5b3` +[kubernetes-node-linux-s390x.tar.gz](https://dl.k8s.io/v1.13.0-rc.2/kubernetes-node-linux-s390x.tar.gz) | `a7171ed95de943a0ac5a32da4458e8d4366eb1fadbe426bebc371d2bb6536636b14db9d2cd03952258b3cb1b99fdca2db07947b028cc6c7bb92f4281ba6f62f2` +[kubernetes-node-windows-amd64.tar.gz](https://dl.k8s.io/v1.13.0-rc.2/kubernetes-node-windows-amd64.tar.gz) | `8a3a71d142b99fb200c4c1c9c0fa4dc6a3b64a0b506dc37dc3d832a94a791619a09ae4b2c6f73802f6833234570633974547f7700c8bb6de71d91ba2c4ac4b54` + +## Changelog since v1.13.0-rc.1 + +### Other notable changes + +* Update Cluster Autoscaler version to 1.13.0. Release notes: https://github.com/kubernetes/autoscaler/releases/tag/cluster-autoscaler-1.13.0 ([#71513](https://github.com/kubernetes/kubernetes/pull/71513), [@losipiuk](https://github.com/losipiuk)) +* fix detach azure disk issue due to dirty cache ([#71495](https://github.com/kubernetes/kubernetes/pull/71495), [@andyzhangx](https://github.com/andyzhangx)) + + + # v1.13.0-rc.1 [Documentation](https://docs.k8s.io) @@ -100,9 +804,8 @@ filename | sha512 hash ### Other notable changes +* CVE-2018-1002105: Fix critical security issue in kube-apiserver upgrade request proxy handler ([#71411](https://github.com/kubernetes/kubernetes/issues/71411), [@liggitt](https://github.com/liggitt)) * Update Cluster Autoscaler version to 1.13.0-rc.2. Release notes: https://github.com/kubernetes/autoscaler/releases/tag/cluster-autoscaler-1.13.0-rc.2 ([#71452](https://github.com/kubernetes/kubernetes/pull/71452), [@losipiuk](https://github.com/losipiuk)) -* Fixes an issue with stuck connections handling error responses ([#71419](https://github.com/kubernetes/kubernetes/pull/71419), [@liggitt](https://github.com/liggitt)) -* Fixes an issue with stuck connections handling error responses ([#71412](https://github.com/kubernetes/kubernetes/pull/71412), [@liggitt](https://github.com/liggitt)) * Upgrade Stackdriver Logging Agent addon image to 0.6-1.6.0-1 to use Fluentd v1.2. This provides nanoseconds timestamp granularity for logs. ([#70954](https://github.com/kubernetes/kubernetes/pull/70954), [@qingling128](https://github.com/qingling128)) * fixes a runtime error occuring when sorting the output of `kubectl get` with empty results ([#70740](https://github.com/kubernetes/kubernetes/pull/70740), [@mfpierre](https://github.com/mfpierre)) * fix azure disk attach/detach failed forever issue ([#71377](https://github.com/kubernetes/kubernetes/pull/71377), [@andyzhangx](https://github.com/andyzhangx)) diff --git a/CHANGELOG-1.4.md b/CHANGELOG-1.4.md index ada428ec673..e5f0b08e712 100644 --- a/CHANGELOG-1.4.md +++ b/CHANGELOG-1.4.md @@ -753,18 +753,18 @@ binary | sha256 hash This is the first release tracked via the use of the [kubernetes/features](https://github.com/kubernetes/features) issues repo. Each Feature issue is owned by a Special Interest Group from [kubernetes/community](https://github.com/kubernetes/community) - **API Machinery** - - [alpha] Generate audit logs for every request user performs against secured API server endpoint. ([docs](http://kubernetes.io/docs/admin/audit/)) ([kubernetes/features#22](https://github.com/kubernetes/features/issues/22)) - - [beta] `kube-apiserver` now publishes a swagger 2.0 spec in addition to a swagger 1.2 spec ([kubernetes/features#53](https://github.com/kubernetes/features/issues/53)) + - [alpha] Generate audit logs for every request user performs against secured API server endpoint. ([docs](http://kubernetes.io/docs/admin/audit/)) ([kubernetes/features#22](https://github.com/kubernetes/enhancements/issues/22)) + - [beta] `kube-apiserver` now publishes a swagger 2.0 spec in addition to a swagger 1.2 spec ([kubernetes/features#53](https://github.com/kubernetes/enhancements/issues/53)) - [beta] Server-side garbage collection is enabled by default. See [user-guide](http://kubernetes.io/docs/user-guide/garbage-collection/) - **Apps** - - [alpha] Introducing 'ScheduledJobs', which allow running time based Jobs, namely once at a specified time or repeatedly at specified point in time. ([docs](http://kubernetes.io/docs/user-guide/scheduled-jobs/)) ([kubernetes/features#19](https://github.com/kubernetes/features/issues/19)) + - [alpha] Introducing 'ScheduledJobs', which allow running time based Jobs, namely once at a specified time or repeatedly at specified point in time. ([docs](http://kubernetes.io/docs/user-guide/scheduled-jobs/)) ([kubernetes/features#19](https://github.com/kubernetes/enhancements/issues/19)) - **Auth** - - [alpha] Container Image Policy allows an access controller to determine whether a pod may be scheduled based on a policy ([docs](http://kubernetes.io/docs/admin/admission-controllers/#imagepolicywebhook)) ([kubernetes/features#59](https://github.com/kubernetes/features/issues/59)) - - [alpha] Access Review APIs expose authorization engine to external inquiries for delegation, inspection, and debugging ([docs](http://kubernetes.io/docs/admin/authorization/)) ([kubernetes/features#37](https://github.com/kubernetes/features/issues/37)) + - [alpha] Container Image Policy allows an access controller to determine whether a pod may be scheduled based on a policy ([docs](http://kubernetes.io/docs/admin/admission-controllers/#imagepolicywebhook)) ([kubernetes/features#59](https://github.com/kubernetes/enhancements/issues/59)) + - [alpha] Access Review APIs expose authorization engine to external inquiries for delegation, inspection, and debugging ([docs](http://kubernetes.io/docs/admin/authorization/)) ([kubernetes/features#37](https://github.com/kubernetes/enhancements/issues/37)) - **Cluster Lifecycle** - - [alpha] Ensure critical cluster infrastructure pods (Heapster, DNS, etc.) can schedule by evicting regular pods when necessary to make the critical pods schedule. ([docs](http://kubernetes.io/docs/admin/rescheduler/#guaranteed-scheduling-of-critical-add-on-pods)) ([kubernetes/features#62](https://github.com/kubernetes/features/issues/62)) - - [alpha] Simplifies bootstrapping of TLS secured communication between the API server and kubelet. ([docs](http://kubernetes.io/docs/admin/master-node-communication/#kubelet-tls-bootstrap)) ([kubernetes/features#43](https://github.com/kubernetes/features/issues/43)) - - [alpha] The `kubeadm` tool makes it much easier to bootstrap Kubernetes. ([docs](http://kubernetes.io/docs/getting-started-guides/kubeadm/)) ([kubernetes/features#11](https://github.com/kubernetes/features/issues/11)) + - [alpha] Ensure critical cluster infrastructure pods (Heapster, DNS, etc.) can schedule by evicting regular pods when necessary to make the critical pods schedule. ([docs](http://kubernetes.io/docs/admin/rescheduler/#guaranteed-scheduling-of-critical-add-on-pods)) ([kubernetes/features#62](https://github.com/kubernetes/enhancements/issues/62)) + - [alpha] Simplifies bootstrapping of TLS secured communication between the API server and kubelet. ([docs](http://kubernetes.io/docs/admin/master-node-communication/#kubelet-tls-bootstrap)) ([kubernetes/features#43](https://github.com/kubernetes/enhancements/issues/43)) + - [alpha] The `kubeadm` tool makes it much easier to bootstrap Kubernetes. ([docs](http://kubernetes.io/docs/getting-started-guides/kubeadm/)) ([kubernetes/features#11](https://github.com/kubernetes/enhancements/issues/11)) - **Federation** - [alpha] Creating a `Federated Ingress` is as simple as submitting an `Ingress` creation request to the Federation API Server. The @@ -774,41 +774,41 @@ This is the first release tracked via the use of the [kubernetes/features](https GCE L7 LoadBalancer is the first supported implementation, and is available in this release. ([docs](http://kubernetes.io/docs/user-guide/federation/federated-ingress.md)) - ([kubernetes/features#82](https://github.com/kubernetes/features/issues/82)) + ([kubernetes/features#82](https://github.com/kubernetes/enhancements/issues/82)) - [beta] `Federated Replica Sets` create and maintain matching `Replica Set`s in some or all clusters in a federation, with the desired replica count distributed equally or according to specified per-cluster weights. ([docs](http://kubernetes.io/docs/user-guide/federation/federated-replicasets.md)) - ([kubernetes/features#46](https://github.com/kubernetes/features/issues/46)) + ([kubernetes/features#46](https://github.com/kubernetes/enhancements/issues/46)) - [beta] `Federated Secrets` are created and kept consistent across all clusters in a federation. ([docs](http://kubernetes.io/docs/user-guide/federation/federated-secrets.md)) - ([kubernetes/features#68](https://github.com/kubernetes/features/issues/68)) + ([kubernetes/features#68](https://github.com/kubernetes/enhancements/issues/68)) - [beta] Federation API server gained support for events and many federation controllers now report important events. ([docs](http://kubernetes.io/docs/user-guide/federation/events)) - ([kubernetes/features#70](https://github.com/kubernetes/features/issues/70)) + ([kubernetes/features#70](https://github.com/kubernetes/enhancements/issues/70)) - [alpha] Creating a `Federated Namespace` causes matching - `Namespace`s to be created and maintained in all the clusters registered with that federation. ([docs](http://kubernetes.io/docs/user-guide/federation/federated-namespaces.md)) ([kubernetes/features#69](https://github.com/kubernetes/features/issues/69)) - - [alpha] ingress has alpha support for a single master multi zone cluster ([docs](http://kubernetes.io/docs/user-guide/ingress.md#failing-across-availability-zones)) ([kubernetes/features#52](https://github.com/kubernetes/features/issues/52)) + `Namespace`s to be created and maintained in all the clusters registered with that federation. ([docs](http://kubernetes.io/docs/user-guide/federation/federated-namespaces.md)) ([kubernetes/features#69](https://github.com/kubernetes/enhancements/issues/69)) + - [alpha] ingress has alpha support for a single master multi zone cluster ([docs](http://kubernetes.io/docs/user-guide/ingress.md#failing-across-availability-zones)) ([kubernetes/features#52](https://github.com/kubernetes/enhancements/issues/52)) - **Network** - - [alpha] Service LB now has alpha support for preserving client source IP ([docs](http://kubernetes.io/docs/user-guide/load-balancer/)) ([kubernetes/features#27](https://github.com/kubernetes/features/issues/27)) + - [alpha] Service LB now has alpha support for preserving client source IP ([docs](http://kubernetes.io/docs/user-guide/load-balancer/)) ([kubernetes/features#27](https://github.com/kubernetes/enhancements/issues/27)) - **Node** - - [alpha] Publish node performance dashboard at http://node-perf-dash.k8s.io/#/builds ([docs](https://github.com/kubernetes/contrib/blob/master/node-perf-dash/README.md)) ([kubernetes/features#83](https://github.com/kubernetes/features/issues/83)) - - [alpha] Pods now have alpha support for setting whitelisted, safe sysctls. Unsafe sysctls can be whitelisted on the kubelet. ([docs](http://kubernetes.io/docs/admin/sysctls/)) ([kubernetes/features#34](https://github.com/kubernetes/features/issues/34)) - - [beta] AppArmor profiles can be specified & applied to pod containers ([docs](http://kubernetes.io/docs/admin/apparmor/)) ([kubernetes/features#24](https://github.com/kubernetes/features/issues/24)) - - [beta] Cluster policy to control access and defaults of security related features ([docs](http://kubernetes.io/docs/user-guide/pod-security-policy/)) ([kubernetes/features#5](https://github.com/kubernetes/features/issues/5)) - - [stable] kubelet is able to evict pods when it observes disk pressure ([docs](http://kubernetes.io/docs/admin/out-of-resource/)) ([kubernetes/features#39](https://github.com/kubernetes/features/issues/39)) - - [stable] Automated docker validation results posted to https://k8s-testgrid.appspot.com/docker [kubernetes/features#57](https://github.com/kubernetes/features/issues/57) + - [alpha] Publish node performance dashboard at http://node-perf-dash.k8s.io/#/builds ([docs](https://github.com/kubernetes/contrib/blob/master/node-perf-dash/README.md)) ([kubernetes/features#83](https://github.com/kubernetes/enhancements/issues/83)) + - [alpha] Pods now have alpha support for setting whitelisted, safe sysctls. Unsafe sysctls can be whitelisted on the kubelet. ([docs](http://kubernetes.io/docs/admin/sysctls/)) ([kubernetes/features#34](https://github.com/kubernetes/enhancements/issues/34)) + - [beta] AppArmor profiles can be specified & applied to pod containers ([docs](http://kubernetes.io/docs/admin/apparmor/)) ([kubernetes/features#24](https://github.com/kubernetes/enhancements/issues/24)) + - [beta] Cluster policy to control access and defaults of security related features ([docs](http://kubernetes.io/docs/user-guide/pod-security-policy/)) ([kubernetes/features#5](https://github.com/kubernetes/enhancements/issues/5)) + - [stable] kubelet is able to evict pods when it observes disk pressure ([docs](http://kubernetes.io/docs/admin/out-of-resource/)) ([kubernetes/features#39](https://github.com/kubernetes/enhancements/issues/39)) + - [stable] Automated docker validation results posted to https://k8s-testgrid.appspot.com/docker [kubernetes/features#57](https://github.com/kubernetes/enhancements/issues/57) - **Scheduling** - - [alpha] Allows pods to require or prohibit (or prefer or prefer not) co-scheduling on the same node (or zone or other topology domain) as another set of pods. ([docs](http://kubernetes.io/docs/user-guide/node-selection/) ([kubernetes/features#51](https://github.com/kubernetes/features/issues/51)) + - [alpha] Allows pods to require or prohibit (or prefer or prefer not) co-scheduling on the same node (or zone or other topology domain) as another set of pods. ([docs](http://kubernetes.io/docs/user-guide/node-selection/) ([kubernetes/features#51](https://github.com/kubernetes/enhancements/issues/51)) - **Storage** - - [beta] Persistent Volume provisioning now supports multiple provisioners using StorageClass configuration. ([docs](http://kubernetes.io/docs/user-guide/persistent-volumes/)) ([kubernetes/features#36](https://github.com/kubernetes/features/issues/36)) - - [stable] New volume plugin for the Quobyte Distributed File System ([docs](http://kubernetes.io/docs/user-guide/volumes/#quobyte)) ([kubernetes/features#80](https://github.com/kubernetes/features/issues/80)) - - [stable] New volume plugin for Azure Data Disk ([docs](http://kubernetes.io/docs/user-guide/volumes/#azurediskvolume)) ([kubernetes/features#79](https://github.com/kubernetes/features/issues/79)) + - [beta] Persistent Volume provisioning now supports multiple provisioners using StorageClass configuration. ([docs](http://kubernetes.io/docs/user-guide/persistent-volumes/)) ([kubernetes/features#36](https://github.com/kubernetes/enhancements/issues/36)) + - [stable] New volume plugin for the Quobyte Distributed File System ([docs](http://kubernetes.io/docs/user-guide/volumes/#quobyte)) ([kubernetes/features#80](https://github.com/kubernetes/enhancements/issues/80)) + - [stable] New volume plugin for Azure Data Disk ([docs](http://kubernetes.io/docs/user-guide/volumes/#azurediskvolume)) ([kubernetes/features#79](https://github.com/kubernetes/enhancements/issues/79)) - **UI** - [stable] Kubernetes Dashboard UI - a great looking Kubernetes Dashboard UI with 90% CLI parity for at-a-glance management. [docs](https://github.com/kubernetes/dashboard) - - [stable] `kubectl` no longer applies defaults before sending objects to the server in create and update requests, allowing the server to apply the defaults. ([kubernetes/features#55](https://github.com/kubernetes/features/issues/55)) + - [stable] `kubectl` no longer applies defaults before sending objects to the server in create and update requests, allowing the server to apply the defaults. ([kubernetes/features#55](https://github.com/kubernetes/enhancements/issues/55)) ## Known Issues diff --git a/CHANGELOG-1.5.md b/CHANGELOG-1.5.md index 99fb9576dcd..30b72d095aa 100644 --- a/CHANGELOG-1.5.md +++ b/CHANGELOG-1.5.md @@ -624,45 +624,45 @@ filename | sha256 hash Features for this release were tracked via the use of the [kubernetes/features](https://github.com/kubernetes/features) issues repo. Each Feature issue is owned by a Special Interest Group from [kubernetes/community](https://github.com/kubernetes/community) - **API Machinery** - - [beta] `kube-apiserver` support for the OpenAPI spec is moving from alpha to beta. The first [non-go client](https://github.com/kubernetes-incubator/client-python) is based on it ([kubernetes/features#53](https://github.com/kubernetes/features/issues/53)) + - [beta] `kube-apiserver` support for the OpenAPI spec is moving from alpha to beta. The first [non-go client](https://github.com/kubernetes-incubator/client-python) is based on it ([kubernetes/features#53](https://github.com/kubernetes/enhancements/issues/53)) - **Apps** - - [stable] When replica sets cannot create pods, they will now report detail via the API about the underlying reason ([kubernetes/features#120](https://github.com/kubernetes/features/issues/120)) - - [stable] `kubectl apply` is now able to delete resources you no longer need with `--prune` ([kubernetes/features#128](https://github.com/kubernetes/features/issues/128)) - - [beta] Deployments that cannot make progress in rolling out the newest version will now indicate via the API they are blocked ([docs](http://kubernetes.io/docs/user-guide/deployments/#failed-deployment)) ([kubernetes/features#122](https://github.com/kubernetes/features/issues/122)) - - [beta] StatefulSets allow workloads that require persistent identity or per-instance storage to be created and managed on Kubernetes. ([docs](http://kubernetes.io/docs/concepts/abstractions/controllers/statefulsets/)) ([kubernetes/features#137](https://github.com/kubernetes/features/issues/137)) - - [beta] In order to preserve safety guarantees the cluster no longer force deletes pods on un-responsive nodes and users are now warned if they try to force delete pods via the CLI. ([docs](http://kubernetes.io/docs/tasks/manage-stateful-set/scale-stateful-set/)) ([kubernetes/features#119](https://github.com/kubernetes/features/issues/119)) + - [stable] When replica sets cannot create pods, they will now report detail via the API about the underlying reason ([kubernetes/features#120](https://github.com/kubernetes/enhancements/issues/120)) + - [stable] `kubectl apply` is now able to delete resources you no longer need with `--prune` ([kubernetes/features#128](https://github.com/kubernetes/enhancements/issues/128)) + - [beta] Deployments that cannot make progress in rolling out the newest version will now indicate via the API they are blocked ([docs](http://kubernetes.io/docs/user-guide/deployments/#failed-deployment)) ([kubernetes/features#122](https://github.com/kubernetes/enhancements/issues/122)) + - [beta] StatefulSets allow workloads that require persistent identity or per-instance storage to be created and managed on Kubernetes. ([docs](http://kubernetes.io/docs/concepts/abstractions/controllers/statefulsets/)) ([kubernetes/features#137](https://github.com/kubernetes/enhancements/issues/137)) + - [beta] In order to preserve safety guarantees the cluster no longer force deletes pods on un-responsive nodes and users are now warned if they try to force delete pods via the CLI. ([docs](http://kubernetes.io/docs/tasks/manage-stateful-set/scale-stateful-set/)) ([kubernetes/features#119](https://github.com/kubernetes/enhancements/issues/119)) - **Auth** - - [alpha] Further polishing of the Role-based access control alpha API including a default set of cluster roles. ([docs](http://kubernetes.io/docs/admin/authorization/)) ([kubernetes/features#2](https://github.com/kubernetes/features/issues/2)) - - [beta] Added ability to authenticate/authorize access to the Kubelet API ([docs](http://kubernetes.io/docs/admin/kubelet-authentication-authorization/)) ([kubernetes/features#89](https://github.com/kubernetes/features/issues/89)) + - [alpha] Further polishing of the Role-based access control alpha API including a default set of cluster roles. ([docs](http://kubernetes.io/docs/admin/authorization/)) ([kubernetes/features#2](https://github.com/kubernetes/enhancements/issues/2)) + - [beta] Added ability to authenticate/authorize access to the Kubelet API ([docs](http://kubernetes.io/docs/admin/kubelet-authentication-authorization/)) ([kubernetes/features#89](https://github.com/kubernetes/enhancements/issues/89)) - **AWS** - - [stable] Roles should appear in kubectl get nodes ([kubernetes/features#113](https://github.com/kubernetes/features/issues/113)) + - [stable] Roles should appear in kubectl get nodes ([kubernetes/features#113](https://github.com/kubernetes/enhancements/issues/113)) - **Cluster Lifecycle** - - [alpha] Improved UX and usability for the kubeadm binary that makes it easy to get a new cluster running. ([docs](http://kubernetes.io/docs/getting-started-guides/kubeadm/)) ([changelog](https://github.com/kubernetes/kubeadm/blob/master/CHANGELOG.md)) ([kubernetes/features#11](https://github.com/kubernetes/features/issues/11)) + - [alpha] Improved UX and usability for the kubeadm binary that makes it easy to get a new cluster running. ([docs](http://kubernetes.io/docs/getting-started-guides/kubeadm/)) ([changelog](https://github.com/kubernetes/kubeadm/blob/master/CHANGELOG.md)) ([kubernetes/features#11](https://github.com/kubernetes/enhancements/issues/11)) - **Cluster Ops** - - [alpha] Added ability to create/remove clusters w/highly available (replicated) masters on GCE using kube-up/kube-down scripts. ([docs](http://kubernetes.io/docs/admin/ha-master-gce/)) ([kubernetes/features#48](https://github.com/kubernetes/features/issues/48)) + - [alpha] Added ability to create/remove clusters w/highly available (replicated) masters on GCE using kube-up/kube-down scripts. ([docs](http://kubernetes.io/docs/admin/ha-master-gce/)) ([kubernetes/features#48](https://github.com/kubernetes/enhancements/issues/48)) - **Federation** - - [alpha] Support for ConfigMaps in federation. ([docs](http://kubernetes.io/docs/user-guide/federation/configmap/)) ([kubernetes/features#105](https://github.com/kubernetes/features/issues/105)) - - [alpha] Alpha level support for DaemonSets in federation. ([docs](http://kubernetes.io/docs/user-guide/federation/daemonsets/)) ([kubernetes/features#101](https://github.com/kubernetes/features/issues/101)) - - [alpha] Alpha level support for Deployments in federation. ([docs](http://kubernetes.io/docs/user-guide/federation/deployment/)) ([kubernetes/features#100](https://github.com/kubernetes/features/issues/100)) - - [alpha] Cluster federation: Added support for DeleteOptions.OrphanDependents for federation resources. ([docs](http://kubernetes.io/docs/user-guide/federation/#cascading-deletion)) ([kubernetes/features#99](https://github.com/kubernetes/features/issues/99)) - - [alpha] Introducing `kubefed`, a new command line tool to simplify federation control plane. ([docs](http://kubernetes.io/docs/admin/federation/kubefed/)) ([kubernetes/features#97](https://github.com/kubernetes/features/issues/97)) + - [alpha] Support for ConfigMaps in federation. ([docs](http://kubernetes.io/docs/user-guide/federation/configmap/)) ([kubernetes/features#105](https://github.com/kubernetes/enhancements/issues/105)) + - [alpha] Alpha level support for DaemonSets in federation. ([docs](http://kubernetes.io/docs/user-guide/federation/daemonsets/)) ([kubernetes/features#101](https://github.com/kubernetes/enhancements/issues/101)) + - [alpha] Alpha level support for Deployments in federation. ([docs](http://kubernetes.io/docs/user-guide/federation/deployment/)) ([kubernetes/features#100](https://github.com/kubernetes/enhancements/issues/100)) + - [alpha] Cluster federation: Added support for DeleteOptions.OrphanDependents for federation resources. ([docs](http://kubernetes.io/docs/user-guide/federation/#cascading-deletion)) ([kubernetes/features#99](https://github.com/kubernetes/enhancements/issues/99)) + - [alpha] Introducing `kubefed`, a new command line tool to simplify federation control plane. ([docs](http://kubernetes.io/docs/admin/federation/kubefed/)) ([kubernetes/features#97](https://github.com/kubernetes/enhancements/issues/97)) - **Network** - - [stable] Services can reference another service by DNS name, rather than being hosted in pods ([kubernetes/features#33](https://github.com/kubernetes/features/issues/33)) - - [beta] Opt in source ip preservation for Services with Type NodePort or LoadBalancer ([docs](http://kubernetes.io/docs/tutorials/services/source-ip/)) ([kubernetes/features#27](https://github.com/kubernetes/features/issues/27)) + - [stable] Services can reference another service by DNS name, rather than being hosted in pods ([kubernetes/features#33](https://github.com/kubernetes/enhancements/issues/33)) + - [beta] Opt in source ip preservation for Services with Type NodePort or LoadBalancer ([docs](http://kubernetes.io/docs/tutorials/services/source-ip/)) ([kubernetes/features#27](https://github.com/kubernetes/enhancements/issues/27)) - [stable] Enable DNS Horizontal Autoscaling with beta ConfigMap parameters support ([docs](http://kubernetes.io/docs/tasks/administer-cluster/dns-horizontal-autoscaling/)) - **Node** - - [alpha] Added ability to preserve access to host userns when userns remapping is enabled in container runtime ([kubernetes/features#127](https://github.com/kubernetes/features/issues/127)) - - [alpha] Introducing the v1alpha1 CRI API to allow pluggable container runtimes; an experimental docker-CRI integration is ready for testing and feedback. ([docs](https://github.com/kubernetes/community/blob/master/contributors/devel/container-runtime-interface.md)) ([kubernetes/features#54](https://github.com/kubernetes/features/issues/54)) - - [alpha] Kubelet launches container in a per pod cgroup hierarchy based on quality of service tier ([kubernetes/features#126](https://github.com/kubernetes/features/issues/126)) - - [beta] Kubelet integrates with memcg notification API to detect when a hard eviction threshold is crossed ([kubernetes/features#125](https://github.com/kubernetes/features/issues/125)) - - [beta] Introducing the beta version containerized node conformance test gcr.io/google_containers/node-test:0.2 for users to verify node setup. ([docs](http://kubernetes.io/docs/admin/node-conformance/)) ([kubernetes/features#84](https://github.com/kubernetes/features/issues/84)) + - [alpha] Added ability to preserve access to host userns when userns remapping is enabled in container runtime ([kubernetes/features#127](https://github.com/kubernetes/enhancements/issues/127)) + - [alpha] Introducing the v1alpha1 CRI API to allow pluggable container runtimes; an experimental docker-CRI integration is ready for testing and feedback. ([docs](https://github.com/kubernetes/community/blob/master/contributors/devel/container-runtime-interface.md)) ([kubernetes/features#54](https://github.com/kubernetes/enhancements/issues/54)) + - [alpha] Kubelet launches container in a per pod cgroup hierarchy based on quality of service tier ([kubernetes/features#126](https://github.com/kubernetes/enhancements/issues/126)) + - [beta] Kubelet integrates with memcg notification API to detect when a hard eviction threshold is crossed ([kubernetes/features#125](https://github.com/kubernetes/enhancements/issues/125)) + - [beta] Introducing the beta version containerized node conformance test gcr.io/google_containers/node-test:0.2 for users to verify node setup. ([docs](http://kubernetes.io/docs/admin/node-conformance/)) ([kubernetes/features#84](https://github.com/kubernetes/enhancements/issues/84)) - **Scheduling** - - [alpha] Added support for accounting opaque integer resources. ([docs](http://kubernetes.io/docs/user-guide/compute-resources/#opaque-integer-resources-alpha-feature)) ([kubernetes/features#76](https://github.com/kubernetes/features/issues/76)) - - [beta] PodDisruptionBudget has been promoted to beta, can be used to safely drain nodes while respecting application SLO's ([docs](http://kubernetes.io/docs/tasks/administer-cluster/safely-drain-node/)) ([kubernetes/features#85](https://github.com/kubernetes/features/issues/85)) + - [alpha] Added support for accounting opaque integer resources. ([docs](http://kubernetes.io/docs/user-guide/compute-resources/#opaque-integer-resources-alpha-feature)) ([kubernetes/features#76](https://github.com/kubernetes/enhancements/issues/76)) + - [beta] PodDisruptionBudget has been promoted to beta, can be used to safely drain nodes while respecting application SLO's ([docs](http://kubernetes.io/docs/tasks/administer-cluster/safely-drain-node/)) ([kubernetes/features#85](https://github.com/kubernetes/enhancements/issues/85)) - **UI** - - [stable] Dashboard UI now shows all user facing objects and their resource usage. ([docs](http://kubernetes.io/docs/user-guide/ui/)) ([kubernetes/features#136](https://github.com/kubernetes/features/issues/136)) + - [stable] Dashboard UI now shows all user facing objects and their resource usage. ([docs](http://kubernetes.io/docs/user-guide/ui/)) ([kubernetes/features#136](https://github.com/kubernetes/enhancements/issues/136)) - **Windows** - - [alpha] Added support for Windows Server 2016 nodes and scheduling Windows Server Containers ([docs](http://kubernetes.io/docs/getting-started-guides/windows/)) ([kubernetes/features#116](https://github.com/kubernetes/features/issues/116)) + - [alpha] Added support for Windows Server 2016 nodes and scheduling Windows Server Containers ([docs](http://kubernetes.io/docs/getting-started-guides/windows/)) ([kubernetes/features#116](https://github.com/kubernetes/enhancements/issues/116)) ## Known Issues diff --git a/CHANGELOG-1.6.md b/CHANGELOG-1.6.md index 7080309563b..a230108938c 100644 --- a/CHANGELOG-1.6.md +++ b/CHANGELOG-1.6.md @@ -1349,7 +1349,7 @@ Features for this release were tracked via the use of the [kubernetes/features]( * **[beta]** `kubefed` has graduated to beta: supports hosting federation on on-prem clusters, automatically configures `kube-dns` in joining clusters and allows passing arguments to federation components. ### Internal Storage Layer -* **[stable]** The internal storage layer for kubernetes cluster state has been updated to use etcd v3 by default. Existing clusters will have to plan for a data migration window. ([docs](https://kubernetes.io/docs/tasks/administer-cluster/upgrade-1-6/))([kubernetes/features#44](https://github.com/kubernetes/features/issues/44)) +* **[stable]** The internal storage layer for kubernetes cluster state has been updated to use etcd v3 by default. Existing clusters will have to plan for a data migration window. ([docs](https://kubernetes.io/docs/tasks/administer-cluster/upgrade-1-6/))([kubernetes/features#44](https://github.com/kubernetes/enhancements/issues/44)) ### kubeadm * **[beta]** Introduces an API for clients to request TLS certificates from the API server. See the [tutorial](https://kubernetes.io/docs/tasks/tls/managing-tls-in-a-cluster). diff --git a/CHANGELOG-1.7.md b/CHANGELOG-1.7.md index 0c713dd36df..faee0bbe8a6 100644 --- a/CHANGELOG-1.7.md +++ b/CHANGELOG-1.7.md @@ -1535,7 +1535,7 @@ Features for this release were tracked via the use of the [kubernetes/features]( * [beta] DaemonSet supports history and rollback. See [Performing a Rollback on a DaemonSet](https://kubernetes.io/docs/tasks/manage-daemon/rollback-daemon-set/). #### Deployments -* [beta] Deployments uses a hashing collision avoidance mechanism that ensures new rollouts will not block on hashing collisions anymore. ([kubernetes/features#287](https://github.com/kubernetes/features/issues/287)) +* [beta] Deployments uses a hashing collision avoidance mechanism that ensures new rollouts will not block on hashing collisions anymore. ([kubernetes/features#287](https://github.com/kubernetes/enhancements/issues/287)) #### PodDisruptionBudget * [beta] PodDisruptionBudget has a new field MaxUnavailable, which allows users to specify the maximum number of disruptions that can be tolerated during eviction. For more information, see [Pod Disruptions](https://kubernetes.io/docs/concepts/workloads/pods/disruptions/) and [Specifying a Disruption Budget for your Application](https://kubernetes.io/docs/tasks/run-application/configure-pdb/). @@ -1569,7 +1569,7 @@ Features for this release were tracked via the use of the [kubernetes/features]( ### **Cluster Lifecycle** #### kubeadm -* [alpha] Manual [upgrades for kubeadm from v1.6 to v1.7](https://kubernetes.io/docs/tasks/administer-cluster/kubeadm-upgrade-1-7/). Automated upgrades ([kubernetes/features#296](https://github.com/kubernetes/features/issues/296)) are targeted for v1.8. +* [alpha] Manual [upgrades for kubeadm from v1.6 to v1.7](https://kubernetes.io/docs/tasks/administer-cluster/kubeadm-upgrade-1-7/). Automated upgrades ([kubernetes/features#296](https://github.com/kubernetes/enhancements/issues/296)) are targeted for v1.8. #### Cloud Provider Support * [alpha] Improved support for out-of-tree and out-of-process cloud providers, a.k.a pluggable cloud providers. See [Build and Run cloud-controller-manager](https://kubernetes.io/docs/tasks/administer-cluster/running-cloud-controller) documentation. @@ -1585,7 +1585,7 @@ Features for this release were tracked via the use of the [kubernetes/features]( ### **Instrumentation** #### Core Metrics API -* [alpha] Introduces a lightweight monitoring component for serving the core resource metrics API used by the Horizontal Pod Autoscaler and other components ([kubernetes/features#271](https://github.com/kubernetes/features/issues/271)) +* [alpha] Introduces a lightweight monitoring component for serving the core resource metrics API used by the Horizontal Pod Autoscaler and other components ([kubernetes/features#271](https://github.com/kubernetes/enhancements/issues/271)) ### **Internationalization** @@ -1707,11 +1707,11 @@ Features for this release were tracked via the use of the [kubernetes/features]( ### **Node Components** #### Container Runtime Interface -* [alpha] CRI validation testing, which provides a test framework and a suite of tests to validate that the CRI server implementation meets all the requirements. This allows the CRI runtime developers to verify that their runtime conforms to CRI, without needing to set up Kubernetes components or run Kubernetes end-to-end tests. ([docs](https://github.com/kubernetes/community/blob/master/contributors/devel/cri-validation.md) and [release notes](https://github.com/kubernetes-incubator/cri-tools/releases/tag/v0.1)) ([kubernetes/features#292](https://github.com/kubernetes/features/issues/292)) +* [alpha] CRI validation testing, which provides a test framework and a suite of tests to validate that the CRI server implementation meets all the requirements. This allows the CRI runtime developers to verify that their runtime conforms to CRI, without needing to set up Kubernetes components or run Kubernetes end-to-end tests. ([docs](https://github.com/kubernetes/community/blob/master/contributors/devel/cri-validation.md) and [release notes](https://github.com/kubernetes-incubator/cri-tools/releases/tag/v0.1)) ([kubernetes/features#292](https://github.com/kubernetes/enhancements/issues/292)) -* [alpha] Adds support of container metrics in CRI ([docs PR](https://github.com/kubernetes/community/pull/742)) ([kubernetes/features#290](https://github.com/kubernetes/features/issues/290)) +* [alpha] Adds support of container metrics in CRI ([docs PR](https://github.com/kubernetes/community/pull/742)) ([kubernetes/features#290](https://github.com/kubernetes/enhancements/issues/290)) -* [alpha] Integration with [containerd] (https://github.com/containerd/containerd) , which supports basic pod lifecycle and image management. ([docs](https://github.com/kubernetes-incubator/cri-containerd/blob/master/README.md) and [release notes](https://github.com/kubernetes-incubator/cri-containerd/releases/tag/v0.1.0)) ([kubernetes/features#286](https://github.com/kubernetes/features/issues/286)) +* [alpha] Integration with [containerd] (https://github.com/containerd/containerd) , which supports basic pod lifecycle and image management. ([docs](https://github.com/kubernetes-incubator/cri-containerd/blob/master/README.md) and [release notes](https://github.com/kubernetes-incubator/cri-containerd/releases/tag/v0.1.0)) ([kubernetes/features#286](https://github.com/kubernetes/enhancements/issues/286)) * [GA] The Docker-CRI implementation is GA. The legacy, non-CRI Docker integration has been completely removed. @@ -1723,7 +1723,7 @@ Features for this release were tracked via the use of the [kubernetes/features]( ### **Scheduling** #### Scheduler Extender -* [alpha] Support for delegating pod binding to a scheduler extender ([kubernetes/features#270](https://github.com/kubernetes/features/issues/270)) +* [alpha] Support for delegating pod binding to a scheduler extender ([kubernetes/features#270](https://github.com/kubernetes/enhancements/issues/270)) ### **Storage** #### Local Storage @@ -1807,7 +1807,7 @@ Features for this release were tracked via the use of the [kubernetes/features]( * PodDisruptionBudget now uses ControllerRef to decide which controller owns a given Pod, so it doesn't get confused by controllers with overlapping selectors. ([#45003](https://github.com/kubernetes/kubernetes/pull/45003), [@krmayankk](https://github.com/krmayankk)) -* Deployments are updated to use (1) a more stable hashing algorithm (fnv) than the previous one (adler) and (2) a hashing collision avoidance mechanism that will ensure new rollouts will not block on hashing collisions anymore. ([#44774](https://github.com/kubernetes/kubernetes/pull/44774), [@kargakis](https://github.com/kargakis))([kubernetes/features#287](https://github.com/kubernetes/features/issues/287)) +* Deployments are updated to use (1) a more stable hashing algorithm (fnv) than the previous one (adler) and (2) a hashing collision avoidance mechanism that will ensure new rollouts will not block on hashing collisions anymore. ([#44774](https://github.com/kubernetes/kubernetes/pull/44774), [@kargakis](https://github.com/kargakis))([kubernetes/features#287](https://github.com/kubernetes/enhancements/issues/287)) * Deployments and DaemonSets rollouts are considered complete when all of the desired replicas are updated and available. This change affects `kubectl rollout status` and Deployment condition. ([#44672](https://github.com/kubernetes/kubernetes/pull/44672), [@kargakis](https://github.com/kargakis)) diff --git a/CHANGELOG-1.8.md b/CHANGELOG-1.8.md index 467302a85f1..42848a7d8a2 100644 --- a/CHANGELOG-1.8.md +++ b/CHANGELOG-1.8.md @@ -1432,7 +1432,7 @@ Service Level Indicators (SLIs) and Service Level Objectives (SLOs) for the syst Here's the release [scalability validation report]. [SIG Scalability]: https://github.com/kubernetes/community/tree/master/sig-scalability -[scalability validation report]: https://github.com/kubernetes/features/tree/master/release-1.8/scalability_validation_report.md +[scalability validation report]: https://github.com/kubernetes/enhancements/tree/master/release-1.8/scalability_validation_report.md ### SIG Scheduling @@ -1611,7 +1611,7 @@ Kubernetes 1.8 adds the apps/v1beta2 group and version, which now consists of th DaemonSet, Deployment, ReplicaSet and StatefulSet kinds. This group and version are part of the Kubernetes Workloads API. We plan to move them to v1 in an upcoming release, so you might want to plan your migration accordingly. -For more information, see [the issue that describes this work in detail](https://github.com/kubernetes/features/issues/353) +For more information, see [the issue that describes this work in detail](https://github.com/kubernetes/enhancements/issues/353) #### API Object Additions and Migrations @@ -1862,7 +1862,7 @@ to the autoscalers in other clusters if required. #### Container Runtime Interface (CRI) -* [alpha] Add a CRI validation test suite and CRI command-line tools. ([#292](https://github.com/kubernetes/features/issues/292), [@feiskyer](https://github.com/feiskyer)) +* [alpha] Add a CRI validation test suite and CRI command-line tools. ([#292](https://github.com/kubernetes/enhancements/issues/292), [@feiskyer](https://github.com/feiskyer)) * [stable] [cri-o](https://github.com/kubernetes-incubator/cri-o): CRI implementation for OCI-based runtimes [[@mrunalp](https://github.com/mrunalp)] @@ -1886,13 +1886,13 @@ to the autoscalers in other clusters if required. #### kubelet -* [alpha] Kubelet now supports alternative container-level CPU affinity policies by using the new CPU manager. ([#375](https://github.com/kubernetes/features/issues/375), [@sjenning](https://github.com/sjenning), [@ConnorDoyle](https://github.com/ConnorDoyle)) +* [alpha] Kubelet now supports alternative container-level CPU affinity policies by using the new CPU manager. ([#375](https://github.com/kubernetes/enhancements/issues/375), [@sjenning](https://github.com/sjenning), [@ConnorDoyle](https://github.com/ConnorDoyle)) -* [alpha] Applications may now request pre-allocated hugepages by using the new `hugepages` resource in the container resource requests. ([#275](https://github.com/kubernetes/features/issues/275), [@derekwaynecarr](https://github.com/derekwaynecarr)) +* [alpha] Applications may now request pre-allocated hugepages by using the new `hugepages` resource in the container resource requests. ([#275](https://github.com/kubernetes/enhancements/issues/275), [@derekwaynecarr](https://github.com/derekwaynecarr)) -* [alpha] Add support for dynamic Kubelet configuration. ([#281](https://github.com/kubernetes/features/issues/281), [@mtaufen](https://github.com/mtaufen)) +* [alpha] Add support for dynamic Kubelet configuration. ([#281](https://github.com/kubernetes/enhancements/issues/281), [@mtaufen](https://github.com/mtaufen)) -* [alpha] Add the Hardware Device Plugins API. ([#368](https://github.com/kubernetes/features/issues/368), [[@jiayingz](https://github.com/jiayingz)], [[@RenaudWasTaken](https://github.com/RenaudWasTaken)]) +* [alpha] Add the Hardware Device Plugins API. ([#368](https://github.com/kubernetes/enhancements/issues/368), [[@jiayingz](https://github.com/jiayingz)], [[@RenaudWasTaken](https://github.com/RenaudWasTaken)]) * [stable] Upgrade cAdvisor to v0.27.1 with the enhancement for node monitoring. [[@dashpole](https://github.com/dashpole)] @@ -1958,33 +1958,33 @@ to the autoscalers in other clusters if required. #### kubeadm -* [beta] A new `upgrade` subcommand allows you to automatically upgrade a self-hosted cluster created with kubeadm. ([#296](https://github.com/kubernetes/features/issues/296), [@luxas](https://github.com/luxas)) +* [beta] A new `upgrade` subcommand allows you to automatically upgrade a self-hosted cluster created with kubeadm. ([#296](https://github.com/kubernetes/enhancements/issues/296), [@luxas](https://github.com/luxas)) -* [alpha] An experimental self-hosted cluster can now easily be created with `kubeadm init`. Enable the feature by setting the SelfHosting feature gate to true: `--feature-gates=SelfHosting=true` ([#296](https://github.com/kubernetes/features/issues/296), [@luxas](https://github.com/luxas)) +* [alpha] An experimental self-hosted cluster can now easily be created with `kubeadm init`. Enable the feature by setting the SelfHosting feature gate to true: `--feature-gates=SelfHosting=true` ([#296](https://github.com/kubernetes/enhancements/issues/296), [@luxas](https://github.com/luxas)) * **NOTE:** Self-hosting will be the default way to host the control plane in the next release, v1.9 -* [alpha] A new `phase` subcommand supports performing only subtasks of the full `kubeadm init` flow. Combined with fine-grained configuration, kubeadm is now more easily consumable by higher-level provisioning tools like kops or GKE. ([#356](https://github.com/kubernetes/features/issues/356), [@luxas](https://github.com/luxas)) +* [alpha] A new `phase` subcommand supports performing only subtasks of the full `kubeadm init` flow. Combined with fine-grained configuration, kubeadm is now more easily consumable by higher-level provisioning tools like kops or GKE. ([#356](https://github.com/kubernetes/enhancements/issues/356), [@luxas](https://github.com/luxas)) * **NOTE:** This command is currently staged under `kubeadm alpha phase` and will be graduated to top level in a future release. #### kops -* [alpha] Added support for targeting bare metal (or non-cloudprovider) machines. ([#360](https://github.com/kubernetes/features/issues/360), [@justinsb](https://github.com/justinsb)). +* [alpha] Added support for targeting bare metal (or non-cloudprovider) machines. ([#360](https://github.com/kubernetes/enhancements/issues/360), [@justinsb](https://github.com/justinsb)). -* [alpha] kops now supports [running as a server](https://github.com/kubernetes/kops/blob/master/docs/api-server/README.md). ([#359](https://github.com/kubernetes/features/issues/359), [@justinsb](https://github.com/justinsb)) +* [alpha] kops now supports [running as a server](https://github.com/kubernetes/kops/blob/master/docs/api-server/README.md). ([#359](https://github.com/kubernetes/enhancements/issues/359), [@justinsb](https://github.com/justinsb)) -* [beta] GCE support is promoted from alpha to beta. ([#358](https://github.com/kubernetes/features/issues/358), [@justinsb](https://github.com/justinsb)). +* [beta] GCE support is promoted from alpha to beta. ([#358](https://github.com/kubernetes/enhancements/issues/358), [@justinsb](https://github.com/justinsb)). #### Cluster Discovery/Bootstrap -* [beta] The authentication and verification mechanism called Bootstrap Tokens is improved. Use Bootstrap Tokens to easily add new node identities to a cluster. ([#130](https://github.com/kubernetes/features/issues/130), [@luxas](https://github.com/luxas), [@jbeda](https://github.com/jbeda)). +* [beta] The authentication and verification mechanism called Bootstrap Tokens is improved. Use Bootstrap Tokens to easily add new node identities to a cluster. ([#130](https://github.com/kubernetes/enhancements/issues/130), [@luxas](https://github.com/luxas), [@jbeda](https://github.com/jbeda)). #### Multi-platform -* [alpha] The Conformance e2e test suite now passes on the arm, arm64, and ppc64le platforms. ([#288](https://github.com/kubernetes/features/issues/288), [@luxas](https://github.com/luxas), [@mkumatag](https://github.com/mkumatag), [@ixdy](https://github.com/ixdy)) +* [alpha] The Conformance e2e test suite now passes on the arm, arm64, and ppc64le platforms. ([#288](https://github.com/kubernetes/enhancements/issues/288), [@luxas](https://github.com/luxas), [@mkumatag](https://github.com/mkumatag), [@ixdy](https://github.com/ixdy)) #### Cloud Providers -* [alpha] Support is improved for the pluggable, out-of-tree and out-of-core cloud providers. ([#88](https://github.com/kubernetes/features/issues/88), [@wlan0](https://github.com/wlan0)) +* [alpha] Support is improved for the pluggable, out-of-tree and out-of-core cloud providers. ([#88](https://github.com/kubernetes/enhancements/issues/88), [@wlan0](https://github.com/wlan0)) ### Network diff --git a/CHANGELOG.md b/CHANGELOG.md index d4ef4289e31..ea537d6f727 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,10 +3,11 @@ ## Current release: -- [CHANGELOG-1.12.md](https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG-1.12.md) +- [CHANGELOG-1.13.md](https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG-1.13.md) ## Older releases: +- [CHANGELOG-1.12.md](https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG-1.12.md) - [CHANGELOG-1.11.md](https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG-1.11.md) - [CHANGELOG-1.10.md](https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG-1.10.md) - [CHANGELOG-1.9.md](https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG-1.9.md) diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json index 276a869fa0f..8dd058cecc4 100644 --- a/Godeps/Godeps.json +++ b/Godeps/Godeps.json @@ -11,6 +11,7 @@ "github.com/bazelbuild/bazel-gazelle/cmd/gazelle", "github.com/kubernetes/repo-infra/kazel", "k8s.io/kube-openapi/cmd/openapi-gen", + "golang.org/x/lint/golint", "./..." ], "Deps": [ @@ -119,6 +120,26 @@ "ImportPath": "github.com/GeertJohan/go.rice/embedded", "Rev": "c02ca9a983da5807ddf7d796784928f5be4afd09" }, + { + "ImportPath": "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud", + "Comment": "1.3.0", + "Rev": "f8e99590510076aa1e3ff07df946f05220c50fb4" + }, + { + "ImportPath": "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/filter", + "Comment": "1.3.0", + "Rev": "f8e99590510076aa1e3ff07df946f05220c50fb4" + }, + { + "ImportPath": "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/meta", + "Comment": "1.3.0", + "Rev": "f8e99590510076aa1e3ff07df946f05220c50fb4" + }, + { + "ImportPath": "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/mock", + "Comment": "1.3.0", + "Rev": "f8e99590510076aa1e3ff07df946f05220c50fb4" + }, { "ImportPath": "github.com/JeffAshton/win_pdh", "Rev": "76bb4ee9f0ab50f77826f2a2ee7fb9d3880d6ec2" @@ -1601,12 +1622,12 @@ }, { "ImportPath": "github.com/go-openapi/jsonpointer", - "Comment": "v0.17.2", + "Comment": "v0.18.0", "Rev": "ef5f0afec364d3b9396b7b77b43dbe26bf1f8004" }, { "ImportPath": "github.com/go-openapi/jsonreference", - "Comment": "v0.17.2", + "Comment": "v0.18.0", "Rev": "8483a886a90412cd6858df4ea3483dce9c8e35a3" }, { @@ -1636,7 +1657,7 @@ }, { "ImportPath": "github.com/go-openapi/validate", - "Comment": "v0.17.2", + "Comment": "v0.18.0", "Rev": "d2eab7d93009e9215fc85b2faa2c2f2a98c2af48" }, { @@ -2424,6 +2445,10 @@ "ImportPath": "github.com/libopenstorage/openstorage/volume", "Rev": "093a0c3888753c2056e7373183693d670c6bba01" }, + { + "ImportPath": "github.com/liggitt/tabwriter", + "Rev": "89fcab3d43de07060e4fd4c1547430ed57e87f24" + }, { "ImportPath": "github.com/magiconair/properties", "Comment": "v1.7.0-4-g61b492c03cf472", @@ -2795,83 +2820,83 @@ }, { "ImportPath": "github.com/opencontainers/runc/libcontainer", - "Comment": "v1.0.0-rc5-46-g871ba2e58e2431", - "Rev": "871ba2e58e24314d1fab4517a80410191ba5ad01" + "Comment": "v1.0.0-rc5-176-gf000fe11ece1b7", + "Rev": "f000fe11ece1b79f744edd9c8e1a53ba0f5e0f24" }, { "ImportPath": "github.com/opencontainers/runc/libcontainer/apparmor", - "Comment": "v1.0.0-rc5-46-g871ba2e58e2431", - "Rev": "871ba2e58e24314d1fab4517a80410191ba5ad01" + "Comment": "v1.0.0-rc5-176-gf000fe11ece1b7", + "Rev": "f000fe11ece1b79f744edd9c8e1a53ba0f5e0f24" }, { "ImportPath": "github.com/opencontainers/runc/libcontainer/cgroups", - "Comment": "v1.0.0-rc5-46-g871ba2e58e2431", - "Rev": "871ba2e58e24314d1fab4517a80410191ba5ad01" + "Comment": "v1.0.0-rc5-176-gf000fe11ece1b7", + "Rev": "f000fe11ece1b79f744edd9c8e1a53ba0f5e0f24" }, { "ImportPath": "github.com/opencontainers/runc/libcontainer/cgroups/fs", - "Comment": "v1.0.0-rc5-46-g871ba2e58e2431", - "Rev": "871ba2e58e24314d1fab4517a80410191ba5ad01" + "Comment": "v1.0.0-rc5-176-gf000fe11ece1b7", + "Rev": "f000fe11ece1b79f744edd9c8e1a53ba0f5e0f24" }, { "ImportPath": "github.com/opencontainers/runc/libcontainer/cgroups/systemd", - "Comment": "v1.0.0-rc5-46-g871ba2e58e2431", - "Rev": "871ba2e58e24314d1fab4517a80410191ba5ad01" + "Comment": "v1.0.0-rc5-176-gf000fe11ece1b7", + "Rev": "f000fe11ece1b79f744edd9c8e1a53ba0f5e0f24" }, { "ImportPath": "github.com/opencontainers/runc/libcontainer/configs", - "Comment": "v1.0.0-rc5-46-g871ba2e58e2431", - "Rev": "871ba2e58e24314d1fab4517a80410191ba5ad01" + "Comment": "v1.0.0-rc5-176-gf000fe11ece1b7", + "Rev": "f000fe11ece1b79f744edd9c8e1a53ba0f5e0f24" }, { "ImportPath": "github.com/opencontainers/runc/libcontainer/configs/validate", - "Comment": "v1.0.0-rc5-46-g871ba2e58e2431", - "Rev": "871ba2e58e24314d1fab4517a80410191ba5ad01" + "Comment": "v1.0.0-rc5-176-gf000fe11ece1b7", + "Rev": "f000fe11ece1b79f744edd9c8e1a53ba0f5e0f24" }, { "ImportPath": "github.com/opencontainers/runc/libcontainer/criurpc", - "Comment": "v1.0.0-rc5-46-g871ba2e58e2431", - "Rev": "871ba2e58e24314d1fab4517a80410191ba5ad01" + "Comment": "v1.0.0-rc5-176-gf000fe11ece1b7", + "Rev": "f000fe11ece1b79f744edd9c8e1a53ba0f5e0f24" }, { "ImportPath": "github.com/opencontainers/runc/libcontainer/intelrdt", - "Comment": "v1.0.0-rc5-46-g871ba2e58e2431", - "Rev": "871ba2e58e24314d1fab4517a80410191ba5ad01" + "Comment": "v1.0.0-rc5-176-gf000fe11ece1b7", + "Rev": "f000fe11ece1b79f744edd9c8e1a53ba0f5e0f24" }, { "ImportPath": "github.com/opencontainers/runc/libcontainer/keys", - "Comment": "v1.0.0-rc5-46-g871ba2e58e2431", - "Rev": "871ba2e58e24314d1fab4517a80410191ba5ad01" + "Comment": "v1.0.0-rc5-176-gf000fe11ece1b7", + "Rev": "f000fe11ece1b79f744edd9c8e1a53ba0f5e0f24" }, { "ImportPath": "github.com/opencontainers/runc/libcontainer/mount", - "Comment": "v1.0.0-rc5-46-g871ba2e58e2431", - "Rev": "871ba2e58e24314d1fab4517a80410191ba5ad01" + "Comment": "v1.0.0-rc5-176-gf000fe11ece1b7", + "Rev": "f000fe11ece1b79f744edd9c8e1a53ba0f5e0f24" }, { "ImportPath": "github.com/opencontainers/runc/libcontainer/seccomp", - "Comment": "v1.0.0-rc5-46-g871ba2e58e2431", - "Rev": "871ba2e58e24314d1fab4517a80410191ba5ad01" + "Comment": "v1.0.0-rc5-176-gf000fe11ece1b7", + "Rev": "f000fe11ece1b79f744edd9c8e1a53ba0f5e0f24" }, { "ImportPath": "github.com/opencontainers/runc/libcontainer/stacktrace", - "Comment": "v1.0.0-rc5-46-g871ba2e58e2431", - "Rev": "871ba2e58e24314d1fab4517a80410191ba5ad01" + "Comment": "v1.0.0-rc5-176-gf000fe11ece1b7", + "Rev": "f000fe11ece1b79f744edd9c8e1a53ba0f5e0f24" }, { "ImportPath": "github.com/opencontainers/runc/libcontainer/system", - "Comment": "v1.0.0-rc5-46-g871ba2e58e2431", - "Rev": "871ba2e58e24314d1fab4517a80410191ba5ad01" + "Comment": "v1.0.0-rc5-176-gf000fe11ece1b7", + "Rev": "f000fe11ece1b79f744edd9c8e1a53ba0f5e0f24" }, { "ImportPath": "github.com/opencontainers/runc/libcontainer/user", - "Comment": "v1.0.0-rc5-46-g871ba2e58e2431", - "Rev": "871ba2e58e24314d1fab4517a80410191ba5ad01" + "Comment": "v1.0.0-rc5-176-gf000fe11ece1b7", + "Rev": "f000fe11ece1b79f744edd9c8e1a53ba0f5e0f24" }, { "ImportPath": "github.com/opencontainers/runc/libcontainer/utils", - "Comment": "v1.0.0-rc5-46-g871ba2e58e2431", - "Rev": "871ba2e58e24314d1fab4517a80410191ba5ad01" + "Comment": "v1.0.0-rc5-176-gf000fe11ece1b7", + "Rev": "f000fe11ece1b79f744edd9c8e1a53ba0f5e0f24" }, { "ImportPath": "github.com/opencontainers/runtime-spec/specs-go", @@ -2933,13 +2958,23 @@ }, { "ImportPath": "github.com/prometheus/client_golang/prometheus", - "Comment": "v0.8.0-83-ge7e903064f5e9e", - "Rev": "e7e903064f5e9eb5da98208bae10b475d4db0f8c" + "Comment": "v0.9.1", + "Rev": "abad2d1bd44235a26707c172eab6bca5bf2dbad3" + }, + { + "ImportPath": "github.com/prometheus/client_golang/prometheus/internal", + "Comment": "v0.9.1", + "Rev": "abad2d1bd44235a26707c172eab6bca5bf2dbad3" }, { "ImportPath": "github.com/prometheus/client_golang/prometheus/promhttp", - "Comment": "v0.8.0-83-ge7e903064f5e9e", - "Rev": "e7e903064f5e9eb5da98208bae10b475d4db0f8c" + "Comment": "v0.9.1", + "Rev": "abad2d1bd44235a26707c172eab6bca5bf2dbad3" + }, + { + "ImportPath": "github.com/prometheus/client_golang/prometheus/testutil", + "Comment": "v0.9.1", + "Rev": "abad2d1bd44235a26707c172eab6bca5bf2dbad3" }, { "ImportPath": "github.com/prometheus/client_model/go", @@ -3422,6 +3457,14 @@ "ImportPath": "golang.org/x/crypto/ssh/terminal", "Rev": "de0752318171da717af4ce24d0a2e8626afaeb11" }, + { + "ImportPath": "golang.org/x/lint", + "Rev": "8f45f776aaf18cebc8d65861cc70c33c60471952" + }, + { + "ImportPath": "golang.org/x/lint/golint", + "Rev": "8f45f776aaf18cebc8d65861cc70c33c60471952" + }, { "ImportPath": "golang.org/x/net/context", "Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" @@ -3586,6 +3629,14 @@ "ImportPath": "golang.org/x/tools/go/ast/astutil", "Rev": "2382e3994d48b1d22acc2c86bcad0a2aff028e32" }, + { + "ImportPath": "golang.org/x/tools/go/gcexportdata", + "Rev": "2382e3994d48b1d22acc2c86bcad0a2aff028e32" + }, + { + "ImportPath": "golang.org/x/tools/go/gcimporter15", + "Rev": "2382e3994d48b1d22acc2c86bcad0a2aff028e32" + }, { "ImportPath": "golang.org/x/tools/go/vcs", "Rev": "2382e3994d48b1d22acc2c86bcad0a2aff028e32" @@ -3700,47 +3751,47 @@ }, { "ImportPath": "google.golang.org/api/compute/v0.alpha", - "Rev": "3639d6d93f377f39a1de765fa4ef37b3c7ca8bd9" + "Rev": "583d854617af4d2080b5d2a24d72f7fc5a128ab2" }, { "ImportPath": "google.golang.org/api/compute/v0.beta", - "Rev": "3639d6d93f377f39a1de765fa4ef37b3c7ca8bd9" + "Rev": "583d854617af4d2080b5d2a24d72f7fc5a128ab2" }, { "ImportPath": "google.golang.org/api/compute/v1", - "Rev": "3639d6d93f377f39a1de765fa4ef37b3c7ca8bd9" + "Rev": "583d854617af4d2080b5d2a24d72f7fc5a128ab2" }, { "ImportPath": "google.golang.org/api/container/v1", - "Rev": "3639d6d93f377f39a1de765fa4ef37b3c7ca8bd9" + "Rev": "583d854617af4d2080b5d2a24d72f7fc5a128ab2" }, { "ImportPath": "google.golang.org/api/gensupport", - "Rev": "3639d6d93f377f39a1de765fa4ef37b3c7ca8bd9" + "Rev": "583d854617af4d2080b5d2a24d72f7fc5a128ab2" }, { "ImportPath": "google.golang.org/api/googleapi", - "Rev": "3639d6d93f377f39a1de765fa4ef37b3c7ca8bd9" + "Rev": "583d854617af4d2080b5d2a24d72f7fc5a128ab2" }, { "ImportPath": "google.golang.org/api/googleapi/internal/uritemplates", - "Rev": "3639d6d93f377f39a1de765fa4ef37b3c7ca8bd9" + "Rev": "583d854617af4d2080b5d2a24d72f7fc5a128ab2" }, { "ImportPath": "google.golang.org/api/logging/v2beta1", - "Rev": "3639d6d93f377f39a1de765fa4ef37b3c7ca8bd9" + "Rev": "583d854617af4d2080b5d2a24d72f7fc5a128ab2" }, { "ImportPath": "google.golang.org/api/monitoring/v3", - "Rev": "3639d6d93f377f39a1de765fa4ef37b3c7ca8bd9" + "Rev": "583d854617af4d2080b5d2a24d72f7fc5a128ab2" }, { "ImportPath": "google.golang.org/api/pubsub/v1", - "Rev": "3639d6d93f377f39a1de765fa4ef37b3c7ca8bd9" + "Rev": "583d854617af4d2080b5d2a24d72f7fc5a128ab2" }, { "ImportPath": "google.golang.org/api/tpu/v1", - "Rev": "3639d6d93f377f39a1de765fa4ef37b3c7ca8bd9" + "Rev": "583d854617af4d2080b5d2a24d72f7fc5a128ab2" }, { "ImportPath": "google.golang.org/genproto/googleapis/rpc/status", @@ -4067,6 +4118,106 @@ "ImportPath": "k8s.io/utils/pointer", "Rev": "8e7ff06bf0e2d3289061230af203e430a15b6dcc" }, + { + "ImportPath": "sigs.k8s.io/kustomize/pkg/commands/build", + "Comment": "v1.0.10-69-gef51cceff55b17", + "Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7" + }, + { + "ImportPath": "sigs.k8s.io/kustomize/pkg/constants", + "Comment": "v1.0.10-69-gef51cceff55b17", + "Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7" + }, + { + "ImportPath": "sigs.k8s.io/kustomize/pkg/expansion", + "Comment": "v1.0.10-69-gef51cceff55b17", + "Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7" + }, + { + "ImportPath": "sigs.k8s.io/kustomize/pkg/factory", + "Comment": "v1.0.10-69-gef51cceff55b17", + "Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7" + }, + { + "ImportPath": "sigs.k8s.io/kustomize/pkg/fs", + "Comment": "v1.0.10-69-gef51cceff55b17", + "Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7" + }, + { + "ImportPath": "sigs.k8s.io/kustomize/pkg/gvk", + "Comment": "v1.0.10-69-gef51cceff55b17", + "Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7" + }, + { + "ImportPath": "sigs.k8s.io/kustomize/pkg/ifc", + "Comment": "v1.0.10-69-gef51cceff55b17", + "Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7" + }, + { + "ImportPath": "sigs.k8s.io/kustomize/pkg/ifc/transformer", + "Comment": "v1.0.10-69-gef51cceff55b17", + "Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7" + }, + { + "ImportPath": "sigs.k8s.io/kustomize/pkg/internal/error", + "Comment": "v1.0.10-69-gef51cceff55b17", + "Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7" + }, + { + "ImportPath": "sigs.k8s.io/kustomize/pkg/loader", + "Comment": "v1.0.10-69-gef51cceff55b17", + "Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7" + }, + { + "ImportPath": "sigs.k8s.io/kustomize/pkg/patch", + "Comment": "v1.0.10-69-gef51cceff55b17", + "Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7" + }, + { + "ImportPath": "sigs.k8s.io/kustomize/pkg/patch/transformer", + "Comment": "v1.0.10-69-gef51cceff55b17", + "Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7" + }, + { + "ImportPath": "sigs.k8s.io/kustomize/pkg/resid", + "Comment": "v1.0.10-69-gef51cceff55b17", + "Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7" + }, + { + "ImportPath": "sigs.k8s.io/kustomize/pkg/resmap", + "Comment": "v1.0.10-69-gef51cceff55b17", + "Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7" + }, + { + "ImportPath": "sigs.k8s.io/kustomize/pkg/resource", + "Comment": "v1.0.10-69-gef51cceff55b17", + "Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7" + }, + { + "ImportPath": "sigs.k8s.io/kustomize/pkg/target", + "Comment": "v1.0.10-69-gef51cceff55b17", + "Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7" + }, + { + "ImportPath": "sigs.k8s.io/kustomize/pkg/transformers", + "Comment": "v1.0.10-69-gef51cceff55b17", + "Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7" + }, + { + "ImportPath": "sigs.k8s.io/kustomize/pkg/transformers/config", + "Comment": "v1.0.10-69-gef51cceff55b17", + "Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7" + }, + { + "ImportPath": "sigs.k8s.io/kustomize/pkg/transformers/config/defaultconfig", + "Comment": "v1.0.10-69-gef51cceff55b17", + "Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7" + }, + { + "ImportPath": "sigs.k8s.io/kustomize/pkg/types", + "Comment": "v1.0.10-69-gef51cceff55b17", + "Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7" + }, { "ImportPath": "sigs.k8s.io/structured-merge-diff/fieldpath", "Rev": "d43a45b8663b01dd7d86e7cc1656dd8651280ed7" diff --git a/Godeps/LICENSES b/Godeps/LICENSES index cfd2915eaea..785d54ae30c 100644 --- a/Godeps/LICENSES +++ b/Godeps/LICENSES @@ -61242,6 +61242,846 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ================================================================================ +================================================================================ += vendor/github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud licensed under: = + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + += vendor/github.com/GoogleCloudPlatform/k8s-cloud-provider/LICENSE 3b83ef96387f14655fc854ddc3c6bd57 +================================================================================ + + +================================================================================ += vendor/github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/filter licensed under: = + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + += vendor/github.com/GoogleCloudPlatform/k8s-cloud-provider/LICENSE 3b83ef96387f14655fc854ddc3c6bd57 +================================================================================ + + +================================================================================ += vendor/github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/meta licensed under: = + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + += vendor/github.com/GoogleCloudPlatform/k8s-cloud-provider/LICENSE 3b83ef96387f14655fc854ddc3c6bd57 +================================================================================ + + +================================================================================ += vendor/github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/mock licensed under: = + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + += vendor/github.com/GoogleCloudPlatform/k8s-cloud-provider/LICENSE 3b83ef96387f14655fc854ddc3c6bd57 +================================================================================ + + ================================================================================ = vendor/github.com/gophercloud/gophercloud licensed under: = @@ -74113,6 +74953,41 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI ================================================================================ +================================================================================ += vendor/github.com/liggitt/tabwriter licensed under: = + +Copyright (c) 2009 The Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + += vendor/github.com/liggitt/tabwriter/LICENSE 5d4950ecb7b26d2c5e4e7b4e0dd74707 +================================================================================ + + ================================================================================ = vendor/github.com/magiconair/properties licensed under: = @@ -85696,6 +86571,215 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ================================================================================ +================================================================================ += vendor/github.com/prometheus/client_golang/prometheus/internal licensed under: = + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + += vendor/github.com/prometheus/client_golang/LICENSE 86d3f3a95c324c9479bd8986968f4327 +================================================================================ + + ================================================================================ = vendor/github.com/prometheus/client_golang/prometheus/promhttp licensed under: = @@ -85905,6 +86989,215 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ================================================================================ +================================================================================ += vendor/github.com/prometheus/client_golang/prometheus/testutil licensed under: = + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + += vendor/github.com/prometheus/client_golang/LICENSE 86d3f3a95c324c9479bd8986968f4327 +================================================================================ + + ================================================================================ = vendor/github.com/prometheus/client_model/go licensed under: = @@ -98293,6 +99586,76 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ================================================================================ +================================================================================ += vendor/golang.org/x/lint licensed under: = + +Copyright (c) 2013 The Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + += vendor/golang.org/x/lint/LICENSE 4c728948788b1a02f33ae4e906546eef +================================================================================ + + +================================================================================ += vendor/golang.org/x/lint/golint licensed under: = + +Copyright (c) 2013 The Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + += vendor/golang.org/x/lint/LICENSE 4c728948788b1a02f33ae4e906546eef +================================================================================ + + ================================================================================ = vendor/golang.org/x/net/context licensed under: = @@ -99728,6 +101091,76 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ================================================================================ +================================================================================ += vendor/golang.org/x/tools/go/gcexportdata licensed under: = + +Copyright (c) 2009 The Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + += vendor/golang.org/x/tools/LICENSE 5d4950ecb7b26d2c5e4e7b4e0dd74707 +================================================================================ + + +================================================================================ += vendor/golang.org/x/tools/go/gcimporter15 licensed under: = + +Copyright (c) 2009 The Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + += vendor/golang.org/x/tools/LICENSE 5d4950ecb7b26d2c5e4e7b4e0dd74707 +================================================================================ + + ================================================================================ = vendor/golang.org/x/tools/go/vcs licensed under: = @@ -112530,216 +113963,6 @@ third-party archives. ================================================================================ -================================================================================ -= vendor/k8s.io/kube-openapi/pkg/schemaconv licensed under: = - - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -= vendor/k8s.io/kube-openapi/LICENSE 3b83ef96387f14655fc854ddc3c6bd57 -================================================================================ - - ================================================================================ = vendor/k8s.io/kube-openapi/pkg/util licensed under: = @@ -114630,6 +115853,4401 @@ third-party archives. ================================================================================ +================================================================================ += vendor/sigs.k8s.io/kustomize/pkg/commands/build licensed under: = + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + += vendor/sigs.k8s.io/kustomize/LICENSE e3fc50a88d0a364313df4b21ef20c29e +================================================================================ + + +================================================================================ += vendor/sigs.k8s.io/kustomize/pkg/constants licensed under: = + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + += vendor/sigs.k8s.io/kustomize/LICENSE e3fc50a88d0a364313df4b21ef20c29e +================================================================================ + + +================================================================================ += vendor/sigs.k8s.io/kustomize/pkg/expansion licensed under: = + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + += vendor/sigs.k8s.io/kustomize/LICENSE e3fc50a88d0a364313df4b21ef20c29e +================================================================================ + + +================================================================================ += vendor/sigs.k8s.io/kustomize/pkg/factory licensed under: = + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + += vendor/sigs.k8s.io/kustomize/LICENSE e3fc50a88d0a364313df4b21ef20c29e +================================================================================ + + +================================================================================ += vendor/sigs.k8s.io/kustomize/pkg/fs licensed under: = + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + += vendor/sigs.k8s.io/kustomize/LICENSE e3fc50a88d0a364313df4b21ef20c29e +================================================================================ + + +================================================================================ += vendor/sigs.k8s.io/kustomize/pkg/gvk licensed under: = + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + += vendor/sigs.k8s.io/kustomize/LICENSE e3fc50a88d0a364313df4b21ef20c29e +================================================================================ + + +================================================================================ += vendor/sigs.k8s.io/kustomize/pkg/ifc licensed under: = + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + += vendor/sigs.k8s.io/kustomize/LICENSE e3fc50a88d0a364313df4b21ef20c29e +================================================================================ + + +================================================================================ += vendor/sigs.k8s.io/kustomize/pkg/ifc/transformer licensed under: = + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + += vendor/sigs.k8s.io/kustomize/LICENSE e3fc50a88d0a364313df4b21ef20c29e +================================================================================ + + +================================================================================ += vendor/sigs.k8s.io/kustomize/pkg/internal/error licensed under: = + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + += vendor/sigs.k8s.io/kustomize/LICENSE e3fc50a88d0a364313df4b21ef20c29e +================================================================================ + + +================================================================================ +<<<<<<< HEAD += vendor/k8s.io/kube-openapi/pkg/schemaconv licensed under: = + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + += vendor/k8s.io/kube-openapi/LICENSE 3b83ef96387f14655fc854ddc3c6bd57 +================================================================================ + + +================================================================================ += vendor/k8s.io/kube-openapi/pkg/util licensed under: = + +======= += vendor/sigs.k8s.io/kustomize/pkg/loader licensed under: = +>>>>>>> upstream/master + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + += vendor/sigs.k8s.io/kustomize/LICENSE e3fc50a88d0a364313df4b21ef20c29e +================================================================================ + + +================================================================================ += vendor/sigs.k8s.io/kustomize/pkg/patch licensed under: = + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + += vendor/sigs.k8s.io/kustomize/LICENSE e3fc50a88d0a364313df4b21ef20c29e +================================================================================ + + +================================================================================ += vendor/sigs.k8s.io/kustomize/pkg/patch/transformer licensed under: = + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + += vendor/sigs.k8s.io/kustomize/LICENSE e3fc50a88d0a364313df4b21ef20c29e +================================================================================ + + +================================================================================ += vendor/sigs.k8s.io/kustomize/pkg/resid licensed under: = + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + += vendor/sigs.k8s.io/kustomize/LICENSE e3fc50a88d0a364313df4b21ef20c29e +================================================================================ + + +================================================================================ += vendor/sigs.k8s.io/kustomize/pkg/resmap licensed under: = + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + += vendor/sigs.k8s.io/kustomize/LICENSE e3fc50a88d0a364313df4b21ef20c29e +================================================================================ + + +================================================================================ += vendor/sigs.k8s.io/kustomize/pkg/resource licensed under: = + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + += vendor/sigs.k8s.io/kustomize/LICENSE e3fc50a88d0a364313df4b21ef20c29e +================================================================================ + + +================================================================================ += vendor/sigs.k8s.io/kustomize/pkg/target licensed under: = + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + += vendor/sigs.k8s.io/kustomize/LICENSE e3fc50a88d0a364313df4b21ef20c29e +================================================================================ + + +================================================================================ += vendor/sigs.k8s.io/kustomize/pkg/transformers licensed under: = + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + += vendor/sigs.k8s.io/kustomize/LICENSE e3fc50a88d0a364313df4b21ef20c29e +================================================================================ + + +================================================================================ += vendor/sigs.k8s.io/kustomize/pkg/transformers/config licensed under: = + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + += vendor/sigs.k8s.io/kustomize/LICENSE e3fc50a88d0a364313df4b21ef20c29e +================================================================================ + + +================================================================================ += vendor/sigs.k8s.io/kustomize/pkg/transformers/config/defaultconfig licensed under: = + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + += vendor/sigs.k8s.io/kustomize/LICENSE e3fc50a88d0a364313df4b21ef20c29e +================================================================================ + + +================================================================================ += vendor/sigs.k8s.io/kustomize/pkg/types licensed under: = + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + += vendor/sigs.k8s.io/kustomize/LICENSE e3fc50a88d0a364313df4b21ef20c29e +================================================================================ + + ================================================================================ = vendor/sigs.k8s.io/structured-merge-diff/fieldpath licensed under: = diff --git a/OWNERS b/OWNERS index 5389e0d07b7..051be253f73 100644 --- a/OWNERS +++ b/OWNERS @@ -7,6 +7,7 @@ filters: - lavalamp - smarterclayton - thockin + - liggitt approvers: - bgrant0607 - brendandburns @@ -17,9 +18,11 @@ filters: - smarterclayton - thockin - wojtek-t + - liggitt # Only meant for FEATURE BRANCH - apelisse - jennybuckley + # Bazel build infrastructure changes often touch files throughout the tree "\\.bzl$": reviewers: diff --git a/OWNERS_ALIASES b/OWNERS_ALIASES index 2cd4262ad72..1f312c51e84 100644 --- a/OWNERS_ALIASES +++ b/OWNERS_ALIASES @@ -108,6 +108,7 @@ aliases: - mbohlool - pweil- - tallclair + - krmayankk sig-auth-serviceaccounts-approvers: - deads2k @@ -119,6 +120,7 @@ aliases: - enj - liggitt - mikedanese + - WanLinghao sig-storage-reviewers: - saad-ali @@ -168,14 +170,18 @@ aliases: - smarterclayton - soltysh sig-testing-reviewers: + - bentheelder + - cblecker - fejta + - krzyzacy - ixdy - - rmmh - spiffxp sig-testing-approvers: + - bentheelder + - cblecker - fejta + - krzyzacy - ixdy - - rmmh - spiffxp sig-node-reviewers: - Random-Liu @@ -236,81 +242,6 @@ aliases: - DirectXMan12 - MaciekPytel - mwielgus - milestone-maintainers: - - lavalamp - - deads2k - - michelleN - - mattfarina - - prydonius - - bgrant0607 - - jdumars - - liggitt - - deads2k - - mwielgus - - directxman12 - - justinsb - - kris-nova - - chrislovecnm - - mfburnett - - slack - - colemickens - - foxish - - AdoHe - - lukemarsden - - jbeda - - roberthbailey - - zehicle - - jdumars - - grodrigues3 - - Phillels - - devin-donnelly - - jaredbhatti - - csbell - - quinton-hoole - - piosz - - fabxc - - thockin - - dcbw - - caseydavenport - - dchen1107 - - derekwaynecarr - - zen - - marcoceppi - - dghubble - - idvoretskyi - - xsgordon - - apsinha - - idvoretskyi - - calebamiles - - calebamiles - - wojtek-t - - countspongebob - - jbeda - - davidopp - - timothysc - - pmorie - - arschles - - vaikas-google - - duglin - - saad-ali - - childsb - - spiffxp - - fejta - - timothysc - - danielromlein - - floreks - - michmike - - abgworrall - - krzyzacy - - steveperry-53 - - radhikpac - - jpbetz - - cmluciano - - bsalamat - - m1093782566 - - tallclair - - feiskyer - - mikedanese api-approvers: # TODO remove jennybuckly and apelisse from this before merging with master - jennybuckley diff --git a/api/openapi-spec/swagger.json b/api/openapi-spec/swagger.json index 91f9b03108a..1b2f68d661a 100644 --- a/api/openapi-spec/swagger.json +++ b/api/openapi-spec/swagger.json @@ -49616,6 +49616,1018 @@ } } }, + "/apis/coordination.k8s.io/v1/": { + "get": { + "description": "get available resources", + "consumes": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf" + ], + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf" + ], + "schemes": [ + "https" + ], + "tags": [ + "coordination_v1" + ], + "operationId": "getCoordinationV1APIResources", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.APIResourceList" + } + }, + "401": { + "description": "Unauthorized" + } + } + } + }, + "/apis/coordination.k8s.io/v1/leases": { + "get": { + "description": "list or watch objects of kind Lease", + "consumes": [ + "*/*" + ], + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf", + "application/json;stream=watch", + "application/vnd.kubernetes.protobuf;stream=watch" + ], + "schemes": [ + "https" + ], + "tags": [ + "coordination_v1" + ], + "operationId": "listCoordinationV1LeaseForAllNamespaces", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/io.k8s.api.coordination.v1.LeaseList" + } + }, + "401": { + "description": "Unauthorized" + } + }, + "x-kubernetes-action": "list", + "x-kubernetes-group-version-kind": { + "group": "coordination.k8s.io", + "kind": "Lease", + "version": "v1" + } + }, + "parameters": [ + { + "uniqueItems": true, + "type": "string", + "description": "The continue option should be set when retrieving more results from the server. Since this value is server defined, clients may only use the continue value from a previous query result with identical query parameters (except for the value of continue) and the server may reject a continue value it does not recognize. If the specified continue value is no longer valid whether due to expiration (generally five to fifteen minutes) or a configuration change on the server, the server will respond with a 410 ResourceExpired error together with a continue token. If the client needs a consistent list, it must restart their list without the continue field. Otherwise, the client may send another list request with the token received with the 410 error, the server will respond with a list starting from the next key, but from the latest snapshot, which is inconsistent from the previous list results - objects that are created, modified, or deleted after the first list request will be included in the response, as long as their keys are after the \"next key\".\n\nThis field is not supported when watch is true. Clients may start a watch from the last resourceVersion value returned by the server and not miss any modifications.", + "name": "continue", + "in": "query" + }, + { + "uniqueItems": true, + "type": "string", + "description": "A selector to restrict the list of returned objects by their fields. Defaults to everything.", + "name": "fieldSelector", + "in": "query" + }, + { + "uniqueItems": true, + "type": "boolean", + "description": "If true, partially initialized resources are included in the response.", + "name": "includeUninitialized", + "in": "query" + }, + { + "uniqueItems": true, + "type": "string", + "description": "A selector to restrict the list of returned objects by their labels. Defaults to everything.", + "name": "labelSelector", + "in": "query" + }, + { + "uniqueItems": true, + "type": "integer", + "description": "limit is a maximum number of responses to return for a list call. If more items exist, the server will set the `continue` field on the list metadata to a value that can be used with the same initial query to retrieve the next set of results. Setting a limit may return fewer than the requested amount of items (up to zero items) in the event all requested objects are filtered out and clients should only use the presence of the continue field to determine whether more results are available. Servers may choose not to support the limit argument and will return all of the available results. If limit is specified and the continue field is empty, clients may assume that no more results are available. This field is not supported if watch is true.\n\nThe server guarantees that the objects returned when using continue will be identical to issuing a single list call without a limit - that is, no objects created, modified, or deleted after the first request is issued will be included in any subsequent continued requests. This is sometimes referred to as a consistent snapshot, and ensures that a client that is using limit to receive smaller chunks of a very large result can ensure they see all possible objects. If objects are updated during a chunked list the version of the object that was present at the time the first list result was calculated is returned.", + "name": "limit", + "in": "query" + }, + { + "uniqueItems": true, + "type": "string", + "description": "If 'true', then the output is pretty printed.", + "name": "pretty", + "in": "query" + }, + { + "uniqueItems": true, + "type": "string", + "description": "When specified with a watch call, shows changes that occur after that particular version of a resource. Defaults to changes from the beginning of history. When specified for list: - if unset, then the result is returned from remote storage based on quorum-read flag; - if it's 0, then we simply return what we currently have in cache, no guarantee; - if set to non zero, then the result is at least as fresh as given rv.", + "name": "resourceVersion", + "in": "query" + }, + { + "uniqueItems": true, + "type": "integer", + "description": "Timeout for the list/watch call. This limits the duration of the call, regardless of any activity or inactivity.", + "name": "timeoutSeconds", + "in": "query" + }, + { + "uniqueItems": true, + "type": "boolean", + "description": "Watch for changes to the described resources and return them as a stream of add, update, and remove notifications. Specify resourceVersion.", + "name": "watch", + "in": "query" + } + ] + }, + "/apis/coordination.k8s.io/v1/namespaces/{namespace}/leases": { + "get": { + "description": "list or watch objects of kind Lease", + "consumes": [ + "*/*" + ], + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf", + "application/json;stream=watch", + "application/vnd.kubernetes.protobuf;stream=watch" + ], + "schemes": [ + "https" + ], + "tags": [ + "coordination_v1" + ], + "operationId": "listCoordinationV1NamespacedLease", + "parameters": [ + { + "uniqueItems": true, + "type": "string", + "description": "The continue option should be set when retrieving more results from the server. Since this value is server defined, clients may only use the continue value from a previous query result with identical query parameters (except for the value of continue) and the server may reject a continue value it does not recognize. If the specified continue value is no longer valid whether due to expiration (generally five to fifteen minutes) or a configuration change on the server, the server will respond with a 410 ResourceExpired error together with a continue token. If the client needs a consistent list, it must restart their list without the continue field. Otherwise, the client may send another list request with the token received with the 410 error, the server will respond with a list starting from the next key, but from the latest snapshot, which is inconsistent from the previous list results - objects that are created, modified, or deleted after the first list request will be included in the response, as long as their keys are after the \"next key\".\n\nThis field is not supported when watch is true. Clients may start a watch from the last resourceVersion value returned by the server and not miss any modifications.", + "name": "continue", + "in": "query" + }, + { + "uniqueItems": true, + "type": "string", + "description": "A selector to restrict the list of returned objects by their fields. Defaults to everything.", + "name": "fieldSelector", + "in": "query" + }, + { + "uniqueItems": true, + "type": "string", + "description": "A selector to restrict the list of returned objects by their labels. Defaults to everything.", + "name": "labelSelector", + "in": "query" + }, + { + "uniqueItems": true, + "type": "integer", + "description": "limit is a maximum number of responses to return for a list call. If more items exist, the server will set the `continue` field on the list metadata to a value that can be used with the same initial query to retrieve the next set of results. Setting a limit may return fewer than the requested amount of items (up to zero items) in the event all requested objects are filtered out and clients should only use the presence of the continue field to determine whether more results are available. Servers may choose not to support the limit argument and will return all of the available results. If limit is specified and the continue field is empty, clients may assume that no more results are available. This field is not supported if watch is true.\n\nThe server guarantees that the objects returned when using continue will be identical to issuing a single list call without a limit - that is, no objects created, modified, or deleted after the first request is issued will be included in any subsequent continued requests. This is sometimes referred to as a consistent snapshot, and ensures that a client that is using limit to receive smaller chunks of a very large result can ensure they see all possible objects. If objects are updated during a chunked list the version of the object that was present at the time the first list result was calculated is returned.", + "name": "limit", + "in": "query" + }, + { + "uniqueItems": true, + "type": "string", + "description": "When specified with a watch call, shows changes that occur after that particular version of a resource. Defaults to changes from the beginning of history. When specified for list: - if unset, then the result is returned from remote storage based on quorum-read flag; - if it's 0, then we simply return what we currently have in cache, no guarantee; - if set to non zero, then the result is at least as fresh as given rv.", + "name": "resourceVersion", + "in": "query" + }, + { + "uniqueItems": true, + "type": "integer", + "description": "Timeout for the list/watch call. This limits the duration of the call, regardless of any activity or inactivity.", + "name": "timeoutSeconds", + "in": "query" + }, + { + "uniqueItems": true, + "type": "boolean", + "description": "Watch for changes to the described resources and return them as a stream of add, update, and remove notifications. Specify resourceVersion.", + "name": "watch", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/io.k8s.api.coordination.v1.LeaseList" + } + }, + "401": { + "description": "Unauthorized" + } + }, + "x-kubernetes-action": "list", + "x-kubernetes-group-version-kind": { + "group": "coordination.k8s.io", + "kind": "Lease", + "version": "v1" + } + }, + "post": { + "description": "create a Lease", + "consumes": [ + "*/*" + ], + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf" + ], + "schemes": [ + "https" + ], + "tags": [ + "coordination_v1" + ], + "operationId": "createCoordinationV1NamespacedLease", + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/io.k8s.api.coordination.v1.Lease" + } + }, + { + "uniqueItems": true, + "type": "string", + "description": "When present, indicates that modifications should not be persisted. An invalid or unrecognized dryRun directive will result in an error response and no further processing of the request. Valid values are: - All: all dry run stages will be processed", + "name": "dryRun", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/io.k8s.api.coordination.v1.Lease" + } + }, + "201": { + "description": "Created", + "schema": { + "$ref": "#/definitions/io.k8s.api.coordination.v1.Lease" + } + }, + "202": { + "description": "Accepted", + "schema": { + "$ref": "#/definitions/io.k8s.api.coordination.v1.Lease" + } + }, + "401": { + "description": "Unauthorized" + } + }, + "x-kubernetes-action": "post", + "x-kubernetes-group-version-kind": { + "group": "coordination.k8s.io", + "kind": "Lease", + "version": "v1" + } + }, + "delete": { + "description": "delete collection of Lease", + "consumes": [ + "*/*" + ], + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf" + ], + "schemes": [ + "https" + ], + "tags": [ + "coordination_v1" + ], + "operationId": "deleteCoordinationV1CollectionNamespacedLease", + "parameters": [ + { + "uniqueItems": true, + "type": "string", + "description": "The continue option should be set when retrieving more results from the server. Since this value is server defined, clients may only use the continue value from a previous query result with identical query parameters (except for the value of continue) and the server may reject a continue value it does not recognize. If the specified continue value is no longer valid whether due to expiration (generally five to fifteen minutes) or a configuration change on the server, the server will respond with a 410 ResourceExpired error together with a continue token. If the client needs a consistent list, it must restart their list without the continue field. Otherwise, the client may send another list request with the token received with the 410 error, the server will respond with a list starting from the next key, but from the latest snapshot, which is inconsistent from the previous list results - objects that are created, modified, or deleted after the first list request will be included in the response, as long as their keys are after the \"next key\".\n\nThis field is not supported when watch is true. Clients may start a watch from the last resourceVersion value returned by the server and not miss any modifications.", + "name": "continue", + "in": "query" + }, + { + "uniqueItems": true, + "type": "string", + "description": "A selector to restrict the list of returned objects by their fields. Defaults to everything.", + "name": "fieldSelector", + "in": "query" + }, + { + "uniqueItems": true, + "type": "string", + "description": "A selector to restrict the list of returned objects by their labels. Defaults to everything.", + "name": "labelSelector", + "in": "query" + }, + { + "uniqueItems": true, + "type": "integer", + "description": "limit is a maximum number of responses to return for a list call. If more items exist, the server will set the `continue` field on the list metadata to a value that can be used with the same initial query to retrieve the next set of results. Setting a limit may return fewer than the requested amount of items (up to zero items) in the event all requested objects are filtered out and clients should only use the presence of the continue field to determine whether more results are available. Servers may choose not to support the limit argument and will return all of the available results. If limit is specified and the continue field is empty, clients may assume that no more results are available. This field is not supported if watch is true.\n\nThe server guarantees that the objects returned when using continue will be identical to issuing a single list call without a limit - that is, no objects created, modified, or deleted after the first request is issued will be included in any subsequent continued requests. This is sometimes referred to as a consistent snapshot, and ensures that a client that is using limit to receive smaller chunks of a very large result can ensure they see all possible objects. If objects are updated during a chunked list the version of the object that was present at the time the first list result was calculated is returned.", + "name": "limit", + "in": "query" + }, + { + "uniqueItems": true, + "type": "string", + "description": "When specified with a watch call, shows changes that occur after that particular version of a resource. Defaults to changes from the beginning of history. When specified for list: - if unset, then the result is returned from remote storage based on quorum-read flag; - if it's 0, then we simply return what we currently have in cache, no guarantee; - if set to non zero, then the result is at least as fresh as given rv.", + "name": "resourceVersion", + "in": "query" + }, + { + "uniqueItems": true, + "type": "integer", + "description": "Timeout for the list/watch call. This limits the duration of the call, regardless of any activity or inactivity.", + "name": "timeoutSeconds", + "in": "query" + }, + { + "uniqueItems": true, + "type": "boolean", + "description": "Watch for changes to the described resources and return them as a stream of add, update, and remove notifications. Specify resourceVersion.", + "name": "watch", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.Status" + } + }, + "401": { + "description": "Unauthorized" + } + }, + "x-kubernetes-action": "deletecollection", + "x-kubernetes-group-version-kind": { + "group": "coordination.k8s.io", + "kind": "Lease", + "version": "v1" + } + }, + "parameters": [ + { + "uniqueItems": true, + "type": "boolean", + "description": "If true, partially initialized resources are included in the response.", + "name": "includeUninitialized", + "in": "query" + }, + { + "uniqueItems": true, + "type": "string", + "description": "object name and auth scope, such as for teams and projects", + "name": "namespace", + "in": "path", + "required": true + }, + { + "uniqueItems": true, + "type": "string", + "description": "If 'true', then the output is pretty printed.", + "name": "pretty", + "in": "query" + } + ] + }, + "/apis/coordination.k8s.io/v1/namespaces/{namespace}/leases/{name}": { + "get": { + "description": "read the specified Lease", + "consumes": [ + "*/*" + ], + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf" + ], + "schemes": [ + "https" + ], + "tags": [ + "coordination_v1" + ], + "operationId": "readCoordinationV1NamespacedLease", + "parameters": [ + { + "uniqueItems": true, + "type": "boolean", + "description": "Should the export be exact. Exact export maintains cluster-specific fields like 'Namespace'.", + "name": "exact", + "in": "query" + }, + { + "uniqueItems": true, + "type": "boolean", + "description": "Should this value be exported. Export strips fields that a user can not specify.", + "name": "export", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/io.k8s.api.coordination.v1.Lease" + } + }, + "401": { + "description": "Unauthorized" + } + }, + "x-kubernetes-action": "get", + "x-kubernetes-group-version-kind": { + "group": "coordination.k8s.io", + "kind": "Lease", + "version": "v1" + } + }, + "put": { + "description": "replace the specified Lease", + "consumes": [ + "*/*" + ], + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf" + ], + "schemes": [ + "https" + ], + "tags": [ + "coordination_v1" + ], + "operationId": "replaceCoordinationV1NamespacedLease", + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/io.k8s.api.coordination.v1.Lease" + } + }, + { + "uniqueItems": true, + "type": "string", + "description": "When present, indicates that modifications should not be persisted. An invalid or unrecognized dryRun directive will result in an error response and no further processing of the request. Valid values are: - All: all dry run stages will be processed", + "name": "dryRun", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/io.k8s.api.coordination.v1.Lease" + } + }, + "201": { + "description": "Created", + "schema": { + "$ref": "#/definitions/io.k8s.api.coordination.v1.Lease" + } + }, + "401": { + "description": "Unauthorized" + } + }, + "x-kubernetes-action": "put", + "x-kubernetes-group-version-kind": { + "group": "coordination.k8s.io", + "kind": "Lease", + "version": "v1" + } + }, + "delete": { + "description": "delete a Lease", + "consumes": [ + "*/*" + ], + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf" + ], + "schemes": [ + "https" + ], + "tags": [ + "coordination_v1" + ], + "operationId": "deleteCoordinationV1NamespacedLease", + "parameters": [ + { + "name": "body", + "in": "body", + "schema": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.DeleteOptions" + } + }, + { + "uniqueItems": true, + "type": "string", + "description": "When present, indicates that modifications should not be persisted. An invalid or unrecognized dryRun directive will result in an error response and no further processing of the request. Valid values are: - All: all dry run stages will be processed", + "name": "dryRun", + "in": "query" + }, + { + "uniqueItems": true, + "type": "integer", + "description": "The duration in seconds before the object should be deleted. Value must be non-negative integer. The value zero indicates delete immediately. If this value is nil, the default grace period for the specified type will be used. Defaults to a per object value if not specified. zero means delete immediately.", + "name": "gracePeriodSeconds", + "in": "query" + }, + { + "uniqueItems": true, + "type": "boolean", + "description": "Deprecated: please use the PropagationPolicy, this field will be deprecated in 1.7. Should the dependent objects be orphaned. If true/false, the \"orphan\" finalizer will be added to/removed from the object's finalizers list. Either this field or PropagationPolicy may be set, but not both.", + "name": "orphanDependents", + "in": "query" + }, + { + "uniqueItems": true, + "type": "string", + "description": "Whether and how garbage collection will be performed. Either this field or OrphanDependents may be set, but not both. The default policy is decided by the existing finalizer set in the metadata.finalizers and the resource-specific default policy. Acceptable values are: 'Orphan' - orphan the dependents; 'Background' - allow the garbage collector to delete the dependents in the background; 'Foreground' - a cascading policy that deletes all dependents in the foreground.", + "name": "propagationPolicy", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.Status" + } + }, + "202": { + "description": "Accepted", + "schema": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.Status" + } + }, + "401": { + "description": "Unauthorized" + } + }, + "x-kubernetes-action": "delete", + "x-kubernetes-group-version-kind": { + "group": "coordination.k8s.io", + "kind": "Lease", + "version": "v1" + } + }, + "patch": { + "description": "partially update the specified Lease", + "consumes": [ + "application/json-patch+json", + "application/merge-patch+json", + "application/strategic-merge-patch+json" + ], + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf" + ], + "schemes": [ + "https" + ], + "tags": [ + "coordination_v1" + ], + "operationId": "patchCoordinationV1NamespacedLease", + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.Patch" + } + }, + { + "uniqueItems": true, + "type": "string", + "description": "When present, indicates that modifications should not be persisted. An invalid or unrecognized dryRun directive will result in an error response and no further processing of the request. Valid values are: - All: all dry run stages will be processed", + "name": "dryRun", + "in": "query" + }, + { + "uniqueItems": true, + "type": "boolean", + "description": "Force is going to \"force\" Apply requests. It means user will re-acquire conflicting fields owned by other people. Force flag must be unset for non-apply patch requests.", + "name": "force", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/io.k8s.api.coordination.v1.Lease" + } + }, + "401": { + "description": "Unauthorized" + } + }, + "x-kubernetes-action": "patch", + "x-kubernetes-group-version-kind": { + "group": "coordination.k8s.io", + "kind": "Lease", + "version": "v1" + } + }, + "parameters": [ + { + "uniqueItems": true, + "type": "string", + "description": "name of the Lease", + "name": "name", + "in": "path", + "required": true + }, + { + "uniqueItems": true, + "type": "string", + "description": "object name and auth scope, such as for teams and projects", + "name": "namespace", + "in": "path", + "required": true + }, + { + "uniqueItems": true, + "type": "string", + "description": "If 'true', then the output is pretty printed.", + "name": "pretty", + "in": "query" + } + ] + }, + "/apis/coordination.k8s.io/v1/watch/leases": { + "get": { + "description": "watch individual changes to a list of Lease. deprecated: use the 'watch' parameter with a list operation instead.", + "consumes": [ + "*/*" + ], + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf", + "application/json;stream=watch", + "application/vnd.kubernetes.protobuf;stream=watch" + ], + "schemes": [ + "https" + ], + "tags": [ + "coordination_v1" + ], + "operationId": "watchCoordinationV1LeaseListForAllNamespaces", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.WatchEvent" + } + }, + "401": { + "description": "Unauthorized" + } + }, + "x-kubernetes-action": "watchlist", + "x-kubernetes-group-version-kind": { + "group": "coordination.k8s.io", + "kind": "Lease", + "version": "v1" + } + }, + "parameters": [ + { + "uniqueItems": true, + "type": "string", + "description": "The continue option should be set when retrieving more results from the server. Since this value is server defined, clients may only use the continue value from a previous query result with identical query parameters (except for the value of continue) and the server may reject a continue value it does not recognize. If the specified continue value is no longer valid whether due to expiration (generally five to fifteen minutes) or a configuration change on the server, the server will respond with a 410 ResourceExpired error together with a continue token. If the client needs a consistent list, it must restart their list without the continue field. Otherwise, the client may send another list request with the token received with the 410 error, the server will respond with a list starting from the next key, but from the latest snapshot, which is inconsistent from the previous list results - objects that are created, modified, or deleted after the first list request will be included in the response, as long as their keys are after the \"next key\".\n\nThis field is not supported when watch is true. Clients may start a watch from the last resourceVersion value returned by the server and not miss any modifications.", + "name": "continue", + "in": "query" + }, + { + "uniqueItems": true, + "type": "string", + "description": "A selector to restrict the list of returned objects by their fields. Defaults to everything.", + "name": "fieldSelector", + "in": "query" + }, + { + "uniqueItems": true, + "type": "boolean", + "description": "If true, partially initialized resources are included in the response.", + "name": "includeUninitialized", + "in": "query" + }, + { + "uniqueItems": true, + "type": "string", + "description": "A selector to restrict the list of returned objects by their labels. Defaults to everything.", + "name": "labelSelector", + "in": "query" + }, + { + "uniqueItems": true, + "type": "integer", + "description": "limit is a maximum number of responses to return for a list call. If more items exist, the server will set the `continue` field on the list metadata to a value that can be used with the same initial query to retrieve the next set of results. Setting a limit may return fewer than the requested amount of items (up to zero items) in the event all requested objects are filtered out and clients should only use the presence of the continue field to determine whether more results are available. Servers may choose not to support the limit argument and will return all of the available results. If limit is specified and the continue field is empty, clients may assume that no more results are available. This field is not supported if watch is true.\n\nThe server guarantees that the objects returned when using continue will be identical to issuing a single list call without a limit - that is, no objects created, modified, or deleted after the first request is issued will be included in any subsequent continued requests. This is sometimes referred to as a consistent snapshot, and ensures that a client that is using limit to receive smaller chunks of a very large result can ensure they see all possible objects. If objects are updated during a chunked list the version of the object that was present at the time the first list result was calculated is returned.", + "name": "limit", + "in": "query" + }, + { + "uniqueItems": true, + "type": "string", + "description": "If 'true', then the output is pretty printed.", + "name": "pretty", + "in": "query" + }, + { + "uniqueItems": true, + "type": "string", + "description": "When specified with a watch call, shows changes that occur after that particular version of a resource. Defaults to changes from the beginning of history. When specified for list: - if unset, then the result is returned from remote storage based on quorum-read flag; - if it's 0, then we simply return what we currently have in cache, no guarantee; - if set to non zero, then the result is at least as fresh as given rv.", + "name": "resourceVersion", + "in": "query" + }, + { + "uniqueItems": true, + "type": "integer", + "description": "Timeout for the list/watch call. This limits the duration of the call, regardless of any activity or inactivity.", + "name": "timeoutSeconds", + "in": "query" + }, + { + "uniqueItems": true, + "type": "boolean", + "description": "Watch for changes to the described resources and return them as a stream of add, update, and remove notifications. Specify resourceVersion.", + "name": "watch", + "in": "query" + } + ] + }, + "/apis/coordination.k8s.io/v1/watch/namespaces/{namespace}/leases": { + "get": { + "description": "watch individual changes to a list of Lease. deprecated: use the 'watch' parameter with a list operation instead.", + "consumes": [ + "*/*" + ], + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf", + "application/json;stream=watch", + "application/vnd.kubernetes.protobuf;stream=watch" + ], + "schemes": [ + "https" + ], + "tags": [ + "coordination_v1" + ], + "operationId": "watchCoordinationV1NamespacedLeaseList", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.WatchEvent" + } + }, + "401": { + "description": "Unauthorized" + } + }, + "x-kubernetes-action": "watchlist", + "x-kubernetes-group-version-kind": { + "group": "coordination.k8s.io", + "kind": "Lease", + "version": "v1" + } + }, + "parameters": [ + { + "uniqueItems": true, + "type": "string", + "description": "The continue option should be set when retrieving more results from the server. Since this value is server defined, clients may only use the continue value from a previous query result with identical query parameters (except for the value of continue) and the server may reject a continue value it does not recognize. If the specified continue value is no longer valid whether due to expiration (generally five to fifteen minutes) or a configuration change on the server, the server will respond with a 410 ResourceExpired error together with a continue token. If the client needs a consistent list, it must restart their list without the continue field. Otherwise, the client may send another list request with the token received with the 410 error, the server will respond with a list starting from the next key, but from the latest snapshot, which is inconsistent from the previous list results - objects that are created, modified, or deleted after the first list request will be included in the response, as long as their keys are after the \"next key\".\n\nThis field is not supported when watch is true. Clients may start a watch from the last resourceVersion value returned by the server and not miss any modifications.", + "name": "continue", + "in": "query" + }, + { + "uniqueItems": true, + "type": "string", + "description": "A selector to restrict the list of returned objects by their fields. Defaults to everything.", + "name": "fieldSelector", + "in": "query" + }, + { + "uniqueItems": true, + "type": "boolean", + "description": "If true, partially initialized resources are included in the response.", + "name": "includeUninitialized", + "in": "query" + }, + { + "uniqueItems": true, + "type": "string", + "description": "A selector to restrict the list of returned objects by their labels. Defaults to everything.", + "name": "labelSelector", + "in": "query" + }, + { + "uniqueItems": true, + "type": "integer", + "description": "limit is a maximum number of responses to return for a list call. If more items exist, the server will set the `continue` field on the list metadata to a value that can be used with the same initial query to retrieve the next set of results. Setting a limit may return fewer than the requested amount of items (up to zero items) in the event all requested objects are filtered out and clients should only use the presence of the continue field to determine whether more results are available. Servers may choose not to support the limit argument and will return all of the available results. If limit is specified and the continue field is empty, clients may assume that no more results are available. This field is not supported if watch is true.\n\nThe server guarantees that the objects returned when using continue will be identical to issuing a single list call without a limit - that is, no objects created, modified, or deleted after the first request is issued will be included in any subsequent continued requests. This is sometimes referred to as a consistent snapshot, and ensures that a client that is using limit to receive smaller chunks of a very large result can ensure they see all possible objects. If objects are updated during a chunked list the version of the object that was present at the time the first list result was calculated is returned.", + "name": "limit", + "in": "query" + }, + { + "uniqueItems": true, + "type": "string", + "description": "object name and auth scope, such as for teams and projects", + "name": "namespace", + "in": "path", + "required": true + }, + { + "uniqueItems": true, + "type": "string", + "description": "If 'true', then the output is pretty printed.", + "name": "pretty", + "in": "query" + }, + { + "uniqueItems": true, + "type": "string", + "description": "When specified with a watch call, shows changes that occur after that particular version of a resource. Defaults to changes from the beginning of history. When specified for list: - if unset, then the result is returned from remote storage based on quorum-read flag; - if it's 0, then we simply return what we currently have in cache, no guarantee; - if set to non zero, then the result is at least as fresh as given rv.", + "name": "resourceVersion", + "in": "query" + }, + { + "uniqueItems": true, + "type": "integer", + "description": "Timeout for the list/watch call. This limits the duration of the call, regardless of any activity or inactivity.", + "name": "timeoutSeconds", + "in": "query" + }, + { + "uniqueItems": true, + "type": "boolean", + "description": "Watch for changes to the described resources and return them as a stream of add, update, and remove notifications. Specify resourceVersion.", + "name": "watch", + "in": "query" + } + ] + }, + "/apis/coordination.k8s.io/v1/watch/namespaces/{namespace}/leases/{name}": { + "get": { + "description": "watch changes to an object of kind Lease. deprecated: use the 'watch' parameter with a list operation instead, filtered to a single item with the 'fieldSelector' parameter.", + "consumes": [ + "*/*" + ], + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf", + "application/json;stream=watch", + "application/vnd.kubernetes.protobuf;stream=watch" + ], + "schemes": [ + "https" + ], + "tags": [ + "coordination_v1" + ], + "operationId": "watchCoordinationV1NamespacedLease", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.WatchEvent" + } + }, + "401": { + "description": "Unauthorized" + } + }, + "x-kubernetes-action": "watch", + "x-kubernetes-group-version-kind": { + "group": "coordination.k8s.io", + "kind": "Lease", + "version": "v1" + } + }, + "parameters": [ + { + "uniqueItems": true, + "type": "string", + "description": "The continue option should be set when retrieving more results from the server. Since this value is server defined, clients may only use the continue value from a previous query result with identical query parameters (except for the value of continue) and the server may reject a continue value it does not recognize. If the specified continue value is no longer valid whether due to expiration (generally five to fifteen minutes) or a configuration change on the server, the server will respond with a 410 ResourceExpired error together with a continue token. If the client needs a consistent list, it must restart their list without the continue field. Otherwise, the client may send another list request with the token received with the 410 error, the server will respond with a list starting from the next key, but from the latest snapshot, which is inconsistent from the previous list results - objects that are created, modified, or deleted after the first list request will be included in the response, as long as their keys are after the \"next key\".\n\nThis field is not supported when watch is true. Clients may start a watch from the last resourceVersion value returned by the server and not miss any modifications.", + "name": "continue", + "in": "query" + }, + { + "uniqueItems": true, + "type": "string", + "description": "A selector to restrict the list of returned objects by their fields. Defaults to everything.", + "name": "fieldSelector", + "in": "query" + }, + { + "uniqueItems": true, + "type": "boolean", + "description": "If true, partially initialized resources are included in the response.", + "name": "includeUninitialized", + "in": "query" + }, + { + "uniqueItems": true, + "type": "string", + "description": "A selector to restrict the list of returned objects by their labels. Defaults to everything.", + "name": "labelSelector", + "in": "query" + }, + { + "uniqueItems": true, + "type": "integer", + "description": "limit is a maximum number of responses to return for a list call. If more items exist, the server will set the `continue` field on the list metadata to a value that can be used with the same initial query to retrieve the next set of results. Setting a limit may return fewer than the requested amount of items (up to zero items) in the event all requested objects are filtered out and clients should only use the presence of the continue field to determine whether more results are available. Servers may choose not to support the limit argument and will return all of the available results. If limit is specified and the continue field is empty, clients may assume that no more results are available. This field is not supported if watch is true.\n\nThe server guarantees that the objects returned when using continue will be identical to issuing a single list call without a limit - that is, no objects created, modified, or deleted after the first request is issued will be included in any subsequent continued requests. This is sometimes referred to as a consistent snapshot, and ensures that a client that is using limit to receive smaller chunks of a very large result can ensure they see all possible objects. If objects are updated during a chunked list the version of the object that was present at the time the first list result was calculated is returned.", + "name": "limit", + "in": "query" + }, + { + "uniqueItems": true, + "type": "string", + "description": "name of the Lease", + "name": "name", + "in": "path", + "required": true + }, + { + "uniqueItems": true, + "type": "string", + "description": "object name and auth scope, such as for teams and projects", + "name": "namespace", + "in": "path", + "required": true + }, + { + "uniqueItems": true, + "type": "string", + "description": "If 'true', then the output is pretty printed.", + "name": "pretty", + "in": "query" + }, + { + "uniqueItems": true, + "type": "string", + "description": "When specified with a watch call, shows changes that occur after that particular version of a resource. Defaults to changes from the beginning of history. When specified for list: - if unset, then the result is returned from remote storage based on quorum-read flag; - if it's 0, then we simply return what we currently have in cache, no guarantee; - if set to non zero, then the result is at least as fresh as given rv.", + "name": "resourceVersion", + "in": "query" + }, + { + "uniqueItems": true, + "type": "integer", + "description": "Timeout for the list/watch call. This limits the duration of the call, regardless of any activity or inactivity.", + "name": "timeoutSeconds", + "in": "query" + }, + { + "uniqueItems": true, + "type": "boolean", + "description": "Watch for changes to the described resources and return them as a stream of add, update, and remove notifications. Specify resourceVersion.", + "name": "watch", + "in": "query" + } + ] + }, "/apis/coordination.k8s.io/v1beta1/": { "get": { "description": "get available resources", @@ -51284,13 +52296,6 @@ "description": "When present, indicates that modifications should not be persisted. An invalid or unrecognized dryRun directive will result in an error response and no further processing of the request. Valid values are: - All: all dry run stages will be processed", "name": "dryRun", "in": "query" - }, - { - "uniqueItems": true, - "type": "boolean", - "description": "Force is going to \"force\" Apply requests. It means user will re-acquire conflicting fields owned by other people. Force flag must be unset for non-apply patch requests.", - "name": "force", - "in": "query" } ], "responses": { @@ -84276,6 +85281,95 @@ } } }, + "io.k8s.api.coordination.v1.Lease": { + "description": "Lease defines a lease concept.", + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "description": "More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta" + }, + "spec": { + "description": "Specification of the Lease. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status", + "$ref": "#/definitions/io.k8s.api.coordination.v1.LeaseSpec" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "coordination.k8s.io", + "kind": "Lease", + "version": "v1" + } + ] + }, + "io.k8s.api.coordination.v1.LeaseList": { + "description": "LeaseList is a list of Lease objects.", + "required": [ + "items" + ], + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "items": { + "description": "Items is a list of schema objects.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.api.coordination.v1.Lease" + } + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "description": "Standard list metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "coordination.k8s.io", + "kind": "LeaseList", + "version": "v1" + } + ] + }, + "io.k8s.api.coordination.v1.LeaseSpec": { + "description": "LeaseSpec is a specification of a Lease.", + "properties": { + "acquireTime": { + "description": "acquireTime is a time when the current lease was acquired.", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.MicroTime" + }, + "holderIdentity": { + "description": "holderIdentity contains the identity of the holder of a current lease.", + "type": "string" + }, + "leaseDurationSeconds": { + "description": "leaseDurationSeconds is a duration that candidates for a lease need to wait to force acquire it. This is measure against time of last observed RenewTime.", + "type": "integer", + "format": "int32" + }, + "leaseTransitions": { + "description": "leaseTransitions is the number of transitions of a lease between holders.", + "type": "integer", + "format": "int32" + }, + "renewTime": { + "description": "renewTime is a time when the current holder of a lease has last updated the lease.", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.MicroTime" + } + } + }, "io.k8s.api.coordination.v1beta1.Lease": { "description": "Lease defines a lease concept.", "properties": { @@ -94629,6 +95723,11 @@ "kind": "DeleteOptions", "version": "v1beta1" }, + { + "group": "coordination.k8s.io", + "kind": "DeleteOptions", + "version": "v1" + }, { "group": "coordination.k8s.io", "kind": "DeleteOptions", @@ -95222,6 +96321,11 @@ "kind": "WatchEvent", "version": "v1beta1" }, + { + "group": "coordination.k8s.io", + "kind": "WatchEvent", + "version": "v1" + }, { "group": "coordination.k8s.io", "kind": "WatchEvent", diff --git a/api/swagger-spec/coordination.k8s.io_v1.json b/api/swagger-spec/coordination.k8s.io_v1.json new file mode 100644 index 00000000000..20c9720deae --- /dev/null +++ b/api/swagger-spec/coordination.k8s.io_v1.json @@ -0,0 +1,1551 @@ +{ + "swaggerVersion": "1.2", + "apiVersion": "coordination.k8s.io/v1", + "basePath": "https://10.10.10.10:6443", + "resourcePath": "/apis/coordination.k8s.io/v1", + "info": { + "title": "", + "description": "" + }, + "apis": [ + { + "path": "/apis/coordination.k8s.io/v1/namespaces/{namespace}/leases", + "description": "API at /apis/coordination.k8s.io/v1", + "operations": [ + { + "type": "v1.LeaseList", + "method": "GET", + "summary": "list or watch objects of kind Lease", + "nickname": "listNamespacedLease", + "parameters": [ + { + "type": "string", + "paramType": "query", + "name": "pretty", + "description": "If 'true', then the output is pretty printed.", + "required": false, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "labelSelector", + "description": "A selector to restrict the list of returned objects by their labels. Defaults to everything.", + "required": false, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "fieldSelector", + "description": "A selector to restrict the list of returned objects by their fields. Defaults to everything.", + "required": false, + "allowMultiple": false + }, + { + "type": "boolean", + "paramType": "query", + "name": "includeUninitialized", + "description": "If true, partially initialized resources are included in the response.", + "required": false, + "allowMultiple": false + }, + { + "type": "boolean", + "paramType": "query", + "name": "watch", + "description": "Watch for changes to the described resources and return them as a stream of add, update, and remove notifications. Specify resourceVersion.", + "required": false, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "resourceVersion", + "description": "When specified with a watch call, shows changes that occur after that particular version of a resource. Defaults to changes from the beginning of history. When specified for list: - if unset, then the result is returned from remote storage based on quorum-read flag; - if it's 0, then we simply return what we currently have in cache, no guarantee; - if set to non zero, then the result is at least as fresh as given rv.", + "required": false, + "allowMultiple": false + }, + { + "type": "integer", + "paramType": "query", + "name": "timeoutSeconds", + "description": "Timeout for the list/watch call. This limits the duration of the call, regardless of any activity or inactivity.", + "required": false, + "allowMultiple": false + }, + { + "type": "integer", + "paramType": "query", + "name": "limit", + "description": "limit is a maximum number of responses to return for a list call. If more items exist, the server will set the `continue` field on the list metadata to a value that can be used with the same initial query to retrieve the next set of results. Setting a limit may return fewer than the requested amount of items (up to zero items) in the event all requested objects are filtered out and clients should only use the presence of the continue field to determine whether more results are available. Servers may choose not to support the limit argument and will return all of the available results. If limit is specified and the continue field is empty, clients may assume that no more results are available. This field is not supported if watch is true.\n\nThe server guarantees that the objects returned when using continue will be identical to issuing a single list call without a limit - that is, no objects created, modified, or deleted after the first request is issued will be included in any subsequent continued requests. This is sometimes referred to as a consistent snapshot, and ensures that a client that is using limit to receive smaller chunks of a very large result can ensure they see all possible objects. If objects are updated during a chunked list the version of the object that was present at the time the first list result was calculated is returned.", + "required": false, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "continue", + "description": "The continue option should be set when retrieving more results from the server. Since this value is server defined, clients may only use the continue value from a previous query result with identical query parameters (except for the value of continue) and the server may reject a continue value it does not recognize. If the specified continue value is no longer valid whether due to expiration (generally five to fifteen minutes) or a configuration change on the server, the server will respond with a 410 ResourceExpired error together with a continue token. If the client needs a consistent list, it must restart their list without the continue field. Otherwise, the client may send another list request with the token received with the 410 error, the server will respond with a list starting from the next key, but from the latest snapshot, which is inconsistent from the previous list results - objects that are created, modified, or deleted after the first list request will be included in the response, as long as their keys are after the \"next key\".\n\nThis field is not supported when watch is true. Clients may start a watch from the last resourceVersion value returned by the server and not miss any modifications.", + "required": false, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "path", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": true, + "allowMultiple": false + } + ], + "responseMessages": [ + { + "code": 200, + "message": "OK", + "responseModel": "v1.LeaseList" + } + ], + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf", + "application/json;stream=watch", + "application/vnd.kubernetes.protobuf;stream=watch" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "v1.Lease", + "method": "POST", + "summary": "create a Lease", + "nickname": "createNamespacedLease", + "parameters": [ + { + "type": "string", + "paramType": "query", + "name": "pretty", + "description": "If 'true', then the output is pretty printed.", + "required": false, + "allowMultiple": false + }, + { + "type": "v1.Lease", + "paramType": "body", + "name": "body", + "description": "", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "dryRun", + "description": "When present, indicates that modifications should not be persisted. An invalid or unrecognized dryRun directive will result in an error response and no further processing of the request. Valid values are: - All: all dry run stages will be processed", + "required": false, + "allowMultiple": false + }, + { + "type": "boolean", + "paramType": "query", + "name": "includeUninitialized", + "description": "If IncludeUninitialized is specified, the object may be returned without completing initialization.", + "required": false, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "path", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": true, + "allowMultiple": false + } + ], + "responseMessages": [ + { + "code": 200, + "message": "OK", + "responseModel": "v1.Lease" + }, + { + "code": 201, + "message": "Created", + "responseModel": "v1.Lease" + }, + { + "code": 202, + "message": "Accepted", + "responseModel": "v1.Lease" + } + ], + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "v1.Status", + "method": "DELETE", + "summary": "delete collection of Lease", + "nickname": "deletecollectionNamespacedLease", + "parameters": [ + { + "type": "string", + "paramType": "query", + "name": "pretty", + "description": "If 'true', then the output is pretty printed.", + "required": false, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "labelSelector", + "description": "A selector to restrict the list of returned objects by their labels. Defaults to everything.", + "required": false, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "fieldSelector", + "description": "A selector to restrict the list of returned objects by their fields. Defaults to everything.", + "required": false, + "allowMultiple": false + }, + { + "type": "boolean", + "paramType": "query", + "name": "includeUninitialized", + "description": "If true, partially initialized resources are included in the response.", + "required": false, + "allowMultiple": false + }, + { + "type": "boolean", + "paramType": "query", + "name": "watch", + "description": "Watch for changes to the described resources and return them as a stream of add, update, and remove notifications. Specify resourceVersion.", + "required": false, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "resourceVersion", + "description": "When specified with a watch call, shows changes that occur after that particular version of a resource. Defaults to changes from the beginning of history. When specified for list: - if unset, then the result is returned from remote storage based on quorum-read flag; - if it's 0, then we simply return what we currently have in cache, no guarantee; - if set to non zero, then the result is at least as fresh as given rv.", + "required": false, + "allowMultiple": false + }, + { + "type": "integer", + "paramType": "query", + "name": "timeoutSeconds", + "description": "Timeout for the list/watch call. This limits the duration of the call, regardless of any activity or inactivity.", + "required": false, + "allowMultiple": false + }, + { + "type": "integer", + "paramType": "query", + "name": "limit", + "description": "limit is a maximum number of responses to return for a list call. If more items exist, the server will set the `continue` field on the list metadata to a value that can be used with the same initial query to retrieve the next set of results. Setting a limit may return fewer than the requested amount of items (up to zero items) in the event all requested objects are filtered out and clients should only use the presence of the continue field to determine whether more results are available. Servers may choose not to support the limit argument and will return all of the available results. If limit is specified and the continue field is empty, clients may assume that no more results are available. This field is not supported if watch is true.\n\nThe server guarantees that the objects returned when using continue will be identical to issuing a single list call without a limit - that is, no objects created, modified, or deleted after the first request is issued will be included in any subsequent continued requests. This is sometimes referred to as a consistent snapshot, and ensures that a client that is using limit to receive smaller chunks of a very large result can ensure they see all possible objects. If objects are updated during a chunked list the version of the object that was present at the time the first list result was calculated is returned.", + "required": false, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "continue", + "description": "The continue option should be set when retrieving more results from the server. Since this value is server defined, clients may only use the continue value from a previous query result with identical query parameters (except for the value of continue) and the server may reject a continue value it does not recognize. If the specified continue value is no longer valid whether due to expiration (generally five to fifteen minutes) or a configuration change on the server, the server will respond with a 410 ResourceExpired error together with a continue token. If the client needs a consistent list, it must restart their list without the continue field. Otherwise, the client may send another list request with the token received with the 410 error, the server will respond with a list starting from the next key, but from the latest snapshot, which is inconsistent from the previous list results - objects that are created, modified, or deleted after the first list request will be included in the response, as long as their keys are after the \"next key\".\n\nThis field is not supported when watch is true. Clients may start a watch from the last resourceVersion value returned by the server and not miss any modifications.", + "required": false, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "path", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": true, + "allowMultiple": false + } + ], + "responseMessages": [ + { + "code": 200, + "message": "OK", + "responseModel": "v1.Status" + } + ], + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/apis/coordination.k8s.io/v1/watch/namespaces/{namespace}/leases", + "description": "API at /apis/coordination.k8s.io/v1", + "operations": [ + { + "type": "v1.WatchEvent", + "method": "GET", + "summary": "watch individual changes to a list of Lease. deprecated: use the 'watch' parameter with a list operation instead.", + "nickname": "watchNamespacedLeaseList", + "parameters": [ + { + "type": "string", + "paramType": "query", + "name": "pretty", + "description": "If 'true', then the output is pretty printed.", + "required": false, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "labelSelector", + "description": "A selector to restrict the list of returned objects by their labels. Defaults to everything.", + "required": false, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "fieldSelector", + "description": "A selector to restrict the list of returned objects by their fields. Defaults to everything.", + "required": false, + "allowMultiple": false + }, + { + "type": "boolean", + "paramType": "query", + "name": "includeUninitialized", + "description": "If true, partially initialized resources are included in the response.", + "required": false, + "allowMultiple": false + }, + { + "type": "boolean", + "paramType": "query", + "name": "watch", + "description": "Watch for changes to the described resources and return them as a stream of add, update, and remove notifications. Specify resourceVersion.", + "required": false, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "resourceVersion", + "description": "When specified with a watch call, shows changes that occur after that particular version of a resource. Defaults to changes from the beginning of history. When specified for list: - if unset, then the result is returned from remote storage based on quorum-read flag; - if it's 0, then we simply return what we currently have in cache, no guarantee; - if set to non zero, then the result is at least as fresh as given rv.", + "required": false, + "allowMultiple": false + }, + { + "type": "integer", + "paramType": "query", + "name": "timeoutSeconds", + "description": "Timeout for the list/watch call. This limits the duration of the call, regardless of any activity or inactivity.", + "required": false, + "allowMultiple": false + }, + { + "type": "integer", + "paramType": "query", + "name": "limit", + "description": "limit is a maximum number of responses to return for a list call. If more items exist, the server will set the `continue` field on the list metadata to a value that can be used with the same initial query to retrieve the next set of results. Setting a limit may return fewer than the requested amount of items (up to zero items) in the event all requested objects are filtered out and clients should only use the presence of the continue field to determine whether more results are available. Servers may choose not to support the limit argument and will return all of the available results. If limit is specified and the continue field is empty, clients may assume that no more results are available. This field is not supported if watch is true.\n\nThe server guarantees that the objects returned when using continue will be identical to issuing a single list call without a limit - that is, no objects created, modified, or deleted after the first request is issued will be included in any subsequent continued requests. This is sometimes referred to as a consistent snapshot, and ensures that a client that is using limit to receive smaller chunks of a very large result can ensure they see all possible objects. If objects are updated during a chunked list the version of the object that was present at the time the first list result was calculated is returned.", + "required": false, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "continue", + "description": "The continue option should be set when retrieving more results from the server. Since this value is server defined, clients may only use the continue value from a previous query result with identical query parameters (except for the value of continue) and the server may reject a continue value it does not recognize. If the specified continue value is no longer valid whether due to expiration (generally five to fifteen minutes) or a configuration change on the server, the server will respond with a 410 ResourceExpired error together with a continue token. If the client needs a consistent list, it must restart their list without the continue field. Otherwise, the client may send another list request with the token received with the 410 error, the server will respond with a list starting from the next key, but from the latest snapshot, which is inconsistent from the previous list results - objects that are created, modified, or deleted after the first list request will be included in the response, as long as their keys are after the \"next key\".\n\nThis field is not supported when watch is true. Clients may start a watch from the last resourceVersion value returned by the server and not miss any modifications.", + "required": false, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "path", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": true, + "allowMultiple": false + } + ], + "responseMessages": [ + { + "code": 200, + "message": "OK", + "responseModel": "v1.WatchEvent" + } + ], + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf", + "application/json;stream=watch", + "application/vnd.kubernetes.protobuf;stream=watch" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/apis/coordination.k8s.io/v1/namespaces/{namespace}/leases/{name}", + "description": "API at /apis/coordination.k8s.io/v1", + "operations": [ + { + "type": "v1.Lease", + "method": "GET", + "summary": "read the specified Lease", + "nickname": "readNamespacedLease", + "parameters": [ + { + "type": "string", + "paramType": "query", + "name": "pretty", + "description": "If 'true', then the output is pretty printed.", + "required": false, + "allowMultiple": false + }, + { + "type": "boolean", + "paramType": "query", + "name": "export", + "description": "Should this value be exported. Export strips fields that a user can not specify.", + "required": false, + "allowMultiple": false + }, + { + "type": "boolean", + "paramType": "query", + "name": "exact", + "description": "Should the export be exact. Exact export maintains cluster-specific fields like 'Namespace'.", + "required": false, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "path", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Lease", + "required": true, + "allowMultiple": false + } + ], + "responseMessages": [ + { + "code": 200, + "message": "OK", + "responseModel": "v1.Lease" + } + ], + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "v1.Lease", + "method": "PUT", + "summary": "replace the specified Lease", + "nickname": "replaceNamespacedLease", + "parameters": [ + { + "type": "string", + "paramType": "query", + "name": "pretty", + "description": "If 'true', then the output is pretty printed.", + "required": false, + "allowMultiple": false + }, + { + "type": "v1.Lease", + "paramType": "body", + "name": "body", + "description": "", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "dryRun", + "description": "When present, indicates that modifications should not be persisted. An invalid or unrecognized dryRun directive will result in an error response and no further processing of the request. Valid values are: - All: all dry run stages will be processed", + "required": false, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "path", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Lease", + "required": true, + "allowMultiple": false + } + ], + "responseMessages": [ + { + "code": 200, + "message": "OK", + "responseModel": "v1.Lease" + }, + { + "code": 201, + "message": "Created", + "responseModel": "v1.Lease" + } + ], + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "v1.Lease", + "method": "PATCH", + "summary": "partially update the specified Lease", + "nickname": "patchNamespacedLease", + "parameters": [ + { + "type": "string", + "paramType": "query", + "name": "pretty", + "description": "If 'true', then the output is pretty printed.", + "required": false, + "allowMultiple": false + }, + { + "type": "v1.Patch", + "paramType": "body", + "name": "body", + "description": "", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "dryRun", + "description": "When present, indicates that modifications should not be persisted. An invalid or unrecognized dryRun directive will result in an error response and no further processing of the request. Valid values are: - All: all dry run stages will be processed", + "required": false, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "path", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Lease", + "required": true, + "allowMultiple": false + } + ], + "responseMessages": [ + { + "code": 200, + "message": "OK", + "responseModel": "v1.Lease" + } + ], + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf" + ], + "consumes": [ + "application/json-patch+json", + "application/merge-patch+json", + "application/strategic-merge-patch+json" + ] + }, + { + "type": "v1.Status", + "method": "DELETE", + "summary": "delete a Lease", + "nickname": "deleteNamespacedLease", + "parameters": [ + { + "type": "string", + "paramType": "query", + "name": "pretty", + "description": "If 'true', then the output is pretty printed.", + "required": false, + "allowMultiple": false + }, + { + "type": "v1.DeleteOptions", + "paramType": "body", + "name": "body", + "description": "", + "required": false, + "allowMultiple": false + }, + { + "type": "integer", + "paramType": "query", + "name": "gracePeriodSeconds", + "description": "The duration in seconds before the object should be deleted. Value must be non-negative integer. The value zero indicates delete immediately. If this value is nil, the default grace period for the specified type will be used. Defaults to a per object value if not specified. zero means delete immediately.", + "required": false, + "allowMultiple": false + }, + { + "type": "boolean", + "paramType": "query", + "name": "orphanDependents", + "description": "Deprecated: please use the PropagationPolicy, this field will be deprecated in 1.7. Should the dependent objects be orphaned. If true/false, the \"orphan\" finalizer will be added to/removed from the object's finalizers list. Either this field or PropagationPolicy may be set, but not both.", + "required": false, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "propagationPolicy", + "description": "Whether and how garbage collection will be performed. Either this field or OrphanDependents may be set, but not both. The default policy is decided by the existing finalizer set in the metadata.finalizers and the resource-specific default policy. Acceptable values are: 'Orphan' - orphan the dependents; 'Background' - allow the garbage collector to delete the dependents in the background; 'Foreground' - a cascading policy that deletes all dependents in the foreground.", + "required": false, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "dryRun", + "description": "When present, indicates that modifications should not be persisted. An invalid or unrecognized dryRun directive will result in an error response and no further processing of the request. Valid values are: - All: all dry run stages will be processed", + "required": false, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "path", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Lease", + "required": true, + "allowMultiple": false + } + ], + "responseMessages": [ + { + "code": 200, + "message": "OK", + "responseModel": "v1.Status" + }, + { + "code": 202, + "message": "Accepted", + "responseModel": "v1.Status" + } + ], + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/apis/coordination.k8s.io/v1/watch/namespaces/{namespace}/leases/{name}", + "description": "API at /apis/coordination.k8s.io/v1", + "operations": [ + { + "type": "v1.WatchEvent", + "method": "GET", + "summary": "watch changes to an object of kind Lease. deprecated: use the 'watch' parameter with a list operation instead, filtered to a single item with the 'fieldSelector' parameter.", + "nickname": "watchNamespacedLease", + "parameters": [ + { + "type": "string", + "paramType": "query", + "name": "pretty", + "description": "If 'true', then the output is pretty printed.", + "required": false, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "labelSelector", + "description": "A selector to restrict the list of returned objects by their labels. Defaults to everything.", + "required": false, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "fieldSelector", + "description": "A selector to restrict the list of returned objects by their fields. Defaults to everything.", + "required": false, + "allowMultiple": false + }, + { + "type": "boolean", + "paramType": "query", + "name": "includeUninitialized", + "description": "If true, partially initialized resources are included in the response.", + "required": false, + "allowMultiple": false + }, + { + "type": "boolean", + "paramType": "query", + "name": "watch", + "description": "Watch for changes to the described resources and return them as a stream of add, update, and remove notifications. Specify resourceVersion.", + "required": false, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "resourceVersion", + "description": "When specified with a watch call, shows changes that occur after that particular version of a resource. Defaults to changes from the beginning of history. When specified for list: - if unset, then the result is returned from remote storage based on quorum-read flag; - if it's 0, then we simply return what we currently have in cache, no guarantee; - if set to non zero, then the result is at least as fresh as given rv.", + "required": false, + "allowMultiple": false + }, + { + "type": "integer", + "paramType": "query", + "name": "timeoutSeconds", + "description": "Timeout for the list/watch call. This limits the duration of the call, regardless of any activity or inactivity.", + "required": false, + "allowMultiple": false + }, + { + "type": "integer", + "paramType": "query", + "name": "limit", + "description": "limit is a maximum number of responses to return for a list call. If more items exist, the server will set the `continue` field on the list metadata to a value that can be used with the same initial query to retrieve the next set of results. Setting a limit may return fewer than the requested amount of items (up to zero items) in the event all requested objects are filtered out and clients should only use the presence of the continue field to determine whether more results are available. Servers may choose not to support the limit argument and will return all of the available results. If limit is specified and the continue field is empty, clients may assume that no more results are available. This field is not supported if watch is true.\n\nThe server guarantees that the objects returned when using continue will be identical to issuing a single list call without a limit - that is, no objects created, modified, or deleted after the first request is issued will be included in any subsequent continued requests. This is sometimes referred to as a consistent snapshot, and ensures that a client that is using limit to receive smaller chunks of a very large result can ensure they see all possible objects. If objects are updated during a chunked list the version of the object that was present at the time the first list result was calculated is returned.", + "required": false, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "continue", + "description": "The continue option should be set when retrieving more results from the server. Since this value is server defined, clients may only use the continue value from a previous query result with identical query parameters (except for the value of continue) and the server may reject a continue value it does not recognize. If the specified continue value is no longer valid whether due to expiration (generally five to fifteen minutes) or a configuration change on the server, the server will respond with a 410 ResourceExpired error together with a continue token. If the client needs a consistent list, it must restart their list without the continue field. Otherwise, the client may send another list request with the token received with the 410 error, the server will respond with a list starting from the next key, but from the latest snapshot, which is inconsistent from the previous list results - objects that are created, modified, or deleted after the first list request will be included in the response, as long as their keys are after the \"next key\".\n\nThis field is not supported when watch is true. Clients may start a watch from the last resourceVersion value returned by the server and not miss any modifications.", + "required": false, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "path", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Lease", + "required": true, + "allowMultiple": false + } + ], + "responseMessages": [ + { + "code": 200, + "message": "OK", + "responseModel": "v1.WatchEvent" + } + ], + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf", + "application/json;stream=watch", + "application/vnd.kubernetes.protobuf;stream=watch" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/apis/coordination.k8s.io/v1/leases", + "description": "API at /apis/coordination.k8s.io/v1", + "operations": [ + { + "type": "v1.LeaseList", + "method": "GET", + "summary": "list or watch objects of kind Lease", + "nickname": "listLeaseForAllNamespaces", + "parameters": [ + { + "type": "string", + "paramType": "query", + "name": "pretty", + "description": "If 'true', then the output is pretty printed.", + "required": false, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "labelSelector", + "description": "A selector to restrict the list of returned objects by their labels. Defaults to everything.", + "required": false, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "fieldSelector", + "description": "A selector to restrict the list of returned objects by their fields. Defaults to everything.", + "required": false, + "allowMultiple": false + }, + { + "type": "boolean", + "paramType": "query", + "name": "includeUninitialized", + "description": "If true, partially initialized resources are included in the response.", + "required": false, + "allowMultiple": false + }, + { + "type": "boolean", + "paramType": "query", + "name": "watch", + "description": "Watch for changes to the described resources and return them as a stream of add, update, and remove notifications. Specify resourceVersion.", + "required": false, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "resourceVersion", + "description": "When specified with a watch call, shows changes that occur after that particular version of a resource. Defaults to changes from the beginning of history. When specified for list: - if unset, then the result is returned from remote storage based on quorum-read flag; - if it's 0, then we simply return what we currently have in cache, no guarantee; - if set to non zero, then the result is at least as fresh as given rv.", + "required": false, + "allowMultiple": false + }, + { + "type": "integer", + "paramType": "query", + "name": "timeoutSeconds", + "description": "Timeout for the list/watch call. This limits the duration of the call, regardless of any activity or inactivity.", + "required": false, + "allowMultiple": false + }, + { + "type": "integer", + "paramType": "query", + "name": "limit", + "description": "limit is a maximum number of responses to return for a list call. If more items exist, the server will set the `continue` field on the list metadata to a value that can be used with the same initial query to retrieve the next set of results. Setting a limit may return fewer than the requested amount of items (up to zero items) in the event all requested objects are filtered out and clients should only use the presence of the continue field to determine whether more results are available. Servers may choose not to support the limit argument and will return all of the available results. If limit is specified and the continue field is empty, clients may assume that no more results are available. This field is not supported if watch is true.\n\nThe server guarantees that the objects returned when using continue will be identical to issuing a single list call without a limit - that is, no objects created, modified, or deleted after the first request is issued will be included in any subsequent continued requests. This is sometimes referred to as a consistent snapshot, and ensures that a client that is using limit to receive smaller chunks of a very large result can ensure they see all possible objects. If objects are updated during a chunked list the version of the object that was present at the time the first list result was calculated is returned.", + "required": false, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "continue", + "description": "The continue option should be set when retrieving more results from the server. Since this value is server defined, clients may only use the continue value from a previous query result with identical query parameters (except for the value of continue) and the server may reject a continue value it does not recognize. If the specified continue value is no longer valid whether due to expiration (generally five to fifteen minutes) or a configuration change on the server, the server will respond with a 410 ResourceExpired error together with a continue token. If the client needs a consistent list, it must restart their list without the continue field. Otherwise, the client may send another list request with the token received with the 410 error, the server will respond with a list starting from the next key, but from the latest snapshot, which is inconsistent from the previous list results - objects that are created, modified, or deleted after the first list request will be included in the response, as long as their keys are after the \"next key\".\n\nThis field is not supported when watch is true. Clients may start a watch from the last resourceVersion value returned by the server and not miss any modifications.", + "required": false, + "allowMultiple": false + } + ], + "responseMessages": [ + { + "code": 200, + "message": "OK", + "responseModel": "v1.LeaseList" + } + ], + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf", + "application/json;stream=watch", + "application/vnd.kubernetes.protobuf;stream=watch" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/apis/coordination.k8s.io/v1/watch/leases", + "description": "API at /apis/coordination.k8s.io/v1", + "operations": [ + { + "type": "v1.WatchEvent", + "method": "GET", + "summary": "watch individual changes to a list of Lease. deprecated: use the 'watch' parameter with a list operation instead.", + "nickname": "watchLeaseListForAllNamespaces", + "parameters": [ + { + "type": "string", + "paramType": "query", + "name": "pretty", + "description": "If 'true', then the output is pretty printed.", + "required": false, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "labelSelector", + "description": "A selector to restrict the list of returned objects by their labels. Defaults to everything.", + "required": false, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "fieldSelector", + "description": "A selector to restrict the list of returned objects by their fields. Defaults to everything.", + "required": false, + "allowMultiple": false + }, + { + "type": "boolean", + "paramType": "query", + "name": "includeUninitialized", + "description": "If true, partially initialized resources are included in the response.", + "required": false, + "allowMultiple": false + }, + { + "type": "boolean", + "paramType": "query", + "name": "watch", + "description": "Watch for changes to the described resources and return them as a stream of add, update, and remove notifications. Specify resourceVersion.", + "required": false, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "resourceVersion", + "description": "When specified with a watch call, shows changes that occur after that particular version of a resource. Defaults to changes from the beginning of history. When specified for list: - if unset, then the result is returned from remote storage based on quorum-read flag; - if it's 0, then we simply return what we currently have in cache, no guarantee; - if set to non zero, then the result is at least as fresh as given rv.", + "required": false, + "allowMultiple": false + }, + { + "type": "integer", + "paramType": "query", + "name": "timeoutSeconds", + "description": "Timeout for the list/watch call. This limits the duration of the call, regardless of any activity or inactivity.", + "required": false, + "allowMultiple": false + }, + { + "type": "integer", + "paramType": "query", + "name": "limit", + "description": "limit is a maximum number of responses to return for a list call. If more items exist, the server will set the `continue` field on the list metadata to a value that can be used with the same initial query to retrieve the next set of results. Setting a limit may return fewer than the requested amount of items (up to zero items) in the event all requested objects are filtered out and clients should only use the presence of the continue field to determine whether more results are available. Servers may choose not to support the limit argument and will return all of the available results. If limit is specified and the continue field is empty, clients may assume that no more results are available. This field is not supported if watch is true.\n\nThe server guarantees that the objects returned when using continue will be identical to issuing a single list call without a limit - that is, no objects created, modified, or deleted after the first request is issued will be included in any subsequent continued requests. This is sometimes referred to as a consistent snapshot, and ensures that a client that is using limit to receive smaller chunks of a very large result can ensure they see all possible objects. If objects are updated during a chunked list the version of the object that was present at the time the first list result was calculated is returned.", + "required": false, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "continue", + "description": "The continue option should be set when retrieving more results from the server. Since this value is server defined, clients may only use the continue value from a previous query result with identical query parameters (except for the value of continue) and the server may reject a continue value it does not recognize. If the specified continue value is no longer valid whether due to expiration (generally five to fifteen minutes) or a configuration change on the server, the server will respond with a 410 ResourceExpired error together with a continue token. If the client needs a consistent list, it must restart their list without the continue field. Otherwise, the client may send another list request with the token received with the 410 error, the server will respond with a list starting from the next key, but from the latest snapshot, which is inconsistent from the previous list results - objects that are created, modified, or deleted after the first list request will be included in the response, as long as their keys are after the \"next key\".\n\nThis field is not supported when watch is true. Clients may start a watch from the last resourceVersion value returned by the server and not miss any modifications.", + "required": false, + "allowMultiple": false + } + ], + "responseMessages": [ + { + "code": 200, + "message": "OK", + "responseModel": "v1.WatchEvent" + } + ], + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf", + "application/json;stream=watch", + "application/vnd.kubernetes.protobuf;stream=watch" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/apis/coordination.k8s.io/v1", + "description": "API at /apis/coordination.k8s.io/v1", + "operations": [ + { + "type": "v1.APIResourceList", + "method": "GET", + "summary": "get available resources", + "nickname": "getAPIResources", + "parameters": [], + "produces": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf" + ], + "consumes": [ + "application/json", + "application/yaml", + "application/vnd.kubernetes.protobuf" + ] + } + ] + } + ], + "models": { + "v1.LeaseList": { + "id": "v1.LeaseList", + "description": "LeaseList is a list of Lease objects.", + "required": [ + "items" + ], + "properties": { + "kind": { + "type": "string", + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds" + }, + "apiVersion": { + "type": "string", + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources" + }, + "metadata": { + "$ref": "v1.ListMeta", + "description": "Standard list metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata" + }, + "items": { + "type": "array", + "items": { + "$ref": "v1.Lease" + }, + "description": "Items is a list of schema objects." + } + } + }, + "v1.ListMeta": { + "id": "v1.ListMeta", + "description": "ListMeta describes metadata that synthetic resources must have, including lists and various status objects. A resource may have only one of {ObjectMeta, ListMeta}.", + "properties": { + "selfLink": { + "type": "string", + "description": "selfLink is a URL representing this object. Populated by the system. Read-only." + }, + "resourceVersion": { + "type": "string", + "description": "String that identifies the server's internal version of this object that can be used by clients to determine when objects have changed. Value must be treated as opaque by clients and passed unmodified back to the server. Populated by the system. Read-only. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#concurrency-control-and-consistency" + }, + "continue": { + "type": "string", + "description": "continue may be set if the user set a limit on the number of items returned, and indicates that the server has more data available. The value is opaque and may be used to issue another request to the endpoint that served this list to retrieve the next set of available objects. Continuing a consistent list may not be possible if the server configuration has changed or more than a few minutes have passed. The resourceVersion field returned when using this continue value will be identical to the value in the first response, unless you have received this token from an error message." + } + } + }, + "v1.Lease": { + "id": "v1.Lease", + "description": "Lease defines a lease concept.", + "properties": { + "kind": { + "type": "string", + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds" + }, + "apiVersion": { + "type": "string", + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources" + }, + "metadata": { + "$ref": "v1.ObjectMeta", + "description": "More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata" + }, + "spec": { + "$ref": "v1.LeaseSpec", + "description": "Specification of the Lease. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status" + } + } + }, + "v1.ObjectMeta": { + "id": "v1.ObjectMeta", + "description": "ObjectMeta is metadata that all persisted resources must have, which includes all objects users must create.", + "properties": { + "name": { + "type": "string", + "description": "Name must be unique within a namespace. Is required when creating resources, although some resources may allow a client to request the generation of an appropriate name automatically. Name is primarily intended for creation idempotence and configuration definition. Cannot be updated. More info: http://kubernetes.io/docs/user-guide/identifiers#names" + }, + "generateName": { + "type": "string", + "description": "GenerateName is an optional prefix, used by the server, to generate a unique name ONLY IF the Name field has not been provided. If this field is used, the name returned to the client will be different than the name passed. This value will also be combined with a unique suffix. The provided value has the same validation rules as the Name field, and may be truncated by the length of the suffix required to make the value unique on the server.\n\nIf this field is specified and the generated name exists, the server will NOT return a 409 - instead, it will either return 201 Created or 500 with Reason ServerTimeout indicating a unique name could not be found in the time allotted, and the client should retry (optionally after the time indicated in the Retry-After header).\n\nApplied only if Name is not specified. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#idempotency" + }, + "namespace": { + "type": "string", + "description": "Namespace defines the space within each name must be unique. An empty namespace is equivalent to the \"default\" namespace, but \"default\" is the canonical representation. Not all objects are required to be scoped to a namespace - the value of this field for those objects will be empty.\n\nMust be a DNS_LABEL. Cannot be updated. More info: http://kubernetes.io/docs/user-guide/namespaces" + }, + "selfLink": { + "type": "string", + "description": "SelfLink is a URL representing this object. Populated by the system. Read-only." + }, + "uid": { + "type": "string", + "description": "UID is the unique in time and space value for this object. It is typically generated by the server on successful creation of a resource and is not allowed to change on PUT operations.\n\nPopulated by the system. Read-only. More info: http://kubernetes.io/docs/user-guide/identifiers#uids" + }, + "resourceVersion": { + "type": "string", + "description": "An opaque value that represents the internal version of this object that can be used by clients to determine when objects have changed. May be used for optimistic concurrency, change detection, and the watch operation on a resource or set of resources. Clients must treat these values as opaque and passed unmodified back to the server. They may only be valid for a particular resource or set of resources.\n\nPopulated by the system. Read-only. Value must be treated as opaque by clients and . More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#concurrency-control-and-consistency" + }, + "generation": { + "type": "integer", + "format": "int64", + "description": "A sequence number representing a specific generation of the desired state. Populated by the system. Read-only." + }, + "creationTimestamp": { + "type": "string", + "description": "CreationTimestamp is a timestamp representing the server time when this object was created. It is not guaranteed to be set in happens-before order across separate operations. Clients may not set this value. It is represented in RFC3339 form and is in UTC.\n\nPopulated by the system. Read-only. Null for lists. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata" + }, + "deletionTimestamp": { + "type": "string", + "description": "DeletionTimestamp is RFC 3339 date and time at which this resource will be deleted. This field is set by the server when a graceful deletion is requested by the user, and is not directly settable by a client. The resource is expected to be deleted (no longer visible from resource lists, and not reachable by name) after the time in this field, once the finalizers list is empty. As long as the finalizers list contains items, deletion is blocked. Once the deletionTimestamp is set, this value may not be unset or be set further into the future, although it may be shortened or the resource may be deleted prior to this time. For example, a user may request that a pod is deleted in 30 seconds. The Kubelet will react by sending a graceful termination signal to the containers in the pod. After that 30 seconds, the Kubelet will send a hard termination signal (SIGKILL) to the container and after cleanup, remove the pod from the API. In the presence of network partitions, this object may still exist after this timestamp, until an administrator or automated process can determine the resource is fully terminated. If not set, graceful deletion of the object has not been requested.\n\nPopulated by the system when a graceful deletion is requested. Read-only. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata" + }, + "deletionGracePeriodSeconds": { + "type": "integer", + "format": "int64", + "description": "Number of seconds allowed for this object to gracefully terminate before it will be removed from the system. Only set when deletionTimestamp is also set. May only be shortened. Read-only." + }, + "labels": { + "type": "object", + "description": "Map of string keys and values that can be used to organize and categorize (scope and select) objects. May match selectors of replication controllers and services. More info: http://kubernetes.io/docs/user-guide/labels" + }, + "annotations": { + "type": "object", + "description": "Annotations is an unstructured key value map stored with a resource that may be set by external tools to store and retrieve arbitrary metadata. They are not queryable and should be preserved when modifying objects. More info: http://kubernetes.io/docs/user-guide/annotations" + }, + "ownerReferences": { + "type": "array", + "items": { + "$ref": "v1.OwnerReference" + }, + "description": "List of objects depended by this object. If ALL objects in the list have been deleted, this object will be garbage collected. If this object is managed by a controller, then an entry in this list will point to this controller, with the controller field set to true. There cannot be more than one managing controller." + }, + "initializers": { + "$ref": "v1.Initializers", + "description": "An initializer is a controller which enforces some system invariant at object creation time. This field is a list of initializers that have not yet acted on this object. If nil or empty, this object has been completely initialized. Otherwise, the object is considered uninitialized and is hidden (in list/watch and get calls) from clients that haven't explicitly asked to observe uninitialized objects.\n\nWhen an object is created, the system will populate this list with the current set of initializers. Only privileged users may set or modify this list. Once it is empty, it may not be modified further by any user." + }, + "finalizers": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Must be empty before the object is deleted from the registry. Each entry is an identifier for the responsible component that will remove the entry from the list. If the deletionTimestamp of the object is non-nil, entries in this list can only be removed." + }, + "clusterName": { + "type": "string", + "description": "The name of the cluster which the object belongs to. This is used to distinguish resources with same name and namespace in different clusters. This field is not set anywhere right now and apiserver is going to ignore it if set in create or update request." + } + } + }, + "v1.OwnerReference": { + "id": "v1.OwnerReference", + "description": "OwnerReference contains enough information to let you identify an owning object. An owning object must be in the same namespace as the dependent, or be cluster-scoped, so there is no namespace field.", + "required": [ + "apiVersion", + "kind", + "name", + "uid" + ], + "properties": { + "apiVersion": { + "type": "string", + "description": "API version of the referent." + }, + "kind": { + "type": "string", + "description": "Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds" + }, + "name": { + "type": "string", + "description": "Name of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#names" + }, + "uid": { + "type": "string", + "description": "UID of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#uids" + }, + "controller": { + "type": "boolean", + "description": "If true, this reference points to the managing controller." + }, + "blockOwnerDeletion": { + "type": "boolean", + "description": "If true, AND if the owner has the \"foregroundDeletion\" finalizer, then the owner cannot be deleted from the key-value store until this reference is removed. Defaults to false. To set this field, a user needs \"delete\" permission of the owner, otherwise 422 (Unprocessable Entity) will be returned." + } + } + }, + "v1.Initializers": { + "id": "v1.Initializers", + "description": "Initializers tracks the progress of initialization.", + "required": [ + "pending" + ], + "properties": { + "pending": { + "type": "array", + "items": { + "$ref": "v1.Initializer" + }, + "description": "Pending is a list of initializers that must execute in order before this object is visible. When the last pending initializer is removed, and no failing result is set, the initializers struct will be set to nil and the object is considered as initialized and visible to all clients." + }, + "result": { + "$ref": "v1.Status", + "description": "If result is set with the Failure field, the object will be persisted to storage and then deleted, ensuring that other clients can observe the deletion." + } + } + }, + "v1.Initializer": { + "id": "v1.Initializer", + "description": "Initializer is information about an initializer that has not yet completed.", + "required": [ + "name" + ], + "properties": { + "name": { + "type": "string", + "description": "name of the process that is responsible for initializing this object." + } + } + }, + "v1.Status": { + "id": "v1.Status", + "description": "Status is a return value for calls that don't return other objects.", + "properties": { + "kind": { + "type": "string", + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds" + }, + "apiVersion": { + "type": "string", + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources" + }, + "metadata": { + "$ref": "v1.ListMeta", + "description": "Standard list metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds" + }, + "status": { + "type": "string", + "description": "Status of the operation. One of: \"Success\" or \"Failure\". More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status" + }, + "message": { + "type": "string", + "description": "A human-readable description of the status of this operation." + }, + "reason": { + "type": "string", + "description": "A machine-readable description of why this operation is in the \"Failure\" status. If this value is empty there is no information available. A Reason clarifies an HTTP status code but does not override it." + }, + "details": { + "$ref": "v1.StatusDetails", + "description": "Extended data associated with the reason. Each reason may define its own extended details. This field is optional and the data returned is not guaranteed to conform to any schema except that defined by the reason type." + }, + "code": { + "type": "integer", + "format": "int32", + "description": "Suggested HTTP return code for this status, 0 if not set." + } + } + }, + "v1.StatusDetails": { + "id": "v1.StatusDetails", + "description": "StatusDetails is a set of additional properties that MAY be set by the server to provide additional information about a response. The Reason field of a Status object defines what attributes will be set. Clients must ignore fields that do not match the defined type of each attribute, and should assume that any attribute may be empty, invalid, or under defined.", + "properties": { + "name": { + "type": "string", + "description": "The name attribute of the resource associated with the status StatusReason (when there is a single name which can be described)." + }, + "group": { + "type": "string", + "description": "The group attribute of the resource associated with the status StatusReason." + }, + "kind": { + "type": "string", + "description": "The kind attribute of the resource associated with the status StatusReason. On some operations may differ from the requested resource Kind. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds" + }, + "uid": { + "type": "string", + "description": "UID of the resource. (when there is a single resource which can be described). More info: http://kubernetes.io/docs/user-guide/identifiers#uids" + }, + "causes": { + "type": "array", + "items": { + "$ref": "v1.StatusCause" + }, + "description": "The Causes array includes more details associated with the StatusReason failure. Not all StatusReasons may provide detailed causes." + }, + "retryAfterSeconds": { + "type": "integer", + "format": "int32", + "description": "If specified, the time in seconds before the operation should be retried. Some errors may indicate the client must take an alternate action - for those errors this field may indicate how long to wait before taking the alternate action." + } + } + }, + "v1.StatusCause": { + "id": "v1.StatusCause", + "description": "StatusCause provides more information about an api.Status failure, including cases when multiple errors are encountered.", + "properties": { + "reason": { + "type": "string", + "description": "A machine-readable description of the cause of the error. If this value is empty there is no information available." + }, + "message": { + "type": "string", + "description": "A human-readable description of the cause of the error. This field may be presented as-is to a reader." + }, + "field": { + "type": "string", + "description": "The field of the resource that has caused this error, as named by its JSON serialization. May include dot and postfix notation for nested attributes. Arrays are zero-indexed. Fields may appear more than once in an array of causes due to fields having multiple errors. Optional.\n\nExamples:\n \"name\" - the field \"name\" on the current resource\n \"items[0].name\" - the field \"name\" on the first array entry in \"items\"" + } + } + }, + "v1.LeaseSpec": { + "id": "v1.LeaseSpec", + "description": "LeaseSpec is a specification of a Lease.", + "properties": { + "holderIdentity": { + "type": "string", + "description": "holderIdentity contains the identity of the holder of a current lease." + }, + "leaseDurationSeconds": { + "type": "integer", + "format": "int32", + "description": "leaseDurationSeconds is a duration that candidates for a lease need to wait to force acquire it. This is measure against time of last observed RenewTime." + }, + "acquireTime": { + "type": "string", + "description": "acquireTime is a time when the current lease was acquired." + }, + "renewTime": { + "type": "string", + "description": "renewTime is a time when the current holder of a lease has last updated the lease." + }, + "leaseTransitions": { + "type": "integer", + "format": "int32", + "description": "leaseTransitions is the number of transitions of a lease between holders." + } + } + }, + "v1.WatchEvent": { + "id": "v1.WatchEvent", + "required": [ + "type", + "object" + ], + "properties": { + "type": { + "type": "string" + }, + "object": { + "type": "string" + } + } + }, + "v1.Patch": { + "id": "v1.Patch", + "description": "Patch is provided to give a concrete name and type to the Kubernetes PATCH request body.", + "properties": {} + }, + "v1.DeleteOptions": { + "id": "v1.DeleteOptions", + "description": "DeleteOptions may be provided when deleting an API object.", + "properties": { + "kind": { + "type": "string", + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds" + }, + "apiVersion": { + "type": "string", + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources" + }, + "gracePeriodSeconds": { + "type": "integer", + "format": "int64", + "description": "The duration in seconds before the object should be deleted. Value must be non-negative integer. The value zero indicates delete immediately. If this value is nil, the default grace period for the specified type will be used. Defaults to a per object value if not specified. zero means delete immediately." + }, + "preconditions": { + "$ref": "v1.Preconditions", + "description": "Must be fulfilled before a deletion is carried out. If not possible, a 409 Conflict status will be returned." + }, + "orphanDependents": { + "type": "boolean", + "description": "Deprecated: please use the PropagationPolicy, this field will be deprecated in 1.7. Should the dependent objects be orphaned. If true/false, the \"orphan\" finalizer will be added to/removed from the object's finalizers list. Either this field or PropagationPolicy may be set, but not both." + }, + "propagationPolicy": { + "$ref": "v1.DeletionPropagation", + "description": "Whether and how garbage collection will be performed. Either this field or OrphanDependents may be set, but not both. The default policy is decided by the existing finalizer set in the metadata.finalizers and the resource-specific default policy. Acceptable values are: 'Orphan' - orphan the dependents; 'Background' - allow the garbage collector to delete the dependents in the background; 'Foreground' - a cascading policy that deletes all dependents in the foreground." + }, + "dryRun": { + "type": "array", + "items": { + "type": "string" + }, + "description": "When present, indicates that modifications should not be persisted. An invalid or unrecognized dryRun directive will result in an error response and no further processing of the request. Valid values are: - All: all dry run stages will be processed" + } + } + }, + "v1.Preconditions": { + "id": "v1.Preconditions", + "description": "Preconditions must be fulfilled before an operation (update, delete, etc.) is carried out.", + "properties": { + "uid": { + "$ref": "types.UID", + "description": "Specifies the target UID." + } + } + }, + "types.UID": { + "id": "types.UID", + "properties": {} + }, + "v1.DeletionPropagation": { + "id": "v1.DeletionPropagation", + "properties": {} + }, + "v1.APIResourceList": { + "id": "v1.APIResourceList", + "description": "APIResourceList is a list of APIResource, it is used to expose the name of the resources supported in a specific group and version, and if the resource is namespaced.", + "required": [ + "groupVersion", + "resources" + ], + "properties": { + "kind": { + "type": "string", + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds" + }, + "apiVersion": { + "type": "string", + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources" + }, + "groupVersion": { + "type": "string", + "description": "groupVersion is the group and version this APIResourceList is for." + }, + "resources": { + "type": "array", + "items": { + "$ref": "v1.APIResource" + }, + "description": "resources contains the name of the resources and if they are namespaced." + } + } + }, + "v1.APIResource": { + "id": "v1.APIResource", + "description": "APIResource specifies the name of a resource and whether it is namespaced.", + "required": [ + "name", + "singularName", + "namespaced", + "kind", + "verbs" + ], + "properties": { + "name": { + "type": "string", + "description": "name is the plural name of the resource." + }, + "singularName": { + "type": "string", + "description": "singularName is the singular name of the resource. This allows clients to handle plural and singular opaquely. The singularName is more correct for reporting status on a single item and both singular and plural are allowed from the kubectl CLI interface." + }, + "namespaced": { + "type": "boolean", + "description": "namespaced indicates if a resource is namespaced or not." + }, + "group": { + "type": "string", + "description": "group is the preferred group of the resource. Empty implies the group of the containing resource list. For subresources, this may have a different value, for example: Scale\"." + }, + "version": { + "type": "string", + "description": "version is the preferred version of the resource. Empty implies the version of the containing resource list For subresources, this may have a different value, for example: v1 (while inside a v1beta1 version of the core resource's group)\"." + }, + "kind": { + "type": "string", + "description": "kind is the kind for the resource (e.g. 'Foo' is the kind for a resource 'foo')" + }, + "verbs": { + "type": "array", + "items": { + "type": "string" + }, + "description": "verbs is a list of supported kube verbs (this includes get, list, watch, create, update, patch, delete, deletecollection, and proxy)" + }, + "shortNames": { + "type": "array", + "items": { + "type": "string" + }, + "description": "shortNames is a list of suggested short names of the resource." + }, + "categories": { + "type": "array", + "items": { + "type": "string" + }, + "description": "categories is a list of the grouped resources this resource belongs to (e.g. 'all')" + } + } + } + } + } diff --git a/api/swagger-spec/resourceListing.json b/api/swagger-spec/resourceListing.json index ad7391b5684..b7551fb7b67 100644 --- a/api/swagger-spec/resourceListing.json +++ b/api/swagger-spec/resourceListing.json @@ -97,6 +97,10 @@ "path": "/apis/coordination.k8s.io/v1beta1", "description": "API at /apis/coordination.k8s.io/v1beta1" }, + { + "path": "/apis/coordination.k8s.io/v1", + "description": "API at /apis/coordination.k8s.io/v1" + }, { "path": "/apis/coordination.k8s.io", "description": "get information of a group" diff --git a/build/BUILD b/build/BUILD index 8c5b6164b6a..c5657f7d008 100644 --- a/build/BUILD +++ b/build/BUILD @@ -89,12 +89,6 @@ grep ^STABLE_BUILD_SCM_REVISION bazel-out/stable-status.txt \ stamp = 1, ) -genrule( - name = "cni_package_version", - outs = ["cni_version"], - cmd = "echo 0.5.1 >$@", -) - release_filegroup( name = "docker-artifacts", srcs = [":%s.tar" % binary for binary in DOCKERIZED_BINARIES.keys()] + diff --git a/build/build-image/cross/Dockerfile b/build/build-image/cross/Dockerfile index 8e4bc0f8843..2c1dcf2062d 100644 --- a/build/build-image/cross/Dockerfile +++ b/build/build-image/cross/Dockerfile @@ -15,7 +15,7 @@ # This file creates a standard build environment for building cross # platform go binary for the architecture kubernetes cares about. -FROM golang:1.11.2 +FROM golang:1.11.4 ENV GOARM 7 ENV KUBE_DYNAMIC_CROSSPLATFORMS \ @@ -44,7 +44,7 @@ RUN apt-get update \ # Use dynamic cgo linking for architectures other than amd64 for the server platforms # To install crossbuild essential for other architectures add the following repository. RUN echo "deb http://archive.ubuntu.com/ubuntu xenial main universe" > /etc/apt/sources.list.d/cgocrosscompiling.list \ - && apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 40976EAF437D05B5 3B4FE6ACC0B21F32 \ + && apt-key adv --no-tty --keyserver keyserver.ubuntu.com --recv-keys 40976EAF437D05B5 3B4FE6ACC0B21F32 \ && apt-get update \ && apt-get install -y build-essential \ && for platform in ${KUBE_DYNAMIC_CROSSPLATFORMS}; do apt-get install -y crossbuild-essential-${platform}; done \ diff --git a/build/build-image/cross/VERSION b/build/build-image/cross/VERSION index 19abf8ebbbf..2f1c98bfeca 100644 --- a/build/build-image/cross/VERSION +++ b/build/build-image/cross/VERSION @@ -1 +1 @@ -v1.11.2-1 +v1.11.4-1 diff --git a/build/debs/BUILD b/build/debs/BUILD index 26e2cc7ca29..e1cbfeccebe 100644 --- a/build/debs/BUILD +++ b/build/debs/BUILD @@ -3,7 +3,7 @@ package(default_visibility = ["//visibility:public"]) load("@io_kubernetes_build//defs:deb.bzl", "k8s_deb", "deb_data") load("@io_kubernetes_build//defs:build.bzl", "release_filegroup") load("@io_kubernetes_build//defs:pkg.bzl", "pkg_tar") -load("//build:workspace.bzl", "CRI_TOOLS_VERSION") +load("//build:workspace.bzl", "CNI_VERSION", "CRI_TOOLS_VERSION") # We do not include kube-scheduler, kube-controller-manager, # kube-apiserver, and kube-proxy in this list even though we @@ -153,7 +153,7 @@ k8s_deb( "ethtool", "iproute2", "iptables (>= 1.4.21)", - "kubernetes-cni (>= 0.6.0)", + "kubernetes-cni (>= %s)" % CNI_VERSION, "mount", "socat", "util-linux", @@ -169,7 +169,7 @@ k8s_deb( depends = [ "kubelet (>= 1.8.0)", "kubectl (>= 1.8.0)", - "kubernetes-cni (>= 0.6.0)", + "kubernetes-cni (>= %s)" % CNI_VERSION, "cri-tools (>= 1.11.0)", ], description = """Kubernetes Cluster Bootstrapping Tool @@ -184,7 +184,7 @@ k8s_deb( description = """Kubernetes Packaging of CNI The Container Networking Interface tools for provisioning container networks. """, - version_file = "//build:cni_package_version", + version = CNI_VERSION, ) k8s_deb( diff --git a/build/lib/release.sh b/build/lib/release.sh index 98f6767d958..18e2ca65440 100644 --- a/build/lib/release.sh +++ b/build/lib/release.sh @@ -30,6 +30,7 @@ readonly RELEASE_IMAGES="${LOCAL_OUTPUT_ROOT}/release-images" KUBE_BUILD_HYPERKUBE=${KUBE_BUILD_HYPERKUBE:-y} KUBE_BUILD_CONFORMANCE=${KUBE_BUILD_CONFORMANCE:-y} +KUBE_BUILD_PULL_LATEST_IMAGES=${KUBE_BUILD_PULL_LATEST_IMAGES:-y} # Validate a ci version # @@ -372,7 +373,15 @@ EOF if [[ "${base_image}" =~ busybox ]]; then echo "COPY nsswitch.conf /etc/" >> "${docker_file_path}" fi - "${DOCKER[@]}" build --pull -q -t "${docker_image_tag}" "${docker_build_path}" >/dev/null + + # provide `--pull` argument to `docker build` if `KUBE_BUILD_PULL_LATEST_IMAGES` + # is set to y or Y; otherwise try to build the image without forcefully + # pulling the latest base image. + local -a docker_build_opts=() + if [[ "${KUBE_BUILD_PULL_LATEST_IMAGES}" =~ [yY] ]]; then + docker_build_opts+=("--pull") + fi + "${DOCKER[@]}" build "${docker_build_opts[@]}" -q -t "${docker_image_tag}" "${docker_build_path}" >/dev/null "${DOCKER[@]}" save "${docker_image_tag}" > "${binary_dir}/${binary_name}.tar" echo "${docker_tag}" > "${binary_dir}/${binary_name}.docker_tag" rm -rf "${docker_build_path}" diff --git a/build/root/WORKSPACE b/build/root/WORKSPACE index cee89622008..3e6d3131fb7 100644 --- a/build/root/WORKSPACE +++ b/build/root/WORKSPACE @@ -1,11 +1,11 @@ load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive", "http_file") load("//build:workspace_mirror.bzl", "mirror") -load("//build:workspace.bzl", "CRI_TOOLS_VERSION") +load("//build:workspace.bzl", "CNI_VERSION", "CRI_TOOLS_VERSION") http_archive( name = "io_bazel_rules_go", - sha256 = "f87fa87475ea107b3c69196f39c82b7bbf58fe27c62a338684c20ca17d1d8613", - urls = mirror("https://github.com/bazelbuild/rules_go/releases/download/0.16.2/rules_go-0.16.2.tar.gz"), + sha256 = "7be7dc01f1e0afdba6c8eb2b43d2fa01c743be1b9273ab1eaf6c233df078d705", + urls = mirror("https://github.com/bazelbuild/rules_go/releases/download/0.16.5/rules_go-0.16.5.tar.gz"), ) http_archive( @@ -22,12 +22,12 @@ http_archive( urls = mirror("https://github.com/bazelbuild/bazel-skylib/archive/2169ae1c374aab4a09aa90e65efe1a3aad4e279b.tar.gz"), ) -ETCD_VERSION = "3.2.24" +ETCD_VERSION = "3.3.10" http_archive( name = "com_coreos_etcd", build_file = "@//third_party:etcd.BUILD", - sha256 = "947849dbcfa13927c81236fb76a7c01d587bbab42ab1e807184cd91b026ebed7", + sha256 = "1620a59150ec0a0124a65540e23891243feb2d9a628092fb1edcc23974724a45", strip_prefix = "etcd-v%s-linux-amd64" % ETCD_VERSION, urls = mirror("https://github.com/coreos/etcd/releases/download/v%s/etcd-v%s-linux-amd64.tar.gz" % (ETCD_VERSION, ETCD_VERSION)), ) @@ -49,7 +49,7 @@ load("@io_bazel_rules_docker//docker:docker.bzl", "docker_pull", "docker_reposit go_rules_dependencies() go_register_toolchains( - go_version = "1.11.2", + go_version = "1.11.4", ) docker_repositories() @@ -58,7 +58,7 @@ http_file( name = "kubernetes_cni", downloaded_file_path = "kubernetes_cni.tgz", sha256 = "f04339a21b8edf76d415e7f17b620e63b8f37a76b2f706671587ab6464411f2d", - urls = mirror("https://storage.googleapis.com/kubernetes-release/network-plugins/cni-plugins-amd64-v0.6.0.tgz"), + urls = mirror("https://storage.googleapis.com/kubernetes-release/network-plugins/cni-plugins-amd64-v%s.tgz" % CNI_VERSION), ) http_file( diff --git a/build/rpms/BUILD b/build/rpms/BUILD index 8d6b9284401..be011df488e 100644 --- a/build/rpms/BUILD +++ b/build/rpms/BUILD @@ -1,7 +1,7 @@ package(default_visibility = ["//visibility:public"]) load("@bazel_tools//tools/build_defs/pkg:rpm.bzl", "pkg_rpm") -load("//build:workspace.bzl", "CRI_TOOLS_VERSION") +load("//build:workspace.bzl", "CNI_VERSION", "CRI_TOOLS_VERSION") filegroup( name = "rpms", @@ -66,7 +66,7 @@ pkg_rpm( ], spec_file = "kubernetes-cni.spec", tags = ["manual"], - version_file = "//build:cni_package_version", + version = CNI_VERSION, ) pkg_rpm( diff --git a/build/workspace.bzl b/build/workspace.bzl index 162839b6457..edd2af76e70 100644 --- a/build/workspace.bzl +++ b/build/workspace.bzl @@ -13,3 +13,5 @@ # limitations under the License. CRI_TOOLS_VERSION = "1.12.0" + +CNI_VERSION = "0.6.0" diff --git a/cluster/addons/addon-manager/kube-addons.sh b/cluster/addons/addon-manager/kube-addons.sh index 9332663a314..e0fbeb1781d 100755 --- a/cluster/addons/addon-manager/kube-addons.sh +++ b/cluster/addons/addon-manager/kube-addons.sh @@ -44,12 +44,11 @@ KUBECTL_PRUNE_WHITELIST=( core/v1/Service batch/v1/Job batch/v1beta1/CronJob - extensions/v1beta1/DaemonSet - extensions/v1beta1/Deployment + apps/v1/DaemonSet + apps/v1/Deployment + apps/v1/ReplicaSet + apps/v1/StatefulSet extensions/v1beta1/Ingress - extensions/v1beta1/ReplicaSet - apps/v1beta1/StatefulSet - apps/v1beta1/Deployment ) ADDON_CHECK_INTERVAL_SEC=${TEST_ADDON_CHECK_INTERVAL_SEC:-60} diff --git a/cluster/addons/calico-policy-controller/bgpconfigurations-crd.yaml b/cluster/addons/calico-policy-controller/bgpconfigurations-crd.yaml new file mode 100644 index 00000000000..9916794c425 --- /dev/null +++ b/cluster/addons/calico-policy-controller/bgpconfigurations-crd.yaml @@ -0,0 +1,15 @@ +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: bgpconfigurations.crd.projectcalico.org + labels: + kubernetes.io/cluster-service: "true" + addonmanager.kubernetes.io/mode: Reconcile +spec: + scope: Cluster + group: crd.projectcalico.org + version: v1 + names: + kind: BGPConfiguration + plural: bgpconfigurations + singular: bgpconfiguration diff --git a/cluster/addons/calico-policy-controller/calico-node-daemonset.yaml b/cluster/addons/calico-policy-controller/calico-node-daemonset.yaml index 025818768f8..491b2172e6e 100644 --- a/cluster/addons/calico-policy-controller/calico-node-daemonset.yaml +++ b/cluster/addons/calico-policy-controller/calico-node-daemonset.yaml @@ -1,5 +1,5 @@ kind: DaemonSet -apiVersion: extensions/v1beta1 +apiVersion: apps/v1 metadata: name: calico-node namespace: kube-system diff --git a/cluster/addons/calico-policy-controller/calico-node-vertical-autoscaler-deployment.yaml b/cluster/addons/calico-policy-controller/calico-node-vertical-autoscaler-deployment.yaml index c7919269216..9d07ad2c375 100644 --- a/cluster/addons/calico-policy-controller/calico-node-vertical-autoscaler-deployment.yaml +++ b/cluster/addons/calico-policy-controller/calico-node-vertical-autoscaler-deployment.yaml @@ -1,5 +1,5 @@ kind: Deployment -apiVersion: extensions/v1beta1 +apiVersion: apps/v1 metadata: name: calico-node-vertical-autoscaler namespace: kube-system @@ -9,6 +9,9 @@ metadata: addonmanager.kubernetes.io/mode: Reconcile spec: replicas: 1 + selector: + matchLabels: + k8s-app: calico-node-autoscaler template: metadata: labels: diff --git a/cluster/addons/calico-policy-controller/typha-deployment.yaml b/cluster/addons/calico-policy-controller/typha-deployment.yaml index f8209868ddc..f8f143f57ed 100644 --- a/cluster/addons/calico-policy-controller/typha-deployment.yaml +++ b/cluster/addons/calico-policy-controller/typha-deployment.yaml @@ -1,4 +1,4 @@ -apiVersion: extensions/v1beta1 +apiVersion: apps/v1 kind: Deployment metadata: name: calico-typha @@ -9,6 +9,9 @@ metadata: k8s-app: calico-typha spec: revisionHistoryLimit: 2 + selector: + matchLabels: + k8s-app: calico-typha template: metadata: labels: diff --git a/cluster/addons/calico-policy-controller/typha-horizontal-autoscaler-deployment.yaml b/cluster/addons/calico-policy-controller/typha-horizontal-autoscaler-deployment.yaml index 359ff0dcca0..85c477a685b 100644 --- a/cluster/addons/calico-policy-controller/typha-horizontal-autoscaler-deployment.yaml +++ b/cluster/addons/calico-policy-controller/typha-horizontal-autoscaler-deployment.yaml @@ -1,4 +1,4 @@ -apiVersion: extensions/v1beta1 +apiVersion: apps/v1 kind: Deployment metadata: name: calico-typha-horizontal-autoscaler @@ -9,6 +9,9 @@ metadata: addonmanager.kubernetes.io/mode: Reconcile spec: replicas: 1 + selector: + matchLabels: + k8s-app: calico-typha-autoscaler template: metadata: labels: diff --git a/cluster/addons/calico-policy-controller/typha-vertical-autoscaler-deployment.yaml b/cluster/addons/calico-policy-controller/typha-vertical-autoscaler-deployment.yaml index 05489182704..8fecf5860df 100644 --- a/cluster/addons/calico-policy-controller/typha-vertical-autoscaler-deployment.yaml +++ b/cluster/addons/calico-policy-controller/typha-vertical-autoscaler-deployment.yaml @@ -1,5 +1,5 @@ kind: Deployment -apiVersion: extensions/v1beta1 +apiVersion: apps/v1 metadata: name: calico-typha-vertical-autoscaler namespace: kube-system @@ -9,6 +9,9 @@ metadata: addonmanager.kubernetes.io/mode: Reconcile spec: replicas: 1 + selector: + matchLabels: + k8s-app: calico-typha-autoscaler template: metadata: labels: diff --git a/cluster/addons/cluster-monitoring/google/heapster-controller.yaml b/cluster/addons/cluster-monitoring/google/heapster-controller.yaml index 08acfe41427..22e8e6dfbbb 100644 --- a/cluster/addons/cluster-monitoring/google/heapster-controller.yaml +++ b/cluster/addons/cluster-monitoring/google/heapster-controller.yaml @@ -33,7 +33,7 @@ data: apiVersion: nannyconfig/v1alpha1 kind: NannyConfiguration --- -apiVersion: extensions/v1beta1 +apiVersion: apps/v1 kind: Deployment metadata: name: heapster-v1.6.0-beta.1 diff --git a/cluster/addons/cluster-monitoring/googleinfluxdb/heapster-controller-combined.yaml b/cluster/addons/cluster-monitoring/googleinfluxdb/heapster-controller-combined.yaml index 21b308d4a93..3925899ceb1 100644 --- a/cluster/addons/cluster-monitoring/googleinfluxdb/heapster-controller-combined.yaml +++ b/cluster/addons/cluster-monitoring/googleinfluxdb/heapster-controller-combined.yaml @@ -33,7 +33,7 @@ data: apiVersion: nannyconfig/v1alpha1 kind: NannyConfiguration --- -apiVersion: extensions/v1beta1 +apiVersion: apps/v1 kind: Deployment metadata: name: heapster-v1.6.0-beta.1 diff --git a/cluster/addons/cluster-monitoring/influxdb/heapster-controller.yaml b/cluster/addons/cluster-monitoring/influxdb/heapster-controller.yaml index 52cca111fef..7a3729f4c46 100644 --- a/cluster/addons/cluster-monitoring/influxdb/heapster-controller.yaml +++ b/cluster/addons/cluster-monitoring/influxdb/heapster-controller.yaml @@ -33,7 +33,7 @@ data: apiVersion: nannyconfig/v1alpha1 kind: NannyConfiguration --- -apiVersion: extensions/v1beta1 +apiVersion: apps/v1 kind: Deployment metadata: name: heapster-v1.6.0-beta.1 diff --git a/cluster/addons/cluster-monitoring/influxdb/influxdb-grafana-controller.yaml b/cluster/addons/cluster-monitoring/influxdb/influxdb-grafana-controller.yaml index dd0ebe652d4..7c83907edfe 100644 --- a/cluster/addons/cluster-monitoring/influxdb/influxdb-grafana-controller.yaml +++ b/cluster/addons/cluster-monitoring/influxdb/influxdb-grafana-controller.yaml @@ -1,5 +1,5 @@ kind: Deployment -apiVersion: extensions/v1beta1 +apiVersion: apps/v1 metadata: name: monitoring-influxdb-grafana-v4 namespace: kube-system diff --git a/cluster/addons/cluster-monitoring/stackdriver/heapster-controller.yaml b/cluster/addons/cluster-monitoring/stackdriver/heapster-controller.yaml index c6ae82a0bf5..a18cbbbcc82 100644 --- a/cluster/addons/cluster-monitoring/stackdriver/heapster-controller.yaml +++ b/cluster/addons/cluster-monitoring/stackdriver/heapster-controller.yaml @@ -20,7 +20,7 @@ data: apiVersion: nannyconfig/v1alpha1 kind: NannyConfiguration --- -apiVersion: extensions/v1beta1 +apiVersion: apps/v1 kind: Deployment metadata: name: heapster-v1.6.0-beta.1 diff --git a/cluster/addons/cluster-monitoring/standalone/heapster-controller.yaml b/cluster/addons/cluster-monitoring/standalone/heapster-controller.yaml index 485471df7f3..c24c7a43ee7 100644 --- a/cluster/addons/cluster-monitoring/standalone/heapster-controller.yaml +++ b/cluster/addons/cluster-monitoring/standalone/heapster-controller.yaml @@ -20,7 +20,7 @@ data: apiVersion: nannyconfig/v1alpha1 kind: NannyConfiguration --- -apiVersion: extensions/v1beta1 +apiVersion: apps/v1 kind: Deployment metadata: name: heapster-v1.6.0-beta.1 diff --git a/cluster/addons/dashboard/dashboard-controller.yaml b/cluster/addons/dashboard/dashboard-controller.yaml index 0c802a07b17..1d9d3aa3940 100644 --- a/cluster/addons/dashboard/dashboard-controller.yaml +++ b/cluster/addons/dashboard/dashboard-controller.yaml @@ -31,7 +31,7 @@ spec: priorityClassName: system-cluster-critical containers: - name: kubernetes-dashboard - image: k8s.gcr.io/kubernetes-dashboard-amd64:v1.10.0 + image: k8s.gcr.io/kubernetes-dashboard-amd64:v1.10.1 resources: limits: cpu: 100m diff --git a/cluster/addons/dns/coredns/coredns.yaml.base b/cluster/addons/dns/coredns/coredns.yaml.base index fd9025ae090..e58502d9f04 100644 --- a/cluster/addons/dns/coredns/coredns.yaml.base +++ b/cluster/addons/dns/coredns/coredns.yaml.base @@ -77,7 +77,7 @@ data: loadbalance } --- -apiVersion: extensions/v1beta1 +apiVersion: apps/v1 kind: Deployment metadata: name: coredns diff --git a/cluster/addons/dns/coredns/coredns.yaml.in b/cluster/addons/dns/coredns/coredns.yaml.in index 05db14e0d2a..ecfb6415607 100644 --- a/cluster/addons/dns/coredns/coredns.yaml.in +++ b/cluster/addons/dns/coredns/coredns.yaml.in @@ -77,7 +77,7 @@ data: loadbalance } --- -apiVersion: extensions/v1beta1 +apiVersion: apps/v1 kind: Deployment metadata: name: coredns diff --git a/cluster/addons/dns/coredns/coredns.yaml.sed b/cluster/addons/dns/coredns/coredns.yaml.sed index 169ddf266aa..3ab9f844476 100644 --- a/cluster/addons/dns/coredns/coredns.yaml.sed +++ b/cluster/addons/dns/coredns/coredns.yaml.sed @@ -77,7 +77,7 @@ data: loadbalance } --- -apiVersion: extensions/v1beta1 +apiVersion: apps/v1 kind: Deployment metadata: name: coredns diff --git a/cluster/addons/dns/kube-dns/kube-dns.yaml.base b/cluster/addons/dns/kube-dns/kube-dns.yaml.base index 84b8767192e..b6096e13e13 100644 --- a/cluster/addons/dns/kube-dns/kube-dns.yaml.base +++ b/cluster/addons/dns/kube-dns/kube-dns.yaml.base @@ -56,7 +56,7 @@ metadata: labels: addonmanager.kubernetes.io/mode: EnsureExists --- -apiVersion: extensions/v1beta1 +apiVersion: apps/v1 kind: Deployment metadata: name: kube-dns diff --git a/cluster/addons/dns/kube-dns/kube-dns.yaml.in b/cluster/addons/dns/kube-dns/kube-dns.yaml.in index e35264a1a03..79da48824f8 100644 --- a/cluster/addons/dns/kube-dns/kube-dns.yaml.in +++ b/cluster/addons/dns/kube-dns/kube-dns.yaml.in @@ -56,7 +56,7 @@ metadata: labels: addonmanager.kubernetes.io/mode: EnsureExists --- -apiVersion: extensions/v1beta1 +apiVersion: apps/v1 kind: Deployment metadata: name: kube-dns diff --git a/cluster/addons/dns/kube-dns/kube-dns.yaml.sed b/cluster/addons/dns/kube-dns/kube-dns.yaml.sed index b06ed28b918..2b7f0e7d9ef 100644 --- a/cluster/addons/dns/kube-dns/kube-dns.yaml.sed +++ b/cluster/addons/dns/kube-dns/kube-dns.yaml.sed @@ -56,7 +56,7 @@ metadata: labels: addonmanager.kubernetes.io/mode: EnsureExists --- -apiVersion: extensions/v1beta1 +apiVersion: apps/v1 kind: Deployment metadata: name: kube-dns diff --git a/cluster/addons/dns/nodelocaldns/README.md b/cluster/addons/dns/nodelocaldns/README.md index 976e440f768..fc84f783789 100644 --- a/cluster/addons/dns/nodelocaldns/README.md +++ b/cluster/addons/dns/nodelocaldns/README.md @@ -8,6 +8,8 @@ Design details [here](https://github.com/kubernetes/community/blob/master/keps/s This directory contains the addon config yaml - `nodelocaldns.yaml` The variables will be substituted by the configure scripts when the yaml is copied into master. +To create a GCE cluster with nodelocaldns enabled, use the command: +`KUBE_ENABLE_NODELOCAL_DNS=true go run hack/e2e.go -v --up` ### Network policy and DNS connectivity @@ -32,4 +34,4 @@ spec: policyTypes: - Ingress - Egress -``` \ No newline at end of file +``` diff --git a/cluster/addons/dns/nodelocaldns/nodelocaldns.yaml b/cluster/addons/dns/nodelocaldns/nodelocaldns.yaml index fdf0f421eac..b0fe946cd46 100644 --- a/cluster/addons/dns/nodelocaldns/nodelocaldns.yaml +++ b/cluster/addons/dns/nodelocaldns/nodelocaldns.yaml @@ -84,7 +84,7 @@ metadata: name: node-local-dns namespace: kube-system labels: - k8s-app: kube-dns + k8s-app: node-local-dns kubernetes.io/cluster-service: "true" addonmanager.kubernetes.io/mode: Reconcile spec: diff --git a/cluster/addons/fluentd-elasticsearch/OWNERS b/cluster/addons/fluentd-elasticsearch/OWNERS index 214b9bdcaf8..8637ca6100c 100644 --- a/cluster/addons/fluentd-elasticsearch/OWNERS +++ b/cluster/addons/fluentd-elasticsearch/OWNERS @@ -1,8 +1,10 @@ approvers: - coffeepac +- monotek - piosz reviewers: - coffeepac +- monotek - piosz labels: - sig/instrumentation diff --git a/cluster/addons/fluentd-gcp/event-exporter.yaml b/cluster/addons/fluentd-gcp/event-exporter.yaml index cb914c721b3..600784b2612 100644 --- a/cluster/addons/fluentd-gcp/event-exporter.yaml +++ b/cluster/addons/fluentd-gcp/event-exporter.yaml @@ -26,7 +26,7 @@ subjects: name: event-exporter-sa namespace: kube-system --- -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment metadata: name: event-exporter-v0.2.3 @@ -38,6 +38,10 @@ metadata: addonmanager.kubernetes.io/mode: Reconcile spec: replicas: 1 + selector: + matchLabels: + k8s-app: event-exporter + version: v0.2.3 template: metadata: labels: diff --git a/cluster/addons/fluentd-gcp/fluentd-gcp-ds.yaml b/cluster/addons/fluentd-gcp/fluentd-gcp-ds.yaml index acd63d541a4..7210ae18631 100644 --- a/cluster/addons/fluentd-gcp/fluentd-gcp-ds.yaml +++ b/cluster/addons/fluentd-gcp/fluentd-gcp-ds.yaml @@ -1,4 +1,4 @@ -apiVersion: extensions/v1beta1 +apiVersion: apps/v1 kind: DaemonSet metadata: name: fluentd-gcp-{{ fluentd_gcp_yaml_version }} @@ -9,6 +9,10 @@ metadata: addonmanager.kubernetes.io/mode: Reconcile version: {{ fluentd_gcp_yaml_version }} spec: + selector: + matchLabels: + k8s-app: fluentd-gcp + version: {{ fluentd_gcp_yaml_version }} updateStrategy: type: RollingUpdate template: diff --git a/cluster/addons/fluentd-gcp/scaler-deployment.yaml b/cluster/addons/fluentd-gcp/scaler-deployment.yaml index 04e0e31b827..a2448ddd1c0 100644 --- a/cluster/addons/fluentd-gcp/scaler-deployment.yaml +++ b/cluster/addons/fluentd-gcp/scaler-deployment.yaml @@ -31,6 +31,6 @@ spec: - name: MEMORY_REQUEST value: 200Mi - name: CPU_LIMIT - value: 1000m + value: "1" - name: MEMORY_LIMIT value: 500Mi diff --git a/cluster/addons/ip-masq-agent/ip-masq-agent.yaml b/cluster/addons/ip-masq-agent/ip-masq-agent.yaml index b6ede4f2fdc..2c3d81c3801 100644 --- a/cluster/addons/ip-masq-agent/ip-masq-agent.yaml +++ b/cluster/addons/ip-masq-agent/ip-masq-agent.yaml @@ -9,7 +9,7 @@ metadata: addonmanager.kubernetes.io/mode: Reconcile --- # https://github.com/kubernetes-incubator/ip-masq-agent/blob/v2.0.0/README.md -apiVersion: extensions/v1beta1 +apiVersion: apps/v1 kind: DaemonSet metadata: name: ip-masq-agent @@ -17,6 +17,9 @@ metadata: labels: addonmanager.kubernetes.io/mode: Reconcile spec: + selector: + matchLabels: + k8s-app: ip-masq-agent template: metadata: labels: diff --git a/cluster/addons/kube-proxy/kube-proxy-ds.yaml b/cluster/addons/kube-proxy/kube-proxy-ds.yaml index d11765bb076..e082ca4d16b 100644 --- a/cluster/addons/kube-proxy/kube-proxy-ds.yaml +++ b/cluster/addons/kube-proxy/kube-proxy-ds.yaml @@ -1,7 +1,7 @@ # Please keep kube-proxy configuration in-sync with: # cluster/saltbase/salt/kube-proxy/kube-proxy.manifest -apiVersion: extensions/v1beta1 +apiVersion: apps/v1 kind: DaemonSet metadata: labels: diff --git a/cluster/addons/metadata-agent/stackdriver/metadata-agent.yaml b/cluster/addons/metadata-agent/stackdriver/metadata-agent.yaml index d5abe020235..301a8fdd8ce 100644 --- a/cluster/addons/metadata-agent/stackdriver/metadata-agent.yaml +++ b/cluster/addons/metadata-agent/stackdriver/metadata-agent.yaml @@ -8,7 +8,7 @@ metadata: addonmanager.kubernetes.io/mode: Reconcile --- kind: DaemonSet -apiVersion: extensions/v1beta1 +apiVersion: apps/v1 metadata: labels: app: metadata-agent @@ -69,7 +69,7 @@ spec: type: RollingUpdate --- kind: Deployment -apiVersion: apps/v1beta1 +apiVersion: apps/v1 metadata: labels: app: metadata-agent-cluster-level diff --git a/cluster/addons/metadata-proxy/gce/metadata-proxy.yaml b/cluster/addons/metadata-proxy/gce/metadata-proxy.yaml index e2d7a46fcf9..231f14010b4 100644 --- a/cluster/addons/metadata-proxy/gce/metadata-proxy.yaml +++ b/cluster/addons/metadata-proxy/gce/metadata-proxy.yaml @@ -8,7 +8,7 @@ metadata: kubernetes.io/cluster-service: "true" addonmanager.kubernetes.io/mode: Reconcile --- -apiVersion: extensions/v1beta1 +apiVersion: apps/v1 kind: DaemonSet metadata: name: metadata-proxy-v0.1 @@ -19,6 +19,10 @@ metadata: addonmanager.kubernetes.io/mode: Reconcile version: v0.1 spec: + selector: + matchLabels: + k8s-app: metadata-proxy + version: v0.1 updateStrategy: type: RollingUpdate template: @@ -44,7 +48,7 @@ spec: effect: "NoSchedule" containers: - name: metadata-proxy - image: k8s.gcr.io/metadata-proxy:v0.1.10 + image: k8s.gcr.io/metadata-proxy:v0.1.11 securityContext: privileged: true # Request and limit resources to get guaranteed QoS. diff --git a/cluster/addons/metrics-server/metrics-server-deployment.yaml b/cluster/addons/metrics-server/metrics-server-deployment.yaml index 8fc49327d1f..a38303b0d9c 100644 --- a/cluster/addons/metrics-server/metrics-server-deployment.yaml +++ b/cluster/addons/metrics-server/metrics-server-deployment.yaml @@ -20,7 +20,7 @@ data: apiVersion: nannyconfig/v1alpha1 kind: NannyConfiguration --- -apiVersion: extensions/v1beta1 +apiVersion: apps/v1 kind: Deployment metadata: name: metrics-server-v0.3.1 diff --git a/cluster/addons/node-problem-detector/npd.yaml b/cluster/addons/node-problem-detector/npd.yaml index b25d2066d62..ee598636be6 100644 --- a/cluster/addons/node-problem-detector/npd.yaml +++ b/cluster/addons/node-problem-detector/npd.yaml @@ -23,7 +23,7 @@ subjects: name: node-problem-detector namespace: kube-system --- -apiVersion: extensions/v1beta1 +apiVersion: apps/v1 kind: DaemonSet metadata: name: npd-v0.4.1 @@ -34,6 +34,10 @@ metadata: kubernetes.io/cluster-service: "true" addonmanager.kubernetes.io/mode: Reconcile spec: + selector: + matchLabels: + k8s-app: node-problem-detector + version: v0.4.1 template: metadata: labels: diff --git a/cluster/addons/prometheus/alertmanager-deployment.yaml b/cluster/addons/prometheus/alertmanager-deployment.yaml index 440f3d8d3ae..85cecd3dd21 100644 --- a/cluster/addons/prometheus/alertmanager-deployment.yaml +++ b/cluster/addons/prometheus/alertmanager-deployment.yaml @@ -1,4 +1,4 @@ -apiVersion: extensions/v1beta1 +apiVersion: apps/v1 kind: Deployment metadata: name: alertmanager diff --git a/cluster/addons/prometheus/kube-state-metrics-deployment.yaml b/cluster/addons/prometheus/kube-state-metrics-deployment.yaml index 1a673db0b6d..b12bedf5807 100644 --- a/cluster/addons/prometheus/kube-state-metrics-deployment.yaml +++ b/cluster/addons/prometheus/kube-state-metrics-deployment.yaml @@ -1,4 +1,4 @@ -apiVersion: extensions/v1beta1 +apiVersion: apps/v1 kind: Deployment metadata: name: kube-state-metrics diff --git a/cluster/addons/prometheus/node-exporter-ds.yml b/cluster/addons/prometheus/node-exporter-ds.yml index 0c5881c21d8..0635357e783 100644 --- a/cluster/addons/prometheus/node-exporter-ds.yml +++ b/cluster/addons/prometheus/node-exporter-ds.yml @@ -1,4 +1,4 @@ -apiVersion: extensions/v1beta1 +apiVersion: apps/v1 kind: DaemonSet metadata: name: node-exporter @@ -9,6 +9,10 @@ metadata: addonmanager.kubernetes.io/mode: Reconcile version: v0.15.2 spec: + selector: + matchLabels: + k8s-app: node-exporter + version: v0.15.2 updateStrategy: type: OnDelete template: diff --git a/cluster/addons/runtimeclass/runtimeclass_crd.yaml b/cluster/addons/runtimeclass/runtimeclass_crd.yaml index cbb09740e2f..16e7aff097e 100644 --- a/cluster/addons/runtimeclass/runtimeclass_crd.yaml +++ b/cluster/addons/runtimeclass/runtimeclass_crd.yaml @@ -15,6 +15,13 @@ spec: plural: runtimeclasses singular: runtimeclass kind: RuntimeClass + additionalPrinterColumns: + - name: Runtime-Handler + type: string + JSONPath: .spec.runtimeHandler + - name: Age + type: date + JSONPath: .metadata.creationTimestamp scope: Cluster validation: openAPIV3Schema: diff --git a/cluster/gce/config-test.sh b/cluster/gce/config-test.sh index d2a37f3f446..aca76802e76 100755 --- a/cluster/gce/config-test.sh +++ b/cluster/gce/config-test.sh @@ -177,7 +177,7 @@ ENABLE_METADATA_AGENT="${KUBE_ENABLE_METADATA_AGENT:-none}" # Useful for scheduling heapster in large clusters with nodes of small size. HEAPSTER_MACHINE_TYPE="${HEAPSTER_MACHINE_TYPE:-}" -# Set etcd image (e.g. k8s.gcr.io/etcd) and version (e.g. 3.2.24-1) if you need +# Set etcd image (e.g. k8s.gcr.io/etcd) and version (e.g. 3.3.10-0) if you need # non-default version. ETCD_IMAGE="${TEST_ETCD_IMAGE:-}" ETCD_DOCKER_REPOSITORY="${TEST_ETCD_DOCKER_REPOSITORY:-}" diff --git a/cluster/gce/gci/configure-helper.sh b/cluster/gce/gci/configure-helper.sh index 8427fc35e75..153f7a56449 100644 --- a/cluster/gce/gci/configure-helper.sh +++ b/cluster/gce/gci/configure-helper.sh @@ -1089,6 +1089,11 @@ EOF } function create-node-problem-detector-kubeconfig { + local apiserver_address="${1}" + if [[ -z "${apiserver_address}" ]]; then + echo "Must provide API server address to create node-problem-detector kubeconfig file!" + exit 1 + fi echo "Creating node-problem-detector kubeconfig file" mkdir -p /var/lib/node-problem-detector cat </var/lib/node-problem-detector/kubeconfig @@ -1101,6 +1106,7 @@ users: clusters: - name: local cluster: + server: https://${apiserver_address} certificate-authority-data: ${CA_CERT} contexts: - context: @@ -1230,7 +1236,7 @@ function start-node-problem-detector { local -r km_config="${KUBE_HOME}/node-problem-detector/config/kernel-monitor.json" # TODO(random-liu): Handle this for alternative container runtime. local -r dm_config="${KUBE_HOME}/node-problem-detector/config/docker-monitor.json" - local -r custom_km_config="${KUBE_HOME}/node-problem-detector/config/kernel-monitor-counter.json" + local -r custom_km_config="${KUBE_HOME}/node-problem-detector/config/kernel-monitor-counter.json,${KUBE_HOME}/node-problem-detector/config/systemd-monitor-counter.json,${KUBE_HOME}/node-problem-detector/config/docker-monitor-counter.json" echo "Using node problem detector binary at ${npd_bin}" local flags="${NPD_TEST_LOG_LEVEL:-"--v=2"} ${NPD_TEST_ARGS:-}" flags+=" --logtostderr" @@ -2290,8 +2296,9 @@ function update-dashboard-controller { # Sets up the manifests of coreDNS for k8s addons. function setup-coredns-manifest { - local -r coredns_file="${dst_dir}/dns/coredns/coredns.yaml" - mv "${dst_dir}/dns/coredns/coredns.yaml.in" "${coredns_file}" + setup-addon-manifests "addons" "0-dns/coredns" + local -r coredns_file="${dst_dir}/0-dns/coredns/coredns.yaml" + mv "${dst_dir}/0-dns/coredns/coredns.yaml.in" "${coredns_file}" # Replace the salt configurations with variable values. sed -i -e "s@{{ *pillar\['dns_domain'\] *}}@${DNS_DOMAIN}@g" "${coredns_file}" sed -i -e "s@{{ *pillar\['dns_server'\] *}}@${DNS_SERVER_IP}@g" "${coredns_file}" @@ -2334,8 +2341,9 @@ function setup-fluentd { # Sets up the manifests of kube-dns for k8s addons. function setup-kube-dns-manifest { - local -r kubedns_file="${dst_dir}/dns/kube-dns/kube-dns.yaml" - mv "${dst_dir}/dns/kube-dns/kube-dns.yaml.in" "${kubedns_file}" + setup-addon-manifests "addons" "0-dns/kube-dns" + local -r kubedns_file="${dst_dir}/0-dns/kube-dns/kube-dns.yaml" + mv "${dst_dir}/0-dns/kube-dns/kube-dns.yaml.in" "${kubedns_file}" if [ -n "${CUSTOM_KUBE_DNS_YAML:-}" ]; then # Replace with custom GKE kube-dns deployment. cat > "${kubedns_file}" <-". IMAGE_TAG=$(LATEST_ETCD_VERSION)-$(REVISION) @@ -52,7 +52,7 @@ MANIFEST_IMAGE := $(PUSH_REGISTRY)/etcd # This option is for running docker manifest command export DOCKER_CLI_EXPERIMENTAL := enabled # golang version should match the golang version from https://github.com/coreos/etcd/releases for the current ETCD_VERSION. -GOLANG_VERSION?=1.8.7 +GOLANG_VERSION?=1.10.4 GOARM=7 TEMP_DIR:=$(shell mktemp -d) @@ -159,7 +159,7 @@ build-integration-test-image: build integration-test: docker run --interactive -v $(shell pwd)/../../../:/go/src/k8s.io/kubernetes -e GOARCH=$(ARCH) etcd-integration-test \ - /bin/bash -c "CGO_ENABLED=0 go test -tags=integration -v k8s.io/kubernetes/cluster/images/etcd/migrate -args -v 10 -logtostderr true" + /bin/bash -c "CGO_ENABLED=0 go test -tags=integration k8s.io/kubernetes/cluster/images/etcd/migrate -args -v 10 -logtostderr true" integration-build-test: build-integration-test-image integration-test test: unit-test integration-build-test diff --git a/cluster/images/etcd/README.md b/cluster/images/etcd/README.md index 25b4026be77..6c768f9ba18 100644 --- a/cluster/images/etcd/README.md +++ b/cluster/images/etcd/README.md @@ -26,7 +26,7 @@ server. `migrate` writes a `version.txt` file to track the "current" version of etcd that was used to persist data to disk. A "target" version may also be provided -by the `TARGET_STORAGE` (e.g. "etcd3") and `TARGET_VERSION` (e.g. "3.2.24" ) +by the `TARGET_STORAGE` (e.g. "etcd3") and `TARGET_VERSION` (e.g. "3.3.10" ) environment variables. If the persisted version differs from the target version, `migrate-if-needed.sh` will migrate the data from the current to the target version. diff --git a/cluster/images/etcd/migrate-if-needed.sh b/cluster/images/etcd/migrate-if-needed.sh index 38e2565fcf1..1998e237dff 100755 --- a/cluster/images/etcd/migrate-if-needed.sh +++ b/cluster/images/etcd/migrate-if-needed.sh @@ -18,7 +18,7 @@ # This script performs etcd upgrade based on the following environmental # variables: # TARGET_STORAGE - API of etcd to be used (supported: 'etcd2', 'etcd3') -# TARGET_VERSION - etcd release to be used (supported: '2.2.1', '2.3.7', '3.0.17', '3.1.12', '3.2.24') +# TARGET_VERSION - etcd release to be used (supported: '2.2.1', '2.3.7', '3.0.17', '3.1.12', '3.2.24', "3.3.10") # DATA_DIRECTORY - directory with etcd data # # The current etcd version and storage format is detected based on the @@ -30,6 +30,7 @@ # - 2.3.7/etcd2 -> 3.0.17/etcd2 # - 3.0.17/etcd3 -> 3.1.12/etcd3 # - 3.1.12/etcd3 -> 3.2.24/etcd3 +# - 3.2.24/etcd3 -> 3.3.10/etcd3 # # NOTE: The releases supported in this script has to match release binaries # present in the etcd image (to make this script work correctly). @@ -42,7 +43,7 @@ set -o nounset # NOTE: BUNDLED_VERSION has to match release binaries present in the # etcd image (to make this script work correctly). -BUNDLED_VERSIONS="2.2.1, 2.3.7, 3.0.17, 3.1.12, 3.2.24" +BUNDLED_VERSIONS="2.2.1, 2.3.7, 3.0.17, 3.1.12, 3.2.24, 3.3.10" ETCD_NAME="${ETCD_NAME:-etcd-$(hostname)}" if [ -z "${DATA_DIRECTORY:-}" ]; then diff --git a/cluster/images/kubemark/Makefile b/cluster/images/kubemark/Makefile index 7cba455a478..611e1712cdb 100644 --- a/cluster/images/kubemark/Makefile +++ b/cluster/images/kubemark/Makefile @@ -31,6 +31,6 @@ gcloudpush: build docker push $(REGISTRY)/kubemark:$(IMAGE_TAG) push: build - docker -- push $(REGISTRY)/kubemark:$(IMAGE_TAG) + docker push $(REGISTRY)/kubemark:$(IMAGE_TAG) .PHONY: all build gcloudpush push diff --git a/cluster/juju/layers/kubernetes-worker/reactive/kubernetes_worker.py b/cluster/juju/layers/kubernetes-worker/reactive/kubernetes_worker.py index 746a5837559..3b6270e5ed1 100644 --- a/cluster/juju/layers/kubernetes-worker/reactive/kubernetes_worker.py +++ b/cluster/juju/layers/kubernetes-worker/reactive/kubernetes_worker.py @@ -926,7 +926,7 @@ def launch_default_ingress_controller(): if get_version('kubelet') < (1, 9): context['daemonset_api_version'] = 'extensions/v1beta1' else: - context['daemonset_api_version'] = 'apps/v1beta2' + context['daemonset_api_version'] = 'apps/v1' context['juju_application'] = hookenv.service_name() manifest = addon_path.format('ingress-daemon-set.yaml') render('ingress-daemon-set.yaml', manifest, context) diff --git a/cluster/juju/layers/kubernetes-worker/templates/microbot-example.yaml b/cluster/juju/layers/kubernetes-worker/templates/microbot-example.yaml index 323a07cefcb..81bb731a6b0 100644 --- a/cluster/juju/layers/kubernetes-worker/templates/microbot-example.yaml +++ b/cluster/juju/layers/kubernetes-worker/templates/microbot-example.yaml @@ -1,4 +1,4 @@ -apiVersion: extensions/v1beta1 +apiVersion: apps/v1 kind: Deployment metadata: creationTimestamp: null diff --git a/cluster/juju/layers/kubernetes-worker/templates/nfs-provisioner.yaml b/cluster/juju/layers/kubernetes-worker/templates/nfs-provisioner.yaml index de3023a657e..66aa9fd65b3 100644 --- a/cluster/juju/layers/kubernetes-worker/templates/nfs-provisioner.yaml +++ b/cluster/juju/layers/kubernetes-worker/templates/nfs-provisioner.yaml @@ -7,11 +7,16 @@ metadata: provisioner: fuseim.pri/ifs --- kind: Deployment -apiVersion: extensions/v1beta1 +apiVersion: apps/v1 metadata: name: nfs-client-provisioner + labels: + app: nfs-client-provisioner spec: replicas: 1 + selector: + matchLabels: + app: nfs-client-provisioner strategy: type: Recreate template: diff --git a/cluster/kubemark/gce/config-default.sh b/cluster/kubemark/gce/config-default.sh index e80feb79bd1..9f0f9669257 100644 --- a/cluster/kubemark/gce/config-default.sh +++ b/cluster/kubemark/gce/config-default.sh @@ -66,6 +66,8 @@ ETCD_COMPACTION_INTERVAL_SEC="${KUBEMARK_ETCD_COMPACTION_INTERVAL_SEC:-}" # non-default version. ETCD_IMAGE="${TEST_ETCD_IMAGE:-}" ETCD_VERSION="${TEST_ETCD_VERSION:-}" +ETCD_SERVERS="${KUBEMARK_ETCD_SERVERS:-}" +ETCD_SERVERS_OVERRIDES="${KUBEMARK_ETCD_SERVERS_OVERRIDES:-}" # Storage backend. 'etcd2' and 'etcd3' are supported. STORAGE_BACKEND=${STORAGE_BACKEND:-} diff --git a/cluster/log-dump/log-dump.sh b/cluster/log-dump/log-dump.sh index 6609fd01292..634deadcd90 100755 --- a/cluster/log-dump/log-dump.sh +++ b/cluster/log-dump/log-dump.sh @@ -435,6 +435,9 @@ function detect_node_failures() { fi detect-node-names + if [ -z "${INSTANCE_GROUPS:-}" ]; then + return + fi for group in "${INSTANCE_GROUPS[@]}"; do local creation_timestamp=$(gcloud compute instance-groups managed describe \ "${group}" \ diff --git a/cluster/log-dump/logexporter-daemonset.yaml b/cluster/log-dump/logexporter-daemonset.yaml index 660f7e8405f..69a0d91fcda 100644 --- a/cluster/log-dump/logexporter-daemonset.yaml +++ b/cluster/log-dump/logexporter-daemonset.yaml @@ -20,7 +20,7 @@ type: Opaque data: service-account.json: {{.ServiceAccountCredentials}} --- -apiVersion: apps/v1beta2 +apiVersion: apps/v1 kind: DaemonSet metadata: name: logexporter diff --git a/cmd/cloud-controller-manager/OWNERS b/cmd/cloud-controller-manager/OWNERS index d7318e2841f..eacd4ab9ec6 100644 --- a/cmd/cloud-controller-manager/OWNERS +++ b/cmd/cloud-controller-manager/OWNERS @@ -9,6 +9,7 @@ reviewers: - luxas - wlan0 - andrewsykim +- cheftako - stewart-yu - sttts labels: diff --git a/cmd/cloud-controller-manager/app/controllermanager.go b/cmd/cloud-controller-manager/app/controllermanager.go index 73f99ecf778..ebdb60f5ccd 100644 --- a/cmd/cloud-controller-manager/app/controllermanager.go +++ b/cmd/cloud-controller-manager/app/controllermanager.go @@ -226,12 +226,23 @@ func startControllers(c *cloudcontrollerconfig.CompletedConfig, stop <-chan stru nodeController := cloudcontrollers.NewCloudNodeController( c.SharedInformers.Core().V1().Nodes(), client("cloud-node-controller"), cloud, - c.ComponentConfig.KubeCloudShared.NodeMonitorPeriod.Duration, c.ComponentConfig.NodeStatusUpdateFrequency.Duration) - nodeController.Run(stop) + go nodeController.Run(stop) time.Sleep(wait.Jitter(c.ComponentConfig.Generic.ControllerStartInterval.Duration, ControllerStartJitter)) + cloudNodeLifecycleController, err := cloudcontrollers.NewCloudNodeLifecycleController( + c.SharedInformers.Core().V1().Nodes(), + client("cloud-node-lifecycle-controller"), cloud, + c.ComponentConfig.KubeCloudShared.NodeMonitorPeriod.Duration, + ) + if err != nil { + klog.Errorf("failed to start cloud node lifecycle controller: %s", err) + } else { + go cloudNodeLifecycleController.Run(stop) + time.Sleep(wait.Jitter(c.ComponentConfig.Generic.ControllerStartInterval.Duration, ControllerStartJitter)) + } + // Start the PersistentVolumeLabelController pvlController := cloudcontrollers.NewPersistentVolumeLabelController(client("pvl-controller"), cloud) go pvlController.Run(5, stop) diff --git a/cmd/controller-manager/OWNERS b/cmd/controller-manager/OWNERS index d6532cf8d8f..f6339f17866 100644 --- a/cmd/controller-manager/OWNERS +++ b/cmd/controller-manager/OWNERS @@ -1,6 +1,7 @@ approvers: - deads2k - cheftako +- stewart-yu - sttts reviewers: - caesarxuchao diff --git a/cmd/hyperkube/main.go b/cmd/hyperkube/main.go index 8cb1ec2ad42..617050a0cd1 100644 --- a/cmd/hyperkube/main.go +++ b/cmd/hyperkube/main.go @@ -85,7 +85,7 @@ func commandFor(basename string, defaultCommand *cobra.Command, commands []func( // NewHyperKubeCommand is the entry point for hyperkube func NewHyperKubeCommand(stopCh <-chan struct{}) (*cobra.Command, []func() *cobra.Command) { - // these have to be functions since the command is polymorphic. Cobra wants you to be top level + // these have to be functions since the command is polymorphic. Cobra wants you to be top level // command to get executed apiserver := func() *cobra.Command { ret := kubeapiserver.NewAPIServerCommand(stopCh) diff --git a/cmd/kube-apiserver/OWNERS b/cmd/kube-apiserver/OWNERS index 319b71ce058..02d03e318fe 100644 --- a/cmd/kube-apiserver/OWNERS +++ b/cmd/kube-apiserver/OWNERS @@ -9,6 +9,7 @@ approvers: - sttts reviewers: - lavalamp +- cheftako - smarterclayton - wojtek-t - deads2k diff --git a/cmd/kube-apiserver/app/aggregator.go b/cmd/kube-apiserver/app/aggregator.go index 00b97e32af6..692cb02fc1f 100644 --- a/cmd/kube-apiserver/app/aggregator.go +++ b/cmd/kube-apiserver/app/aggregator.go @@ -269,6 +269,7 @@ var apiVersionPriorities = map[schema.GroupVersion]priority{ {Group: "admissionregistration.k8s.io", Version: "v1alpha1"}: {group: 16700, version: 9}, {Group: "scheduling.k8s.io", Version: "v1beta1"}: {group: 16600, version: 12}, {Group: "scheduling.k8s.io", Version: "v1alpha1"}: {group: 16600, version: 9}, + {Group: "coordination.k8s.io", Version: "v1"}: {group: 16500, version: 15}, {Group: "coordination.k8s.io", Version: "v1beta1"}: {group: 16500, version: 9}, {Group: "auditregistration.k8s.io", Version: "v1alpha1"}: {group: 16400, version: 1}, // Append a new group to the end of the list if unsure. diff --git a/cmd/kube-apiserver/app/options/options_test.go b/cmd/kube-apiserver/app/options/options_test.go index c3ef30e2c33..00ebd03a0ad 100644 --- a/cmd/kube-apiserver/app/options/options_test.go +++ b/cmd/kube-apiserver/app/options/options_test.go @@ -141,12 +141,14 @@ func TestAddFlags(t *testing.T) { }, Etcd: &apiserveroptions.EtcdOptions{ StorageConfig: storagebackend.Config{ - Type: "etcd3", - ServerList: nil, + Type: "etcd3", + Transport: storagebackend.TransportConfig{ + ServerList: nil, + KeyFile: "/var/run/kubernetes/etcd.key", + CAFile: "/var/run/kubernetes/etcdca.crt", + CertFile: "/var/run/kubernetes/etcdce.crt", + }, Prefix: "/registry", - KeyFile: "/var/run/kubernetes/etcd.key", - CAFile: "/var/run/kubernetes/etcdca.crt", - CertFile: "/var/run/kubernetes/etcdce.crt", CompactionInterval: storagebackend.DefaultCompactInterval, CountMetricPollPeriod: time.Minute, }, diff --git a/cmd/kube-apiserver/app/server.go b/cmd/kube-apiserver/app/server.go index 0151fa1b7fb..cb88f75ed5a 100644 --- a/cmd/kube-apiserver/app/server.go +++ b/cmd/kube-apiserver/app/server.go @@ -287,8 +287,8 @@ func CreateKubeAPIServerConfig( return } - if _, port, err := net.SplitHostPort(s.Etcd.StorageConfig.ServerList[0]); err == nil && port != "0" && len(port) != 0 { - if err := utilwait.PollImmediate(etcdRetryInterval, etcdRetryLimit*etcdRetryInterval, preflight.EtcdConnection{ServerList: s.Etcd.StorageConfig.ServerList}.CheckEtcdServers); err != nil { + if _, port, err := net.SplitHostPort(s.Etcd.StorageConfig.Transport.ServerList[0]); err == nil && port != "0" && len(port) != 0 { + if err := utilwait.PollImmediate(etcdRetryInterval, etcdRetryLimit*etcdRetryInterval, preflight.EtcdConnection{ServerList: s.Etcd.StorageConfig.Transport.ServerList}.CheckEtcdServers); err != nil { lastErr = fmt.Errorf("error waiting for etcd connection: %v", err) return } @@ -504,7 +504,12 @@ func buildGenericConfig( func BuildAuthenticator(s *options.ServerRunOptions, extclient clientgoclientset.Interface, versionedInformer clientgoinformers.SharedInformerFactory) (authenticator.Request, *spec.SecurityDefinitions, error) { authenticatorConfig := s.Authentication.ToAuthenticationConfig() if s.Authentication.ServiceAccounts.Lookup { - authenticatorConfig.ServiceAccountTokenGetter = serviceaccountcontroller.NewGetterFromClient(extclient) + authenticatorConfig.ServiceAccountTokenGetter = serviceaccountcontroller.NewGetterFromClient( + extclient, + versionedInformer.Core().V1().Secrets().Lister(), + versionedInformer.Core().V1().ServiceAccounts().Lister(), + versionedInformer.Core().V1().Pods().Lister(), + ) } authenticatorConfig.BootstrapTokenAuthenticator = bootstrap.NewTokenAuthenticator( versionedInformer.Core().V1().Secrets().Lister().Secrets(v1.NamespaceSystem), diff --git a/cmd/kube-controller-manager/OWNERS b/cmd/kube-controller-manager/OWNERS index e8e10481cd4..b3260a6d225 100644 --- a/cmd/kube-controller-manager/OWNERS +++ b/cmd/kube-controller-manager/OWNERS @@ -8,6 +8,7 @@ reviewers: - a-robinson - brendandburns - caesarxuchao +- cheftako - cjcullen - dalanlan - david-mcmahon @@ -60,6 +61,7 @@ reviewers: - smarterclayton - soltysh - spiffxp +- stewart-yu - sttts - thockin - timothysc diff --git a/cmd/kube-controller-manager/app/BUILD b/cmd/kube-controller-manager/app/BUILD index f4fdeb6af49..49d8221b345 100644 --- a/cmd/kube-controller-manager/app/BUILD +++ b/cmd/kube-controller-manager/app/BUILD @@ -46,6 +46,7 @@ go_library( "//pkg/controller/certificates/cleaner:go_default_library", "//pkg/controller/certificates/rootcacertpublisher:go_default_library", "//pkg/controller/certificates/signer:go_default_library", + "//pkg/controller/cloud:go_default_library", "//pkg/controller/clusterroleaggregation:go_default_library", "//pkg/controller/cronjob:go_default_library", "//pkg/controller/daemon:go_default_library", diff --git a/cmd/kube-controller-manager/app/controllermanager.go b/cmd/kube-controller-manager/app/controllermanager.go index 2cf1ddf932f..737b7d4e6cd 100644 --- a/cmd/kube-controller-manager/app/controllermanager.go +++ b/cmd/kube-controller-manager/app/controllermanager.go @@ -383,13 +383,13 @@ func NewControllerInitializers(loopMode ControllerLoopMode) map[string]InitFunc controllers["bootstrapsigner"] = startBootstrapSignerController controllers["tokencleaner"] = startTokenCleanerController controllers["nodeipam"] = startNodeIpamController + controllers["nodelifecycle"] = startNodeLifecycleController if loopMode == IncludeCloudLoops { controllers["service"] = startServiceController controllers["route"] = startRouteController + controllers["cloudnodelifecycle"] = startCloudNodeLifecycleController // TODO: volume controller into the IncludeCloudLoops only set. - // TODO: Separate cluster in cloud check from node lifecycle controller. } - controllers["nodelifecycle"] = startNodeLifecycleController controllers["persistentvolume-binder"] = startPersistentVolumeBinderController controllers["attachdetach"] = startAttachDetachController controllers["persistentvolume-expander"] = startVolumeExpandController diff --git a/cmd/kube-controller-manager/app/core.go b/cmd/kube-controller-manager/app/core.go index f485ff74191..45f663b86bd 100644 --- a/cmd/kube-controller-manager/app/core.go +++ b/cmd/kube-controller-manager/app/core.go @@ -38,6 +38,7 @@ import ( clientset "k8s.io/client-go/kubernetes" csiclientset "k8s.io/csi-api/pkg/client/clientset/versioned" "k8s.io/kubernetes/pkg/controller" + cloudcontroller "k8s.io/kubernetes/pkg/controller/cloud" endpointcontroller "k8s.io/kubernetes/pkg/controller/endpoint" "k8s.io/kubernetes/pkg/controller/garbagecollector" namespacecontroller "k8s.io/kubernetes/pkg/controller/namespace" @@ -124,8 +125,7 @@ func startNodeLifecycleController(ctx ControllerContext) (http.Handler, bool, er ctx.InformerFactory.Coordination().V1beta1().Leases(), ctx.InformerFactory.Core().V1().Pods(), ctx.InformerFactory.Core().V1().Nodes(), - ctx.InformerFactory.Extensions().V1beta1().DaemonSets(), - ctx.Cloud, + ctx.InformerFactory.Apps().V1().DaemonSets(), ctx.ClientBuilder.ClientOrDie("node-controller"), ctx.ComponentConfig.KubeCloudShared.NodeMonitorPeriod.Duration, ctx.ComponentConfig.NodeLifecycleController.NodeStartupGracePeriod.Duration, @@ -146,6 +146,24 @@ func startNodeLifecycleController(ctx ControllerContext) (http.Handler, bool, er return nil, true, nil } +func startCloudNodeLifecycleController(ctx ControllerContext) (http.Handler, bool, error) { + cloudNodeLifecycleController, err := cloudcontroller.NewCloudNodeLifecycleController( + ctx.InformerFactory.Core().V1().Nodes(), + ctx.ClientBuilder.ClientOrDie("cloud-node-lifecycle-controller"), + ctx.Cloud, + ctx.ComponentConfig.KubeCloudShared.NodeMonitorPeriod.Duration, + ) + if err != nil { + // the controller manager should continue to run if the "Instances" interface is not + // supported, though it's unlikely for a cloud provider to not support it + klog.Errorf("failed to start cloud node lifecycle controller: %v", err) + return nil, false, nil + } + + go cloudNodeLifecycleController.Run(ctx.Stop) + return nil, true, nil +} + func startRouteController(ctx ControllerContext) (http.Handler, bool, error) { if !ctx.ComponentConfig.KubeCloudShared.AllocateNodeCIDRs || !ctx.ComponentConfig.KubeCloudShared.ConfigureCloudRoutes { klog.Infof("Will not configure cloud provider routes for allocate-node-cidrs: %v, configure-cloud-routes: %v.", ctx.ComponentConfig.KubeCloudShared.AllocateNodeCIDRs, ctx.ComponentConfig.KubeCloudShared.ConfigureCloudRoutes) diff --git a/cmd/kube-controller-manager/app/policy.go b/cmd/kube-controller-manager/app/policy.go index d841d8dd144..03c84b6644a 100644 --- a/cmd/kube-controller-manager/app/policy.go +++ b/cmd/kube-controller-manager/app/policy.go @@ -44,9 +44,9 @@ func startDisruptionController(ctx ControllerContext) (http.Handler, bool, error ctx.InformerFactory.Core().V1().Pods(), ctx.InformerFactory.Policy().V1beta1().PodDisruptionBudgets(), ctx.InformerFactory.Core().V1().ReplicationControllers(), - ctx.InformerFactory.Extensions().V1beta1().ReplicaSets(), - ctx.InformerFactory.Extensions().V1beta1().Deployments(), - ctx.InformerFactory.Apps().V1beta1().StatefulSets(), + ctx.InformerFactory.Apps().V1().ReplicaSets(), + ctx.InformerFactory.Apps().V1().Deployments(), + ctx.InformerFactory.Apps().V1().StatefulSets(), ctx.ClientBuilder.ClientOrDie("disruption-controller"), ).Run(ctx.Stop) return nil, true, nil diff --git a/cmd/kube-proxy/app/BUILD b/cmd/kube-proxy/app/BUILD index b99cf2ca155..f76d4542965 100644 --- a/cmd/kube-proxy/app/BUILD +++ b/cmd/kube-proxy/app/BUILD @@ -43,6 +43,7 @@ go_library( "//pkg/version/verflag:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/config:go_default_library", + "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/runtime/serializer/json:go_default_library", diff --git a/cmd/kube-proxy/app/server.go b/cmd/kube-proxy/app/server.go index e1774499657..f0edc12c75b 100644 --- a/cmd/kube-proxy/app/server.go +++ b/cmd/kube-proxy/app/server.go @@ -30,6 +30,7 @@ import ( "k8s.io/api/core/v1" apimachineryconfig "k8s.io/apimachinery/pkg/apis/config" + v1meta "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/serializer" "k8s.io/apimachinery/pkg/runtime/serializer/json" @@ -537,10 +538,11 @@ func (s *ProxyServer) Run() error { // the only remediation we know is to restart the docker daemon. // Here we'll send an node event with specific reason and message, the // administrator should decide whether and how to handle this issue, - // whether to drain the node and restart docker. + // whether to drain the node and restart docker. Occurs in other container runtimes + // as well. // TODO(random-liu): Remove this when the docker bug is fixed. - const message = "DOCKER RESTART NEEDED (docker issue #24000): /sys is read-only: " + - "cannot modify conntrack limits, problems may arise later." + const message = "CRI error: /sys is read-only: " + + "cannot modify conntrack limits, problems may arise later (If running Docker, see docker issue #24000)" s.Recorder.Eventf(s.NodeRef, api.EventTypeWarning, err.Error(), message) } } @@ -560,7 +562,10 @@ func (s *ProxyServer) Run() error { } } - informerFactory := informers.NewSharedInformerFactory(s.Client, s.ConfigSyncPeriod) + informerFactory := informers.NewSharedInformerFactoryWithOptions(s.Client, s.ConfigSyncPeriod, + informers.WithTweakListOptions(func(options *v1meta.ListOptions) { + options.LabelSelector = "!service.kubernetes.io/service-proxy-name" + })) // Create configs (i.e. Watches for Services and Endpoints) // Note: RegisterHandler() calls need to happen before creation of Sources because sources diff --git a/cmd/kube-scheduler/app/BUILD b/cmd/kube-scheduler/app/BUILD index a3243f96ab4..21a9687b190 100644 --- a/cmd/kube-scheduler/app/BUILD +++ b/cmd/kube-scheduler/app/BUILD @@ -14,7 +14,6 @@ go_library( "//cmd/kube-scheduler/app/options:go_default_library", "//pkg/api/legacyscheme:go_default_library", "//pkg/controller:go_default_library", - "//pkg/features:go_default_library", "//pkg/scheduler:go_default_library", "//pkg/scheduler/algorithmprovider:go_default_library", "//pkg/scheduler/api:go_default_library", @@ -38,10 +37,8 @@ go_library( "//staging/src/k8s.io/apiserver/pkg/server/healthz:go_default_library", "//staging/src/k8s.io/apiserver/pkg/server/mux:go_default_library", "//staging/src/k8s.io/apiserver/pkg/server/routes:go_default_library", - "//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library", "//staging/src/k8s.io/apiserver/pkg/util/flag:go_default_library", "//staging/src/k8s.io/apiserver/pkg/util/globalflag:go_default_library", - "//staging/src/k8s.io/client-go/informers/storage/v1:go_default_library", "//staging/src/k8s.io/client-go/kubernetes/typed/core/v1:go_default_library", "//staging/src/k8s.io/client-go/tools/leaderelection:go_default_library", "//vendor/github.com/prometheus/client_golang/prometheus:go_default_library", diff --git a/cmd/kube-scheduler/app/options/options.go b/cmd/kube-scheduler/app/options/options.go index 86f698bff69..972a6b7f09b 100644 --- a/cmd/kube-scheduler/app/options/options.go +++ b/cmd/kube-scheduler/app/options/options.go @@ -104,6 +104,7 @@ func NewOptions() (*Options, error) { }, } + o.Authentication.TolerateInClusterLookupFailure = true o.Authentication.RemoteKubeConfigFileOptional = true o.Authorization.RemoteKubeConfigFileOptional = true o.Authorization.AlwaysAllowPaths = []string{"/healthz"} diff --git a/cmd/kube-scheduler/app/options/options_test.go b/cmd/kube-scheduler/app/options/options_test.go index 34cd2404231..b20fb0b0f8c 100644 --- a/cmd/kube-scheduler/app/options/options_test.go +++ b/cmd/kube-scheduler/app/options/options_test.go @@ -225,8 +225,7 @@ users: Burst: 100, ContentType: "application/vnd.kubernetes.protobuf", }, - PercentageOfNodesToScore: 50, - BindTimeoutSeconds: &defaultBindTimeoutSeconds, + BindTimeoutSeconds: &defaultBindTimeoutSeconds, }, }, { @@ -306,8 +305,7 @@ users: Burst: 100, ContentType: "application/vnd.kubernetes.protobuf", }, - PercentageOfNodesToScore: 50, - BindTimeoutSeconds: &defaultBindTimeoutSeconds, + BindTimeoutSeconds: &defaultBindTimeoutSeconds, }, }, { diff --git a/cmd/kube-scheduler/app/server.go b/cmd/kube-scheduler/app/server.go index 615f9e8f18f..f57f812bf7f 100644 --- a/cmd/kube-scheduler/app/server.go +++ b/cmd/kube-scheduler/app/server.go @@ -38,17 +38,14 @@ import ( "k8s.io/apiserver/pkg/server/healthz" "k8s.io/apiserver/pkg/server/mux" "k8s.io/apiserver/pkg/server/routes" - utilfeature "k8s.io/apiserver/pkg/util/feature" apiserverflag "k8s.io/apiserver/pkg/util/flag" "k8s.io/apiserver/pkg/util/globalflag" - storageinformers "k8s.io/client-go/informers/storage/v1" v1core "k8s.io/client-go/kubernetes/typed/core/v1" "k8s.io/client-go/tools/leaderelection" schedulerserverconfig "k8s.io/kubernetes/cmd/kube-scheduler/app/config" "k8s.io/kubernetes/cmd/kube-scheduler/app/options" "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/controller" - "k8s.io/kubernetes/pkg/features" "k8s.io/kubernetes/pkg/scheduler" "k8s.io/kubernetes/pkg/scheduler/algorithmprovider" schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" @@ -165,11 +162,6 @@ func runCommand(cmd *cobra.Command, args []string, opts *options.Options) error // Run executes the scheduler based on the given configuration. It only return on error or when stopCh is closed. func Run(cc schedulerserverconfig.CompletedConfig, stopCh <-chan struct{}) error { - var storageClassInformer storageinformers.StorageClassInformer - if utilfeature.DefaultFeatureGate.Enabled(features.VolumeScheduling) { - storageClassInformer = cc.InformerFactory.Storage().V1().StorageClasses() - } - // Create the scheduler. sched, err := scheduler.New(cc.Client, cc.InformerFactory.Core().V1().Nodes(), @@ -181,13 +173,12 @@ func Run(cc schedulerserverconfig.CompletedConfig, stopCh <-chan struct{}) error cc.InformerFactory.Apps().V1().StatefulSets(), cc.InformerFactory.Core().V1().Services(), cc.InformerFactory.Policy().V1beta1().PodDisruptionBudgets(), - storageClassInformer, + cc.InformerFactory.Storage().V1().StorageClasses(), cc.Recorder, cc.ComponentConfig.AlgorithmSource, stopCh, scheduler.WithName(cc.ComponentConfig.SchedulerName), scheduler.WithHardPodAffinitySymmetricWeight(cc.ComponentConfig.HardPodAffinitySymmetricWeight), - scheduler.WithEquivalenceClassCacheEnabled(cc.ComponentConfig.EnableContentionProfiling), scheduler.WithPreemptionDisabled(cc.ComponentConfig.DisablePreemption), scheduler.WithPercentageOfNodesToScore(cc.ComponentConfig.PercentageOfNodesToScore), scheduler.WithBindTimeoutSeconds(*cc.ComponentConfig.BindTimeoutSeconds)) @@ -197,6 +188,7 @@ func Run(cc schedulerserverconfig.CompletedConfig, stopCh <-chan struct{}) error // Prepare the event broadcaster. if cc.Broadcaster != nil && cc.EventClient != nil { + cc.Broadcaster.StartLogging(klog.V(6).Infof) cc.Broadcaster.StartRecordingToSink(&v1core.EventSinkImpl{Interface: cc.EventClient.Events("")}) } @@ -336,11 +328,6 @@ func newHealthzHandler(config *kubeschedulerconfig.KubeSchedulerConfiguration, s // NewSchedulerConfig creates the scheduler configuration. This is exposed for use by tests. func NewSchedulerConfig(s schedulerserverconfig.CompletedConfig) (*factory.Config, error) { - var storageClassInformer storageinformers.StorageClassInformer - if utilfeature.DefaultFeatureGate.Enabled(features.VolumeScheduling) { - storageClassInformer = s.InformerFactory.Storage().V1().StorageClasses() - } - // Set up the configurator which can create schedulers from configs. configurator := factory.NewConfigFactory(&factory.ConfigFactoryArgs{ SchedulerName: s.ComponentConfig.SchedulerName, @@ -354,9 +341,8 @@ func NewSchedulerConfig(s schedulerserverconfig.CompletedConfig) (*factory.Confi StatefulSetInformer: s.InformerFactory.Apps().V1().StatefulSets(), ServiceInformer: s.InformerFactory.Core().V1().Services(), PdbInformer: s.InformerFactory.Policy().V1beta1().PodDisruptionBudgets(), - StorageClassInformer: storageClassInformer, + StorageClassInformer: s.InformerFactory.Storage().V1().StorageClasses(), HardPodAffinitySymmetricWeight: s.ComponentConfig.HardPodAffinitySymmetricWeight, - EnableEquivalenceClassCache: utilfeature.DefaultFeatureGate.Enabled(features.EnableEquivalenceClassCache), DisablePreemption: s.ComponentConfig.DisablePreemption, PercentageOfNodesToScore: s.ComponentConfig.PercentageOfNodesToScore, BindTimeoutSeconds: *s.ComponentConfig.BindTimeoutSeconds, diff --git a/cmd/kubeadm/.import-restrictions b/cmd/kubeadm/.import-restrictions index 988c92e551e..b2ceea03ec9 100644 --- a/cmd/kubeadm/.import-restrictions +++ b/cmd/kubeadm/.import-restrictions @@ -71,7 +71,7 @@ "k8s.io/kubernetes/pkg/registry/core/service/ipallocator", "k8s.io/kubernetes/pkg/scheduler/algorithm", "k8s.io/kubernetes/pkg/scheduler/api", - "k8s.io/kubernetes/pkg/scheduler/cache", + "k8s.io/kubernetes/pkg/scheduler/nodeinfo", "k8s.io/kubernetes/pkg/scheduler/internal/cache", "k8s.io/kubernetes/pkg/scheduler/util", "k8s.io/kubernetes/pkg/security/apparmor", diff --git a/cmd/kubeadm/app/apis/kubeadm/bootstraptokenhelpers_test.go b/cmd/kubeadm/app/apis/kubeadm/bootstraptokenhelpers_test.go index 153d08e7c33..b867876e888 100644 --- a/cmd/kubeadm/app/apis/kubeadm/bootstraptokenhelpers_test.go +++ b/cmd/kubeadm/app/apis/kubeadm/bootstraptokenhelpers_test.go @@ -64,14 +64,16 @@ func TestToSecret(t *testing.T) { }, } for _, rt := range tests { - actual := rt.bt.ToSecret() - if !reflect.DeepEqual(actual, rt.secret) { - t.Errorf( - "failed BootstrapToken.ToSecret():\n\texpected: %v\n\t actual: %v", - rt.secret, - actual, - ) - } + t.Run(rt.bt.Token.ID, func(t *testing.T) { + actual := rt.bt.ToSecret() + if !reflect.DeepEqual(actual, rt.secret) { + t.Errorf( + "failed BootstrapToken.ToSecret():\n\texpected: %v\n\t actual: %v", + rt.secret, + actual, + ) + } + }) } } @@ -92,27 +94,31 @@ func TestBootstrapTokenToSecretRoundtrip(t *testing.T) { }, } for _, rt := range tests { - actual, err := BootstrapTokenFromSecret(rt.bt.ToSecret()) - if err != nil { - t.Errorf("failed BootstrapToken to Secret roundtrip with error: %v", err) - } - if !reflect.DeepEqual(actual, rt.bt) { - t.Errorf( - "failed BootstrapToken to Secret roundtrip:\n\texpected: %v\n\t actual: %v", - rt.bt, - actual, - ) - } + t.Run(rt.bt.Token.ID, func(t *testing.T) { + actual, err := BootstrapTokenFromSecret(rt.bt.ToSecret()) + if err != nil { + t.Errorf("failed BootstrapToken to Secret roundtrip with error: %v", err) + } + if !reflect.DeepEqual(actual, rt.bt) { + t.Errorf( + "failed BootstrapToken to Secret roundtrip:\n\texpected: %v\n\t actual: %v", + rt.bt, + actual, + ) + } + }) } } func TestEncodeTokenSecretData(t *testing.T) { var tests = []struct { + name string bt *BootstrapToken data map[string][]byte }{ { - &BootstrapToken{ // the minimum amount of information needed to be specified + "the minimum amount of information needed to be specified", + &BootstrapToken{ Token: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}, }, map[string][]byte{ @@ -121,7 +127,8 @@ func TestEncodeTokenSecretData(t *testing.T) { }, }, { - &BootstrapToken{ // adds description + "adds description", + &BootstrapToken{ Token: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}, Description: "foo", }, @@ -132,7 +139,8 @@ func TestEncodeTokenSecretData(t *testing.T) { }, }, { - &BootstrapToken{ // adds ttl + "adds ttl", + &BootstrapToken{ Token: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}, TTL: &metav1.Duration{ Duration: mustParseDuration("2h", t), @@ -145,7 +153,8 @@ func TestEncodeTokenSecretData(t *testing.T) { }, }, { - &BootstrapToken{ // adds expiration + "adds expiration", + &BootstrapToken{ Token: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}, Expires: &metav1.Time{ Time: refTime, @@ -158,7 +167,8 @@ func TestEncodeTokenSecretData(t *testing.T) { }, }, { - &BootstrapToken{ // adds ttl and expiration, should favor expiration + "adds ttl and expiration, should favor expiration", + &BootstrapToken{ Token: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}, TTL: &metav1.Duration{ Duration: mustParseDuration("2h", t), @@ -174,7 +184,8 @@ func TestEncodeTokenSecretData(t *testing.T) { }, }, { - &BootstrapToken{ // adds usages + "adds usages", + &BootstrapToken{ Token: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}, Usages: []string{"authentication", "signing"}, }, @@ -186,7 +197,8 @@ func TestEncodeTokenSecretData(t *testing.T) { }, }, { - &BootstrapToken{ // adds groups + "adds groups", + &BootstrapToken{ Token: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}, Groups: []string{"system:bootstrappers", "system:bootstrappers:foo"}, }, @@ -197,7 +209,8 @@ func TestEncodeTokenSecretData(t *testing.T) { }, }, { - &BootstrapToken{ // all together + "all together", + &BootstrapToken{ Token: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}, Description: "foo", TTL: &metav1.Duration{ @@ -221,14 +234,16 @@ func TestEncodeTokenSecretData(t *testing.T) { }, } for _, rt := range tests { - actual := encodeTokenSecretData(rt.bt, refTime) - if !reflect.DeepEqual(actual, rt.data) { - t.Errorf( - "failed encodeTokenSecretData:\n\texpected: %v\n\t actual: %v", - rt.data, - actual, - ) - } + t.Run(rt.name, func(t *testing.T) { + actual := encodeTokenSecretData(rt.bt, refTime) + if !reflect.DeepEqual(actual, rt.data) { + t.Errorf( + "failed encodeTokenSecretData:\n\texpected: %v\n\t actual: %v", + rt.data, + actual, + ) + } + }) } } @@ -242,12 +257,14 @@ func mustParseDuration(durationStr string, t *testing.T) time.Duration { func TestBootstrapTokenFromSecret(t *testing.T) { var tests = []struct { + desc string name string data map[string][]byte bt *BootstrapToken expectedError bool }{ - { // minimum information + { + "minimum information", "bootstrap-token-abcdef", map[string][]byte{ "token-id": []byte("abcdef"), @@ -258,7 +275,8 @@ func TestBootstrapTokenFromSecret(t *testing.T) { }, false, }, - { // invalid token id + { + "invalid token id", "bootstrap-token-abcdef", map[string][]byte{ "token-id": []byte("abcdeF"), @@ -267,7 +285,8 @@ func TestBootstrapTokenFromSecret(t *testing.T) { nil, true, }, - { // invalid secret naming + { + "invalid secret naming", "foo", map[string][]byte{ "token-id": []byte("abcdef"), @@ -276,7 +295,8 @@ func TestBootstrapTokenFromSecret(t *testing.T) { nil, true, }, - { // invalid token secret + { + "invalid token secret", "bootstrap-token-abcdef", map[string][]byte{ "token-id": []byte("abcdef"), @@ -285,7 +305,8 @@ func TestBootstrapTokenFromSecret(t *testing.T) { nil, true, }, - { // adds description + { + "adds description", "bootstrap-token-abcdef", map[string][]byte{ "token-id": []byte("abcdef"), @@ -298,7 +319,8 @@ func TestBootstrapTokenFromSecret(t *testing.T) { }, false, }, - { // adds expiration + { + "adds expiration", "bootstrap-token-abcdef", map[string][]byte{ "token-id": []byte("abcdef"), @@ -313,7 +335,8 @@ func TestBootstrapTokenFromSecret(t *testing.T) { }, false, }, - { // invalid expiration + { + "invalid expiration", "bootstrap-token-abcdef", map[string][]byte{ "token-id": []byte("abcdef"), @@ -323,7 +346,8 @@ func TestBootstrapTokenFromSecret(t *testing.T) { nil, true, }, - { // adds usages + { + "adds usages", "bootstrap-token-abcdef", map[string][]byte{ "token-id": []byte("abcdef"), @@ -337,7 +361,8 @@ func TestBootstrapTokenFromSecret(t *testing.T) { }, false, }, - { // should ignore usages that aren't set to true + { + "should ignore usages that aren't set to true", "bootstrap-token-abcdef", map[string][]byte{ "token-id": []byte("abcdef"), @@ -353,7 +378,8 @@ func TestBootstrapTokenFromSecret(t *testing.T) { }, false, }, - { // adds groups + { + "adds groups", "bootstrap-token-abcdef", map[string][]byte{ "token-id": []byte("abcdef"), @@ -366,7 +392,8 @@ func TestBootstrapTokenFromSecret(t *testing.T) { }, false, }, - { // all fields set + { + "all fields set", "bootstrap-token-abcdef", map[string][]byte{ "token-id": []byte("abcdef"), @@ -390,34 +417,36 @@ func TestBootstrapTokenFromSecret(t *testing.T) { }, } for _, rt := range tests { - actual, err := BootstrapTokenFromSecret(&v1.Secret{ - ObjectMeta: metav1.ObjectMeta{ - Name: rt.name, - Namespace: "kube-system", - }, - Type: v1.SecretType("bootstrap.kubernetes.io/token"), - Data: rt.data, - }) - if (err != nil) != rt.expectedError { - t.Errorf( - "failed BootstrapTokenFromSecret\n\texpected error: %t\n\t actual error: %v", - rt.expectedError, - err, - ) - } else { - if actual == nil && rt.bt == nil { - // if both pointers are nil, it's okay, just continue - continue - } - // If one of the pointers is defined but the other isn't, throw error. If both pointers are defined but unequal, throw error - if (actual == nil && rt.bt != nil) || (actual != nil && rt.bt == nil) || !reflect.DeepEqual(*actual, *rt.bt) { + t.Run(rt.desc, func(t *testing.T) { + actual, err := BootstrapTokenFromSecret(&v1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: rt.name, + Namespace: "kube-system", + }, + Type: v1.SecretType("bootstrap.kubernetes.io/token"), + Data: rt.data, + }) + if (err != nil) != rt.expectedError { t.Errorf( - "failed BootstrapTokenFromSecret\n\texpected: %s\n\t actual: %s", - jsonMarshal(rt.bt), - jsonMarshal(actual), + "failed BootstrapTokenFromSecret\n\texpected error: %t\n\t actual error: %v", + rt.expectedError, + err, ) + } else { + if actual == nil && rt.bt == nil { + // if both pointers are nil, it's okay, just continue + return + } + // If one of the pointers is defined but the other isn't, throw error. If both pointers are defined but unequal, throw error + if (actual == nil && rt.bt != nil) || (actual != nil && rt.bt == nil) || !reflect.DeepEqual(*actual, *rt.bt) { + t.Errorf( + "failed BootstrapTokenFromSecret\n\texpected: %s\n\t actual: %s", + jsonMarshal(rt.bt), + jsonMarshal(actual), + ) + } } - } + }) } } @@ -428,11 +457,13 @@ func jsonMarshal(bt *BootstrapToken) string { func TestGetSecretString(t *testing.T) { var tests = []struct { + name string secret *v1.Secret key string expectedVal string }{ { + name: "existing key", secret: &v1.Secret{ ObjectMeta: metav1.ObjectMeta{Name: "foo"}, Data: map[string][]byte{ @@ -443,6 +474,7 @@ func TestGetSecretString(t *testing.T) { expectedVal: "bar", }, { + name: "non-existing key", secret: &v1.Secret{ ObjectMeta: metav1.ObjectMeta{Name: "foo"}, Data: map[string][]byte{ @@ -453,6 +485,7 @@ func TestGetSecretString(t *testing.T) { expectedVal: "", }, { + name: "no data", secret: &v1.Secret{ ObjectMeta: metav1.ObjectMeta{Name: "foo"}, }, @@ -461,13 +494,15 @@ func TestGetSecretString(t *testing.T) { }, } for _, rt := range tests { - actual := getSecretString(rt.secret, rt.key) - if actual != rt.expectedVal { - t.Errorf( - "failed getSecretString:\n\texpected: %s\n\t actual: %s", - rt.expectedVal, - actual, - ) - } + t.Run(rt.name, func(t *testing.T) { + actual := getSecretString(rt.secret, rt.key) + if actual != rt.expectedVal { + t.Errorf( + "failed getSecretString:\n\texpected: %s\n\t actual: %s", + rt.expectedVal, + actual, + ) + } + }) } } diff --git a/cmd/kubeadm/app/apis/kubeadm/bootstraptokenstring_test.go b/cmd/kubeadm/app/apis/kubeadm/bootstraptokenstring_test.go index f43f7892290..040a2090508 100644 --- a/cmd/kubeadm/app/apis/kubeadm/bootstraptokenstring_test.go +++ b/cmd/kubeadm/app/apis/kubeadm/bootstraptokenstring_test.go @@ -34,17 +34,19 @@ func TestMarshalJSON(t *testing.T) { {BootstrapTokenString{ID: "h", Secret: "b"}, `"h.b"`}, } for _, rt := range tests { - b, err := json.Marshal(rt.bts) - if err != nil { - t.Fatalf("json.Marshal returned an unexpected error: %v", err) - } - if string(b) != rt.expected { - t.Errorf( - "failed BootstrapTokenString.MarshalJSON:\n\texpected: %s\n\t actual: %s", - rt.expected, - string(b), - ) - } + t.Run(rt.bts.ID, func(t *testing.T) { + b, err := json.Marshal(rt.bts) + if err != nil { + t.Fatalf("json.Marshal returned an unexpected error: %v", err) + } + if string(b) != rt.expected { + t.Errorf( + "failed BootstrapTokenString.MarshalJSON:\n\texpected: %s\n\t actual: %s", + rt.expected, + string(b), + ) + } + }) } } @@ -64,17 +66,19 @@ func TestUnmarshalJSON(t *testing.T) { {`"123456.aabbccddeeffgghh"`, &BootstrapTokenString{ID: "123456", Secret: "aabbccddeeffgghh"}, false}, } for _, rt := range tests { - newbts := &BootstrapTokenString{} - err := json.Unmarshal([]byte(rt.input), newbts) - if (err != nil) != rt.expectedError { - t.Errorf("failed BootstrapTokenString.UnmarshalJSON:\n\texpected error: %t\n\t actual error: %v", rt.expectedError, err) - } else if !reflect.DeepEqual(rt.bts, newbts) { - t.Errorf( - "failed BootstrapTokenString.UnmarshalJSON:\n\texpected: %v\n\t actual: %v", - rt.bts, - newbts, - ) - } + t.Run(rt.input, func(t *testing.T) { + newbts := &BootstrapTokenString{} + err := json.Unmarshal([]byte(rt.input), newbts) + if (err != nil) != rt.expectedError { + t.Errorf("failed BootstrapTokenString.UnmarshalJSON:\n\texpected error: %t\n\t actual error: %v", rt.expectedError, err) + } else if !reflect.DeepEqual(rt.bts, newbts) { + t.Errorf( + "failed BootstrapTokenString.UnmarshalJSON:\n\texpected: %v\n\t actual: %v", + rt.bts, + newbts, + ) + } + }) } } @@ -87,9 +91,11 @@ func TestJSONRoundtrip(t *testing.T) { {"", &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}}, } for _, rt := range tests { - if err := roundtrip(rt.input, rt.bts); err != nil { - t.Errorf("failed BootstrapTokenString JSON roundtrip with error: %v", err) - } + t.Run(rt.input, func(t *testing.T) { + if err := roundtrip(rt.input, rt.bts); err != nil { + t.Errorf("failed BootstrapTokenString JSON roundtrip with error: %v", err) + } + }) } } @@ -140,14 +146,16 @@ func TestTokenFromIDAndSecret(t *testing.T) { {BootstrapTokenString{ID: "h", Secret: "b"}, "h.b"}, } for _, rt := range tests { - actual := rt.bts.String() - if actual != rt.expected { - t.Errorf( - "failed BootstrapTokenString.String():\n\texpected: %s\n\t actual: %s", - rt.expected, - actual, - ) - } + t.Run(rt.bts.ID, func(t *testing.T) { + actual := rt.bts.String() + if actual != rt.expected { + t.Errorf( + "failed BootstrapTokenString.String():\n\texpected: %s\n\t actual: %s", + rt.expected, + actual, + ) + } + }) } } @@ -175,22 +183,24 @@ func TestNewBootstrapTokenString(t *testing.T) { {token: "123456.1234560123456789", expectedError: false, bts: &BootstrapTokenString{ID: "123456", Secret: "1234560123456789"}}, } for _, rt := range tests { - actual, err := NewBootstrapTokenString(rt.token) - if (err != nil) != rt.expectedError { - t.Errorf( - "failed NewBootstrapTokenString for the token %q\n\texpected error: %t\n\t actual error: %v", - rt.token, - rt.expectedError, - err, - ) - } else if !reflect.DeepEqual(actual, rt.bts) { - t.Errorf( - "failed NewBootstrapTokenString for the token %q\n\texpected: %v\n\t actual: %v", - rt.token, - rt.bts, - actual, - ) - } + t.Run(rt.token, func(t *testing.T) { + actual, err := NewBootstrapTokenString(rt.token) + if (err != nil) != rt.expectedError { + t.Errorf( + "failed NewBootstrapTokenString for the token %q\n\texpected error: %t\n\t actual error: %v", + rt.token, + rt.expectedError, + err, + ) + } else if !reflect.DeepEqual(actual, rt.bts) { + t.Errorf( + "failed NewBootstrapTokenString for the token %q\n\texpected: %v\n\t actual: %v", + rt.token, + rt.bts, + actual, + ) + } + }) } } @@ -215,23 +225,25 @@ func TestNewBootstrapTokenStringFromIDAndSecret(t *testing.T) { {id: "123456", secret: "1234560123456789", expectedError: false, bts: &BootstrapTokenString{ID: "123456", Secret: "1234560123456789"}}, } for _, rt := range tests { - actual, err := NewBootstrapTokenStringFromIDAndSecret(rt.id, rt.secret) - if (err != nil) != rt.expectedError { - t.Errorf( - "failed NewBootstrapTokenStringFromIDAndSecret for the token with id %q and secret %q\n\texpected error: %t\n\t actual error: %v", - rt.id, - rt.secret, - rt.expectedError, - err, - ) - } else if !reflect.DeepEqual(actual, rt.bts) { - t.Errorf( - "failed NewBootstrapTokenStringFromIDAndSecret for the token with id %q and secret %q\n\texpected: %v\n\t actual: %v", - rt.id, - rt.secret, - rt.bts, - actual, - ) - } + t.Run(rt.id, func(t *testing.T) { + actual, err := NewBootstrapTokenStringFromIDAndSecret(rt.id, rt.secret) + if (err != nil) != rt.expectedError { + t.Errorf( + "failed NewBootstrapTokenStringFromIDAndSecret for the token with id %q and secret %q\n\texpected error: %t\n\t actual error: %v", + rt.id, + rt.secret, + rt.expectedError, + err, + ) + } else if !reflect.DeepEqual(actual, rt.bts) { + t.Errorf( + "failed NewBootstrapTokenStringFromIDAndSecret for the token with id %q and secret %q\n\texpected: %v\n\t actual: %v", + rt.id, + rt.secret, + rt.bts, + actual, + ) + } + }) } } diff --git a/cmd/kubeadm/app/apis/kubeadm/v1alpha3/bootstraptokenstring_test.go b/cmd/kubeadm/app/apis/kubeadm/v1alpha3/bootstraptokenstring_test.go index 320d9d5660d..2c096507c4d 100644 --- a/cmd/kubeadm/app/apis/kubeadm/v1alpha3/bootstraptokenstring_test.go +++ b/cmd/kubeadm/app/apis/kubeadm/v1alpha3/bootstraptokenstring_test.go @@ -34,17 +34,19 @@ func TestMarshalJSON(t *testing.T) { {BootstrapTokenString{ID: "h", Secret: "b"}, `"h.b"`}, } for _, rt := range tests { - b, err := json.Marshal(rt.bts) - if err != nil { - t.Fatalf("json.Marshal returned an unexpected error: %v", err) - } - if string(b) != rt.expected { - t.Errorf( - "failed BootstrapTokenString.MarshalJSON:\n\texpected: %s\n\t actual: %s", - rt.expected, - string(b), - ) - } + t.Run(rt.bts.ID, func(t *testing.T) { + b, err := json.Marshal(rt.bts) + if err != nil { + t.Fatalf("json.Marshal returned an unexpected error: %v", err) + } + if string(b) != rt.expected { + t.Errorf( + "failed BootstrapTokenString.MarshalJSON:\n\texpected: %s\n\t actual: %s", + rt.expected, + string(b), + ) + } + }) } } @@ -64,17 +66,19 @@ func TestUnmarshalJSON(t *testing.T) { {`"123456.aabbccddeeffgghh"`, &BootstrapTokenString{ID: "123456", Secret: "aabbccddeeffgghh"}, false}, } for _, rt := range tests { - newbts := &BootstrapTokenString{} - err := json.Unmarshal([]byte(rt.input), newbts) - if (err != nil) != rt.expectedError { - t.Errorf("failed BootstrapTokenString.UnmarshalJSON:\n\texpected error: %t\n\t actual error: %v", rt.expectedError, err) - } else if !reflect.DeepEqual(rt.bts, newbts) { - t.Errorf( - "failed BootstrapTokenString.UnmarshalJSON:\n\texpected: %v\n\t actual: %v", - rt.bts, - newbts, - ) - } + t.Run(rt.input, func(t *testing.T) { + newbts := &BootstrapTokenString{} + err := json.Unmarshal([]byte(rt.input), newbts) + if (err != nil) != rt.expectedError { + t.Errorf("failed BootstrapTokenString.UnmarshalJSON:\n\texpected error: %t\n\t actual error: %v", rt.expectedError, err) + } else if !reflect.DeepEqual(rt.bts, newbts) { + t.Errorf( + "failed BootstrapTokenString.UnmarshalJSON:\n\texpected: %v\n\t actual: %v", + rt.bts, + newbts, + ) + } + }) } } @@ -87,9 +91,11 @@ func TestJSONRoundtrip(t *testing.T) { {"", &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}}, } for _, rt := range tests { - if err := roundtrip(rt.input, rt.bts); err != nil { - t.Errorf("failed BootstrapTokenString JSON roundtrip with error: %v", err) - } + t.Run(rt.input, func(t *testing.T) { + if err := roundtrip(rt.input, rt.bts); err != nil { + t.Errorf("failed BootstrapTokenString JSON roundtrip with error: %v", err) + } + }) } } @@ -140,14 +146,16 @@ func TestTokenFromIDAndSecret(t *testing.T) { {BootstrapTokenString{ID: "h", Secret: "b"}, "h.b"}, } for _, rt := range tests { - actual := rt.bts.String() - if actual != rt.expected { - t.Errorf( - "failed BootstrapTokenString.String():\n\texpected: %s\n\t actual: %s", - rt.expected, - actual, - ) - } + t.Run(rt.bts.ID, func(t *testing.T) { + actual := rt.bts.String() + if actual != rt.expected { + t.Errorf( + "failed BootstrapTokenString.String():\n\texpected: %s\n\t actual: %s", + rt.expected, + actual, + ) + } + }) } } @@ -175,22 +183,24 @@ func TestNewBootstrapTokenString(t *testing.T) { {token: "123456.1234560123456789", expectedError: false, bts: &BootstrapTokenString{ID: "123456", Secret: "1234560123456789"}}, } for _, rt := range tests { - actual, err := NewBootstrapTokenString(rt.token) - if (err != nil) != rt.expectedError { - t.Errorf( - "failed NewBootstrapTokenString for the token %q\n\texpected error: %t\n\t actual error: %v", - rt.token, - rt.expectedError, - err, - ) - } else if !reflect.DeepEqual(actual, rt.bts) { - t.Errorf( - "failed NewBootstrapTokenString for the token %q\n\texpected: %v\n\t actual: %v", - rt.token, - rt.bts, - actual, - ) - } + t.Run(rt.token, func(t *testing.T) { + actual, err := NewBootstrapTokenString(rt.token) + if (err != nil) != rt.expectedError { + t.Errorf( + "failed NewBootstrapTokenString for the token %q\n\texpected error: %t\n\t actual error: %v", + rt.token, + rt.expectedError, + err, + ) + } else if !reflect.DeepEqual(actual, rt.bts) { + t.Errorf( + "failed NewBootstrapTokenString for the token %q\n\texpected: %v\n\t actual: %v", + rt.token, + rt.bts, + actual, + ) + } + }) } } @@ -215,23 +225,25 @@ func TestNewBootstrapTokenStringFromIDAndSecret(t *testing.T) { {id: "123456", secret: "1234560123456789", expectedError: false, bts: &BootstrapTokenString{ID: "123456", Secret: "1234560123456789"}}, } for _, rt := range tests { - actual, err := NewBootstrapTokenStringFromIDAndSecret(rt.id, rt.secret) - if (err != nil) != rt.expectedError { - t.Errorf( - "failed NewBootstrapTokenStringFromIDAndSecret for the token with id %q and secret %q\n\texpected error: %t\n\t actual error: %v", - rt.id, - rt.secret, - rt.expectedError, - err, - ) - } else if !reflect.DeepEqual(actual, rt.bts) { - t.Errorf( - "failed NewBootstrapTokenStringFromIDAndSecret for the token with id %q and secret %q\n\texpected: %v\n\t actual: %v", - rt.id, - rt.secret, - rt.bts, - actual, - ) - } + t.Run(rt.id, func(t *testing.T) { + actual, err := NewBootstrapTokenStringFromIDAndSecret(rt.id, rt.secret) + if (err != nil) != rt.expectedError { + t.Errorf( + "failed NewBootstrapTokenStringFromIDAndSecret for the token with id %q and secret %q\n\texpected error: %t\n\t actual error: %v", + rt.id, + rt.secret, + rt.expectedError, + err, + ) + } else if !reflect.DeepEqual(actual, rt.bts) { + t.Errorf( + "failed NewBootstrapTokenStringFromIDAndSecret for the token with id %q and secret %q\n\texpected: %v\n\t actual: %v", + rt.id, + rt.secret, + rt.bts, + actual, + ) + } + }) } } diff --git a/cmd/kubeadm/app/apis/kubeadm/v1alpha3/conversion_test.go b/cmd/kubeadm/app/apis/kubeadm/v1alpha3/conversion_test.go index 1891e506b76..718c9392c9a 100644 --- a/cmd/kubeadm/app/apis/kubeadm/v1alpha3/conversion_test.go +++ b/cmd/kubeadm/app/apis/kubeadm/v1alpha3/conversion_test.go @@ -46,13 +46,15 @@ func TestJoinConfigurationConversion(t *testing.T) { expectedError: true, }, } - for _, tc := range testcases { - internal := &kubeadm.JoinConfiguration{} - err := Convert_v1alpha3_JoinConfiguration_To_kubeadm_JoinConfiguration(tc.old, internal, nil) - if (err != nil) != tc.expectedError { - t.Errorf("ImageToImageMeta returned unexpected error: %v, saw: %v", tc.expectedError, (err != nil)) - return - } + for name, tc := range testcases { + t.Run(name, func(t *testing.T) { + internal := &kubeadm.JoinConfiguration{} + err := Convert_v1alpha3_JoinConfiguration_To_kubeadm_JoinConfiguration(tc.old, internal, nil) + if (err != nil) != tc.expectedError { + t.Errorf("ImageToImageMeta returned unexpected error: %v, saw: %v", tc.expectedError, (err != nil)) + return + } + }) } } @@ -76,12 +78,14 @@ func TestInitConfigurationConversion(t *testing.T) { expectedErr: true, }, } - for _, tc := range testcases { - internal := &kubeadm.InitConfiguration{} - err := Convert_v1alpha3_InitConfiguration_To_kubeadm_InitConfiguration(tc.old, internal, nil) - if (err != nil) != tc.expectedErr { - t.Errorf("no error was expected but '%s' was found", err) - } + for name, tc := range testcases { + t.Run(name, func(t *testing.T) { + internal := &kubeadm.InitConfiguration{} + err := Convert_v1alpha3_InitConfiguration_To_kubeadm_InitConfiguration(tc.old, internal, nil) + if (err != nil) != tc.expectedErr { + t.Errorf("no error was expected but '%s' was found", err) + } + }) } } diff --git a/cmd/kubeadm/app/apis/kubeadm/v1alpha3/doc.go b/cmd/kubeadm/app/apis/kubeadm/v1alpha3/doc.go index 6d6c2309c0b..a3a3c8710e7 100644 --- a/cmd/kubeadm/app/apis/kubeadm/v1alpha3/doc.go +++ b/cmd/kubeadm/app/apis/kubeadm/v1alpha3/doc.go @@ -177,7 +177,7 @@ limitations under the License. // value: "master" // effect: "NoSchedule" // kubeletExtraArgs: -// cgroupDriver: "cgroupfs" +// cgroup-driver: "cgroupfs" // apiEndpoint: // advertiseAddress: "10.100.0.1" // bindPort: 6443 diff --git a/cmd/kubeadm/app/apis/kubeadm/v1beta1/bootstraptokenstring_test.go b/cmd/kubeadm/app/apis/kubeadm/v1beta1/bootstraptokenstring_test.go index ed19f900a8b..2601e9b0733 100644 --- a/cmd/kubeadm/app/apis/kubeadm/v1beta1/bootstraptokenstring_test.go +++ b/cmd/kubeadm/app/apis/kubeadm/v1beta1/bootstraptokenstring_test.go @@ -34,17 +34,19 @@ func TestMarshalJSON(t *testing.T) { {BootstrapTokenString{ID: "h", Secret: "b"}, `"h.b"`}, } for _, rt := range tests { - b, err := json.Marshal(rt.bts) - if err != nil { - t.Fatalf("json.Marshal returned an unexpected error: %v", err) - } - if string(b) != rt.expected { - t.Errorf( - "failed BootstrapTokenString.MarshalJSON:\n\texpected: %s\n\t actual: %s", - rt.expected, - string(b), - ) - } + t.Run(rt.bts.ID, func(t *testing.T) { + b, err := json.Marshal(rt.bts) + if err != nil { + t.Fatalf("json.Marshal returned an unexpected error: %v", err) + } + if string(b) != rt.expected { + t.Errorf( + "failed BootstrapTokenString.MarshalJSON:\n\texpected: %s\n\t actual: %s", + rt.expected, + string(b), + ) + } + }) } } @@ -64,17 +66,19 @@ func TestUnmarshalJSON(t *testing.T) { {`"123456.aabbccddeeffgghh"`, &BootstrapTokenString{ID: "123456", Secret: "aabbccddeeffgghh"}, false}, } for _, rt := range tests { - newbts := &BootstrapTokenString{} - err := json.Unmarshal([]byte(rt.input), newbts) - if (err != nil) != rt.expectedError { - t.Errorf("failed BootstrapTokenString.UnmarshalJSON:\n\texpected error: %t\n\t actual error: %v", rt.expectedError, err) - } else if !reflect.DeepEqual(rt.bts, newbts) { - t.Errorf( - "failed BootstrapTokenString.UnmarshalJSON:\n\texpected: %v\n\t actual: %v", - rt.bts, - newbts, - ) - } + t.Run(rt.input, func(t *testing.T) { + newbts := &BootstrapTokenString{} + err := json.Unmarshal([]byte(rt.input), newbts) + if (err != nil) != rt.expectedError { + t.Errorf("failed BootstrapTokenString.UnmarshalJSON:\n\texpected error: %t\n\t actual error: %v", rt.expectedError, err) + } else if !reflect.DeepEqual(rt.bts, newbts) { + t.Errorf( + "failed BootstrapTokenString.UnmarshalJSON:\n\texpected: %v\n\t actual: %v", + rt.bts, + newbts, + ) + } + }) } } @@ -87,9 +91,11 @@ func TestJSONRoundtrip(t *testing.T) { {"", &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}}, } for _, rt := range tests { - if err := roundtrip(rt.input, rt.bts); err != nil { - t.Errorf("failed BootstrapTokenString JSON roundtrip with error: %v", err) - } + t.Run(rt.input, func(t *testing.T) { + if err := roundtrip(rt.input, rt.bts); err != nil { + t.Errorf("failed BootstrapTokenString JSON roundtrip with error: %v", err) + } + }) } } @@ -140,14 +146,16 @@ func TestTokenFromIDAndSecret(t *testing.T) { {BootstrapTokenString{ID: "h", Secret: "b"}, "h.b"}, } for _, rt := range tests { - actual := rt.bts.String() - if actual != rt.expected { - t.Errorf( - "failed BootstrapTokenString.String():\n\texpected: %s\n\t actual: %s", - rt.expected, - actual, - ) - } + t.Run(rt.bts.ID, func(t *testing.T) { + actual := rt.bts.String() + if actual != rt.expected { + t.Errorf( + "failed BootstrapTokenString.String():\n\texpected: %s\n\t actual: %s", + rt.expected, + actual, + ) + } + }) } } @@ -175,22 +183,24 @@ func TestNewBootstrapTokenString(t *testing.T) { {token: "123456.1234560123456789", expectedError: false, bts: &BootstrapTokenString{ID: "123456", Secret: "1234560123456789"}}, } for _, rt := range tests { - actual, err := NewBootstrapTokenString(rt.token) - if (err != nil) != rt.expectedError { - t.Errorf( - "failed NewBootstrapTokenString for the token %q\n\texpected error: %t\n\t actual error: %v", - rt.token, - rt.expectedError, - err, - ) - } else if !reflect.DeepEqual(actual, rt.bts) { - t.Errorf( - "failed NewBootstrapTokenString for the token %q\n\texpected: %v\n\t actual: %v", - rt.token, - rt.bts, - actual, - ) - } + t.Run(rt.token, func(t *testing.T) { + actual, err := NewBootstrapTokenString(rt.token) + if (err != nil) != rt.expectedError { + t.Errorf( + "failed NewBootstrapTokenString for the token %q\n\texpected error: %t\n\t actual error: %v", + rt.token, + rt.expectedError, + err, + ) + } else if !reflect.DeepEqual(actual, rt.bts) { + t.Errorf( + "failed NewBootstrapTokenString for the token %q\n\texpected: %v\n\t actual: %v", + rt.token, + rt.bts, + actual, + ) + } + }) } } @@ -215,23 +225,25 @@ func TestNewBootstrapTokenStringFromIDAndSecret(t *testing.T) { {id: "123456", secret: "1234560123456789", expectedError: false, bts: &BootstrapTokenString{ID: "123456", Secret: "1234560123456789"}}, } for _, rt := range tests { - actual, err := NewBootstrapTokenStringFromIDAndSecret(rt.id, rt.secret) - if (err != nil) != rt.expectedError { - t.Errorf( - "failed NewBootstrapTokenStringFromIDAndSecret for the token with id %q and secret %q\n\texpected error: %t\n\t actual error: %v", - rt.id, - rt.secret, - rt.expectedError, - err, - ) - } else if !reflect.DeepEqual(actual, rt.bts) { - t.Errorf( - "failed NewBootstrapTokenStringFromIDAndSecret for the token with id %q and secret %q\n\texpected: %v\n\t actual: %v", - rt.id, - rt.secret, - rt.bts, - actual, - ) - } + t.Run(rt.id, func(t *testing.T) { + actual, err := NewBootstrapTokenStringFromIDAndSecret(rt.id, rt.secret) + if (err != nil) != rt.expectedError { + t.Errorf( + "failed NewBootstrapTokenStringFromIDAndSecret for the token with id %q and secret %q\n\texpected error: %t\n\t actual error: %v", + rt.id, + rt.secret, + rt.expectedError, + err, + ) + } else if !reflect.DeepEqual(actual, rt.bts) { + t.Errorf( + "failed NewBootstrapTokenStringFromIDAndSecret for the token with id %q and secret %q\n\texpected: %v\n\t actual: %v", + rt.id, + rt.secret, + rt.bts, + actual, + ) + } + }) } } diff --git a/cmd/kubeadm/app/apis/kubeadm/v1beta1/doc.go b/cmd/kubeadm/app/apis/kubeadm/v1beta1/doc.go index dfd0f2552a3..e88276027bb 100644 --- a/cmd/kubeadm/app/apis/kubeadm/v1beta1/doc.go +++ b/cmd/kubeadm/app/apis/kubeadm/v1beta1/doc.go @@ -154,7 +154,7 @@ limitations under the License. // deployed in the cluster. If this object is not provided or provided only partially, kubeadm applies defaults. // // See https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet/ or https://godoc.org/k8s.io/kubelet/config/v1beta1#KubeletConfiguration -// for kube proxy official documentation. +// for kubelet official documentation. // // Here is a fully populated example of a single YAML file containing multiple // configuration types to be used during a `kubeadm init` run. diff --git a/cmd/kubeadm/app/apis/kubeadm/validation/BUILD b/cmd/kubeadm/app/apis/kubeadm/validation/BUILD index 600a2ce38db..65a7864cd34 100644 --- a/cmd/kubeadm/app/apis/kubeadm/validation/BUILD +++ b/cmd/kubeadm/app/apis/kubeadm/validation/BUILD @@ -8,6 +8,7 @@ go_library( deps = [ "//cmd/kubeadm/app/apis/kubeadm:go_default_library", "//cmd/kubeadm/app/apis/kubeadm/v1beta1:go_default_library", + "//cmd/kubeadm/app/cmd/options:go_default_library", "//cmd/kubeadm/app/componentconfigs:go_default_library", "//cmd/kubeadm/app/constants:go_default_library", "//cmd/kubeadm/app/features:go_default_library", diff --git a/cmd/kubeadm/app/apis/kubeadm/validation/validation.go b/cmd/kubeadm/app/apis/kubeadm/validation/validation.go index 77f12dea1c2..15a9e0c90a6 100644 --- a/cmd/kubeadm/app/apis/kubeadm/validation/validation.go +++ b/cmd/kubeadm/app/apis/kubeadm/validation/validation.go @@ -34,6 +34,7 @@ import ( bootstraputil "k8s.io/cluster-bootstrap/token/util" "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" kubeadmapiv1beta1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta1" + kubeadmcmdoptions "k8s.io/kubernetes/cmd/kubeadm/app/cmd/options" "k8s.io/kubernetes/cmd/kubeadm/app/componentconfigs" "k8s.io/kubernetes/cmd/kubeadm/app/constants" "k8s.io/kubernetes/cmd/kubeadm/app/features" @@ -146,7 +147,7 @@ func ValidateDiscoveryBootstrapToken(b *kubeadm.BootstrapTokenDiscovery, fldPath allErrs = append(allErrs, field.Invalid(fldPath, "", "using token-based discovery without caCertHashes can be unsafe. Set unsafeSkipCAVerification to continue")) } - allErrs = append(allErrs, ValidateToken(b.Token, fldPath.Child("token"))...) + allErrs = append(allErrs, ValidateToken(b.Token, fldPath.Child(kubeadmcmdoptions.TokenStr))...) allErrs = append(allErrs, ValidateDiscoveryTokenAPIServer(b.APIServerEndpoint, fldPath.Child("apiServerEndpoints"))...) return allErrs @@ -199,9 +200,9 @@ func ValidateBootstrapTokens(bts []kubeadm.BootstrapToken, fldPath *field.Path) allErrs := field.ErrorList{} for i, bt := range bts { btPath := fldPath.Child(fmt.Sprintf("%d", i)) - allErrs = append(allErrs, ValidateToken(bt.Token.String(), btPath.Child("token"))...) - allErrs = append(allErrs, ValidateTokenUsages(bt.Usages, btPath.Child("usages"))...) - allErrs = append(allErrs, ValidateTokenGroups(bt.Usages, bt.Groups, btPath.Child("groups"))...) + allErrs = append(allErrs, ValidateToken(bt.Token.String(), btPath.Child(kubeadmcmdoptions.TokenStr))...) + allErrs = append(allErrs, ValidateTokenUsages(bt.Usages, btPath.Child(kubeadmcmdoptions.TokenUsages))...) + allErrs = append(allErrs, ValidateTokenGroups(bt.Usages, bt.Groups, btPath.Child(kubeadmcmdoptions.TokenGroups))...) if bt.Expires != nil && bt.TTL != nil { allErrs = append(allErrs, field.Invalid(btPath, "", "the BootstrapToken .TTL and .Expires fields are mutually exclusive")) diff --git a/cmd/kubeadm/app/cmd/BUILD b/cmd/kubeadm/app/cmd/BUILD index e542aa60f27..6c1db7d23f7 100644 --- a/cmd/kubeadm/app/cmd/BUILD +++ b/cmd/kubeadm/app/cmd/BUILD @@ -80,6 +80,7 @@ go_test( srcs = [ "completion_test.go", "config_test.go", + "init_test.go", "join_test.go", "reset_test.go", "token_test.go", @@ -91,8 +92,10 @@ go_test( "//cmd/kubeadm/app/apis/kubeadm/scheme:go_default_library", "//cmd/kubeadm/app/apis/kubeadm/v1beta1:go_default_library", "//cmd/kubeadm/app/apis/kubeadm/validation:go_default_library", + "//cmd/kubeadm/app/cmd/options:go_default_library", "//cmd/kubeadm/app/componentconfigs:go_default_library", "//cmd/kubeadm/app/constants:go_default_library", + "//cmd/kubeadm/app/features:go_default_library", "//cmd/kubeadm/app/preflight:go_default_library", "//cmd/kubeadm/app/util:go_default_library", "//cmd/kubeadm/app/util/config:go_default_library", diff --git a/cmd/kubeadm/app/cmd/alpha/BUILD b/cmd/kubeadm/app/cmd/alpha/BUILD index 1e2b35048c7..2046387f563 100644 --- a/cmd/kubeadm/app/cmd/alpha/BUILD +++ b/cmd/kubeadm/app/cmd/alpha/BUILD @@ -63,9 +63,9 @@ go_test( deps = [ "//cmd/kubeadm/app/constants:go_default_library", "//cmd/kubeadm/app/phases/certs:go_default_library", + "//cmd/kubeadm/app/util/certs:go_default_library", "//cmd/kubeadm/app/util/pkiutil:go_default_library", "//cmd/kubeadm/test:go_default_library", - "//cmd/kubeadm/test/certs:go_default_library", "//cmd/kubeadm/test/cmd:go_default_library", "//cmd/kubeadm/test/kubeconfig:go_default_library", "//staging/src/k8s.io/client-go/tools/clientcmd:go_default_library", diff --git a/cmd/kubeadm/app/cmd/alpha/certs.go b/cmd/kubeadm/app/cmd/alpha/certs.go index 08ee5294d2f..dfba33209d1 100644 --- a/cmd/kubeadm/app/cmd/alpha/certs.go +++ b/cmd/kubeadm/app/cmd/alpha/certs.go @@ -40,7 +40,7 @@ var ( Extra attributes such as SANs will be based on the existing certificates, there is no need to resupply them. `) allLongDesc = normalizer.LongDesc(` - Renews all known certificates necessary to run the control plan. Renewals are run unconditionally, regardless + Renews all known certificates necessary to run the control plane. Renewals are run unconditionally, regardless of expiration date. Renewals can also be run individually for more control. `) ) diff --git a/cmd/kubeadm/app/cmd/alpha/certs_test.go b/cmd/kubeadm/app/cmd/alpha/certs_test.go index 47798fd76cf..9e184a3509e 100644 --- a/cmd/kubeadm/app/cmd/alpha/certs_test.go +++ b/cmd/kubeadm/app/cmd/alpha/certs_test.go @@ -31,9 +31,9 @@ import ( "github.com/spf13/cobra" kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants" "k8s.io/kubernetes/cmd/kubeadm/app/phases/certs" + certstestutil "k8s.io/kubernetes/cmd/kubeadm/app/util/certs" "k8s.io/kubernetes/cmd/kubeadm/app/util/pkiutil" testutil "k8s.io/kubernetes/cmd/kubeadm/test" - certstestutil "k8s.io/kubernetes/cmd/kubeadm/test/certs" cmdtestutil "k8s.io/kubernetes/cmd/kubeadm/test/cmd" ) diff --git a/cmd/kubeadm/app/cmd/alpha/kubeconfig_test.go b/cmd/kubeadm/app/cmd/alpha/kubeconfig_test.go index 834edce4085..e2711b4453c 100644 --- a/cmd/kubeadm/app/cmd/alpha/kubeconfig_test.go +++ b/cmd/kubeadm/app/cmd/alpha/kubeconfig_test.go @@ -52,16 +52,19 @@ func TestKubeConfigSubCommandsThatWritesToOut(t *testing.T) { } var tests = []struct { + name string command string withClientCert bool withToken bool additionalFlags []string }{ - { // Test user subCommand withClientCert + { + name: "user subCommand withClientCert", command: "user", withClientCert: true, }, - { // Test user subCommand withToken + { + name: "user subCommand withToken", withToken: true, command: "user", additionalFlags: []string{"--token=123456"}, @@ -69,36 +72,38 @@ func TestKubeConfigSubCommandsThatWritesToOut(t *testing.T) { } for _, test := range tests { - buf := new(bytes.Buffer) + t.Run(test.name, func(t *testing.T) { + buf := new(bytes.Buffer) - // Get subcommands working in the temporary directory - cmd := newCmdUserKubeConfig(buf) + // Get subcommands working in the temporary directory + cmd := newCmdUserKubeConfig(buf) - // Execute the subcommand - allFlags := append(commonFlags, test.additionalFlags...) - cmd.SetArgs(allFlags) - if err := cmd.Execute(); err != nil { - t.Fatal("Could not execute subcommand") - } + // Execute the subcommand + allFlags := append(commonFlags, test.additionalFlags...) + cmd.SetArgs(allFlags) + if err := cmd.Execute(); err != nil { + t.Fatal("Could not execute subcommand") + } - // reads kubeconfig written to stdout - config, err := clientcmd.Load(buf.Bytes()) - if err != nil { - t.Errorf("couldn't read kubeconfig file from buffer: %v", err) - continue - } + // reads kubeconfig written to stdout + config, err := clientcmd.Load(buf.Bytes()) + if err != nil { + t.Errorf("couldn't read kubeconfig file from buffer: %v", err) + return + } - // checks that CLI flags are properly propagated - kubeconfigtestutil.AssertKubeConfigCurrentCluster(t, config, "https://1.2.3.4:1234", caCert) + // checks that CLI flags are properly propagated + kubeconfigtestutil.AssertKubeConfigCurrentCluster(t, config, "https://1.2.3.4:1234", caCert) - if test.withClientCert { - // checks that kubeconfig files have expected client cert - kubeconfigtestutil.AssertKubeConfigCurrentAuthInfoWithClientCert(t, config, caCert, "myUser") - } + if test.withClientCert { + // checks that kubeconfig files have expected client cert + kubeconfigtestutil.AssertKubeConfigCurrentAuthInfoWithClientCert(t, config, caCert, "myUser") + } - if test.withToken { - // checks that kubeconfig files have expected token - kubeconfigtestutil.AssertKubeConfigCurrentAuthInfoWithToken(t, config, "myUser", "123456") - } + if test.withToken { + // checks that kubeconfig files have expected token + kubeconfigtestutil.AssertKubeConfigCurrentAuthInfoWithToken(t, config, "myUser", "123456") + } + }) } } diff --git a/cmd/kubeadm/app/cmd/alpha/kubelet.go b/cmd/kubeadm/app/cmd/alpha/kubelet.go index 8ab3575ad99..f8eb6780ffb 100644 --- a/cmd/kubeadm/app/cmd/alpha/kubelet.go +++ b/cmd/kubeadm/app/cmd/alpha/kubelet.go @@ -17,6 +17,8 @@ limitations under the License. package alpha import ( + "fmt" + "github.com/pkg/errors" "github.com/spf13/cobra" "k8s.io/apimachinery/pkg/util/version" @@ -38,13 +40,13 @@ var ( "kubelet --version" or respects the --kubelet-version parameter. ` + cmdutil.AlphaDisclaimer) - kubeletConfigDownloadExample = normalizer.Examples(` + kubeletConfigDownloadExample = normalizer.Examples(fmt.Sprintf(` # Downloads the kubelet configuration from the ConfigMap in the cluster. Autodetects the kubelet version. kubeadm alpha phase kubelet config download # Downloads the kubelet configuration from the ConfigMap in the cluster. Uses a specific desired kubelet version. - kubeadm alpha phase kubelet config download --kubelet-version v1.12.0 - `) + kubeadm alpha phase kubelet config download --kubelet-version %s + `, constants.CurrentKubernetesVersion)) kubeletConfigEnableDynamicLongDesc = normalizer.LongDesc(` Enables or updates dynamic kubelet configuration for a Node, against the kubelet-config-1.X ConfigMap in the cluster, @@ -55,13 +57,13 @@ var ( ` + cmdutil.AlphaDisclaimer) - kubeletConfigEnableDynamicExample = normalizer.Examples(` + kubeletConfigEnableDynamicExample = normalizer.Examples(fmt.Sprintf(` # Enables dynamic kubelet configuration for a Node. - kubeadm alpha phase kubelet enable-dynamic-config --node-name node-1 --kubelet-version v1.12.0 + kubeadm alpha phase kubelet enable-dynamic-config --node-name node-1 --kubelet-version %s WARNING: This feature is still experimental, and disabled by default. Enable only if you know what you are doing, as it may have surprising side-effects at this stage. - `) + `, constants.CurrentKubernetesVersion)) ) // newCmdKubeletUtility returns command for `kubeadm phase kubelet` diff --git a/cmd/kubeadm/app/cmd/alpha/selfhosting.go b/cmd/kubeadm/app/cmd/alpha/selfhosting.go index b45b6b54d55..42849f7c7af 100644 --- a/cmd/kubeadm/app/cmd/alpha/selfhosting.go +++ b/cmd/kubeadm/app/cmd/alpha/selfhosting.go @@ -18,11 +18,11 @@ package alpha import ( "bufio" - "errors" "fmt" "io" "strings" + "github.com/pkg/errors" "github.com/spf13/cobra" kubeadmscheme "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme" diff --git a/cmd/kubeadm/app/cmd/cmd.go b/cmd/kubeadm/app/cmd/cmd.go index 17b827f4056..602f61fb092 100644 --- a/cmd/kubeadm/app/cmd/cmd.go +++ b/cmd/kubeadm/app/cmd/cmd.go @@ -82,7 +82,7 @@ func NewKubeadmCommand(in io.Reader, out, err io.Writer) *cobra.Command { cmds.AddCommand(NewCmdCompletion(out, "")) cmds.AddCommand(NewCmdConfig(out)) - cmds.AddCommand(NewCmdInit(out)) + cmds.AddCommand(NewCmdInit(out, nil)) cmds.AddCommand(NewCmdJoin(out)) cmds.AddCommand(NewCmdReset(in, out)) cmds.AddCommand(NewCmdVersion(out)) diff --git a/cmd/kubeadm/app/cmd/completion.go b/cmd/kubeadm/app/cmd/completion.go index 2fae2b34326..43d27abf851 100644 --- a/cmd/kubeadm/app/cmd/completion.go +++ b/cmd/kubeadm/app/cmd/completion.go @@ -73,7 +73,7 @@ var ( # Load the kubeadm completion code for bash into the current shell source <(kubeadm completion bash) - # Write bash completion code to a file and source if from .bash_profile + # Write bash completion code to a file and source it from .bash_profile kubeadm completion bash > ~/.kube/kubeadm_completion.bash.inc printf "\n# Kubeadm shell completion\nsource '$HOME/.kube/kubeadm_completion.bash.inc'\n" >> $HOME/.bash_profile source $HOME/.bash_profile diff --git a/cmd/kubeadm/app/cmd/completion_test.go b/cmd/kubeadm/app/cmd/completion_test.go index e13eed481fd..d74c1d2111e 100644 --- a/cmd/kubeadm/app/cmd/completion_test.go +++ b/cmd/kubeadm/app/cmd/completion_test.go @@ -88,8 +88,10 @@ func TestRunCompletion(t *testing.T) { parentCmd.AddCommand(cmd) for _, tc := range testCases { - if err := RunCompletion(&out, "", cmd, tc.args); (err != nil) != tc.expectedError { - t.Errorf("Test case %q: TestRunCompletion expected error: %v, saw: %v", tc.name, tc.expectedError, (err != nil)) - } + t.Run(tc.name, func(t *testing.T) { + if err := RunCompletion(&out, "", cmd, tc.args); (err != nil) != tc.expectedError { + t.Errorf("Test case %q: TestRunCompletion expected error: %v, saw: %v", tc.name, tc.expectedError, (err != nil)) + } + }) } } diff --git a/cmd/kubeadm/app/cmd/config.go b/cmd/kubeadm/app/cmd/config.go index 48a363cb7ab..e4545c9f5c2 100644 --- a/cmd/kubeadm/app/cmd/config.go +++ b/cmd/kubeadm/app/cmd/config.go @@ -85,7 +85,6 @@ func NewCmdConfig(out io.Writer) *cobra.Command { kubeConfigFile = cmdutil.FindExistingKubeConfig(kubeConfigFile) cmd.AddCommand(NewCmdConfigPrint(out)) - cmd.AddCommand(NewCmdConfigPrintDefault(out)) cmd.AddCommand(NewCmdConfigMigrate(out)) cmd.AddCommand(NewCmdConfigUpload(out, &kubeConfigFile)) cmd.AddCommand(NewCmdConfigView(out, &kubeConfigFile)) @@ -142,7 +141,7 @@ func runConfigPrintActionDefaults(out io.Writer, componentConfigs []string, conf allBytes := [][]byte{initialConfig} for _, componentConfig := range componentConfigs { - cfgBytes, err := getDefaultComponentConfigAPIObjectBytes(componentConfig) + cfgBytes, err := getDefaultComponentConfigBytes(componentConfig) kubeadmutil.CheckErr(err) allBytes = append(allBytes, cfgBytes) } @@ -150,68 +149,23 @@ func runConfigPrintActionDefaults(out io.Writer, componentConfigs []string, conf fmt.Fprint(out, string(bytes.Join(allBytes, []byte(constants.YAMLDocumentSeparator)))) } -// NewCmdConfigPrintDefault returns cobra.Command for "kubeadm config print-default" command -func NewCmdConfigPrintDefault(out io.Writer) *cobra.Command { - apiObjects := []string{} - cmd := &cobra.Command{ - Use: "print-default", - Aliases: []string{"print-defaults"}, - Short: "Print the default values for a kubeadm configuration object.", - Long: fmt.Sprintf(dedent.Dedent(` - This command prints objects such as the default InitConfiguration that is used for 'kubeadm init' and 'kubeadm upgrade', - and the default JoinConfiguration object that is used for 'kubeadm join'. - - For documentation visit: https://godoc.org/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha3 - - Note that sensitive values like the Bootstrap Token fields are replaced with placeholder values like %q in order to pass validation but - not perform the real computation for creating a token. - `), placeholderToken), - Deprecated: "Please, use `kubeadm config print` instead.", - Run: func(cmd *cobra.Command, args []string) { - if len(apiObjects) == 0 { - apiObjects = getSupportedAPIObjects() - } - allBytes := [][]byte{} - for _, apiObject := range apiObjects { - cfgBytes, err := getDefaultAPIObjectBytes(apiObject) - kubeadmutil.CheckErr(err) - allBytes = append(allBytes, cfgBytes) - } - fmt.Fprint(out, string(bytes.Join(allBytes, []byte(constants.YAMLDocumentSeparator)))) - }, - } - cmd.Flags().StringSliceVar(&apiObjects, "api-objects", apiObjects, - fmt.Sprintf("A comma-separated list for API objects to print the default values for. Available values: %v. This flag unset means 'print all known objects'", getAllAPIObjectNames())) - return cmd -} - -func getDefaultComponentConfigAPIObjectBytes(apiObject string) ([]byte, error) { +func getDefaultComponentConfigBytes(apiObject string) ([]byte, error) { registration, ok := componentconfigs.Known[componentconfigs.RegistrationKind(apiObject)] if !ok { return []byte{}, errors.Errorf("--component-configs needs to contain some of %v", getSupportedComponentConfigAPIObjects()) } - return getDefaultComponentConfigBytes(registration) -} -func getDefaultAPIObjectBytes(apiObject string) ([]byte, error) { - switch apiObject { - case constants.InitConfigurationKind: - return getDefaultInitConfigBytesByKind(constants.InitConfigurationKind) - - case constants.ClusterConfigurationKind: - return getDefaultInitConfigBytesByKind(constants.ClusterConfigurationKind) - - case constants.JoinConfigurationKind: - return getDefaultNodeConfigBytes() - - default: - // Is this a component config? - registration, ok := componentconfigs.Known[componentconfigs.RegistrationKind(apiObject)] - if !ok { - return []byte{}, errors.Errorf("--api-object needs to be one of %v", getAllAPIObjectNames()) - } - return getDefaultComponentConfigBytes(registration) + defaultedInitConfig, err := getDefaultedInitConfig() + if err != nil { + return []byte{}, err } + + realObj, ok := registration.GetFromInternalConfig(&defaultedInitConfig.ClusterConfiguration) + if !ok { + return []byte{}, errors.New("GetFromInternalConfig failed") + } + + return registration.Marshal(realObj) } // getSupportedComponentConfigAPIObjects returns all currently supported component config API object names @@ -223,23 +177,6 @@ func getSupportedComponentConfigAPIObjects() []string { return objects } -// getSupportedAPIObjects returns all currently supported API object names -func getSupportedAPIObjects() []string { - baseObjects := []string{constants.InitConfigurationKind, constants.ClusterConfigurationKind, constants.JoinConfigurationKind} - objects := getSupportedComponentConfigAPIObjects() - objects = append(objects, baseObjects...) - return objects -} - -// getAllAPIObjectNames returns currently supported API object names and their historical aliases -// NB. currently there is no historical supported API objects, but we keep this function for future changes -func getAllAPIObjectNames() []string { - historicAPIObjectAliases := []string{} - objects := getSupportedAPIObjects() - objects = append(objects, historicAPIObjectAliases...) - return objects -} - func getDefaultedInitConfig() (*kubeadmapi.InitConfiguration, error) { return configutil.ConfigFileAndDefaultsToInternalConfig("", &kubeadmapiv1beta1.InitConfiguration{ // TODO: Probably move to getDefaultedClusterConfig? @@ -260,18 +197,6 @@ func getDefaultInitConfigBytes() ([]byte, error) { return configutil.MarshalKubeadmConfigObject(internalcfg) } -func getDefaultInitConfigBytesByKind(kind string) ([]byte, error) { - b, err := getDefaultInitConfigBytes() - if err != nil { - return []byte{}, err - } - gvkmap, err := kubeadmutil.SplitYAMLDocuments(b) - if err != nil { - return []byte{}, err - } - return gvkmap[kubeadmapiv1beta1.SchemeGroupVersion.WithKind(kind)], nil -} - func getDefaultNodeConfigBytes() ([]byte, error) { internalcfg, err := configutil.JoinConfigFileAndDefaultsToInternalConfig("", &kubeadmapiv1beta1.JoinConfiguration{ Discovery: kubeadmapiv1beta1.Discovery{ @@ -289,20 +214,6 @@ func getDefaultNodeConfigBytes() ([]byte, error) { return configutil.MarshalKubeadmConfigObject(internalcfg) } -func getDefaultComponentConfigBytes(registration componentconfigs.Registration) ([]byte, error) { - defaultedInitConfig, err := getDefaultedInitConfig() - if err != nil { - return []byte{}, err - } - - realobj, ok := registration.GetFromInternalConfig(&defaultedInitConfig.ClusterConfiguration) - if !ok { - return []byte{}, errors.New("GetFromInternalConfig failed") - } - - return registration.Marshal(realobj) -} - // NewCmdConfigMigrate returns cobra.Command for "kubeadm config migrate" command func NewCmdConfigMigrate(out io.Writer) *cobra.Command { var oldCfgPath, newCfgPath string diff --git a/cmd/kubeadm/app/cmd/config_test.go b/cmd/kubeadm/app/cmd/config_test.go index a9bffee2b71..0a7a9f8fc2e 100644 --- a/cmd/kubeadm/app/cmd/config_test.go +++ b/cmd/kubeadm/app/cmd/config_test.go @@ -18,6 +18,7 @@ package cmd import ( "bytes" + "fmt" "io" "io/ioutil" "os" @@ -41,11 +42,12 @@ import ( const ( defaultNumberOfImages = 8 - // dummyKubernetesVersion is just used for unit testing, in order to not make - // kubeadm lookup dl.k8s.io to resolve what the latest stable release is - dummyKubernetesVersion = "v1.12.0" ) +// dummyKubernetesVersion is just used for unit testing, in order to not make +// kubeadm lookup dl.k8s.io to resolve what the latest stable release is +var dummyKubernetesVersion = constants.MinimumControlPlaneVersion.String() + func TestNewCmdConfigImagesList(t *testing.T) { var output bytes.Buffer mockK8sVersion := dummyKubernetesVersion @@ -83,11 +85,11 @@ func TestImagesListRunWithCustomConfigPath(t *testing.T) { expectedImageSubstrings: []string{ "coredns", }, - configContents: []byte(dedent.Dedent(` + configContents: []byte(dedent.Dedent(fmt.Sprintf(` apiVersion: kubeadm.k8s.io/v1beta1 kind: ClusterConfiguration - kubernetesVersion: v1.12.0 - `)), + kubernetesVersion: %s + `, constants.MinimumControlPlaneVersion))), }, } diff --git a/cmd/kubeadm/app/cmd/init.go b/cmd/kubeadm/app/cmd/init.go index 22939087d9a..9c6764d7f91 100644 --- a/cmd/kubeadm/app/cmd/init.go +++ b/cmd/kubeadm/app/cmd/init.go @@ -124,13 +124,17 @@ type initData struct { } // NewCmdInit returns "kubeadm init" command. -func NewCmdInit(out io.Writer) *cobra.Command { - initOptions := newInitOptions() +// NB. initOptions is exposed as parameter for allowing unit testing of +// the newInitOptions method, that implements all the command options validation logic +func NewCmdInit(out io.Writer, initOptions *initOptions) *cobra.Command { + if initOptions == nil { + initOptions = newInitOptions() + } initRunner := workflow.NewRunner() cmd := &cobra.Command{ Use: "init", - Short: "Run this command in order to set up the Kubernetes master.", + Short: "Run this command in order to set up the Kubernetes control plane.", Run: func(cmd *cobra.Command, args []string) { c, err := initRunner.InitData() kubeadmutil.CheckErr(err) @@ -192,7 +196,7 @@ func NewCmdInit(out io.Writer) *cobra.Command { func AddInitConfigFlags(flagSet *flag.FlagSet, cfg *kubeadmapiv1beta1.InitConfiguration, featureGatesString *string) { flagSet.StringVar( &cfg.LocalAPIEndpoint.AdvertiseAddress, options.APIServerAdvertiseAddress, cfg.LocalAPIEndpoint.AdvertiseAddress, - "The IP address the API Server will advertise it's listening on. Specify '0.0.0.0' to use the address of the default network interface.", + "The IP address the API Server will advertise it's listening on. If not set the default network interface will be used.", ) flagSet.Int32Var( &cfg.LocalAPIEndpoint.BindPort, options.APIServerBindPort, cfg.LocalAPIEndpoint.BindPort, @@ -289,7 +293,9 @@ func newInitData(cmd *cobra.Command, options *initOptions, out io.Writer) (initD } ignorePreflightErrorsSet, err := validation.ValidateIgnorePreflightErrors(options.ignorePreflightErrors) - kubeadmutil.CheckErr(err) + if err != nil { + return initData{}, err + } if err = validation.ValidateMixedArguments(cmd.Flags()); err != nil { return initData{}, err diff --git a/cmd/kubeadm/app/cmd/init_test.go b/cmd/kubeadm/app/cmd/init_test.go new file mode 100644 index 00000000000..4c9e72dfa26 --- /dev/null +++ b/cmd/kubeadm/app/cmd/init_test.go @@ -0,0 +1,159 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package cmd + +import ( + "fmt" + "io/ioutil" + "os" + "path/filepath" + "testing" + + "k8s.io/kubernetes/cmd/kubeadm/app/cmd/options" + "k8s.io/kubernetes/cmd/kubeadm/app/features" +) + +const ( + testInitConfig = `--- +apiVersion: kubeadm.k8s.io/v1beta1 +kind: InitConfiguration +localAPIEndpoint: + advertiseAddress: "1.2.3.4" +bootstrapTokens: +- token: "abcdef.0123456789abcdef" +nodeRegistration: + criSocket: /run/containerd/containerd.sock + name: someName +--- +apiVersion: kubeadm.k8s.io/v1beta1 +kind: ClusterConfiguration +controlPlaneEndpoint: "3.4.5.6" +` +) + +func TestNewInitData(t *testing.T) { + // create temp directory + tmpDir, err := ioutil.TempDir("", "kubeadm-init-test") + if err != nil { + t.Errorf("Unable to create temporary directory: %v", err) + } + defer os.RemoveAll(tmpDir) + + // create config file + configFilePath := filepath.Join(tmpDir, "test-config-file") + cfgFile, err := os.Create(configFilePath) + if err != nil { + t.Errorf("Unable to create file %q: %v", configFilePath, err) + } + defer cfgFile.Close() + if _, err = cfgFile.WriteString(testInitConfig); err != nil { + t.Fatalf("Unable to write file %q: %v", configFilePath, err) + } + + testCases := []struct { + name string + args []string + flags map[string]string + validate func(*testing.T, *initData) + expectError bool + }{ + // Init data passed using flags + { + name: "pass without any flag (use defaults)", + }, + { + name: "fail if unknown feature gates flag are passed", + flags: map[string]string{ + options.FeatureGatesString: "unknown=true", + }, + expectError: true, + }, + { + name: "fail if deprecetes feature gates are set", + flags: map[string]string{ + options.FeatureGatesString: fmt.Sprintf("%s=true", features.CoreDNS), + }, + expectError: true, + }, + { + name: "fails if invalid preflight checks are provided", + flags: map[string]string{ + options.IgnorePreflightErrors: "all,something-else", + }, + expectError: true, + }, + + // Init data passed using config file + { + name: "Pass with config from file", + flags: map[string]string{ + options.CfgPath: configFilePath, + }, + }, + { + name: "--cri-socket and --node-name flags override config from file", + flags: map[string]string{ + options.CfgPath: configFilePath, + options.NodeCRISocket: "/var/run/crio/crio.sock", + options.NodeName: "anotherName", + }, + validate: func(t *testing.T, data *initData) { + // validate that cri-socket and node-name are overwritten + if data.cfg.NodeRegistration.CRISocket != "/var/run/crio/crio.sock" { + t.Errorf("Invalid NodeRegistration.CRISocket") + } + if data.cfg.NodeRegistration.Name != "anotherName" { + t.Errorf("Invalid NodeRegistration.Name") + } + }, + }, + { + name: "fail if mixedArguments are passed", + flags: map[string]string{ + options.CfgPath: configFilePath, + options.APIServerAdvertiseAddress: "1.2.3.4", + }, + expectError: true, + }, + } + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + // initialize an external init option and inject it to the init cmd + initOptions := newInitOptions() + cmd := NewCmdInit(nil, initOptions) + + // sets cmd flags (that will be reflected on the init options) + for f, v := range tc.flags { + cmd.Flags().Set(f, v) + } + + // test newInitData method + data, err := newInitData(cmd, initOptions, nil) + if err != nil && !tc.expectError { + t.Fatalf("newInitData returned unexpected error: %v", err) + } + if err == nil && tc.expectError { + t.Fatalf("newInitData didn't return error when expected") + } + + // exec additional validation on the returned value + if tc.validate != nil { + tc.validate(t, &data) + } + }) + } +} diff --git a/cmd/kubeadm/app/cmd/join.go b/cmd/kubeadm/app/cmd/join.go index 6ae7eabf937..b80fe5088ae 100644 --- a/cmd/kubeadm/app/cmd/join.go +++ b/cmd/kubeadm/app/cmd/join.go @@ -316,7 +316,7 @@ func NewJoin(cfgPath string, defaultcfg *kubeadmapiv1beta1.JoinConfiguration, ig internalCfg.NodeRegistration.CRISocket = defaultcfg.NodeRegistration.CRISocket } - if defaultcfg.ControlPlane != nil { + if internalCfg.ControlPlane != nil { if err := configutil.VerifyAPIServerBindAddress(internalCfg.ControlPlane.LocalAPIEndpoint.AdvertiseAddress); err != nil { return nil, err } @@ -586,10 +586,12 @@ func (j *Join) PostInstallControlPlane(initConfiguration *kubeadmapi.InitConfigu func waitForTLSBootstrappedClient() error { fmt.Println("[tlsbootstrap] Waiting for the kubelet to perform the TLS Bootstrap...") - kubeletKubeConfig := filepath.Join(kubeadmconstants.KubernetesDir, kubeadmconstants.KubeletKubeConfigFileName) // Loop on every falsy return. Return with an error if raised. Exit successfully if true is returned. return wait.PollImmediate(kubeadmconstants.APICallRetryInterval, kubeadmconstants.TLSBootstrapTimeout, func() (bool, error) { - _, err := os.Stat(kubeletKubeConfig) + // Check that we can create a client set out of the kubelet kubeconfig. This ensures not + // only that the kubeconfig file exists, but that other files required by it also exist (like + // client certificate and key) + _, err := kubeconfigutil.ClientSetFromFile(kubeadmconstants.GetKubeletKubeConfigPath()) return (err == nil), nil }) } diff --git a/cmd/kubeadm/app/cmd/options/constant.go b/cmd/kubeadm/app/cmd/options/constant.go index f966750e05f..bd74e94c07b 100644 --- a/cmd/kubeadm/app/cmd/options/constant.go +++ b/cmd/kubeadm/app/cmd/options/constant.go @@ -84,3 +84,18 @@ const CSROnly = "csr-only" // CSRDir flag sets the location for CSRs and flags to be output const CSRDir = "csr-dir" + +// TokenStr flag sets the token +const TokenStr = "token" + +// TokenTTL flag sets the time to live for token +const TokenTTL = "token-ttl" + +// TokenUsages flag sets the usages of the token +const TokenUsages = "usages" + +// TokenGroups flag sets the authentication groups of the token +const TokenGroups = "groups" + +// TokenDescription flag sets the description of the token +const TokenDescription = "description" diff --git a/cmd/kubeadm/app/cmd/options/token.go b/cmd/kubeadm/app/cmd/options/token.go index a5b7ebd125a..d4b44eeb778 100644 --- a/cmd/kubeadm/app/cmd/options/token.go +++ b/cmd/kubeadm/app/cmd/options/token.go @@ -45,14 +45,14 @@ type BootstrapTokenOptions struct { // AddTokenFlag adds the --token flag to the given flagset func (bto *BootstrapTokenOptions) AddTokenFlag(fs *pflag.FlagSet) { fs.StringVar( - &bto.TokenStr, "token", "", + &bto.TokenStr, TokenStr, "", "The token to use for establishing bidirectional trust between nodes and masters. The format is [a-z0-9]{6}\\.[a-z0-9]{16} - e.g. abcdef.0123456789abcdef", ) } // AddTTLFlag adds the --token-ttl flag to the given flagset func (bto *BootstrapTokenOptions) AddTTLFlag(fs *pflag.FlagSet) { - bto.AddTTLFlagWithName(fs, "token-ttl") + bto.AddTTLFlagWithName(fs, TokenTTL) } // AddTTLFlagWithName adds the --token-ttl flag with a custom flag name given flagset @@ -66,7 +66,7 @@ func (bto *BootstrapTokenOptions) AddTTLFlagWithName(fs *pflag.FlagSet, flagName // AddUsagesFlag adds the --usages flag to the given flagset func (bto *BootstrapTokenOptions) AddUsagesFlag(fs *pflag.FlagSet) { fs.StringSliceVar( - &bto.Usages, "usages", bto.Usages, + &bto.Usages, TokenUsages, bto.Usages, fmt.Sprintf("Describes the ways in which this token can be used. You can pass --usages multiple times or provide a comma separated list of options. Valid options: [%s]", strings.Join(kubeadmconstants.DefaultTokenUsages, ",")), ) } @@ -74,7 +74,7 @@ func (bto *BootstrapTokenOptions) AddUsagesFlag(fs *pflag.FlagSet) { // AddGroupsFlag adds the --groups flag to the given flagset func (bto *BootstrapTokenOptions) AddGroupsFlag(fs *pflag.FlagSet) { fs.StringSliceVar( - &bto.Groups, "groups", bto.Groups, + &bto.Groups, TokenGroups, bto.Groups, fmt.Sprintf("Extra groups that this token will authenticate as when used for authentication. Must match %q", bootstrapapi.BootstrapGroupPattern), ) } @@ -82,7 +82,7 @@ func (bto *BootstrapTokenOptions) AddGroupsFlag(fs *pflag.FlagSet) { // AddDescriptionFlag adds the --description flag to the given flagset func (bto *BootstrapTokenOptions) AddDescriptionFlag(fs *pflag.FlagSet) { fs.StringVar( - &bto.Description, "description", bto.Description, + &bto.Description, TokenDescription, bto.Description, "A human friendly description of how this token is used.", ) } diff --git a/cmd/kubeadm/app/cmd/phases/BUILD b/cmd/kubeadm/app/cmd/phases/BUILD index 08d64316565..ca17f2dc792 100644 --- a/cmd/kubeadm/app/cmd/phases/BUILD +++ b/cmd/kubeadm/app/cmd/phases/BUILD @@ -22,7 +22,6 @@ go_library( "//cmd/kubeadm/app/apis/kubeadm:go_default_library", "//cmd/kubeadm/app/apis/kubeadm/scheme:go_default_library", "//cmd/kubeadm/app/apis/kubeadm/v1beta1:go_default_library", - "//cmd/kubeadm/app/apis/kubeadm/validation:go_default_library", "//cmd/kubeadm/app/cmd/options:go_default_library", "//cmd/kubeadm/app/cmd/phases/workflow:go_default_library", "//cmd/kubeadm/app/cmd/util:go_default_library", @@ -42,7 +41,6 @@ go_library( "//cmd/kubeadm/app/preflight:go_default_library", "//cmd/kubeadm/app/util:go_default_library", "//cmd/kubeadm/app/util/apiclient:go_default_library", - "//cmd/kubeadm/app/util/config:go_default_library", "//cmd/kubeadm/app/util/dryrun:go_default_library", "//cmd/kubeadm/app/util/pkiutil:go_default_library", "//pkg/util/normalizer:go_default_library", @@ -52,7 +50,6 @@ go_library( "//staging/src/k8s.io/client-go/kubernetes:go_default_library", "//vendor/github.com/pkg/errors:go_default_library", "//vendor/github.com/renstrom/dedent:go_default_library", - "//vendor/github.com/spf13/cobra:go_default_library", "//vendor/github.com/spf13/pflag:go_default_library", "//vendor/k8s.io/klog:go_default_library", "//vendor/k8s.io/utils/exec:go_default_library", @@ -71,9 +68,9 @@ go_test( "//cmd/kubeadm/app/apis/kubeadm/v1beta1:go_default_library", "//cmd/kubeadm/app/cmd/phases/workflow:go_default_library", "//cmd/kubeadm/app/phases/certs:go_default_library", + "//cmd/kubeadm/app/util/certs:go_default_library", "//cmd/kubeadm/app/util/pkiutil:go_default_library", "//cmd/kubeadm/test:go_default_library", - "//cmd/kubeadm/test/certs:go_default_library", "//pkg/version:go_default_library", "//vendor/github.com/spf13/cobra:go_default_library", ], diff --git a/cmd/kubeadm/app/cmd/phases/bootstraptoken.go b/cmd/kubeadm/app/cmd/phases/bootstraptoken.go index b6492960f8b..4bbbb96bd73 100644 --- a/cmd/kubeadm/app/cmd/phases/bootstraptoken.go +++ b/cmd/kubeadm/app/cmd/phases/bootstraptoken.go @@ -18,7 +18,6 @@ package phases import ( "fmt" - "path/filepath" "github.com/pkg/errors" @@ -26,7 +25,6 @@ import ( kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" "k8s.io/kubernetes/cmd/kubeadm/app/cmd/options" "k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/workflow" - kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants" clusterinfophase "k8s.io/kubernetes/cmd/kubeadm/app/phases/bootstraptoken/clusterinfo" nodebootstraptokenphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/bootstraptoken/node" "k8s.io/kubernetes/pkg/util/normalizer" @@ -51,7 +49,7 @@ var ( type bootstrapTokenData interface { Cfg() *kubeadmapi.InitConfiguration Client() (clientset.Interface, error) - KubeConfigDir() string + KubeConfigPath() string SkipTokenPrint() bool Tokens() []string } @@ -66,7 +64,7 @@ func NewBootstrapTokenPhase() workflow.Phase { Long: bootstrapTokenLongDesc, InheritFlags: []string{ options.CfgPath, - options.KubeconfigDir, + options.KubeconfigPath, options.SkipTokenPrint, }, Run: runBoostrapToken, @@ -113,8 +111,7 @@ func runBoostrapToken(c workflow.RunData) error { } // Create the cluster-info ConfigMap with the associated RBAC rules - adminKubeConfigPath := filepath.Join(data.KubeConfigDir(), kubeadmconstants.AdminKubeConfigFileName) - if err := clusterinfophase.CreateBootstrapConfigMapIfNotExists(client, adminKubeConfigPath); err != nil { + if err := clusterinfophase.CreateBootstrapConfigMapIfNotExists(client, data.KubeConfigPath()); err != nil { return errors.Wrap(err, "error creating bootstrap ConfigMap") } if err := clusterinfophase.CreateClusterInfoRBACRules(client); err != nil { diff --git a/cmd/kubeadm/app/cmd/phases/certs_test.go b/cmd/kubeadm/app/cmd/phases/certs_test.go index 3e9c49d8d62..f72208c5f31 100644 --- a/cmd/kubeadm/app/cmd/phases/certs_test.go +++ b/cmd/kubeadm/app/cmd/phases/certs_test.go @@ -24,9 +24,9 @@ import ( kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" "k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/workflow" "k8s.io/kubernetes/cmd/kubeadm/app/phases/certs" + certstestutil "k8s.io/kubernetes/cmd/kubeadm/app/util/certs" "k8s.io/kubernetes/cmd/kubeadm/app/util/pkiutil" testutil "k8s.io/kubernetes/cmd/kubeadm/test" - certstestutil "k8s.io/kubernetes/cmd/kubeadm/test/certs" ) type testCertsData struct { diff --git a/cmd/kubeadm/app/cmd/phases/controlplane.go b/cmd/kubeadm/app/cmd/phases/controlplane.go index 6a191b06044..36cd706c545 100644 --- a/cmd/kubeadm/app/cmd/phases/controlplane.go +++ b/cmd/kubeadm/app/cmd/phases/controlplane.go @@ -17,9 +17,10 @@ limitations under the License. package phases import ( - "errors" "fmt" + "github.com/pkg/errors" + kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" "k8s.io/kubernetes/cmd/kubeadm/app/cmd/options" "k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/workflow" @@ -149,9 +150,6 @@ func runControlPlaneSubPhase(component string) func(c workflow.RunData) error { cfg := data.Cfg() fmt.Printf("[control-plane] Creating static Pod manifest for %q\n", component) - if err := controlplane.CreateStaticPodFiles(data.ManifestDir(), cfg, component); err != nil { - return err - } - return nil + return controlplane.CreateStaticPodFiles(data.ManifestDir(), cfg, component) } } diff --git a/cmd/kubeadm/app/cmd/phases/markcontrolplane.go b/cmd/kubeadm/app/cmd/phases/markcontrolplane.go index 37dd80564d3..cf5f26778b8 100644 --- a/cmd/kubeadm/app/cmd/phases/markcontrolplane.go +++ b/cmd/kubeadm/app/cmd/phases/markcontrolplane.go @@ -69,9 +69,5 @@ func runMarkControlPlane(c workflow.RunData) error { } nodeRegistration := data.Cfg().NodeRegistration - if err := markcontrolplanephase.MarkControlPlane(client, nodeRegistration.Name, nodeRegistration.Taints); err != nil { - return err - } - - return nil + return markcontrolplanephase.MarkControlPlane(client, nodeRegistration.Name, nodeRegistration.Taints) } diff --git a/cmd/kubeadm/app/cmd/phases/util.go b/cmd/kubeadm/app/cmd/phases/util.go index 4a4d280cefb..c0a2c2f6492 100644 --- a/cmd/kubeadm/app/cmd/phases/util.go +++ b/cmd/kubeadm/app/cmd/phases/util.go @@ -17,50 +17,10 @@ limitations under the License. package phases import ( - "github.com/spf13/cobra" - - kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" kubeadmapiv1beta1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta1" - "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation" - kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util" - configutil "k8s.io/kubernetes/cmd/kubeadm/app/util/config" "k8s.io/kubernetes/pkg/version" ) -// runCmdPhase creates a cobra.Command Run function, by composing the call to the given cmdFunc with necessary additional steps (e.g preparation of input parameters) -func runCmdPhase(cmdFunc func(outDir string, cfg *kubeadmapi.InitConfiguration) error, outDir, cfgPath *string, cfg *kubeadmapiv1beta1.InitConfiguration, defaultKubernetesVersion string) func(cmd *cobra.Command, args []string) { - - // the following statement build a closure that wraps a call to a cmdFunc, binding - // the function itself with the specific parameters of each sub command. - // Please note that specific parameter should be passed as value, while other parameters - passed as reference - - // are shared between sub commands and gets access to current value e.g. flags value. - - return func(cmd *cobra.Command, args []string) { - if err := validation.ValidateMixedArguments(cmd.Flags()); err != nil { - kubeadmutil.CheckErr(err) - } - - // This is used for unit testing only... - // If we wouldn't set this to something, the code would dynamically look up the version from the internet - // By setting this explicitly for tests workarounds that - if defaultKubernetesVersion != "" { - cfg.KubernetesVersion = defaultKubernetesVersion - } else { - // KubernetesVersion is not used, but we set it explicitly to avoid the lookup - // of the version from the internet when executing ConfigFileAndDefaultsToInternalConfig - SetKubernetesVersion(cfg) - } - - // This call returns the ready-to-use configuration based on the configuration file that might or might not exist and the default cfg populated by flags - internalcfg, err := configutil.ConfigFileAndDefaultsToInternalConfig(*cfgPath, cfg) - kubeadmutil.CheckErr(err) - - // Execute the cmdFunc - err = cmdFunc(*outDir, internalcfg) - kubeadmutil.CheckErr(err) - } -} - // SetKubernetesVersion gets the current Kubeadm version and sets it as KubeadmVersion in the config, // unless it's already set to a value different from the default. func SetKubernetesVersion(cfg *kubeadmapiv1beta1.InitConfiguration) { diff --git a/cmd/kubeadm/app/cmd/phases/workflow/doc_test.go b/cmd/kubeadm/app/cmd/phases/workflow/doc_test.go index 0211f42364d..47fb88b8f0d 100644 --- a/cmd/kubeadm/app/cmd/phases/workflow/doc_test.go +++ b/cmd/kubeadm/app/cmd/phases/workflow/doc_test.go @@ -17,9 +17,9 @@ limitations under the License. package workflow import ( - "errors" "fmt" + "github.com/pkg/errors" "github.com/spf13/cobra" ) diff --git a/cmd/kubeadm/app/cmd/reset.go b/cmd/kubeadm/app/cmd/reset.go index 4f2261f54c3..93545b18658 100644 --- a/cmd/kubeadm/app/cmd/reset.go +++ b/cmd/kubeadm/app/cmd/reset.go @@ -156,7 +156,7 @@ func (r *Reset) Run(out io.Writer, client clientset.Interface) error { // Try to unmount mounted directories under kubeadmconstants.KubeletRunDirectory in order to be able to remove the kubeadmconstants.KubeletRunDirectory directory later fmt.Printf("[reset] unmounting mounted directories in %q\n", kubeadmconstants.KubeletRunDirectory) - umountDirsCmd := fmt.Sprintf("awk '$2 ~ path {print $2}' path=%s /proc/mounts | xargs -r umount", kubeadmconstants.KubeletRunDirectory) + umountDirsCmd := fmt.Sprintf("awk '$2 ~ path {print $2}' path=%s/ /proc/mounts | xargs -r umount", kubeadmconstants.KubeletRunDirectory) klog.V(1).Infof("[reset] executing command %q", umountDirsCmd) umountOutputBytes, err := exec.Command("sh", "-c", umountDirsCmd).Output() @@ -225,7 +225,7 @@ func getEtcdDataDir(manifestPath string, client clientset.Interface) (string, er } } if dataDir == "" { - return dataDir, fmt.Errorf("invalid etcd pod manifest") + return dataDir, errors.New("invalid etcd pod manifest") } return dataDir, nil } @@ -239,10 +239,7 @@ func removeContainers(execer utilsexec.Interface, criSocketPath string) error { if err != nil { return err } - if err := containerRuntime.RemoveContainers(containers); err != nil { - return err - } - return nil + return containerRuntime.RemoveContainers(containers) } // cleanDir removes everything in a directory, but not the directory itself diff --git a/cmd/kubeadm/app/cmd/reset_test.go b/cmd/kubeadm/app/cmd/reset_test.go index 063d59b6cbe..d7e44cad578 100644 --- a/cmd/kubeadm/app/cmd/reset_test.go +++ b/cmd/kubeadm/app/cmd/reset_test.go @@ -195,51 +195,53 @@ func TestConfigDirCleaner(t *testing.T) { } for name, test := range tests { - t.Logf("Running test: %s", name) + t.Run(name, func(t *testing.T) { + t.Logf("Running test: %s", name) - // Create a temporary directory for our fake config dir: - tmpDir, err := ioutil.TempDir("", "kubeadm-reset-test") - if err != nil { - t.Errorf("Unable to create temporary directory: %s", err) - } - - for _, createDir := range test.setupDirs { - err := os.Mkdir(filepath.Join(tmpDir, createDir), 0700) + // Create a temporary directory for our fake config dir: + tmpDir, err := ioutil.TempDir("", "kubeadm-reset-test") if err != nil { - t.Errorf("Unable to setup test config directory: %s", err) + t.Errorf("Unable to create temporary directory: %s", err) } - } - for _, createFile := range test.setupFiles { - fullPath := filepath.Join(tmpDir, createFile) - f, err := os.Create(fullPath) - if err != nil { - t.Errorf("Unable to create test file: %s", err) + for _, createDir := range test.setupDirs { + err := os.Mkdir(filepath.Join(tmpDir, createDir), 0700) + if err != nil { + t.Errorf("Unable to setup test config directory: %s", err) + } } - f.Close() - } - if test.resetDir == "" { - test.resetDir = "pki" - } - resetConfigDir(tmpDir, filepath.Join(tmpDir, test.resetDir)) + for _, createFile := range test.setupFiles { + fullPath := filepath.Join(tmpDir, createFile) + f, err := os.Create(fullPath) + if err != nil { + t.Errorf("Unable to create test file: %s", err) + } + f.Close() + } - // Verify the files we cleanup implicitly in every test: - assertExists(t, tmpDir) - assertNotExists(t, filepath.Join(tmpDir, kubeadmconstants.AdminKubeConfigFileName)) - assertNotExists(t, filepath.Join(tmpDir, kubeadmconstants.KubeletKubeConfigFileName)) - assertDirEmpty(t, filepath.Join(tmpDir, "manifests")) - assertDirEmpty(t, filepath.Join(tmpDir, "pki")) + if test.resetDir == "" { + test.resetDir = "pki" + } + resetConfigDir(tmpDir, filepath.Join(tmpDir, test.resetDir)) - // Verify the files as requested by the test: - for _, path := range test.verifyExists { - assertExists(t, filepath.Join(tmpDir, path)) - } - for _, path := range test.verifyNotExists { - assertNotExists(t, filepath.Join(tmpDir, path)) - } + // Verify the files we cleanup implicitly in every test: + assertExists(t, tmpDir) + assertNotExists(t, filepath.Join(tmpDir, kubeadmconstants.AdminKubeConfigFileName)) + assertNotExists(t, filepath.Join(tmpDir, kubeadmconstants.KubeletKubeConfigFileName)) + assertDirEmpty(t, filepath.Join(tmpDir, "manifests")) + assertDirEmpty(t, filepath.Join(tmpDir, "pki")) - os.RemoveAll(tmpDir) + // Verify the files as requested by the test: + for _, path := range test.verifyExists { + assertExists(t, filepath.Join(tmpDir, path)) + } + for _, path := range test.verifyNotExists { + assertNotExists(t, filepath.Join(tmpDir, path)) + } + + os.RemoveAll(tmpDir) + }) } } @@ -309,38 +311,40 @@ func TestGetEtcdDataDir(t *testing.T) { } for name, test := range tests { - tmpdir := testutil.SetupTempDir(t) - defer os.RemoveAll(tmpdir) + t.Run(name, func(t *testing.T) { + tmpdir := testutil.SetupTempDir(t) + defer os.RemoveAll(tmpdir) - manifestPath := filepath.Join(tmpdir, "etcd.yaml") - if test.writeManifest { - err := ioutil.WriteFile(manifestPath, []byte(test.podYaml), 0644) - if err != nil { - t.Fatalf(dedent.Dedent("failed to write pod manifest\n%s\n\tfatal error: %v"), name, err) + manifestPath := filepath.Join(tmpdir, "etcd.yaml") + if test.writeManifest { + err := ioutil.WriteFile(manifestPath, []byte(test.podYaml), 0644) + if err != nil { + t.Fatalf(dedent.Dedent("failed to write pod manifest\n%s\n\tfatal error: %v"), name, err) + } } - } - var dataDir string - var err error - if test.validClient { - client := clientsetfake.NewSimpleClientset() - dataDir, err = getEtcdDataDir(manifestPath, client) - } else { - dataDir, err = getEtcdDataDir(manifestPath, nil) - } + var dataDir string + var err error + if test.validClient { + client := clientsetfake.NewSimpleClientset() + dataDir, err = getEtcdDataDir(manifestPath, client) + } else { + dataDir, err = getEtcdDataDir(manifestPath, nil) + } - if (err != nil) != test.expectErr { - t.Fatalf(dedent.Dedent( - "getEtcdDataDir failed\n%s\nexpected error: %t\n\tgot: %t\nerror: %v"), - name, - test.expectErr, - (err != nil), - err, - ) - } + if (err != nil) != test.expectErr { + t.Fatalf(dedent.Dedent( + "getEtcdDataDir failed\n%s\nexpected error: %t\n\tgot: %t\nerror: %v"), + name, + test.expectErr, + (err != nil), + err, + ) + } - if dataDir != test.dataDir { - t.Fatalf(dedent.Dedent("getEtcdDataDir failed\n%s\n\texpected: %s\ngot: %s"), name, test.dataDir, dataDir) - } + if dataDir != test.dataDir { + t.Fatalf(dedent.Dedent("getEtcdDataDir failed\n%s\n\texpected: %s\ngot: %s"), name, test.dataDir, dataDir) + } + }) } } diff --git a/cmd/kubeadm/app/cmd/token_test.go b/cmd/kubeadm/app/cmd/token_test.go index 8de0595a6c9..ba2b654f7c2 100644 --- a/cmd/kubeadm/app/cmd/token_test.go +++ b/cmd/kubeadm/app/cmd/token_test.go @@ -25,13 +25,14 @@ import ( "testing" "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/api/errors" + apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/client-go/kubernetes/fake" core "k8s.io/client-go/testing" "k8s.io/client-go/tools/clientcmd" kubeadmapiv1beta1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta1" + "k8s.io/kubernetes/cmd/kubeadm/app/constants" ) const ( @@ -96,7 +97,7 @@ func TestRunCreateToken(t *testing.T) { var buf bytes.Buffer fakeClient := &fake.Clientset{} fakeClient.AddReactor("get", "secrets", func(action core.Action) (handled bool, ret runtime.Object, err error) { - return true, nil, errors.NewNotFound(v1.Resource("secrets"), "foo") + return true, nil, apierrors.NewNotFound(v1.Resource("secrets"), "foo") }) testCases := []struct { @@ -166,31 +167,33 @@ func TestRunCreateToken(t *testing.T) { }, } for _, tc := range testCases { - bts, err := kubeadmapiv1beta1.NewBootstrapTokenString(tc.token) - if err != nil && len(tc.token) != 0 { // if tc.token is "" it's okay as it will be generated later at runtime - t.Fatalf("token couldn't be parsed for testing: %v", err) - } + t.Run(tc.name, func(t *testing.T) { + bts, err := kubeadmapiv1beta1.NewBootstrapTokenString(tc.token) + if err != nil && len(tc.token) != 0 { // if tc.token is "" it's okay as it will be generated later at runtime + t.Fatalf("token couldn't be parsed for testing: %v", err) + } - cfg := &kubeadmapiv1beta1.InitConfiguration{ - ClusterConfiguration: kubeadmapiv1beta1.ClusterConfiguration{ - // KubernetesVersion is not used, but we set this explicitly to avoid - // the lookup of the version from the internet when executing ConfigFileAndDefaultsToInternalConfig - KubernetesVersion: "v1.12.0", - }, - BootstrapTokens: []kubeadmapiv1beta1.BootstrapToken{ - { - Token: bts, - TTL: &metav1.Duration{Duration: 0}, - Usages: tc.usages, - Groups: tc.extraGroups, + cfg := &kubeadmapiv1beta1.InitConfiguration{ + ClusterConfiguration: kubeadmapiv1beta1.ClusterConfiguration{ + // KubernetesVersion is not used, but we set this explicitly to avoid + // the lookup of the version from the internet when executing ConfigFileAndDefaultsToInternalConfig + KubernetesVersion: constants.MinimumControlPlaneVersion.String(), }, - }, - } + BootstrapTokens: []kubeadmapiv1beta1.BootstrapToken{ + { + Token: bts, + TTL: &metav1.Duration{Duration: 0}, + Usages: tc.usages, + Groups: tc.extraGroups, + }, + }, + } - err = RunCreateToken(&buf, fakeClient, "", cfg, tc.printJoin, "") - if (err != nil) != tc.expectedError { - t.Errorf("Test case %s: RunCreateToken expected error: %v, saw: %v", tc.name, tc.expectedError, (err != nil)) - } + err = RunCreateToken(&buf, fakeClient, "", cfg, tc.printJoin, "") + if (err != nil) != tc.expectedError { + t.Errorf("Test case %s: RunCreateToken expected error: %v, saw: %v", tc.name, tc.expectedError, (err != nil)) + } + }) } } @@ -252,24 +255,26 @@ func TestNewCmdToken(t *testing.T) { } for _, tc := range testCases { - // the command is created for each test so that the kubeConfigFile - // variable in NewCmdToken() is reset. - cmd := NewCmdToken(&buf, &bufErr) - if _, err = f.WriteString(tc.configToWrite); err != nil { - t.Errorf("Unable to write test file %q: %v", fullPath, err) - } - // store the current value of the environment variable. - storedEnv := os.Getenv(clientcmd.RecommendedConfigPathEnvVar) - if tc.kubeConfigEnv != "" { - os.Setenv(clientcmd.RecommendedConfigPathEnvVar, tc.kubeConfigEnv) - } - cmd.SetArgs(tc.args) - err := cmd.Execute() - if (err != nil) != tc.expectedError { - t.Errorf("Test case %q: NewCmdToken expected error: %v, saw: %v", tc.name, tc.expectedError, (err != nil)) - } - // restore the environment variable. - os.Setenv(clientcmd.RecommendedConfigPathEnvVar, storedEnv) + t.Run(tc.name, func(t *testing.T) { + // the command is created for each test so that the kubeConfigFile + // variable in NewCmdToken() is reset. + cmd := NewCmdToken(&buf, &bufErr) + if _, err = f.WriteString(tc.configToWrite); err != nil { + t.Errorf("Unable to write test file %q: %v", fullPath, err) + } + // store the current value of the environment variable. + storedEnv := os.Getenv(clientcmd.RecommendedConfigPathEnvVar) + if tc.kubeConfigEnv != "" { + os.Setenv(clientcmd.RecommendedConfigPathEnvVar, tc.kubeConfigEnv) + } + cmd.SetArgs(tc.args) + err := cmd.Execute() + if (err != nil) != tc.expectedError { + t.Errorf("Test case %q: NewCmdToken expected error: %v, saw: %v", tc.name, tc.expectedError, (err != nil)) + } + // restore the environment variable. + os.Setenv(clientcmd.RecommendedConfigPathEnvVar, storedEnv) + }) } } diff --git a/cmd/kubeadm/app/cmd/upgrade/apply_test.go b/cmd/kubeadm/app/cmd/upgrade/apply_test.go index 80d55ac1529..2a820efdcfe 100644 --- a/cmd/kubeadm/app/cmd/upgrade/apply_test.go +++ b/cmd/kubeadm/app/cmd/upgrade/apply_test.go @@ -28,11 +28,13 @@ import ( func TestSetImplicitFlags(t *testing.T) { var tests = []struct { + name string flags *applyFlags expectedFlags applyFlags errExpected bool }{ - { // if not dryRun or force is set; the nonInteractiveMode field should not be touched + { + name: "if not dryRun or force is set; the nonInteractiveMode field should not be touched", flags: &applyFlags{ newK8sVersionStr: "v1.8.0", dryRun: false, @@ -46,7 +48,8 @@ func TestSetImplicitFlags(t *testing.T) { nonInteractiveMode: false, }, }, - { // if not dryRun or force is set; the nonInteractiveMode field should not be touched + { + name: "if not dryRun or force is set; the nonInteractiveMode field should not be touched", flags: &applyFlags{ newK8sVersionStr: "v1.8.0", dryRun: false, @@ -60,7 +63,8 @@ func TestSetImplicitFlags(t *testing.T) { nonInteractiveMode: true, }, }, - { // if dryRun or force is set; the nonInteractiveMode field should be set to true + { + name: "if dryRun or force is set; the nonInteractiveMode field should be set to true", flags: &applyFlags{ newK8sVersionStr: "v1.8.0", dryRun: true, @@ -74,7 +78,8 @@ func TestSetImplicitFlags(t *testing.T) { nonInteractiveMode: true, }, }, - { // if dryRun or force is set; the nonInteractiveMode field should be set to true + { + name: "if dryRun or force is set; the nonInteractiveMode field should be set to true", flags: &applyFlags{ newK8sVersionStr: "v1.8.0", dryRun: false, @@ -88,7 +93,8 @@ func TestSetImplicitFlags(t *testing.T) { nonInteractiveMode: true, }, }, - { // if dryRun or force is set; the nonInteractiveMode field should be set to true + { + name: "if dryRun or force is set; the nonInteractiveMode field should be set to true", flags: &applyFlags{ newK8sVersionStr: "v1.8.0", dryRun: true, @@ -102,7 +108,8 @@ func TestSetImplicitFlags(t *testing.T) { nonInteractiveMode: true, }, }, - { // if dryRun or force is set; the nonInteractiveMode field should be set to true + { + name: "if dryRun or force is set; the nonInteractiveMode field should be set to true", flags: &applyFlags{ newK8sVersionStr: "v1.8.0", dryRun: true, @@ -116,7 +123,8 @@ func TestSetImplicitFlags(t *testing.T) { nonInteractiveMode: true, }, }, - { // if the new version is empty; it should error out + { + name: "if the new version is empty; it should error out", flags: &applyFlags{ newK8sVersionStr: "", }, @@ -127,27 +135,29 @@ func TestSetImplicitFlags(t *testing.T) { }, } for _, rt := range tests { - actualErr := SetImplicitFlags(rt.flags) + t.Run(rt.name, func(t *testing.T) { + actualErr := SetImplicitFlags(rt.flags) - // If an error was returned; make newK8sVersion nil so it's easy to match using reflect.DeepEqual later (instead of a random pointer) - if actualErr != nil { - rt.flags.newK8sVersion = nil - } + // If an error was returned; make newK8sVersion nil so it's easy to match using reflect.DeepEqual later (instead of a random pointer) + if actualErr != nil { + rt.flags.newK8sVersion = nil + } - if !reflect.DeepEqual(*rt.flags, rt.expectedFlags) { - t.Errorf( - "failed SetImplicitFlags:\n\texpected flags: %v\n\t actual: %v", - rt.expectedFlags, - *rt.flags, - ) - } - if (actualErr != nil) != rt.errExpected { - t.Errorf( - "failed SetImplicitFlags:\n\texpected error: %t\n\t actual: %t", - rt.errExpected, - (actualErr != nil), - ) - } + if !reflect.DeepEqual(*rt.flags, rt.expectedFlags) { + t.Errorf( + "failed SetImplicitFlags:\n\texpected flags: %v\n\t actual: %v", + rt.expectedFlags, + *rt.flags, + ) + } + if (actualErr != nil) != rt.errExpected { + t.Errorf( + "failed SetImplicitFlags:\n\texpected error: %t\n\t actual: %t", + rt.errExpected, + (actualErr != nil), + ) + } + }) } } diff --git a/cmd/kubeadm/app/cmd/upgrade/common.go b/cmd/kubeadm/app/cmd/upgrade/common.go index 28158e9b142..e70a8c0ceaa 100644 --- a/cmd/kubeadm/app/cmd/upgrade/common.go +++ b/cmd/kubeadm/app/cmd/upgrade/common.go @@ -25,6 +25,7 @@ import ( "strings" "github.com/pkg/errors" + apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/sets" diff --git a/cmd/kubeadm/app/cmd/upgrade/common_test.go b/cmd/kubeadm/app/cmd/upgrade/common_test.go index 513ff84edeb..a82e5d9becf 100644 --- a/cmd/kubeadm/app/cmd/upgrade/common_test.go +++ b/cmd/kubeadm/app/cmd/upgrade/common_test.go @@ -25,15 +25,18 @@ import ( func TestPrintConfiguration(t *testing.T) { var tests = []struct { + name string cfg *kubeadmapi.ClusterConfiguration buf *bytes.Buffer expectedBytes []byte }{ { + name: "config is nil", cfg: nil, expectedBytes: []byte(""), }, { + name: "cluster config with local Etcd", cfg: &kubeadmapi.ClusterConfiguration{ KubernetesVersion: "v1.7.1", Etcd: kubeadmapi.Etcd{ @@ -67,6 +70,7 @@ func TestPrintConfiguration(t *testing.T) { `), }, { + name: "cluster config with ServiceSubnet and external Etcd", cfg: &kubeadmapi.ClusterConfiguration{ KubernetesVersion: "v1.7.1", Networking: kubeadmapi.Networking{ @@ -108,15 +112,17 @@ func TestPrintConfiguration(t *testing.T) { }, } for _, rt := range tests { - rt.buf = bytes.NewBufferString("") - printConfiguration(rt.cfg, rt.buf) - actualBytes := rt.buf.Bytes() - if !bytes.Equal(actualBytes, rt.expectedBytes) { - t.Errorf( - "failed PrintConfiguration:\n\texpected: %q\n\t actual: %q", - string(rt.expectedBytes), - string(actualBytes), - ) - } + t.Run(rt.name, func(t *testing.T) { + rt.buf = bytes.NewBufferString("") + printConfiguration(rt.cfg, rt.buf) + actualBytes := rt.buf.Bytes() + if !bytes.Equal(actualBytes, rt.expectedBytes) { + t.Errorf( + "failed PrintConfiguration:\n\texpected: %q\n\t actual: %q", + string(rt.expectedBytes), + string(actualBytes), + ) + } + }) } } diff --git a/cmd/kubeadm/app/cmd/upgrade/node.go b/cmd/kubeadm/app/cmd/upgrade/node.go index a915d2c9134..f7d25d735ac 100644 --- a/cmd/kubeadm/app/cmd/upgrade/node.go +++ b/cmd/kubeadm/app/cmd/upgrade/node.go @@ -46,14 +46,14 @@ var ( what the _desired_ kubelet version is. Give `) - upgradeNodeConfigExample = normalizer.Examples(` + upgradeNodeConfigExample = normalizer.Examples(fmt.Sprintf(` # Downloads the kubelet configuration from the ConfigMap in the cluster. Uses a specific desired kubelet version. - kubeadm upgrade node config --kubelet-version v1.13.0 + kubeadm upgrade node config --kubelet-version %s # Simulates the downloading of the kubelet configuration from the ConfigMap in the cluster with a specific desired # version. Does not change any state locally on the node. - kubeadm upgrade node config --kubelet-version v1.13.0 --dry-run - `) + kubeadm upgrade node config --kubelet-version %[1]s --dry-run + `, constants.CurrentKubernetesVersion)) ) type nodeUpgradeFlags struct { diff --git a/cmd/kubeadm/app/cmd/upgrade/plan_test.go b/cmd/kubeadm/app/cmd/upgrade/plan_test.go index 5ea882565a9..7f4c703607f 100644 --- a/cmd/kubeadm/app/cmd/upgrade/plan_test.go +++ b/cmd/kubeadm/app/cmd/upgrade/plan_test.go @@ -27,35 +27,42 @@ import ( func TestSortedSliceFromStringIntMap(t *testing.T) { var tests = []struct { + name string strMap map[string]uint16 expectedSlice []string - }{ // The returned slice should be alphabetically sorted based on the string keys in the map + }{ { + name: "the returned slice should be alphabetically sorted based on the string keys in the map", strMap: map[string]uint16{"foo": 1, "bar": 2}, expectedSlice: []string{"bar", "foo"}, }, - { // The int value should not affect this func + { + name: "the int value should not affect this func", strMap: map[string]uint16{"foo": 2, "bar": 1}, expectedSlice: []string{"bar", "foo"}, }, { + name: "slice with 4 keys and different values", strMap: map[string]uint16{"b": 2, "a": 1, "cb": 0, "ca": 1000}, expectedSlice: []string{"a", "b", "ca", "cb"}, }, - { // This should work for version numbers as well; and the lowest version should come first + { + name: "this should work for version numbers as well; and the lowest version should come first", strMap: map[string]uint16{"v1.7.0": 1, "v1.6.1": 1, "v1.6.2": 1, "v1.8.0": 1, "v1.8.0-alpha.1": 1}, expectedSlice: []string{"v1.6.1", "v1.6.2", "v1.7.0", "v1.8.0", "v1.8.0-alpha.1"}, }, } for _, rt := range tests { - actualSlice := sortedSliceFromStringIntMap(rt.strMap) - if !reflect.DeepEqual(actualSlice, rt.expectedSlice) { - t.Errorf( - "failed SortedSliceFromStringIntMap:\n\texpected: %v\n\t actual: %v", - rt.expectedSlice, - actualSlice, - ) - } + t.Run(rt.name, func(t *testing.T) { + actualSlice := sortedSliceFromStringIntMap(rt.strMap) + if !reflect.DeepEqual(actualSlice, rt.expectedSlice) { + t.Errorf( + "failed SortedSliceFromStringIntMap:\n\texpected: %v\n\t actual: %v", + rt.expectedSlice, + actualSlice, + ) + } + }) } } diff --git a/cmd/kubeadm/app/cmd/util/cmdutil_test.go b/cmd/kubeadm/app/cmd/util/cmdutil_test.go index 40fcf87dfbd..72ee829315c 100644 --- a/cmd/kubeadm/app/cmd/util/cmdutil_test.go +++ b/cmd/kubeadm/app/cmd/util/cmdutil_test.go @@ -22,43 +22,51 @@ import ( func TestValidateExactArgNumber(t *testing.T) { var tests = []struct { + name string args, supportedArgs []string expectedErr bool }{ - { // one arg given and one arg expected + { + name: "one arg given and one arg expected", args: []string{"my-node-1234"}, supportedArgs: []string{"node-name"}, expectedErr: false, }, - { // two args given and two args expected + { + name: "two args given and two args expected", args: []string{"my-node-1234", "foo"}, supportedArgs: []string{"node-name", "second-toplevel-arg"}, expectedErr: false, }, - { // too few supplied args + { + name: "too few supplied args", args: []string{}, supportedArgs: []string{"node-name"}, expectedErr: true, }, - { // too few non-empty args + { + name: "too few non-empty args", args: []string{""}, supportedArgs: []string{"node-name"}, expectedErr: true, }, - { // too many args + { + name: "too many args", args: []string{"my-node-1234", "foo"}, supportedArgs: []string{"node-name"}, expectedErr: true, }, } for _, rt := range tests { - actual := ValidateExactArgNumber(rt.args, rt.supportedArgs) - if (actual != nil) != rt.expectedErr { - t.Errorf( - "failed ValidateExactArgNumber:\n\texpected error: %t\n\t actual error: %t", - rt.expectedErr, - (actual != nil), - ) - } + t.Run(rt.name, func(t *testing.T) { + actual := ValidateExactArgNumber(rt.args, rt.supportedArgs) + if (actual != nil) != rt.expectedErr { + t.Errorf( + "failed ValidateExactArgNumber:\n\texpected error: %t\n\t actual error: %t", + rt.expectedErr, + (actual != nil), + ) + } + }) } } diff --git a/cmd/kubeadm/app/cmd/version_test.go b/cmd/kubeadm/app/cmd/version_test.go index b72977e5806..3e93a44f630 100644 --- a/cmd/kubeadm/app/cmd/version_test.go +++ b/cmd/kubeadm/app/cmd/version_test.go @@ -69,28 +69,30 @@ func TestRunVersion(t *testing.T) { }, } for _, tc := range testCases { - var err error - if len(tc.flag) > 0 { - if err = cmd.Flags().Set(flagNameOutput, tc.flag); err != nil { + t.Run(tc.name, func(t *testing.T) { + var err error + if len(tc.flag) > 0 { + if err = cmd.Flags().Set(flagNameOutput, tc.flag); err != nil { + goto error + } + } + buf.Reset() + if err = RunVersion(&buf, cmd); err != nil { goto error } - } - buf.Reset() - if err = RunVersion(&buf, cmd); err != nil { - goto error - } - if buf.String() == "" { - err = errors.New("empty output") - goto error - } - if tc.shouldBeValidYAML { - err = yaml.Unmarshal(buf.Bytes(), &iface) - } else if tc.shouldBeValidJSON { - err = json.Unmarshal(buf.Bytes(), &iface) - } - error: - if (err != nil) != tc.expectedError { - t.Errorf("Test case %q: RunVersion expected error: %v, saw: %v; %v", tc.name, tc.expectedError, err != nil, err) - } + if buf.String() == "" { + err = errors.New("empty output") + goto error + } + if tc.shouldBeValidYAML { + err = yaml.Unmarshal(buf.Bytes(), &iface) + } else if tc.shouldBeValidJSON { + err = json.Unmarshal(buf.Bytes(), &iface) + } + error: + if (err != nil) != tc.expectedError { + t.Errorf("Test case %q: RunVersion expected error: %v, saw: %v; %v", tc.name, tc.expectedError, err != nil, err) + } + }) } } diff --git a/cmd/kubeadm/app/componentconfigs/registrations.go b/cmd/kubeadm/app/componentconfigs/registrations.go index ebe125d1a65..c814cd5db60 100644 --- a/cmd/kubeadm/app/componentconfigs/registrations.go +++ b/cmd/kubeadm/app/componentconfigs/registrations.go @@ -74,10 +74,7 @@ func (r Registration) Unmarshal(fileContent []byte) (runtime.Object, error) { func unmarshalObject(obj runtime.Object, fileContent []byte) error { // Decode the file content using the componentconfig Codecs that knows about all APIs - if err := runtime.DecodeInto(Codecs.UniversalDecoder(), fileContent, obj); err != nil { - return err - } - return nil + return runtime.DecodeInto(Codecs.UniversalDecoder(), fileContent, obj) } const ( diff --git a/cmd/kubeadm/app/componentconfigs/validation_test.go b/cmd/kubeadm/app/componentconfigs/validation_test.go index 29343f8645e..308d75ddee1 100644 --- a/cmd/kubeadm/app/componentconfigs/validation_test.go +++ b/cmd/kubeadm/app/componentconfigs/validation_test.go @@ -31,11 +31,13 @@ import ( func TestValidateKubeProxyConfiguration(t *testing.T) { var tests = []struct { + name string clusterConfig *kubeadm.ClusterConfiguration msg string expectErr bool }{ { + name: "valid config", clusterConfig: &kubeadm.ClusterConfiguration{ ComponentConfigs: kubeadm.ComponentConfigs{ KubeProxy: &kubeproxyconfig.KubeProxyConfiguration{ @@ -67,6 +69,7 @@ func TestValidateKubeProxyConfiguration(t *testing.T) { expectErr: false, }, { + name: "invalid BindAddress", clusterConfig: &kubeadm.ClusterConfiguration{ ComponentConfigs: kubeadm.ComponentConfigs{ KubeProxy: &kubeproxyconfig.KubeProxyConfiguration{ @@ -100,6 +103,7 @@ func TestValidateKubeProxyConfiguration(t *testing.T) { expectErr: true, }, { + name: "invalid HealthzBindAddress", clusterConfig: &kubeadm.ClusterConfiguration{ ComponentConfigs: kubeadm.ComponentConfigs{ KubeProxy: &kubeproxyconfig.KubeProxyConfiguration{ @@ -133,6 +137,7 @@ func TestValidateKubeProxyConfiguration(t *testing.T) { expectErr: true, }, { + name: "invalid MetricsBindAddress", clusterConfig: &kubeadm.ClusterConfiguration{ ComponentConfigs: kubeadm.ComponentConfigs{ KubeProxy: &kubeproxyconfig.KubeProxyConfiguration{ @@ -166,6 +171,7 @@ func TestValidateKubeProxyConfiguration(t *testing.T) { expectErr: true, }, { + name: "invalid ClusterCIDR", clusterConfig: &kubeadm.ClusterConfiguration{ ComponentConfigs: kubeadm.ComponentConfigs{ KubeProxy: &kubeproxyconfig.KubeProxyConfiguration{ @@ -199,6 +205,7 @@ func TestValidateKubeProxyConfiguration(t *testing.T) { expectErr: true, }, { + name: "invalid UDPIdleTimeout", clusterConfig: &kubeadm.ClusterConfiguration{ ComponentConfigs: kubeadm.ComponentConfigs{ KubeProxy: &kubeproxyconfig.KubeProxyConfiguration{ @@ -232,6 +239,7 @@ func TestValidateKubeProxyConfiguration(t *testing.T) { expectErr: true, }, { + name: "invalid ConfigSyncPeriod", clusterConfig: &kubeadm.ClusterConfiguration{ ComponentConfigs: kubeadm.ComponentConfigs{ KubeProxy: &kubeproxyconfig.KubeProxyConfiguration{ @@ -266,22 +274,26 @@ func TestValidateKubeProxyConfiguration(t *testing.T) { }, } for i, rt := range tests { - err := ValidateKubeProxyConfiguration(rt.clusterConfig, nil).ToAggregate() - if (err != nil) != rt.expectErr { - t.Errorf("%d failed ValidateKubeProxyConfiguration: expected error %t, got error %t", i, rt.expectErr, err != nil) - } - if err != nil && !strings.Contains(err.Error(), rt.msg) { - t.Errorf("%d failed ValidateKubeProxyConfiguration: unexpected error: %v, expected: %s", i, err, rt.msg) - } + t.Run(rt.name, func(t *testing.T) { + err := ValidateKubeProxyConfiguration(rt.clusterConfig, nil).ToAggregate() + if (err != nil) != rt.expectErr { + t.Errorf("%d failed ValidateKubeProxyConfiguration: expected error %t, got error %t", i, rt.expectErr, err != nil) + } + if err != nil && !strings.Contains(err.Error(), rt.msg) { + t.Errorf("%d failed ValidateKubeProxyConfiguration: unexpected error: %v, expected: %s", i, err, rt.msg) + } + }) } } func TestValidateKubeletConfiguration(t *testing.T) { var tests = []struct { + name string clusterConfig *kubeadm.ClusterConfiguration expectErr bool }{ { + name: "valid configuration", clusterConfig: &kubeadm.ClusterConfiguration{ ComponentConfigs: kubeadm.ComponentConfigs{ Kubelet: &kubeletconfig.KubeletConfiguration{ @@ -314,6 +326,7 @@ func TestValidateKubeletConfiguration(t *testing.T) { expectErr: false, }, { + name: "invalid configuration", clusterConfig: &kubeadm.ClusterConfiguration{ ComponentConfigs: kubeadm.ComponentConfigs{ Kubelet: &kubeletconfig.KubeletConfiguration{ @@ -345,9 +358,11 @@ func TestValidateKubeletConfiguration(t *testing.T) { }, } for i, rt := range tests { - err := ValidateKubeletConfiguration(rt.clusterConfig, nil).ToAggregate() - if (err != nil) != rt.expectErr { - t.Errorf("%d failed ValidateKubeletConfiguration: expected error %t, got error %t", i, rt.expectErr, err != nil) - } + t.Run(rt.name, func(t *testing.T) { + err := ValidateKubeletConfiguration(rt.clusterConfig, nil).ToAggregate() + if (err != nil) != rt.expectErr { + t.Errorf("%d failed ValidateKubeletConfiguration: expected error %t, got error %t", i, rt.expectErr, err != nil) + } + }) } } diff --git a/cmd/kubeadm/app/constants/constants.go b/cmd/kubeadm/app/constants/constants.go index da728133f70..129425fe538 100644 --- a/cmd/kubeadm/app/constants/constants.go +++ b/cmd/kubeadm/app/constants/constants.go @@ -250,7 +250,7 @@ const ( MinExternalEtcdVersion = "3.2.18" // DefaultEtcdVersion indicates the default etcd version that kubeadm uses - DefaultEtcdVersion = "3.2.24" + DefaultEtcdVersion = "3.3.10" // PauseVersion indicates the default pause image version for kubeadm PauseVersion = "3.1" @@ -382,12 +382,16 @@ var ( // MinimumKubeletVersion specifies the minimum version of kubelet which kubeadm supports MinimumKubeletVersion = version.MustParseSemantic("v1.12.0") + // CurrentKubernetesVersion specifies current Kubernetes version supported by kubeadm + CurrentKubernetesVersion = version.MustParseSemantic("v1.13.0") + // SupportedEtcdVersion lists officially supported etcd versions with corresponding Kubernetes releases SupportedEtcdVersion = map[uint8]string{ 10: "3.1.12", 11: "3.2.18", 12: "3.2.24", 13: "3.2.24", + 14: "3.3.10", } ) diff --git a/cmd/kubeadm/app/constants/constants_test.go b/cmd/kubeadm/app/constants/constants_test.go index bbcab17240c..115526bb6da 100644 --- a/cmd/kubeadm/app/constants/constants_test.go +++ b/cmd/kubeadm/app/constants/constants_test.go @@ -100,14 +100,16 @@ func TestGetStaticPodFilepath(t *testing.T) { }, } for _, rt := range tests { - actual := GetStaticPodFilepath(rt.componentName, rt.manifestsDir) - if actual != rt.expected { - t.Errorf( - "failed GetStaticPodFilepath:\n\texpected: %s\n\t actual: %s", - rt.expected, - actual, - ) - } + t.Run(rt.componentName, func(t *testing.T) { + actual := GetStaticPodFilepath(rt.componentName, rt.manifestsDir) + if actual != rt.expected { + t.Errorf( + "failed GetStaticPodFilepath:\n\texpected: %s\n\t actual: %s", + rt.expected, + actual, + ) + } + }) } } @@ -133,14 +135,16 @@ func TestAddSelfHostedPrefix(t *testing.T) { }, } for _, rt := range tests { - actual := AddSelfHostedPrefix(rt.componentName) - if actual != rt.expected { - t.Errorf( - "failed AddSelfHostedPrefix:\n\texpected: %s\n\t actual: %s", - rt.expected, - actual, - ) - } + t.Run(rt.componentName, func(t *testing.T) { + actual := AddSelfHostedPrefix(rt.componentName) + if actual != rt.expected { + t.Errorf( + "failed AddSelfHostedPrefix:\n\texpected: %s\n\t actual: %s", + rt.expected, + actual, + ) + } + }) } } @@ -155,11 +159,6 @@ func TestEtcdSupportedVersion(t *testing.T) { expectedVersion: nil, expectedError: errors.New("Unsupported or unknown Kubernetes version(1.99.0)"), }, - { - kubernetesVersion: "1.10.0", - expectedVersion: version.MustParseSemantic("3.1.12"), - expectedError: nil, - }, { kubernetesVersion: "1.10.2", expectedVersion: version.MustParseSemantic("3.1.12"), @@ -175,30 +174,42 @@ func TestEtcdSupportedVersion(t *testing.T) { expectedVersion: version.MustParseSemantic("3.2.24"), expectedError: nil, }, + { + kubernetesVersion: "1.13.1", + expectedVersion: version.MustParseSemantic("3.2.24"), + expectedError: nil, + }, + { + kubernetesVersion: "1.14.0", + expectedVersion: version.MustParseSemantic("3.3.10"), + expectedError: nil, + }, } for _, rt := range tests { - actualVersion, actualError := EtcdSupportedVersion(rt.kubernetesVersion) - if actualError != nil { - if rt.expectedError == nil { - t.Errorf("failed EtcdSupportedVersion:\n\texpected no error, but got: %v", actualError) - } else if actualError.Error() != rt.expectedError.Error() { - t.Errorf( - "failed EtcdSupportedVersion:\n\texpected error: %v\n\t actual error: %v", - rt.expectedError, - actualError, - ) + t.Run(rt.kubernetesVersion, func(t *testing.T) { + actualVersion, actualError := EtcdSupportedVersion(rt.kubernetesVersion) + if actualError != nil { + if rt.expectedError == nil { + t.Errorf("failed EtcdSupportedVersion:\n\texpected no error, but got: %v", actualError) + } else if actualError.Error() != rt.expectedError.Error() { + t.Errorf( + "failed EtcdSupportedVersion:\n\texpected error: %v\n\t actual error: %v", + rt.expectedError, + actualError, + ) + } + } else { + if rt.expectedError != nil { + t.Errorf("failed EtcdSupportedVersion:\n\texpected error: %v, but got no error", rt.expectedError) + } else if strings.Compare(actualVersion.String(), rt.expectedVersion.String()) != 0 { + t.Errorf( + "failed EtcdSupportedVersion:\n\texpected version: %s\n\t actual version: %s", + rt.expectedVersion.String(), + actualVersion.String(), + ) + } } - } else { - if rt.expectedError != nil { - t.Errorf("failed EtcdSupportedVersion:\n\texpected error: %v, but got no error", rt.expectedError) - } else if strings.Compare(actualVersion.String(), rt.expectedVersion.String()) != 0 { - t.Errorf( - "failed EtcdSupportedVersion:\n\texpected version: %s\n\t actual version: %s", - rt.expectedVersion.String(), - actualVersion.String(), - ) - } - } + }) } } @@ -217,13 +228,15 @@ func TestGetKubeDNSVersion(t *testing.T) { }, } for _, rt := range tests { - actualDNSVersion := GetDNSVersion(rt.dns) - if actualDNSVersion != rt.expected { - t.Errorf( - "failed GetDNSVersion:\n\texpected: %s\n\t actual: %s", - rt.expected, - actualDNSVersion, - ) - } + t.Run(string(rt.dns), func(t *testing.T) { + actualDNSVersion := GetDNSVersion(rt.dns) + if actualDNSVersion != rt.expected { + t.Errorf( + "failed GetDNSVersion:\n\texpected: %s\n\t actual: %s", + rt.expected, + actualDNSVersion, + ) + } + }) } } diff --git a/cmd/kubeadm/app/discovery/discovery_test.go b/cmd/kubeadm/app/discovery/discovery_test.go index 96fb4f14e63..66ccff97111 100644 --- a/cmd/kubeadm/app/discovery/discovery_test.go +++ b/cmd/kubeadm/app/discovery/discovery_test.go @@ -24,11 +24,17 @@ import ( func TestFor(t *testing.T) { tests := []struct { + name string d kubeadm.JoinConfiguration expect bool }{ - {d: kubeadm.JoinConfiguration{}, expect: false}, { + name: "default Discovery", + d: kubeadm.JoinConfiguration{}, + expect: false, + }, + { + name: "file Discovery with a path", d: kubeadm.JoinConfiguration{ Discovery: kubeadm.Discovery{ File: &kubeadm.FileDiscovery{ @@ -39,6 +45,7 @@ func TestFor(t *testing.T) { expect: false, }, { + name: "file Discovery with an url", d: kubeadm.JoinConfiguration{ Discovery: kubeadm.Discovery{ File: &kubeadm.FileDiscovery{ @@ -49,6 +56,7 @@ func TestFor(t *testing.T) { expect: false, }, { + name: "BootstrapTokenDiscovery", d: kubeadm.JoinConfiguration{ Discovery: kubeadm.Discovery{ BootstrapToken: &kubeadm.BootstrapTokenDiscovery{ @@ -60,13 +68,15 @@ func TestFor(t *testing.T) { }, } for _, rt := range tests { - _, actual := For(&rt.d) - if (actual == nil) != rt.expect { - t.Errorf( - "failed For:\n\texpected: %t\n\t actual: %t", - rt.expect, - (actual == nil), - ) - } + t.Run(rt.name, func(t *testing.T) { + _, actual := For(&rt.d) + if (actual == nil) != rt.expect { + t.Errorf( + "failed For:\n\texpected: %t\n\t actual: %t", + rt.expect, + (actual == nil), + ) + } + }) } } diff --git a/cmd/kubeadm/app/discovery/file/file.go b/cmd/kubeadm/app/discovery/file/file.go index a7b60d616bb..e32843a71b4 100644 --- a/cmd/kubeadm/app/discovery/file/file.go +++ b/cmd/kubeadm/app/discovery/file/file.go @@ -21,6 +21,7 @@ import ( "io/ioutil" "github.com/pkg/errors" + "k8s.io/api/core/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" diff --git a/cmd/kubeadm/app/features/BUILD b/cmd/kubeadm/app/features/BUILD index e02ece2dd8b..f51ca8da81b 100644 --- a/cmd/kubeadm/app/features/BUILD +++ b/cmd/kubeadm/app/features/BUILD @@ -35,7 +35,7 @@ go_test( srcs = ["features_test.go"], embed = [":go_default_library"], deps = [ - "//staging/src/k8s.io/apimachinery/pkg/util/version:go_default_library", + "//cmd/kubeadm/app/constants:go_default_library", "//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library", ], ) diff --git a/cmd/kubeadm/app/features/features_test.go b/cmd/kubeadm/app/features/features_test.go index e0679eabc93..d40b654a39d 100644 --- a/cmd/kubeadm/app/features/features_test.go +++ b/cmd/kubeadm/app/features/features_test.go @@ -20,12 +20,10 @@ import ( "reflect" "testing" - "k8s.io/apimachinery/pkg/util/version" utilfeature "k8s.io/apiserver/pkg/util/feature" + "k8s.io/kubernetes/cmd/kubeadm/app/constants" ) -var TestMinVersion = version.MustParseSemantic("v1.12.0-alpha.1") - func TestKnownFeatures(t *testing.T) { var someFeatures = FeatureList{ "feature2": {FeatureSpec: utilfeature.FeatureSpec{Default: true, PreRelease: utilfeature.Alpha}}, @@ -110,44 +108,49 @@ func TestNewFeatureGate(t *testing.T) { } for _, test := range tests { + t.Run(test.value, func(t *testing.T) { + r, err := NewFeatureGate(&someFeatures, test.value) - r, err := NewFeatureGate(&someFeatures, test.value) + if !test.expectedError && err != nil { + t.Errorf("NewFeatureGate failed when not expected: %v", err) + return + } else if test.expectedError && err == nil { + t.Error("NewFeatureGate didn't failed when expected") + return + } - if !test.expectedError && err != nil { - t.Errorf("NewFeatureGate failed when not expected: %v", err) - continue - } else if test.expectedError && err == nil { - t.Error("NewFeatureGate didn't failed when expected") - continue - } - - if !reflect.DeepEqual(r, test.expectedFeaturesGate) { - t.Errorf("NewFeatureGate returned a unexpected value") - } + if !reflect.DeepEqual(r, test.expectedFeaturesGate) { + t.Errorf("NewFeatureGate returned a unexpected value") + } + }) } } func TestValidateVersion(t *testing.T) { var someFeatures = FeatureList{ "feature1": {FeatureSpec: utilfeature.FeatureSpec{Default: false, PreRelease: utilfeature.Beta}}, - "feature2": {FeatureSpec: utilfeature.FeatureSpec{Default: true, PreRelease: utilfeature.Alpha}, MinimumVersion: TestMinVersion}, + "feature2": {FeatureSpec: utilfeature.FeatureSpec{Default: true, PreRelease: utilfeature.Alpha}, MinimumVersion: constants.MinimumControlPlaneVersion.WithPreRelease("alpha.1")}, } var tests = []struct { + name string requestedVersion string requestedFeatures map[string]bool expectedError bool }{ - { //no min version + { + name: "no min version", requestedFeatures: map[string]bool{"feature1": true}, expectedError: false, }, - { //min version but correct value given + { + name: "min version but correct value given", requestedFeatures: map[string]bool{"feature2": true}, - requestedVersion: "v1.12.0", + requestedVersion: constants.MinimumControlPlaneVersion.String(), expectedError: false, }, - { //min version and incorrect value given + { + name: "min version and incorrect value given", requestedFeatures: map[string]bool{"feature2": true}, requestedVersion: "v1.11.2", expectedError: true, @@ -155,14 +158,16 @@ func TestValidateVersion(t *testing.T) { } for _, test := range tests { - err := ValidateVersion(someFeatures, test.requestedFeatures, test.requestedVersion) - if !test.expectedError && err != nil { - t.Errorf("ValidateVersion failed when not expected: %v", err) - continue - } else if test.expectedError && err == nil { - t.Error("ValidateVersion didn't failed when expected") - continue - } + t.Run(test.name, func(t *testing.T) { + err := ValidateVersion(someFeatures, test.requestedFeatures, test.requestedVersion) + if !test.expectedError && err != nil { + t.Errorf("ValidateVersion failed when not expected: %v", err) + return + } else if test.expectedError && err == nil { + t.Error("ValidateVersion didn't failed when expected") + return + } + }) } } @@ -187,23 +192,28 @@ func TestCheckDeprecatedFlags(t *testing.T) { } var tests = []struct { + name string features map[string]bool expectedMsg map[string]string }{ - { // feature deprecated + { + name: "deprecated feature", features: map[string]bool{"deprecated": true}, expectedMsg: map[string]string{"deprecated": dummyMessage}, }, - { // valid feature + { + name: "valid feature", features: map[string]bool{"feature1": true}, expectedMsg: map[string]string{}, }, } for _, test := range tests { - msg := CheckDeprecatedFlags(&someFeatures, test.features) - if !reflect.DeepEqual(test.expectedMsg, msg) { - t.Error("CheckDeprecatedFlags didn't returned expected message") - } + t.Run(test.name, func(t *testing.T) { + msg := CheckDeprecatedFlags(&someFeatures, test.features) + if !reflect.DeepEqual(test.expectedMsg, msg) { + t.Error("CheckDeprecatedFlags didn't returned expected message") + } + }) } } diff --git a/cmd/kubeadm/app/phases/addons/dns/dns.go b/cmd/kubeadm/app/phases/addons/dns/dns.go index dc9e604ba79..5ffb4270673 100644 --- a/cmd/kubeadm/app/phases/addons/dns/dns.go +++ b/cmd/kubeadm/app/phases/addons/dns/dns.go @@ -23,6 +23,7 @@ import ( "github.com/mholt/caddy/caddyfile" "github.com/pkg/errors" + apps "k8s.io/api/apps/v1" "k8s.io/api/core/v1" rbac "k8s.io/api/rbac/v1" diff --git a/cmd/kubeadm/app/phases/addons/proxy/BUILD b/cmd/kubeadm/app/phases/addons/proxy/BUILD index 9e7b581f79e..455ffc16b82 100644 --- a/cmd/kubeadm/app/phases/addons/proxy/BUILD +++ b/cmd/kubeadm/app/phases/addons/proxy/BUILD @@ -12,6 +12,7 @@ go_test( embed = [":go_default_library"], deps = [ "//cmd/kubeadm/app/apis/kubeadm/v1beta1:go_default_library", + "//cmd/kubeadm/app/constants:go_default_library", "//cmd/kubeadm/app/util:go_default_library", "//cmd/kubeadm/app/util/config:go_default_library", "//pkg/apis/core:go_default_library", diff --git a/cmd/kubeadm/app/phases/addons/proxy/proxy_test.go b/cmd/kubeadm/app/phases/addons/proxy/proxy_test.go index 2f3dc32d16c..10fe642eb06 100644 --- a/cmd/kubeadm/app/phases/addons/proxy/proxy_test.go +++ b/cmd/kubeadm/app/phases/addons/proxy/proxy_test.go @@ -27,6 +27,7 @@ import ( clientsetfake "k8s.io/client-go/kubernetes/fake" core "k8s.io/client-go/testing" kubeadmapiv1beta1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta1" + "k8s.io/kubernetes/cmd/kubeadm/app/constants" kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util" configutil "k8s.io/kubernetes/cmd/kubeadm/app/util/config" api "k8s.io/kubernetes/pkg/apis/core" @@ -183,7 +184,7 @@ func TestEnsureProxyAddon(t *testing.T) { PodSubnet: "5.6.7.8/24", }, ImageRepository: "someRepo", - KubernetesVersion: "v1.12.0", + KubernetesVersion: constants.MinimumControlPlaneVersion.String(), }, } diff --git a/cmd/kubeadm/app/phases/certs/BUILD b/cmd/kubeadm/app/phases/certs/BUILD index a138ced2e8a..c8a637aa156 100644 --- a/cmd/kubeadm/app/phases/certs/BUILD +++ b/cmd/kubeadm/app/phases/certs/BUILD @@ -16,9 +16,9 @@ go_test( deps = [ "//cmd/kubeadm/app/apis/kubeadm:go_default_library", "//cmd/kubeadm/app/constants:go_default_library", + "//cmd/kubeadm/app/util/certs:go_default_library", "//cmd/kubeadm/app/util/pkiutil:go_default_library", "//cmd/kubeadm/test:go_default_library", - "//cmd/kubeadm/test/certs:go_default_library", "//staging/src/k8s.io/client-go/util/cert:go_default_library", "//vendor/github.com/pkg/errors:go_default_library", "//vendor/github.com/stretchr/testify/assert:go_default_library", diff --git a/cmd/kubeadm/app/phases/certs/certs.go b/cmd/kubeadm/app/phases/certs/certs.go index e89176686e7..6a0e659be4d 100644 --- a/cmd/kubeadm/app/phases/certs/certs.go +++ b/cmd/kubeadm/app/phases/certs/certs.go @@ -59,11 +59,7 @@ func CreatePKIAssets(cfg *kubeadmapi.InitConfiguration) error { fmt.Printf("[certs] valid certificates and keys now exist in %q\n", cfg.CertificatesDir) // Service accounts are not x509 certs, so handled separately - if err := CreateServiceAccountKeyAndPublicKeyFiles(cfg); err != nil { - return err - } - - return nil + return CreateServiceAccountKeyAndPublicKeyFiles(cfg) } // CreateServiceAccountKeyAndPublicKeyFiles create a new public/private key files for signing service account users. @@ -134,7 +130,7 @@ func CreateCACertAndKeyFiles(certSpec *KubeadmCert, cfg *kubeadmapi.InitConfigur func NewCSR(certSpec *KubeadmCert, cfg *kubeadmapi.InitConfiguration) (*x509.CertificateRequest, *rsa.PrivateKey, error) { certConfig, err := certSpec.GetConfig(cfg) if err != nil { - return nil, nil, fmt.Errorf("failed to retrieve cert configuration: %v", err) + return nil, nil, errors.Wrap(err, "failed to retrieve cert configuration") } return pkiutil.NewCSRAndKey(certConfig) diff --git a/cmd/kubeadm/app/phases/certs/certs_test.go b/cmd/kubeadm/app/phases/certs/certs_test.go index d13416f3177..f83437de1f4 100644 --- a/cmd/kubeadm/app/phases/certs/certs_test.go +++ b/cmd/kubeadm/app/phases/certs/certs_test.go @@ -32,9 +32,9 @@ import ( certutil "k8s.io/client-go/util/cert" kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants" + certstestutil "k8s.io/kubernetes/cmd/kubeadm/app/util/certs" "k8s.io/kubernetes/cmd/kubeadm/app/util/pkiutil" testutil "k8s.io/kubernetes/cmd/kubeadm/test" - certstestutil "k8s.io/kubernetes/cmd/kubeadm/test/certs" ) func createTestCSR(t *testing.T) (*x509.CertificateRequest, *rsa.PrivateKey) { diff --git a/cmd/kubeadm/app/phases/certs/renewal/BUILD b/cmd/kubeadm/app/phases/certs/renewal/BUILD index 6172ca48370..98da00fd170 100644 --- a/cmd/kubeadm/app/phases/certs/renewal/BUILD +++ b/cmd/kubeadm/app/phases/certs/renewal/BUILD @@ -31,9 +31,9 @@ go_test( embed = [":go_default_library"], deps = [ "//cmd/kubeadm/app/phases/certs:go_default_library", + "//cmd/kubeadm/app/util/certs:go_default_library", "//cmd/kubeadm/app/util/pkiutil:go_default_library", "//cmd/kubeadm/test:go_default_library", - "//cmd/kubeadm/test/certs:go_default_library", "//staging/src/k8s.io/api/certificates/v1beta1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library", diff --git a/cmd/kubeadm/app/phases/certs/renewal/renewal_test.go b/cmd/kubeadm/app/phases/certs/renewal/renewal_test.go index 6b24c6f0606..199127862ce 100644 --- a/cmd/kubeadm/app/phases/certs/renewal/renewal_test.go +++ b/cmd/kubeadm/app/phases/certs/renewal/renewal_test.go @@ -33,9 +33,9 @@ import ( k8stesting "k8s.io/client-go/testing" certutil "k8s.io/client-go/util/cert" "k8s.io/kubernetes/cmd/kubeadm/app/phases/certs" + certtestutil "k8s.io/kubernetes/cmd/kubeadm/app/util/certs" "k8s.io/kubernetes/cmd/kubeadm/app/util/pkiutil" testutil "k8s.io/kubernetes/cmd/kubeadm/test" - certtestutil "k8s.io/kubernetes/cmd/kubeadm/test/certs" ) func TestRenewImplementations(t *testing.T) { diff --git a/cmd/kubeadm/app/phases/controlplane/manifests.go b/cmd/kubeadm/app/phases/controlplane/manifests.go index 0f618a8471f..56271314697 100644 --- a/cmd/kubeadm/app/phases/controlplane/manifests.go +++ b/cmd/kubeadm/app/phases/controlplane/manifests.go @@ -245,26 +245,26 @@ func calcNodeCidrSize(podSubnet string) string { // getControllerManagerCommand builds the right controller manager command from the given config object and version func getControllerManagerCommand(cfg *kubeadmapi.InitConfiguration, k8sVersion *version.Version) []string { + + kubeconfigFile := filepath.Join(kubeadmconstants.KubernetesDir, kubeadmconstants.ControllerManagerKubeConfigFileName) + caFile := filepath.Join(cfg.CertificatesDir, kubeadmconstants.CACertName) + defaultArguments := map[string]string{ - "address": "127.0.0.1", + "bind-address": "127.0.0.1", "leader-elect": "true", - "kubeconfig": filepath.Join(kubeadmconstants.KubernetesDir, kubeadmconstants.ControllerManagerKubeConfigFileName), - "root-ca-file": filepath.Join(cfg.CertificatesDir, kubeadmconstants.CACertName), + "kubeconfig": kubeconfigFile, + "authentication-kubeconfig": kubeconfigFile, + "authorization-kubeconfig": kubeconfigFile, + "client-ca-file": caFile, + "requestheader-client-ca-file": filepath.Join(cfg.CertificatesDir, kubeadmconstants.FrontProxyCACertName), + "root-ca-file": caFile, "service-account-private-key-file": filepath.Join(cfg.CertificatesDir, kubeadmconstants.ServiceAccountPrivateKeyName), - "cluster-signing-cert-file": filepath.Join(cfg.CertificatesDir, kubeadmconstants.CACertName), + "cluster-signing-cert-file": caFile, "cluster-signing-key-file": filepath.Join(cfg.CertificatesDir, kubeadmconstants.CAKeyName), "use-service-account-credentials": "true", "controllers": "*,bootstrapsigner,tokencleaner", } - //add the extra arguments for v1.12+ - if k8sVersion.Major() >= 1 && k8sVersion.Minor() >= 12 { - defaultArguments["authentication-kubeconfig"] = filepath.Join(kubeadmconstants.KubernetesDir, kubeadmconstants.ControllerManagerKubeConfigFileName) - defaultArguments["authorization-kubeconfig"] = filepath.Join(kubeadmconstants.KubernetesDir, kubeadmconstants.ControllerManagerKubeConfigFileName) - defaultArguments["client-ca-file"] = filepath.Join(cfg.CertificatesDir, kubeadmconstants.CACertName) - defaultArguments["requestheader-client-ca-file"] = filepath.Join(cfg.CertificatesDir, kubeadmconstants.FrontProxyCACertName) - } - // If using external CA, pass empty string to controller manager instead of ca.key/ca.crt path, // so that the csrsigning controller fails to start if res, _ := certphase.UsingExternalCA(cfg); res { @@ -290,7 +290,7 @@ func getControllerManagerCommand(cfg *kubeadmapi.InitConfiguration, k8sVersion * // getSchedulerCommand builds the right scheduler command from the given config object and version func getSchedulerCommand(cfg *kubeadmapi.InitConfiguration) []string { defaultArguments := map[string]string{ - "address": "127.0.0.1", + "bind-address": "127.0.0.1", "leader-elect": "true", "kubeconfig": filepath.Join(kubeadmconstants.KubernetesDir, kubeadmconstants.SchedulerKubeConfigFileName), } diff --git a/cmd/kubeadm/app/phases/controlplane/manifests_test.go b/cmd/kubeadm/app/phases/controlplane/manifests_test.go index fa45da80194..13be4fa6713 100644 --- a/cmd/kubeadm/app/phases/controlplane/manifests_test.go +++ b/cmd/kubeadm/app/phases/controlplane/manifests_test.go @@ -40,6 +40,8 @@ const ( etcdDataDir = "/var/lib/etcd" ) +var cpVersion = kubeadmconstants.MinimumControlPlaneVersion.WithPreRelease("beta.2").String() + func TestGetStaticPodSpecs(t *testing.T) { // Creates a Master Configuration @@ -180,45 +182,6 @@ func TestGetAPIServerCommand(t *testing.T) { "--etcd-keyfile=" + testCertsDir + "/apiserver-etcd-client.key", }, }, - { - name: "ignores the audit policy if the feature gate is not enabled", - cfg: &kubeadmapi.InitConfiguration{ - LocalAPIEndpoint: kubeadmapi.APIEndpoint{BindPort: 123, AdvertiseAddress: "4.3.2.1"}, - ClusterConfiguration: kubeadmapi.ClusterConfiguration{ - Networking: kubeadmapi.Networking{ServiceSubnet: "bar"}, - CertificatesDir: testCertsDir, - }, - }, - expected: []string{ - "kube-apiserver", - "--insecure-port=0", - "--enable-admission-plugins=NodeRestriction", - "--service-cluster-ip-range=bar", - "--service-account-key-file=" + testCertsDir + "/sa.pub", - "--client-ca-file=" + testCertsDir + "/ca.crt", - "--tls-cert-file=" + testCertsDir + "/apiserver.crt", - "--tls-private-key-file=" + testCertsDir + "/apiserver.key", - "--kubelet-client-certificate=" + testCertsDir + "/apiserver-kubelet-client.crt", - "--kubelet-client-key=" + testCertsDir + "/apiserver-kubelet-client.key", - "--enable-bootstrap-token-auth=true", - fmt.Sprintf("--secure-port=%d", 123), - "--allow-privileged=true", - "--kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname", - "--proxy-client-cert-file=/var/lib/certs/front-proxy-client.crt", - "--proxy-client-key-file=/var/lib/certs/front-proxy-client.key", - "--requestheader-username-headers=X-Remote-User", - "--requestheader-group-headers=X-Remote-Group", - "--requestheader-extra-headers-prefix=X-Remote-Extra-", - "--requestheader-client-ca-file=" + testCertsDir + "/front-proxy-ca.crt", - "--requestheader-allowed-names=front-proxy-client", - "--authorization-mode=Node,RBAC", - "--advertise-address=4.3.2.1", - fmt.Sprintf("--etcd-servers=https://127.0.0.1:%d", kubeadmconstants.EtcdListenClientPort), - "--etcd-cafile=" + testCertsDir + "/etcd/ca.crt", - "--etcd-certfile=" + testCertsDir + "/apiserver-etcd-client.crt", - "--etcd-keyfile=" + testCertsDir + "/apiserver-etcd-client.key", - }, - }, { name: "ipv6 advertise address", cfg: &kubeadmapi.InitConfiguration{ @@ -574,14 +537,14 @@ func TestGetControllerManagerCommand(t *testing.T) { expected []string }{ { - name: "custom certs dir for v1.12.0-beta.2", + name: "custom certs dir for " + cpVersion, cfg: &kubeadmapi.ClusterConfiguration{ CertificatesDir: testCertsDir, - KubernetesVersion: "v1.12.0-beta.2", + KubernetesVersion: cpVersion, }, expected: []string{ "kube-controller-manager", - "--address=127.0.0.1", + "--bind-address=127.0.0.1", "--leader-elect=true", "--kubeconfig=" + kubeadmconstants.KubernetesDir + "/controller-manager.conf", "--root-ca-file=" + testCertsDir + "/ca.crt", @@ -597,15 +560,15 @@ func TestGetControllerManagerCommand(t *testing.T) { }, }, { - name: "custom cluster-cidr for v1.12.0-beta.2", + name: "custom cluster-cidr for " + cpVersion, cfg: &kubeadmapi.ClusterConfiguration{ Networking: kubeadmapi.Networking{PodSubnet: "10.0.1.15/16"}, CertificatesDir: testCertsDir, - KubernetesVersion: "v1.12.0-beta.2", + KubernetesVersion: cpVersion, }, expected: []string{ "kube-controller-manager", - "--address=127.0.0.1", + "--bind-address=127.0.0.1", "--leader-elect=true", "--kubeconfig=" + kubeadmconstants.KubernetesDir + "/controller-manager.conf", "--root-ca-file=" + testCertsDir + "/ca.crt", @@ -624,18 +587,18 @@ func TestGetControllerManagerCommand(t *testing.T) { }, }, { - name: "custom extra-args for v1.12.0-beta.2", + name: "custom extra-args for " + cpVersion, cfg: &kubeadmapi.ClusterConfiguration{ Networking: kubeadmapi.Networking{PodSubnet: "10.0.1.15/16"}, ControllerManager: kubeadmapi.ControlPlaneComponent{ ExtraArgs: map[string]string{"node-cidr-mask-size": "20"}, }, CertificatesDir: testCertsDir, - KubernetesVersion: "v1.12.0-beta.2", + KubernetesVersion: cpVersion, }, expected: []string{ "kube-controller-manager", - "--address=127.0.0.1", + "--bind-address=127.0.0.1", "--leader-elect=true", "--kubeconfig=" + kubeadmconstants.KubernetesDir + "/controller-manager.conf", "--root-ca-file=" + testCertsDir + "/ca.crt", @@ -654,15 +617,15 @@ func TestGetControllerManagerCommand(t *testing.T) { }, }, { - name: "custom IPv6 networking for v1.12.0-beta.2", + name: "custom IPv6 networking for " + cpVersion, cfg: &kubeadmapi.ClusterConfiguration{ Networking: kubeadmapi.Networking{PodSubnet: "2001:db8::/64"}, CertificatesDir: testCertsDir, - KubernetesVersion: "v1.12.0-beta.2", + KubernetesVersion: cpVersion, }, expected: []string{ "kube-controller-manager", - "--address=127.0.0.1", + "--bind-address=127.0.0.1", "--leader-elect=true", "--kubeconfig=" + kubeadmconstants.KubernetesDir + "/controller-manager.conf", "--root-ca-file=" + testCertsDir + "/ca.crt", @@ -680,97 +643,6 @@ func TestGetControllerManagerCommand(t *testing.T) { "--node-cidr-mask-size=80", }, }, - { - name: "custom certs dir for v1.11.3", - cfg: &kubeadmapi.ClusterConfiguration{ - CertificatesDir: testCertsDir, - KubernetesVersion: "v1.11.3", - }, - expected: []string{ - "kube-controller-manager", - "--address=127.0.0.1", - "--leader-elect=true", - "--kubeconfig=" + kubeadmconstants.KubernetesDir + "/controller-manager.conf", - "--root-ca-file=" + testCertsDir + "/ca.crt", - "--service-account-private-key-file=" + testCertsDir + "/sa.key", - "--cluster-signing-cert-file=" + testCertsDir + "/ca.crt", - "--cluster-signing-key-file=" + testCertsDir + "/ca.key", - "--use-service-account-credentials=true", - "--controllers=*,bootstrapsigner,tokencleaner", - }, - }, - { - name: "custom cluster-cidr for v1.11.3", - cfg: &kubeadmapi.ClusterConfiguration{ - Networking: kubeadmapi.Networking{PodSubnet: "10.0.1.15/16"}, - CertificatesDir: testCertsDir, - KubernetesVersion: "v1.11.3", - }, - expected: []string{ - "kube-controller-manager", - "--address=127.0.0.1", - "--leader-elect=true", - "--kubeconfig=" + kubeadmconstants.KubernetesDir + "/controller-manager.conf", - "--root-ca-file=" + testCertsDir + "/ca.crt", - "--service-account-private-key-file=" + testCertsDir + "/sa.key", - "--cluster-signing-cert-file=" + testCertsDir + "/ca.crt", - "--cluster-signing-key-file=" + testCertsDir + "/ca.key", - "--use-service-account-credentials=true", - "--controllers=*,bootstrapsigner,tokencleaner", - "--allocate-node-cidrs=true", - "--cluster-cidr=10.0.1.15/16", - "--node-cidr-mask-size=24", - }, - }, - { - name: "custom extra-args for v1.11.3", - cfg: &kubeadmapi.ClusterConfiguration{ - Networking: kubeadmapi.Networking{PodSubnet: "10.0.1.15/16"}, - ControllerManager: kubeadmapi.ControlPlaneComponent{ - ExtraArgs: map[string]string{"node-cidr-mask-size": "20"}, - }, - CertificatesDir: testCertsDir, - KubernetesVersion: "v1.11.3", - }, - expected: []string{ - "kube-controller-manager", - "--address=127.0.0.1", - "--leader-elect=true", - "--kubeconfig=" + kubeadmconstants.KubernetesDir + "/controller-manager.conf", - "--root-ca-file=" + testCertsDir + "/ca.crt", - "--service-account-private-key-file=" + testCertsDir + "/sa.key", - "--cluster-signing-cert-file=" + testCertsDir + "/ca.crt", - "--cluster-signing-key-file=" + testCertsDir + "/ca.key", - "--use-service-account-credentials=true", - "--controllers=*,bootstrapsigner,tokencleaner", - "--allocate-node-cidrs=true", - "--cluster-cidr=10.0.1.15/16", - "--node-cidr-mask-size=20", - }, - }, - { - name: "custom IPv6 networking for v1.11.3", - cfg: &kubeadmapi.ClusterConfiguration{ - Networking: kubeadmapi.Networking{PodSubnet: "2001:db8::/64"}, - CertificatesDir: testCertsDir, - KubernetesVersion: "v1.11.3", - }, - expected: []string{ - "kube-controller-manager", - "--address=127.0.0.1", - "--leader-elect=true", - "--kubeconfig=" + kubeadmconstants.KubernetesDir + "/controller-manager.conf", - "--root-ca-file=" + testCertsDir + "/ca.crt", - "--service-account-private-key-file=" + testCertsDir + "/sa.key", - "--cluster-signing-cert-file=" + testCertsDir + "/ca.crt", - "--cluster-signing-key-file=" + testCertsDir + "/ca.key", - "--use-service-account-credentials=true", - "--controllers=*,bootstrapsigner,tokencleaner", - "--allocate-node-cidrs=true", - "--cluster-cidr=2001:db8::/64", - "--node-cidr-mask-size=80", - }, - }, } for _, rt := range tests { @@ -872,11 +744,11 @@ func TestGetControllerManagerCommandExternalCA(t *testing.T) { expectedArgFunc func(dir string) []string }{ { - name: "caKeyPresent-false for v1.12.0-beta.2", + name: "caKeyPresent-false for " + cpVersion, cfg: &kubeadmapi.InitConfiguration{ LocalAPIEndpoint: kubeadmapi.APIEndpoint{AdvertiseAddress: "1.2.3.4"}, ClusterConfiguration: kubeadmapi.ClusterConfiguration{ - KubernetesVersion: "v1.12.0-beta.2", + KubernetesVersion: cpVersion, Networking: kubeadmapi.Networking{ServiceSubnet: "10.96.0.0/12", DNSDomain: "cluster.local"}, }, }, @@ -884,7 +756,7 @@ func TestGetControllerManagerCommandExternalCA(t *testing.T) { expectedArgFunc: func(tmpdir string) []string { return []string{ "kube-controller-manager", - "--address=127.0.0.1", + "--bind-address=127.0.0.1", "--leader-elect=true", "--kubeconfig=" + kubeadmconstants.KubernetesDir + "/controller-manager.conf", "--root-ca-file=" + tmpdir + "/ca.crt", @@ -901,11 +773,11 @@ func TestGetControllerManagerCommandExternalCA(t *testing.T) { }, }, { - name: "caKeyPresent true for v1.12.0-beta.2", + name: "caKeyPresent true for " + cpVersion, cfg: &kubeadmapi.InitConfiguration{ LocalAPIEndpoint: kubeadmapi.APIEndpoint{AdvertiseAddress: "1.2.3.4"}, ClusterConfiguration: kubeadmapi.ClusterConfiguration{ - KubernetesVersion: "v1.12.0-beta.2", + KubernetesVersion: cpVersion, Networking: kubeadmapi.Networking{ServiceSubnet: "10.96.0.0/12", DNSDomain: "cluster.local"}, }, }, @@ -913,7 +785,7 @@ func TestGetControllerManagerCommandExternalCA(t *testing.T) { expectedArgFunc: func(tmpdir string) []string { return []string{ "kube-controller-manager", - "--address=127.0.0.1", + "--bind-address=127.0.0.1", "--leader-elect=true", "--kubeconfig=" + kubeadmconstants.KubernetesDir + "/controller-manager.conf", "--root-ca-file=" + tmpdir + "/ca.crt", @@ -929,56 +801,6 @@ func TestGetControllerManagerCommandExternalCA(t *testing.T) { } }, }, - { - name: "caKeyPresent-false for v1.11.3", - cfg: &kubeadmapi.InitConfiguration{ - LocalAPIEndpoint: kubeadmapi.APIEndpoint{AdvertiseAddress: "1.2.3.4"}, - ClusterConfiguration: kubeadmapi.ClusterConfiguration{ - KubernetesVersion: "v1.11.3", - Networking: kubeadmapi.Networking{ServiceSubnet: "10.96.0.0/12", DNSDomain: "cluster.local"}, - }, - }, - caKeyPresent: false, - expectedArgFunc: func(tmpdir string) []string { - return []string{ - "kube-controller-manager", - "--address=127.0.0.1", - "--leader-elect=true", - "--kubeconfig=" + kubeadmconstants.KubernetesDir + "/controller-manager.conf", - "--root-ca-file=" + tmpdir + "/ca.crt", - "--service-account-private-key-file=" + tmpdir + "/sa.key", - "--cluster-signing-cert-file=", - "--cluster-signing-key-file=", - "--use-service-account-credentials=true", - "--controllers=*,bootstrapsigner,tokencleaner", - } - }, - }, - { - name: "caKeyPresent true for v1.11.3", - cfg: &kubeadmapi.InitConfiguration{ - LocalAPIEndpoint: kubeadmapi.APIEndpoint{AdvertiseAddress: "1.2.3.4"}, - ClusterConfiguration: kubeadmapi.ClusterConfiguration{ - KubernetesVersion: "v1.11.3", - Networking: kubeadmapi.Networking{ServiceSubnet: "10.96.0.0/12", DNSDomain: "cluster.local"}, - }, - }, - caKeyPresent: true, - expectedArgFunc: func(tmpdir string) []string { - return []string{ - "kube-controller-manager", - "--address=127.0.0.1", - "--leader-elect=true", - "--kubeconfig=" + kubeadmconstants.KubernetesDir + "/controller-manager.conf", - "--root-ca-file=" + tmpdir + "/ca.crt", - "--service-account-private-key-file=" + tmpdir + "/sa.key", - "--cluster-signing-cert-file=" + tmpdir + "/ca.crt", - "--cluster-signing-key-file=" + tmpdir + "/ca.key", - "--use-service-account-credentials=true", - "--controllers=*,bootstrapsigner,tokencleaner", - } - }, - }, } for _, test := range tests { @@ -1022,7 +844,7 @@ func TestGetSchedulerCommand(t *testing.T) { cfg: &kubeadmapi.ClusterConfiguration{}, expected: []string{ "kube-scheduler", - "--address=127.0.0.1", + "--bind-address=127.0.0.1", "--leader-elect=true", "--kubeconfig=" + kubeadmconstants.KubernetesDir + "/scheduler.conf", }, diff --git a/cmd/kubeadm/app/phases/etcd/local.go b/cmd/kubeadm/app/phases/etcd/local.go index 6681d5a8106..c1b7eb565ad 100644 --- a/cmd/kubeadm/app/phases/etcd/local.go +++ b/cmd/kubeadm/app/phases/etcd/local.go @@ -18,6 +18,7 @@ package etcd import ( "fmt" + "os" "path/filepath" "strings" @@ -48,6 +49,12 @@ func CreateLocalEtcdStaticPodManifestFile(manifestDir string, cfg *kubeadmapi.In } // gets etcd StaticPodSpec emptyInitialCluster := []etcdutil.Member{} + + // creates target folder if not already exists + if err := os.MkdirAll(cfg.Etcd.Local.DataDir, 0700); err != nil { + return errors.Wrapf(err, "failed to create etcd directory %q", cfg.Etcd.Local.DataDir) + } + spec := GetEtcdPodSpec(cfg, emptyInitialCluster) // writes etcd StaticPod to disk if err := staticpodutil.WriteStaticPodToDisk(kubeadmconstants.Etcd, manifestDir, spec); err != nil { @@ -100,6 +107,11 @@ func CreateStackedEtcdStaticPodManifestFile(client clientset.Interface, manifest fmt.Println("[etcd] Announced new etcd member joining to the existing etcd cluster") klog.V(1).Infof("Updated etcd member list: %v", initialCluster) + // creates target folder if not already exists + if err := os.MkdirAll(cfg.Etcd.Local.DataDir, 0700); err != nil { + return errors.Wrapf(err, "failed to create etcd directory %q", cfg.Etcd.Local.DataDir) + } + klog.V(1).Info("Creating local etcd static pod manifest file") // gets etcd StaticPodSpec, actualized for the current InitConfiguration and the new list of etcd members spec := GetEtcdPodSpec(cfg, initialCluster) diff --git a/cmd/kubeadm/app/phases/etcd/local_test.go b/cmd/kubeadm/app/phases/etcd/local_test.go index e06ed677c89..8c2aa4ae30d 100644 --- a/cmd/kubeadm/app/phases/etcd/local_test.go +++ b/cmd/kubeadm/app/phases/etcd/local_test.go @@ -67,7 +67,7 @@ func TestCreateLocalEtcdStaticPodManifestFile(t *testing.T) { KubernetesVersion: "v1.7.0", Etcd: kubeadmapi.Etcd{ Local: &kubeadmapi.LocalEtcd{ - DataDir: "/var/lib/etcd", + DataDir: tmpdir + "/etcd", }, }, }, diff --git a/cmd/kubeadm/app/phases/kubeconfig/BUILD b/cmd/kubeadm/app/phases/kubeconfig/BUILD index c23e735b972..8df7d1038ec 100644 --- a/cmd/kubeadm/app/phases/kubeconfig/BUILD +++ b/cmd/kubeadm/app/phases/kubeconfig/BUILD @@ -48,9 +48,9 @@ go_test( "//cmd/kubeadm/app/apis/kubeadm:go_default_library", "//cmd/kubeadm/app/constants:go_default_library", "//cmd/kubeadm/app/util:go_default_library", + "//cmd/kubeadm/app/util/certs:go_default_library", "//cmd/kubeadm/app/util/pkiutil:go_default_library", "//cmd/kubeadm/test:go_default_library", - "//cmd/kubeadm/test/certs:go_default_library", "//cmd/kubeadm/test/kubeconfig:go_default_library", "//staging/src/k8s.io/client-go/tools/clientcmd:go_default_library", "//staging/src/k8s.io/client-go/tools/clientcmd/api:go_default_library", diff --git a/cmd/kubeadm/app/phases/kubeconfig/kubeconfig_test.go b/cmd/kubeadm/app/phases/kubeconfig/kubeconfig_test.go index 8416c672fc0..2d278d990f3 100644 --- a/cmd/kubeadm/app/phases/kubeconfig/kubeconfig_test.go +++ b/cmd/kubeadm/app/phases/kubeconfig/kubeconfig_test.go @@ -34,9 +34,9 @@ import ( kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants" kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util" + certstestutil "k8s.io/kubernetes/cmd/kubeadm/app/util/certs" pkiutil "k8s.io/kubernetes/cmd/kubeadm/app/util/pkiutil" testutil "k8s.io/kubernetes/cmd/kubeadm/test" - certstestutil "k8s.io/kubernetes/cmd/kubeadm/test/certs" kubeconfigtestutil "k8s.io/kubernetes/cmd/kubeadm/test/kubeconfig" ) diff --git a/cmd/kubeadm/app/phases/kubelet/BUILD b/cmd/kubeadm/app/phases/kubelet/BUILD index 537c9134b59..856542ed436 100644 --- a/cmd/kubeadm/app/phases/kubelet/BUILD +++ b/cmd/kubeadm/app/phases/kubelet/BUILD @@ -45,6 +45,7 @@ go_test( embed = [":go_default_library"], deps = [ "//cmd/kubeadm/app/apis/kubeadm:go_default_library", + "//cmd/kubeadm/app/constants:go_default_library", "//pkg/kubelet/apis:go_default_library", "//pkg/kubelet/apis/config:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library", @@ -53,6 +54,7 @@ go_test( "//staging/src/k8s.io/apimachinery/pkg/util/version:go_default_library", "//staging/src/k8s.io/client-go/kubernetes/fake:go_default_library", "//staging/src/k8s.io/client-go/testing:go_default_library", + "//vendor/github.com/pkg/errors:go_default_library", "//vendor/k8s.io/utils/exec:go_default_library", ], ) diff --git a/cmd/kubeadm/app/phases/kubelet/config.go b/cmd/kubeadm/app/phases/kubelet/config.go index 8a88661c635..4797404220b 100644 --- a/cmd/kubeadm/app/phases/kubelet/config.go +++ b/cmd/kubeadm/app/phases/kubelet/config.go @@ -23,6 +23,7 @@ import ( "path/filepath" "github.com/pkg/errors" + "k8s.io/api/core/v1" rbac "k8s.io/api/rbac/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" diff --git a/cmd/kubeadm/app/phases/kubelet/config_test.go b/cmd/kubeadm/app/phases/kubelet/config_test.go index 3783423411e..e0fb858f4ec 100644 --- a/cmd/kubeadm/app/phases/kubelet/config_test.go +++ b/cmd/kubeadm/app/phases/kubelet/config_test.go @@ -26,6 +26,7 @@ import ( "k8s.io/client-go/kubernetes/fake" core "k8s.io/client-go/testing" kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" + "k8s.io/kubernetes/cmd/kubeadm/app/constants" kubeletconfig "k8s.io/kubernetes/pkg/kubelet/apis/config" ) @@ -35,7 +36,7 @@ func TestCreateConfigMap(t *testing.T) { cfg := &kubeadmapi.InitConfiguration{ NodeRegistration: kubeadmapi.NodeRegistrationOptions{Name: nodeName}, ClusterConfiguration: kubeadmapi.ClusterConfiguration{ - KubernetesVersion: "v1.13.0", + KubernetesVersion: constants.CurrentKubernetesVersion.String(), ComponentConfigs: kubeadmapi.ComponentConfigs{ Kubelet: &kubeletconfig.KubeletConfiguration{}, }, diff --git a/cmd/kubeadm/app/phases/kubelet/flags_test.go b/cmd/kubeadm/app/phases/kubelet/flags_test.go index 1b06330504c..4c4b44f288d 100644 --- a/cmd/kubeadm/app/phases/kubelet/flags_test.go +++ b/cmd/kubeadm/app/phases/kubelet/flags_test.go @@ -18,12 +18,13 @@ package kubelet import ( "context" - "errors" "io" "reflect" "strings" "testing" + "github.com/pkg/errors" + "k8s.io/api/core/v1" kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" "k8s.io/utils/exec" diff --git a/cmd/kubeadm/app/phases/selfhosting/podspec_mutation_test.go b/cmd/kubeadm/app/phases/selfhosting/podspec_mutation_test.go index 8f3e64164cf..1e8fbff899b 100644 --- a/cmd/kubeadm/app/phases/selfhosting/podspec_mutation_test.go +++ b/cmd/kubeadm/app/phases/selfhosting/podspec_mutation_test.go @@ -27,11 +27,13 @@ import ( func TestMutatePodSpec(t *testing.T) { var tests = []struct { + name string component string podSpec *v1.PodSpec expected v1.PodSpec }{ { + name: "mutate api server podspec", component: kubeadmconstants.KubeAPIServer, podSpec: &v1.PodSpec{ Containers: []v1.Container{ @@ -73,6 +75,7 @@ func TestMutatePodSpec(t *testing.T) { }, }, { + name: "mutate controller manager podspec", component: kubeadmconstants.KubeControllerManager, podSpec: &v1.PodSpec{}, expected: v1.PodSpec{ @@ -86,6 +89,7 @@ func TestMutatePodSpec(t *testing.T) { }, }, { + name: "mutate scheduler podspec", component: kubeadmconstants.KubeScheduler, podSpec: &v1.PodSpec{}, expected: v1.PodSpec{ @@ -101,20 +105,24 @@ func TestMutatePodSpec(t *testing.T) { } for _, rt := range tests { - mutatePodSpec(GetDefaultMutators(), rt.component, rt.podSpec) + t.Run(rt.name, func(t *testing.T) { + mutatePodSpec(GetDefaultMutators(), rt.component, rt.podSpec) - if !reflect.DeepEqual(*rt.podSpec, rt.expected) { - t.Errorf("failed mutatePodSpec:\nexpected:\n%v\nsaw:\n%v", rt.expected, *rt.podSpec) - } + if !reflect.DeepEqual(*rt.podSpec, rt.expected) { + t.Errorf("failed mutatePodSpec:\nexpected:\n%v\nsaw:\n%v", rt.expected, *rt.podSpec) + } + }) } } func TestAddNodeSelectorToPodSpec(t *testing.T) { var tests = []struct { + name string podSpec *v1.PodSpec expected v1.PodSpec }{ { + name: "empty podspec", podSpec: &v1.PodSpec{}, expected: v1.PodSpec{ NodeSelector: map[string]string{ @@ -123,6 +131,7 @@ func TestAddNodeSelectorToPodSpec(t *testing.T) { }, }, { + name: "podspec with a valid node selector", podSpec: &v1.PodSpec{ NodeSelector: map[string]string{ "foo": "bar", @@ -138,20 +147,24 @@ func TestAddNodeSelectorToPodSpec(t *testing.T) { } for _, rt := range tests { - addNodeSelectorToPodSpec(rt.podSpec) + t.Run(rt.name, func(t *testing.T) { + addNodeSelectorToPodSpec(rt.podSpec) - if !reflect.DeepEqual(*rt.podSpec, rt.expected) { - t.Errorf("failed addNodeSelectorToPodSpec:\nexpected:\n%v\nsaw:\n%v", rt.expected, *rt.podSpec) - } + if !reflect.DeepEqual(*rt.podSpec, rt.expected) { + t.Errorf("failed addNodeSelectorToPodSpec:\nexpected:\n%v\nsaw:\n%v", rt.expected, *rt.podSpec) + } + }) } } func TestSetMasterTolerationOnPodSpec(t *testing.T) { var tests = []struct { + name string podSpec *v1.PodSpec expected v1.PodSpec }{ { + name: "empty podspec", podSpec: &v1.PodSpec{}, expected: v1.PodSpec{ Tolerations: []v1.Toleration{ @@ -160,6 +173,7 @@ func TestSetMasterTolerationOnPodSpec(t *testing.T) { }, }, { + name: "podspec with a valid toleration", podSpec: &v1.PodSpec{ Tolerations: []v1.Toleration{ {Key: "foo", Value: "bar"}, @@ -175,26 +189,31 @@ func TestSetMasterTolerationOnPodSpec(t *testing.T) { } for _, rt := range tests { - setMasterTolerationOnPodSpec(rt.podSpec) + t.Run(rt.name, func(t *testing.T) { + setMasterTolerationOnPodSpec(rt.podSpec) - if !reflect.DeepEqual(*rt.podSpec, rt.expected) { - t.Errorf("failed setMasterTolerationOnPodSpec:\nexpected:\n%v\nsaw:\n%v", rt.expected, *rt.podSpec) - } + if !reflect.DeepEqual(*rt.podSpec, rt.expected) { + t.Errorf("failed setMasterTolerationOnPodSpec:\nexpected:\n%v\nsaw:\n%v", rt.expected, *rt.podSpec) + } + }) } } func TestSetRightDNSPolicyOnPodSpec(t *testing.T) { var tests = []struct { + name string podSpec *v1.PodSpec expected v1.PodSpec }{ { + name: "empty podspec", podSpec: &v1.PodSpec{}, expected: v1.PodSpec{ DNSPolicy: v1.DNSClusterFirstWithHostNet, }, }, { + name: "podspec with a v1.DNSClusterFirst policy", podSpec: &v1.PodSpec{ DNSPolicy: v1.DNSClusterFirst, }, @@ -205,20 +224,24 @@ func TestSetRightDNSPolicyOnPodSpec(t *testing.T) { } for _, rt := range tests { - setRightDNSPolicyOnPodSpec(rt.podSpec) + t.Run(rt.name, func(t *testing.T) { + setRightDNSPolicyOnPodSpec(rt.podSpec) - if !reflect.DeepEqual(*rt.podSpec, rt.expected) { - t.Errorf("failed setRightDNSPolicyOnPodSpec:\nexpected:\n%v\nsaw:\n%v", rt.expected, *rt.podSpec) - } + if !reflect.DeepEqual(*rt.podSpec, rt.expected) { + t.Errorf("failed setRightDNSPolicyOnPodSpec:\nexpected:\n%v\nsaw:\n%v", rt.expected, *rt.podSpec) + } + }) } } func TestSetHostIPOnPodSpec(t *testing.T) { var tests = []struct { + name string podSpec *v1.PodSpec expected v1.PodSpec }{ { + name: "set HOST_IP env var on a podspec", podSpec: &v1.PodSpec{ Containers: []v1.Container{ { @@ -254,21 +277,25 @@ func TestSetHostIPOnPodSpec(t *testing.T) { } for _, rt := range tests { - setHostIPOnPodSpec(rt.podSpec) + t.Run(rt.name, func(t *testing.T) { + setHostIPOnPodSpec(rt.podSpec) - if !reflect.DeepEqual(*rt.podSpec, rt.expected) { - t.Errorf("failed setHostIPOnPodSpec:\nexpected:\n%v\nsaw:\n%v", rt.expected, *rt.podSpec) - } + if !reflect.DeepEqual(*rt.podSpec, rt.expected) { + t.Errorf("failed setHostIPOnPodSpec:\nexpected:\n%v\nsaw:\n%v", rt.expected, *rt.podSpec) + } + }) } } func TestSetSelfHostedVolumesForAPIServer(t *testing.T) { hostPathDirectoryOrCreate := v1.HostPathDirectoryOrCreate var tests = []struct { + name string podSpec *v1.PodSpec expected v1.PodSpec }{ { + name: "set selfhosted volumes for api server", podSpec: &v1.PodSpec{ Containers: []v1.Container{ { @@ -346,13 +373,15 @@ func TestSetSelfHostedVolumesForAPIServer(t *testing.T) { } for _, rt := range tests { - setSelfHostedVolumesForAPIServer(rt.podSpec) - sort.Strings(rt.podSpec.Containers[0].Command) - sort.Strings(rt.expected.Containers[0].Command) + t.Run(rt.name, func(t *testing.T) { + setSelfHostedVolumesForAPIServer(rt.podSpec) + sort.Strings(rt.podSpec.Containers[0].Command) + sort.Strings(rt.expected.Containers[0].Command) - if !reflect.DeepEqual(*rt.podSpec, rt.expected) { - t.Errorf("failed setSelfHostedVolumesForAPIServer:\nexpected:\n%v\nsaw:\n%v", rt.expected, *rt.podSpec) - } + if !reflect.DeepEqual(*rt.podSpec, rt.expected) { + t.Errorf("failed setSelfHostedVolumesForAPIServer:\nexpected:\n%v\nsaw:\n%v", rt.expected, *rt.podSpec) + } + }) } } @@ -360,10 +389,12 @@ func TestSetSelfHostedVolumesForControllerManager(t *testing.T) { hostPathFileOrCreate := v1.HostPathFileOrCreate hostPathDirectoryOrCreate := v1.HostPathDirectoryOrCreate var tests = []struct { + name string podSpec *v1.PodSpec expected v1.PodSpec }{ { + name: "set selfhosted volumes for controller mananger", podSpec: &v1.PodSpec{ Containers: []v1.Container{ { @@ -464,23 +495,27 @@ func TestSetSelfHostedVolumesForControllerManager(t *testing.T) { } for _, rt := range tests { - setSelfHostedVolumesForControllerManager(rt.podSpec) - sort.Strings(rt.podSpec.Containers[0].Command) - sort.Strings(rt.expected.Containers[0].Command) + t.Run(rt.name, func(t *testing.T) { + setSelfHostedVolumesForControllerManager(rt.podSpec) + sort.Strings(rt.podSpec.Containers[0].Command) + sort.Strings(rt.expected.Containers[0].Command) - if !reflect.DeepEqual(*rt.podSpec, rt.expected) { - t.Errorf("failed setSelfHostedVolumesForControllerManager:\nexpected:\n%v\nsaw:\n%v", rt.expected, *rt.podSpec) - } + if !reflect.DeepEqual(*rt.podSpec, rt.expected) { + t.Errorf("failed setSelfHostedVolumesForControllerManager:\nexpected:\n%v\nsaw:\n%v", rt.expected, *rt.podSpec) + } + }) } } func TestSetSelfHostedVolumesForScheduler(t *testing.T) { hostPathFileOrCreate := v1.HostPathFileOrCreate var tests = []struct { + name string podSpec *v1.PodSpec expected v1.PodSpec }{ { + name: "set selfhosted volumes for scheduler", podSpec: &v1.PodSpec{ Containers: []v1.Container{ { @@ -534,12 +569,14 @@ func TestSetSelfHostedVolumesForScheduler(t *testing.T) { } for _, rt := range tests { - setSelfHostedVolumesForScheduler(rt.podSpec) - sort.Strings(rt.podSpec.Containers[0].Command) - sort.Strings(rt.expected.Containers[0].Command) + t.Run(rt.name, func(t *testing.T) { + setSelfHostedVolumesForScheduler(rt.podSpec) + sort.Strings(rt.podSpec.Containers[0].Command) + sort.Strings(rt.expected.Containers[0].Command) - if !reflect.DeepEqual(*rt.podSpec, rt.expected) { - t.Errorf("failed setSelfHostedVolumesForScheduler:\nexpected:\n%v\nsaw:\n%v", rt.expected, *rt.podSpec) - } + if !reflect.DeepEqual(*rt.podSpec, rt.expected) { + t.Errorf("failed setSelfHostedVolumesForScheduler:\nexpected:\n%v\nsaw:\n%v", rt.expected, *rt.podSpec) + } + }) } } diff --git a/cmd/kubeadm/app/phases/selfhosting/selfhosting_test.go b/cmd/kubeadm/app/phases/selfhosting/selfhosting_test.go index 9532367d413..c7ab648cf2b 100644 --- a/cmd/kubeadm/app/phases/selfhosting/selfhosting_test.go +++ b/cmd/kubeadm/app/phases/selfhosting/selfhosting_test.go @@ -223,7 +223,7 @@ spec: - --service-account-private-key-file=/etc/kubernetes/pki/sa.key - --cluster-signing-cert-file=/etc/kubernetes/pki/ca.crt - --cluster-signing-key-file=/etc/kubernetes/pki/ca.key - - --address=127.0.0.1 + - --bind-address=127.0.0.1 - --use-service-account-credentials=true image: k8s.gcr.io/kube-controller-manager-amd64:v1.7.4 livenessProbe: @@ -298,7 +298,7 @@ spec: - --service-account-private-key-file=/etc/kubernetes/pki/sa.key - --cluster-signing-cert-file=/etc/kubernetes/pki/ca.crt - --cluster-signing-key-file=/etc/kubernetes/pki/ca.key - - --address=127.0.0.1 + - --bind-address=127.0.0.1 - --use-service-account-credentials=true image: k8s.gcr.io/kube-controller-manager-amd64:v1.7.4 livenessProbe: @@ -372,7 +372,7 @@ spec: - kube-scheduler - --leader-elect=true - --kubeconfig=/etc/kubernetes/scheduler.conf - - --address=127.0.0.1 + - --bind-address=127.0.0.1 image: k8s.gcr.io/kube-scheduler-amd64:v1.7.4 livenessProbe: failureThreshold: 8 @@ -423,7 +423,7 @@ spec: - kube-scheduler - --leader-elect=true - --kubeconfig=/etc/kubernetes/scheduler.conf - - --address=127.0.0.1 + - --bind-address=127.0.0.1 image: k8s.gcr.io/kube-scheduler-amd64:v1.7.4 livenessProbe: failureThreshold: 8 @@ -488,41 +488,44 @@ func TestBuildDaemonSet(t *testing.T) { } for _, rt := range tests { - tempFile, err := createTempFileWithContent(rt.podBytes) - if err != nil { - t.Errorf("error creating tempfile with content:%v", err) - } - defer os.Remove(tempFile) + t.Run(rt.component, func(t *testing.T) { + tempFile, err := createTempFileWithContent(rt.podBytes) + if err != nil { + t.Errorf("error creating tempfile with content:%v", err) + } + defer os.Remove(tempFile) - podSpec, err := loadPodSpecFromFile(tempFile) - if err != nil { - t.Fatalf("couldn't load the specified Pod Spec") - } + podSpec, err := loadPodSpecFromFile(tempFile) + if err != nil { + t.Fatalf("couldn't load the specified Pod Spec") + } - ds := BuildDaemonSet(rt.component, podSpec, GetDefaultMutators()) - dsBytes, err := util.MarshalToYaml(ds, apps.SchemeGroupVersion) - if err != nil { - t.Fatalf("failed to marshal daemonset to YAML: %v", err) - } + ds := BuildDaemonSet(rt.component, podSpec, GetDefaultMutators()) + dsBytes, err := util.MarshalToYaml(ds, apps.SchemeGroupVersion) + if err != nil { + t.Fatalf("failed to marshal daemonset to YAML: %v", err) + } - if !bytes.Equal(dsBytes, rt.dsBytes) { - t.Errorf("failed TestBuildDaemonSet:\nexpected:\n%s\nsaw:\n%s", rt.dsBytes, dsBytes) - } + if !bytes.Equal(dsBytes, rt.dsBytes) { + t.Errorf("failed TestBuildDaemonSet:\nexpected:\n%s\nsaw:\n%s", rt.dsBytes, dsBytes) + } + }) } } func TestLoadPodSpecFromFile(t *testing.T) { tests := []struct { + name string content string expectError bool }{ { - // No content + name: "no content", content: "", expectError: true, }, { - // Good YAML + name: "valid YAML", content: ` apiVersion: v1 kind: Pod @@ -535,7 +538,7 @@ spec: expectError: false, }, { - // Good JSON + name: "valid JSON", content: ` { "apiVersion": "v1", @@ -554,7 +557,7 @@ spec: expectError: false, }, { - // Bad PodSpec + name: "incorrect PodSpec", content: ` apiVersion: v1 kind: Pod @@ -568,22 +571,26 @@ spec: } for _, rt := range tests { - tempFile, err := createTempFileWithContent([]byte(rt.content)) - if err != nil { - t.Errorf("error creating tempfile with content:%v", err) - } - defer os.Remove(tempFile) + t.Run(rt.name, func(t *testing.T) { + tempFile, err := createTempFileWithContent([]byte(rt.content)) + if err != nil { + t.Errorf("error creating tempfile with content:%v", err) + } + defer os.Remove(tempFile) - _, err = loadPodSpecFromFile(tempFile) - if (err != nil) != rt.expectError { - t.Errorf("failed TestLoadPodSpecFromFile:\nexpected error:\n%t\nsaw:\n%v", rt.expectError, err) - } + _, err = loadPodSpecFromFile(tempFile) + if (err != nil) != rt.expectError { + t.Errorf("failed TestLoadPodSpecFromFile:\nexpected error:\n%t\nsaw:\n%v", rt.expectError, err) + } + }) } - _, err := loadPodSpecFromFile("") - if err == nil { - t.Error("unexpected success: loadPodSpecFromFile should return error when no file is given") - } + t.Run("empty file name", func(t *testing.T) { + _, err := loadPodSpecFromFile("") + if err == nil { + t.Error("unexpected success: loadPodSpecFromFile should return error when no file is given") + } + }) } func createTempFileWithContent(content []byte) (string, error) { diff --git a/cmd/kubeadm/app/phases/selfhosting/selfhosting_volumes.go b/cmd/kubeadm/app/phases/selfhosting/selfhosting_volumes.go index 627fb01f043..d685b39fc8c 100644 --- a/cmd/kubeadm/app/phases/selfhosting/selfhosting_volumes.go +++ b/cmd/kubeadm/app/phases/selfhosting/selfhosting_volumes.go @@ -20,6 +20,7 @@ import ( "fmt" "io/ioutil" "path/filepath" + "strings" "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -128,6 +129,40 @@ func apiServerCertificatesVolumeSource() v1.VolumeSource { }, }, }, + { + Secret: &v1.SecretProjection{ + LocalObjectReference: v1.LocalObjectReference{ + Name: strings.Replace(kubeadmconstants.EtcdCACertAndKeyBaseName, "/", "-", -1), + }, + Items: []v1.KeyToPath{ + { + Key: v1.TLSCertKey, + Path: kubeadmconstants.EtcdCACertName, + }, + { + Key: v1.TLSPrivateKeyKey, + Path: kubeadmconstants.EtcdCAKeyName, + }, + }, + }, + }, + { + Secret: &v1.SecretProjection{ + LocalObjectReference: v1.LocalObjectReference{ + Name: kubeadmconstants.APIServerEtcdClientCertAndKeyBaseName, + }, + Items: []v1.KeyToPath{ + { + Key: v1.TLSCertKey, + Path: kubeadmconstants.APIServerEtcdClientCertName, + }, + { + Key: v1.TLSPrivateKeyKey, + Path: kubeadmconstants.APIServerEtcdClientKeyName, + }, + }, + }, + }, }, }, } @@ -175,7 +210,7 @@ func controllerManagerCertificatesVolumeSource() v1.VolumeSource { func kubeConfigVolumeSource(kubeconfigSecretName string) v1.VolumeSource { return v1.VolumeSource{ Secret: &v1.SecretVolumeSource{ - SecretName: kubeconfigSecretName, + SecretName: strings.Replace(kubeconfigSecretName, "/", "-", -1), }, } } @@ -294,5 +329,15 @@ func getTLSKeyPairs() []*tlsKeyPair { cert: kubeadmconstants.FrontProxyClientCertName, key: kubeadmconstants.FrontProxyClientKeyName, }, + { + name: strings.Replace(kubeadmconstants.EtcdCACertAndKeyBaseName, "/", "-", -1), + cert: kubeadmconstants.EtcdCACertName, + key: kubeadmconstants.EtcdCAKeyName, + }, + { + name: kubeadmconstants.APIServerEtcdClientCertAndKeyBaseName, + cert: kubeadmconstants.APIServerEtcdClientCertName, + key: kubeadmconstants.APIServerEtcdClientKeyName, + }, } } diff --git a/cmd/kubeadm/app/phases/upgrade/BUILD b/cmd/kubeadm/app/phases/upgrade/BUILD index d804a9e2e70..ffaae1e84c2 100644 --- a/cmd/kubeadm/app/phases/upgrade/BUILD +++ b/cmd/kubeadm/app/phases/upgrade/BUILD @@ -82,11 +82,11 @@ go_test( "//cmd/kubeadm/app/phases/controlplane:go_default_library", "//cmd/kubeadm/app/phases/etcd:go_default_library", "//cmd/kubeadm/app/util/apiclient:go_default_library", + "//cmd/kubeadm/app/util/certs:go_default_library", "//cmd/kubeadm/app/util/config:go_default_library", "//cmd/kubeadm/app/util/etcd:go_default_library", "//cmd/kubeadm/app/util/pkiutil:go_default_library", "//cmd/kubeadm/test:go_default_library", - "//cmd/kubeadm/test/certs:go_default_library", "//staging/src/k8s.io/api/apps/v1:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", diff --git a/cmd/kubeadm/app/phases/upgrade/compute_test.go b/cmd/kubeadm/app/phases/upgrade/compute_test.go index fd99f637e4c..3c6c3dcadd7 100644 --- a/cmd/kubeadm/app/phases/upgrade/compute_test.go +++ b/cmd/kubeadm/app/phases/upgrade/compute_test.go @@ -76,11 +76,9 @@ type fakeEtcdClient struct { mismatchedVersions bool } -func (f fakeEtcdClient) HasTLS() bool { return f.TLS } - func (f fakeEtcdClient) ClusterAvailable() (bool, error) { return true, nil } -func (f fakeEtcdClient) WaitForClusterAvailable(delay time.Duration, retries int, retryInterval time.Duration) (bool, error) { +func (f fakeEtcdClient) WaitForClusterAvailable(retries int, retryInterval time.Duration) (bool, error) { return true, nil } @@ -431,7 +429,7 @@ func TestGetAvailableUpgrades(t *testing.T) { stablePatchVersion: "v1.10.5", stableVersion: "v1.10.5", latestDevBranchVersion: "v1.11.0-beta.1", - latestVersion: "v1.12.0-alpha.0", + latestVersion: constants.MinimumControlPlaneVersion.WithPreRelease("alpha.0").String(), }, beforeDNSType: kubeadmapi.CoreDNS, beforeDNSVersion: "1.0.6", @@ -472,7 +470,7 @@ func TestGetAvailableUpgrades(t *testing.T) { stablePatchVersion: "v1.10.5", stableVersion: "v1.10.5", latestDevBranchVersion: "v1.11.0-rc.1", - latestVersion: "v1.12.0-alpha.1", + latestVersion: constants.MinimumControlPlaneVersion.WithPreRelease("alpha.1").String(), }, beforeDNSType: kubeadmapi.CoreDNS, beforeDNSVersion: "1.0.6", @@ -513,7 +511,7 @@ func TestGetAvailableUpgrades(t *testing.T) { stablePatchVersion: "v1.10.5", stableVersion: "v1.10.5", latestDevBranchVersion: "v1.11.6-rc.1", - latestVersion: "v1.12.1-alpha.0", + latestVersion: constants.MinimumControlPlaneVersion.WithPatch(1).WithPreRelease("alpha.0").String(), }, beforeDNSType: kubeadmapi.CoreDNS, beforeDNSVersion: "1.0.6", @@ -554,7 +552,7 @@ func TestGetAvailableUpgrades(t *testing.T) { stablePatchVersion: "v1.10.5", stableVersion: "v1.10.5", latestDevBranchVersion: "v1.11.0-rc.1", - latestVersion: "v1.12.0-alpha.2", + latestVersion: constants.MinimumControlPlaneVersion.WithPreRelease("alpha.2").String(), }, beforeDNSType: kubeadmapi.CoreDNS, beforeDNSVersion: "1.0.6", @@ -593,8 +591,8 @@ func TestGetAvailableUpgrades(t *testing.T) { EtcdVersion: "3.1.12", }, After: ClusterState{ - KubeVersion: "v1.12.0-alpha.2", - KubeadmVersion: "v1.12.0-alpha.2", + KubeVersion: constants.MinimumControlPlaneVersion.WithPreRelease("alpha.2").String(), + KubeadmVersion: constants.MinimumControlPlaneVersion.WithPreRelease("alpha.2").String(), DNSType: kubeadmapi.CoreDNS, DNSVersion: "1.2.6", EtcdVersion: "3.2.24", @@ -627,7 +625,7 @@ func TestGetAvailableUpgrades(t *testing.T) { clusterVersion: "v1.11.1", kubeletVersion: "v1.11.0", kubeadmVersion: "v1.11.1", - }, "v1.12.1"), + }, constants.MinimumControlPlaneVersion.WithPatch(1).String()), etcdClient: etcdClient, beforeDNSType: kubeadmapi.CoreDNS, beforeDNSVersion: "1.0.6", @@ -646,8 +644,8 @@ func TestGetAvailableUpgrades(t *testing.T) { EtcdVersion: "3.1.12", }, After: ClusterState{ - KubeVersion: "v1.12.1", - KubeadmVersion: "v1.12.1", + KubeVersion: constants.MinimumControlPlaneVersion.WithPatch(1).String(), + KubeadmVersion: constants.MinimumControlPlaneVersion.WithPatch(1).String(), DNSType: kubeadmapi.CoreDNS, DNSVersion: "1.2.6", EtcdVersion: "3.2.24", @@ -660,10 +658,10 @@ func TestGetAvailableUpgrades(t *testing.T) { vg: &fakeVersionGetter{ clusterVersion: "v1.11.2", kubeletVersion: "v1.11.2", // the kubelet are on the same version as the control plane - kubeadmVersion: "v1.12.0", + kubeadmVersion: constants.MinimumControlPlaneVersion.String(), - stablePatchVersion: "v1.12.0", - stableVersion: "v1.12.0", + stablePatchVersion: constants.MinimumControlPlaneVersion.String(), + stableVersion: constants.MinimumControlPlaneVersion.String(), }, etcdClient: etcdClient, beforeDNSType: kubeadmapi.KubeDNS, @@ -677,14 +675,14 @@ func TestGetAvailableUpgrades(t *testing.T) { KubeletVersions: map[string]uint16{ "v1.11.2": 1, }, - KubeadmVersion: "v1.12.0", + KubeadmVersion: constants.MinimumControlPlaneVersion.String(), DNSType: kubeadmapi.KubeDNS, DNSVersion: "1.14.7", EtcdVersion: "3.1.12", }, After: ClusterState{ - KubeVersion: "v1.12.0", - KubeadmVersion: "v1.12.0", + KubeVersion: constants.MinimumControlPlaneVersion.String(), + KubeadmVersion: constants.MinimumControlPlaneVersion.String(), DNSType: kubeadmapi.CoreDNS, DNSVersion: "1.2.6", EtcdVersion: "3.2.24", @@ -697,10 +695,10 @@ func TestGetAvailableUpgrades(t *testing.T) { vg: &fakeVersionGetter{ clusterVersion: "v1.11.2", kubeletVersion: "v1.11.2", // the kubelet are on the same version as the control plane - kubeadmVersion: "v1.12.0", + kubeadmVersion: constants.MinimumControlPlaneVersion.String(), - stablePatchVersion: "v1.12.0", - stableVersion: "v1.12.0", + stablePatchVersion: constants.MinimumControlPlaneVersion.String(), + stableVersion: constants.MinimumControlPlaneVersion.String(), }, etcdClient: etcdClient, beforeDNSType: kubeadmapi.KubeDNS, @@ -714,14 +712,14 @@ func TestGetAvailableUpgrades(t *testing.T) { KubeletVersions: map[string]uint16{ "v1.11.2": 1, }, - KubeadmVersion: "v1.12.0", + KubeadmVersion: constants.MinimumControlPlaneVersion.String(), DNSType: kubeadmapi.KubeDNS, DNSVersion: "1.14.7", EtcdVersion: "3.1.12", }, After: ClusterState{ - KubeVersion: "v1.12.0", - KubeadmVersion: "v1.12.0", + KubeVersion: constants.MinimumControlPlaneVersion.String(), + KubeadmVersion: constants.MinimumControlPlaneVersion.String(), DNSType: kubeadmapi.KubeDNS, DNSVersion: "1.14.13", EtcdVersion: "3.2.24", @@ -783,18 +781,21 @@ func TestGetAvailableUpgrades(t *testing.T) { func TestKubeletUpgrade(t *testing.T) { tests := []struct { + name string before map[string]uint16 after string expected bool }{ - { // upgrade available + { + name: "upgrade from v1.10.1 to v1.10.3 is available", before: map[string]uint16{ "v1.10.1": 1, }, after: "v1.10.3", expected: true, }, - { // upgrade available + { + name: "upgrade from v1.10.1 and v1.10.3/100 to v1.10.3 is available", before: map[string]uint16{ "v1.10.1": 1, "v1.10.3": 100, @@ -802,21 +803,24 @@ func TestKubeletUpgrade(t *testing.T) { after: "v1.10.3", expected: true, }, - { // upgrade not available + { + name: "upgrade from v1.10.3 to v1.10.3 is not available", before: map[string]uint16{ "v1.10.3": 1, }, after: "v1.10.3", expected: false, }, - { // upgrade not available + { + name: "upgrade from v1.10.3/100 to v1.10.3 is not available", before: map[string]uint16{ "v1.10.3": 100, }, after: "v1.10.3", expected: false, }, - { // upgrade not available if we don't know anything about the earlier state + { + name: "upgrade is not available if we don't know anything about the earlier state", before: map[string]uint16{}, after: "v1.10.3", expected: false, @@ -824,19 +828,20 @@ func TestKubeletUpgrade(t *testing.T) { } for _, rt := range tests { - - upgrade := Upgrade{ - Before: ClusterState{ - KubeletVersions: rt.before, - }, - After: ClusterState{ - KubeVersion: rt.after, - }, - } - actual := upgrade.CanUpgradeKubelets() - if actual != rt.expected { - t.Errorf("failed TestKubeletUpgrade\n\texpected: %t\n\tgot: %t\n\ttest object: %v", rt.expected, actual, upgrade) - } + t.Run(rt.name, func(t *testing.T) { + upgrade := Upgrade{ + Before: ClusterState{ + KubeletVersions: rt.before, + }, + After: ClusterState{ + KubeVersion: rt.after, + }, + } + actual := upgrade.CanUpgradeKubelets() + if actual != rt.expected { + t.Errorf("failed TestKubeletUpgrade\n\texpected: %t\n\tgot: %t\n\ttest object: %v", rt.expected, actual, upgrade) + } + }) } } @@ -862,7 +867,7 @@ func TestGetBranchFromVersion(t *testing.T) { expectedVersion: "1.9", }, { - version: "v1.12.5", + version: constants.MinimumControlPlaneVersion.WithPatch(5).String(), expectedVersion: "1.12", }, { @@ -885,10 +890,11 @@ func TestGetBranchFromVersion(t *testing.T) { } for _, tc := range testCases { - v := getBranchFromVersion(tc.version) - if v != tc.expectedVersion { - t.Errorf("expected version %s, got %s", tc.expectedVersion, v) - } + t.Run(tc.version, func(t *testing.T) { + v := getBranchFromVersion(tc.version) + if v != tc.expectedVersion { + t.Errorf("expected version %s, got %s", tc.expectedVersion, v) + } + }) } - } diff --git a/cmd/kubeadm/app/phases/upgrade/policy_test.go b/cmd/kubeadm/app/phases/upgrade/policy_test.go index 5808353c705..35fa7defa00 100644 --- a/cmd/kubeadm/app/phases/upgrade/policy_test.go +++ b/cmd/kubeadm/app/phases/upgrade/policy_test.go @@ -20,6 +20,7 @@ import ( "testing" "k8s.io/apimachinery/pkg/util/version" + "k8s.io/kubernetes/cmd/kubeadm/app/constants" ) func TestEnforceVersionPolicies(t *testing.T) { @@ -34,38 +35,38 @@ func TestEnforceVersionPolicies(t *testing.T) { { name: "minor upgrade", vg: &fakeVersionGetter{ - clusterVersion: "v1.12.3", - kubeletVersion: "v1.12.3", - kubeadmVersion: "v1.12.5", + clusterVersion: constants.MinimumControlPlaneVersion.WithPatch(3).String(), + kubeletVersion: constants.MinimumControlPlaneVersion.WithPatch(3).String(), + kubeadmVersion: constants.MinimumControlPlaneVersion.WithPatch(5).String(), }, - newK8sVersion: "v1.12.5", + newK8sVersion: constants.MinimumControlPlaneVersion.WithPatch(5).String(), }, { name: "major upgrade", vg: &fakeVersionGetter{ - clusterVersion: "v1.12.3", - kubeletVersion: "v1.12.2", - kubeadmVersion: "v1.13.1", + clusterVersion: constants.MinimumControlPlaneVersion.WithPatch(3).String(), + kubeletVersion: constants.MinimumControlPlaneVersion.WithPatch(2).String(), + kubeadmVersion: constants.CurrentKubernetesVersion.WithPatch(1).String(), }, - newK8sVersion: "v1.13.0", + newK8sVersion: constants.CurrentKubernetesVersion.String(), }, { name: "downgrade", vg: &fakeVersionGetter{ - clusterVersion: "v1.12.3", - kubeletVersion: "v1.12.3", - kubeadmVersion: "v1.12.3", + clusterVersion: constants.MinimumControlPlaneVersion.WithPatch(3).String(), + kubeletVersion: constants.MinimumKubeletVersion.String(), + kubeadmVersion: constants.MinimumControlPlaneVersion.WithPatch(3).String(), }, - newK8sVersion: "v1.12.2", + newK8sVersion: constants.MinimumControlPlaneVersion.WithPatch(2).String(), }, { name: "same version upgrade", vg: &fakeVersionGetter{ - clusterVersion: "v1.12.3", - kubeletVersion: "v1.12.3", - kubeadmVersion: "v1.12.3", + clusterVersion: constants.MinimumControlPlaneVersion.WithPatch(3).String(), + kubeletVersion: constants.MinimumKubeletVersion.WithPatch(3).String(), + kubeadmVersion: constants.MinimumControlPlaneVersion.WithPatch(3).String(), }, - newK8sVersion: "v1.12.3", + newK8sVersion: constants.MinimumControlPlaneVersion.WithPatch(3).String(), }, { name: "new version must be higher than v1.10.0", @@ -83,9 +84,9 @@ func TestEnforceVersionPolicies(t *testing.T) { vg: &fakeVersionGetter{ clusterVersion: "v1.11.3", kubeletVersion: "v1.11.3", - kubeadmVersion: "v1.13.0", + kubeadmVersion: constants.CurrentKubernetesVersion.String(), }, - newK8sVersion: "v1.13.0", + newK8sVersion: constants.CurrentKubernetesVersion.String(), expectedMandatoryErrs: 1, // can't upgrade two minor versions expectedSkippableErrs: 1, // kubelet <-> apiserver skew too large }, @@ -96,99 +97,99 @@ func TestEnforceVersionPolicies(t *testing.T) { kubeletVersion: "v1.14.3", kubeadmVersion: "v1.14.0", }, - newK8sVersion: "v1.12.3", + newK8sVersion: constants.MinimumControlPlaneVersion.WithPatch(3).String(), expectedMandatoryErrs: 1, // can't downgrade two minor versions expectedSkippableErrs: 1, // can't upgrade old k8s with newer kubeadm }, { name: "kubeadm version must be higher than the new kube version. However, patch version skews may be forced", vg: &fakeVersionGetter{ - clusterVersion: "v1.12.3", - kubeletVersion: "v1.12.3", - kubeadmVersion: "v1.12.3", + clusterVersion: constants.MinimumControlPlaneVersion.WithPatch(3).String(), + kubeletVersion: constants.MinimumKubeletVersion.WithPatch(3).String(), + kubeadmVersion: constants.MinimumControlPlaneVersion.WithPatch(3).String(), }, - newK8sVersion: "v1.12.5", + newK8sVersion: constants.MinimumControlPlaneVersion.WithPatch(5).String(), expectedSkippableErrs: 1, }, { name: "kubeadm version must be higher than the new kube version. Trying to upgrade k8s to a higher minor version than kubeadm itself should never be supported", vg: &fakeVersionGetter{ - clusterVersion: "v1.12.3", - kubeletVersion: "v1.12.3", - kubeadmVersion: "v1.12.3", + clusterVersion: constants.MinimumControlPlaneVersion.WithPatch(3).String(), + kubeletVersion: constants.MinimumKubeletVersion.WithPatch(3).String(), + kubeadmVersion: constants.MinimumControlPlaneVersion.WithPatch(3).String(), }, - newK8sVersion: "v1.13.0", + newK8sVersion: constants.CurrentKubernetesVersion.String(), expectedMandatoryErrs: 1, }, { name: "the maximum skew between the cluster version and the kubelet versions should be one minor version. This may be forced through though.", vg: &fakeVersionGetter{ - clusterVersion: "v1.12.3", + clusterVersion: constants.MinimumControlPlaneVersion.WithPatch(3).String(), kubeletVersion: "v1.11.8", - kubeadmVersion: "v1.13.0", + kubeadmVersion: constants.CurrentKubernetesVersion.String(), }, - newK8sVersion: "v1.13.0", + newK8sVersion: constants.CurrentKubernetesVersion.String(), expectedSkippableErrs: 1, }, { name: "experimental upgrades supported if the flag is set", vg: &fakeVersionGetter{ - clusterVersion: "v1.12.3", - kubeletVersion: "v1.12.3", - kubeadmVersion: "v1.13.0-beta.1", + clusterVersion: constants.MinimumControlPlaneVersion.WithPatch(3).String(), + kubeletVersion: constants.MinimumKubeletVersion.WithPatch(3).String(), + kubeadmVersion: constants.CurrentKubernetesVersion.WithPreRelease("beta.1").String(), }, - newK8sVersion: "v1.13.0-beta.1", + newK8sVersion: constants.CurrentKubernetesVersion.WithPreRelease("beta.1").String(), allowExperimental: true, }, { name: "release candidate upgrades supported if the flag is set", vg: &fakeVersionGetter{ - clusterVersion: "v1.12.3", - kubeletVersion: "v1.12.3", - kubeadmVersion: "v1.13.0-rc.1", + clusterVersion: constants.MinimumControlPlaneVersion.WithPatch(3).String(), + kubeletVersion: constants.MinimumKubeletVersion.WithPatch(3).String(), + kubeadmVersion: constants.CurrentKubernetesVersion.WithPreRelease("rc.1").String(), }, - newK8sVersion: "v1.13.0-rc.1", + newK8sVersion: constants.CurrentKubernetesVersion.WithPreRelease("rc.1").String(), allowRCs: true, }, { name: "release candidate upgrades supported if the flag is set", vg: &fakeVersionGetter{ - clusterVersion: "v1.12.3", - kubeletVersion: "v1.12.3", - kubeadmVersion: "v1.13.0-rc.1", + clusterVersion: constants.MinimumControlPlaneVersion.WithPatch(3).String(), + kubeletVersion: constants.MinimumKubeletVersion.WithPatch(3).String(), + kubeadmVersion: constants.CurrentKubernetesVersion.WithPreRelease("rc.1").String(), }, - newK8sVersion: "v1.13.0-rc.1", + newK8sVersion: constants.CurrentKubernetesVersion.WithPreRelease("rc.1").String(), allowExperimental: true, }, { name: "the user should not be able to upgrade to an experimental version if they haven't opted into that", vg: &fakeVersionGetter{ - clusterVersion: "v1.12.3", - kubeletVersion: "v1.12.3", - kubeadmVersion: "v1.13.0-beta.1", + clusterVersion: constants.MinimumControlPlaneVersion.WithPatch(3).String(), + kubeletVersion: constants.MinimumKubeletVersion.WithPatch(3).String(), + kubeadmVersion: constants.CurrentKubernetesVersion.WithPreRelease("beta.1").String(), }, - newK8sVersion: "v1.13.0-beta.1", + newK8sVersion: constants.CurrentKubernetesVersion.WithPreRelease("beta.1").String(), allowRCs: true, expectedSkippableErrs: 1, }, { name: "the user should not be able to upgrade to an release candidate version if they haven't opted into that", vg: &fakeVersionGetter{ - clusterVersion: "v1.12.3", - kubeletVersion: "v1.12.3", - kubeadmVersion: "v1.13.0-rc.1", + clusterVersion: constants.MinimumControlPlaneVersion.WithPatch(3).String(), + kubeletVersion: constants.MinimumKubeletVersion.WithPatch(3).String(), + kubeadmVersion: constants.CurrentKubernetesVersion.WithPreRelease("rc.1").String(), }, - newK8sVersion: "v1.13.0-rc.1", + newK8sVersion: constants.CurrentKubernetesVersion.WithPreRelease("rc.1").String(), expectedSkippableErrs: 1, }, { name: "the user can't use a newer minor version of kubeadm to upgrade an older version of kubeadm", vg: &fakeVersionGetter{ - clusterVersion: "v1.12.3", - kubeletVersion: "v1.12.3", - kubeadmVersion: "v1.13.0", + clusterVersion: constants.MinimumControlPlaneVersion.WithPatch(3).String(), + kubeletVersion: constants.MinimumKubeletVersion.WithPatch(3).String(), + kubeadmVersion: constants.CurrentKubernetesVersion.String(), }, - newK8sVersion: "v1.12.6", + newK8sVersion: constants.MinimumControlPlaneVersion.WithPatch(6).String(), expectedSkippableErrs: 1, // can't upgrade old k8s with newer kubeadm }, } diff --git a/cmd/kubeadm/app/phases/upgrade/postupgrade.go b/cmd/kubeadm/app/phases/upgrade/postupgrade.go index 1e100eab8b2..8ed3db2beff 100644 --- a/cmd/kubeadm/app/phases/upgrade/postupgrade.go +++ b/cmd/kubeadm/app/phases/upgrade/postupgrade.go @@ -23,10 +23,11 @@ import ( "path/filepath" "time" - pkgerrors "github.com/pkg/errors" + "github.com/pkg/errors" + apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/util/errors" + errorsutil "k8s.io/apimachinery/pkg/util/errors" "k8s.io/apimachinery/pkg/util/version" clientset "k8s.io/client-go/kubernetes" certutil "k8s.io/client-go/util/cert" @@ -61,7 +62,7 @@ func PerformPostUpgradeTasks(client clientset.Interface, cfg *kubeadmapi.InitCon // Create the new, version-branched kubelet ComponentConfig ConfigMap if err := kubeletphase.CreateConfigMap(cfg, client); err != nil { - errs = append(errs, pkgerrors.Wrap(err, "error creating kubelet configuration ConfigMap")) + errs = append(errs, errors.Wrap(err, "error creating kubelet configuration ConfigMap")) } // Write the new kubelet config down to disk and the env file if needed @@ -73,7 +74,7 @@ func PerformPostUpgradeTasks(client clientset.Interface, cfg *kubeadmapi.InitCon // --cri-socket. // TODO: In the future we want to use something more official like NodeStatus or similar for detecting this properly if err := patchnodephase.AnnotateCRISocket(client, cfg.NodeRegistration.Name, cfg.NodeRegistration.CRISocket); err != nil { - errs = append(errs, pkgerrors.Wrap(err, "error uploading crisocket")) + errs = append(errs, errors.Wrap(err, "error uploading crisocket")) } // Create/update RBAC rules that makes the bootstrap tokens able to post CSRs @@ -118,7 +119,7 @@ func PerformPostUpgradeTasks(client clientset.Interface, cfg *kubeadmapi.InitCon if err := proxy.EnsureProxyAddon(cfg, client); err != nil { errs = append(errs, err) } - return errors.NewAggregate(errs) + return errorsutil.NewAggregate(errs) } func removeOldDNSDeploymentIfAnotherDNSIsUsed(cfg *kubeadmapi.InitConfiguration, client clientset.Interface, dryRun bool) error { @@ -138,7 +139,7 @@ func removeOldDNSDeploymentIfAnotherDNSIsUsed(cfg *kubeadmapi.InitConfiguration, return err } if dnsDeployment.Status.ReadyReplicas == 0 { - return pkgerrors.New("the DNS deployment isn't ready yet") + return errors.New("the DNS deployment isn't ready yet") } } @@ -158,7 +159,7 @@ func BackupAPIServerCertIfNeeded(cfg *kubeadmapi.InitConfiguration, dryRun bool) shouldBackup, err := shouldBackupAPIServerCertAndKey(certAndKeyDir) if err != nil { // Don't fail the upgrade phase if failing to determine to backup kube-apiserver cert and key. - return pkgerrors.Wrap(err, "[postupgrade] WARNING: failed to determine to backup kube-apiserver cert and key") + return errors.Wrap(err, "[postupgrade] WARNING: failed to determine to backup kube-apiserver cert and key") } if !shouldBackup { @@ -196,7 +197,7 @@ func writeKubeletConfigFiles(client clientset.Interface, cfg *kubeadmapi.InitCon // *would* post the new kubelet-config-1.X configmap that doesn't exist now when we're trying to download it // again. if !(apierrors.IsNotFound(err) && dryRun) { - errs = append(errs, pkgerrors.Wrap(err, "error downloading kubelet configuration from the ConfigMap")) + errs = append(errs, errors.Wrap(err, "error downloading kubelet configuration from the ConfigMap")) } } @@ -210,14 +211,14 @@ func writeKubeletConfigFiles(client clientset.Interface, cfg *kubeadmapi.InitCon // as we handle that ourselves in the markmaster phase // TODO: Maybe we want to do that some time in the future, in order to remove some logic from the markmaster phase? if err := kubeletphase.WriteKubeletDynamicEnvFile(cfg, false, kubeletDir); err != nil { - errs = append(errs, pkgerrors.Wrap(err, "error writing a dynamic environment file for the kubelet")) + errs = append(errs, errors.Wrap(err, "error writing a dynamic environment file for the kubelet")) } if dryRun { // Print what contents would be written dryrunutil.PrintDryRunFile(kubeadmconstants.KubeletEnvFileName, kubeletDir, kubeadmconstants.KubeletRunDirectory, os.Stdout) } } - return errors.NewAggregate(errs) + return errorsutil.NewAggregate(errs) } // getKubeletDir gets the kubelet directory based on whether the user is dry-running this command or not. @@ -233,7 +234,7 @@ func getKubeletDir(dryRun bool) (string, error) { func backupAPIServerCertAndKey(certAndKeyDir string) error { subDir := filepath.Join(certAndKeyDir, "expired") if err := os.Mkdir(subDir, 0766); err != nil { - return pkgerrors.Wrapf(err, "failed to created backup directory %s", subDir) + return errors.Wrapf(err, "failed to created backup directory %s", subDir) } filesToMove := map[string]string{ @@ -263,7 +264,7 @@ func rollbackFiles(files map[string]string, originalErr error) error { errs = append(errs, err) } } - return pkgerrors.Errorf("couldn't move these files: %v. Got errors: %v", files, errors.NewAggregate(errs)) + return errors.Errorf("couldn't move these files: %v. Got errors: %v", files, errorsutil.NewAggregate(errs)) } // shouldBackupAPIServerCertAndKey checks if the cert of kube-apiserver will be expired in 180 days. @@ -271,10 +272,10 @@ func shouldBackupAPIServerCertAndKey(certAndKeyDir string) (bool, error) { apiServerCert := filepath.Join(certAndKeyDir, kubeadmconstants.APIServerCertName) certs, err := certutil.CertsFromFile(apiServerCert) if err != nil { - return false, pkgerrors.Wrapf(err, "couldn't load the certificate file %s", apiServerCert) + return false, errors.Wrapf(err, "couldn't load the certificate file %s", apiServerCert) } if len(certs) == 0 { - return false, pkgerrors.New("no certificate data found") + return false, errors.New("no certificate data found") } if time.Now().Sub(certs[0].NotBefore) > expiry { diff --git a/cmd/kubeadm/app/phases/upgrade/postupgrade_test.go b/cmd/kubeadm/app/phases/upgrade/postupgrade_test.go index 6b2aebded55..bfd5ab70b9c 100644 --- a/cmd/kubeadm/app/phases/upgrade/postupgrade_test.go +++ b/cmd/kubeadm/app/phases/upgrade/postupgrade_test.go @@ -17,13 +17,14 @@ limitations under the License. package upgrade import ( - "errors" "os" "path/filepath" "strings" "testing" "time" + "github.com/pkg/errors" + kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" "k8s.io/kubernetes/cmd/kubeadm/app/constants" certsphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/certs" @@ -149,35 +150,37 @@ func TestShouldBackupAPIServerCertAndKey(t *testing.T) { expected: true, }, } { - tmpdir := testutil.SetupTempDir(t) - defer os.RemoveAll(tmpdir) - cfg.CertificatesDir = tmpdir + t.Run(desc, func(t *testing.T) { + tmpdir := testutil.SetupTempDir(t) + defer os.RemoveAll(tmpdir) + cfg.CertificatesDir = tmpdir - caCert, caKey, err := certsphase.KubeadmCertRootCA.CreateAsCA(cfg) - if err != nil { - t.Fatalf("failed creation of ca cert and key: %v", err) - } - caCert.NotBefore = caCert.NotBefore.Add(-test.adjustedExpiry).UTC() - - err = certsphase.KubeadmCertAPIServer.CreateFromCA(cfg, caCert, caKey) - if err != nil { - t.Fatalf("Test %s: failed creation of cert and key: %v", desc, err) - } - - certAndKey := []string{filepath.Join(tmpdir, constants.APIServerCertName), filepath.Join(tmpdir, constants.APIServerKeyName)} - for _, path := range certAndKey { - if _, err := os.Stat(path); os.IsNotExist(err) { - t.Fatalf("Test %s: %s not exist: %v", desc, path, err) + caCert, caKey, err := certsphase.KubeadmCertRootCA.CreateAsCA(cfg) + if err != nil { + t.Fatalf("failed creation of ca cert and key: %v", err) } - } + caCert.NotBefore = caCert.NotBefore.Add(-test.adjustedExpiry).UTC() - shouldBackup, err := shouldBackupAPIServerCertAndKey(tmpdir) - if err != nil { - t.Fatalf("Test %s: failed to check shouldBackupAPIServerCertAndKey: %v", desc, err) - } + err = certsphase.KubeadmCertAPIServer.CreateFromCA(cfg, caCert, caKey) + if err != nil { + t.Fatalf("Test %s: failed creation of cert and key: %v", desc, err) + } - if shouldBackup != test.expected { - t.Fatalf("Test %s: shouldBackupAPIServerCertAndKey expected %v, got %v", desc, test.expected, shouldBackup) - } + certAndKey := []string{filepath.Join(tmpdir, constants.APIServerCertName), filepath.Join(tmpdir, constants.APIServerKeyName)} + for _, path := range certAndKey { + if _, err := os.Stat(path); os.IsNotExist(err) { + t.Fatalf("Test %s: %s not exist: %v", desc, path, err) + } + } + + shouldBackup, err := shouldBackupAPIServerCertAndKey(tmpdir) + if err != nil { + t.Fatalf("Test %s: failed to check shouldBackupAPIServerCertAndKey: %v", desc, err) + } + + if shouldBackup != test.expected { + t.Fatalf("Test %s: shouldBackupAPIServerCertAndKey expected %v, got %v", desc, test.expected, shouldBackup) + } + }) } } diff --git a/cmd/kubeadm/app/phases/upgrade/prepull_test.go b/cmd/kubeadm/app/phases/upgrade/prepull_test.go index 5eb4af98cd8..6847d42afd1 100644 --- a/cmd/kubeadm/app/phases/upgrade/prepull_test.go +++ b/cmd/kubeadm/app/phases/upgrade/prepull_test.go @@ -108,26 +108,31 @@ func (p *goodPrepuller) DeleteFunc(component string) error { func TestPrepullImagesInParallel(t *testing.T) { tests := []struct { + name string p Prepuller timeout time.Duration expectedErr bool }{ - { // should error out; create failed + { + name: "should error out; create failed", p: NewFailedCreatePrepuller(), timeout: 10 * time.Second, expectedErr: true, }, - { // should error out; timeout exceeded + { + name: "should error out; timeout exceeded", p: NewForeverWaitPrepuller(), timeout: 10 * time.Second, expectedErr: true, }, - { // should error out; delete failed + { + name: "should error out; delete failed", p: NewFailedDeletePrepuller(), timeout: 10 * time.Second, expectedErr: true, }, - { // should work just fine + { + name: "should work just fine", p: NewGoodPrepuller(), timeout: 10 * time.Second, expectedErr: false, @@ -135,14 +140,15 @@ func TestPrepullImagesInParallel(t *testing.T) { } for _, rt := range tests { - - actualErr := PrepullImagesInParallel(rt.p, rt.timeout, append(constants.MasterComponents, constants.Etcd)) - if (actualErr != nil) != rt.expectedErr { - t.Errorf( - "failed TestPrepullImagesInParallel\n\texpected error: %t\n\tgot: %t", - rt.expectedErr, - (actualErr != nil), - ) - } + t.Run(rt.name, func(t *testing.T) { + actualErr := PrepullImagesInParallel(rt.p, rt.timeout, append(constants.MasterComponents, constants.Etcd)) + if (actualErr != nil) != rt.expectedErr { + t.Errorf( + "failed TestPrepullImagesInParallel\n\texpected error: %t\n\tgot: %t", + rt.expectedErr, + (actualErr != nil), + ) + } + }) } } diff --git a/cmd/kubeadm/app/phases/upgrade/staticpods.go b/cmd/kubeadm/app/phases/upgrade/staticpods.go index cc476549377..bcefea2f843 100644 --- a/cmd/kubeadm/app/phases/upgrade/staticpods.go +++ b/cmd/kubeadm/app/phases/upgrade/staticpods.go @@ -165,7 +165,7 @@ func (spm *KubeStaticPodPathManager) CleanupDirs() error { return nil } -func upgradeComponent(component string, waiter apiclient.Waiter, pathMgr StaticPodPathManager, cfg *kubeadmapi.InitConfiguration, beforePodHash string, recoverManifests map[string]string, isTLSUpgrade bool) error { +func upgradeComponent(component string, waiter apiclient.Waiter, pathMgr StaticPodPathManager, cfg *kubeadmapi.InitConfiguration, beforePodHash string, recoverManifests map[string]string) error { // Special treatment is required for etcd case, when rollbackOldManifests should roll back etcd // manifests only for the case when component is Etcd recoverEtcd := false @@ -173,21 +173,6 @@ func upgradeComponent(component string, waiter apiclient.Waiter, pathMgr StaticP if component == constants.Etcd { recoverEtcd = true } - if isTLSUpgrade { - // We currently depend on getting the Etcd mirror Pod hash from the KubeAPIServer; - // Upgrading the Etcd protocol takes down the apiserver, so we can't verify component restarts if we restart Etcd independently. - // Skip waiting for Etcd to restart and immediately move on to updating the apiserver. - if component == constants.Etcd { - waitForComponentRestart = false - } - // Normally, if an Etcd upgrade is successful, but the apiserver upgrade fails, Etcd is not rolled back. - // In the case of a TLS upgrade, the old KubeAPIServer config is incompatible with the new Etcd confg, so we rollback Etcd - // if the APIServer upgrade fails. - if component == constants.KubeAPIServer { - recoverEtcd = true - fmt.Printf("[upgrade/staticpods] The %s manifest will be restored if component %q fails to upgrade\n", constants.Etcd, component) - } - } if err := renewCerts(cfg, component); err != nil { return errors.Wrapf(err, "failed to renew certificates for component %q", component) @@ -252,7 +237,7 @@ func upgradeComponent(component string, waiter apiclient.Waiter, pathMgr StaticP } // performEtcdStaticPodUpgrade performs upgrade of etcd, it returns bool which indicates fatal error or not and the actual error. -func performEtcdStaticPodUpgrade(client clientset.Interface, waiter apiclient.Waiter, pathMgr StaticPodPathManager, cfg *kubeadmapi.InitConfiguration, recoverManifests map[string]string, isTLSUpgrade bool, oldEtcdClient, newEtcdClient etcdutil.ClusterInterrogator) (bool, error) { +func performEtcdStaticPodUpgrade(client clientset.Interface, waiter apiclient.Waiter, pathMgr StaticPodPathManager, cfg *kubeadmapi.InitConfiguration, recoverManifests map[string]string, oldEtcdClient, newEtcdClient etcdutil.ClusterInterrogator) (bool, error) { // Add etcd static pod spec only if external etcd is not configured if cfg.Etcd.External != nil { return false, errors.New("external etcd detected, won't try to change any etcd state") @@ -312,26 +297,16 @@ func performEtcdStaticPodUpgrade(client clientset.Interface, waiter apiclient.Wa return true, errors.Wrap(err, "error creating local etcd static pod manifest file") } - // Waiter configurations for checking etcd status - noDelay := 0 * time.Second - podRestartDelay := noDelay - if isTLSUpgrade { - // If we are upgrading TLS we need to wait for old static pod to be removed. - // This is needed because we are not able to currently verify that the static pod - // has been updated through the apiserver across an etcd TLS upgrade. - // This value is arbitrary but seems to be long enough in manual testing. - podRestartDelay = 30 * time.Second - } retries := 10 retryInterval := 15 * time.Second // Perform etcd upgrade using common to all control plane components function - if err := upgradeComponent(constants.Etcd, waiter, pathMgr, cfg, beforeEtcdPodHash, recoverManifests, isTLSUpgrade); err != nil { + if err := upgradeComponent(constants.Etcd, waiter, pathMgr, cfg, beforeEtcdPodHash, recoverManifests); err != nil { fmt.Printf("[upgrade/etcd] Failed to upgrade etcd: %v\n", err) // Since upgrade component failed, the old etcd manifest has either been restored or was never touched // Now we need to check the health of etcd cluster if it is up with old manifest fmt.Println("[upgrade/etcd] Waiting for previous etcd to become available") - if _, err := oldEtcdClient.WaitForClusterAvailable(noDelay, retries, retryInterval); err != nil { + if _, err := oldEtcdClient.WaitForClusterAvailable(retries, retryInterval); err != nil { fmt.Printf("[upgrade/etcd] Failed to healthcheck previous etcd: %v\n", err) // At this point we know that etcd cluster is dead and it is safe to copy backup datastore and to rollback old etcd manifest @@ -344,7 +319,7 @@ func performEtcdStaticPodUpgrade(client clientset.Interface, waiter apiclient.Wa // Now that we've rolled back the data, let's check if the cluster comes up fmt.Println("[upgrade/etcd] Waiting for previous etcd to become available") - if _, err := oldEtcdClient.WaitForClusterAvailable(noDelay, retries, retryInterval); err != nil { + if _, err := oldEtcdClient.WaitForClusterAvailable(retries, retryInterval); err != nil { fmt.Printf("[upgrade/etcd] Failed to healthcheck previous etcd: %v\n", err) // Nothing else left to try to recover etcd cluster return true, errors.Wrapf(err, "fatal error rolling back local etcd cluster manifest, the backup of etcd database is stored here:(%s)", backupEtcdDir) @@ -369,7 +344,7 @@ func performEtcdStaticPodUpgrade(client clientset.Interface, waiter apiclient.Wa // Checking health state of etcd after the upgrade fmt.Println("[upgrade/etcd] Waiting for etcd to become available") - if _, err = newEtcdClient.WaitForClusterAvailable(podRestartDelay, retries, retryInterval); err != nil { + if _, err = newEtcdClient.WaitForClusterAvailable(retries, retryInterval); err != nil { fmt.Printf("[upgrade/etcd] Failed to healthcheck etcd: %v\n", err) // Despite the fact that upgradeComponent was successful, there is something wrong with the etcd cluster // First step is to restore back up of datastore @@ -387,7 +362,7 @@ func performEtcdStaticPodUpgrade(client clientset.Interface, waiter apiclient.Wa // Assuming rollback of the old etcd manifest was successful, check the status of etcd cluster again fmt.Println("[upgrade/etcd] Waiting for previous etcd to become available") - if _, err := oldEtcdClient.WaitForClusterAvailable(noDelay, retries, retryInterval); err != nil { + if _, err := oldEtcdClient.WaitForClusterAvailable(retries, retryInterval); err != nil { fmt.Printf("[upgrade/etcd] Failed to healthcheck previous etcd: %v\n", err) // Nothing else left to try to recover etcd cluster return true, errors.Wrapf(err, "fatal error rolling back local etcd cluster manifest, the backup of etcd database is stored here:(%s)", backupEtcdDir) @@ -404,7 +379,6 @@ func performEtcdStaticPodUpgrade(client clientset.Interface, waiter apiclient.Wa // StaticPodControlPlane upgrades a static pod-hosted control plane func StaticPodControlPlane(client clientset.Interface, waiter apiclient.Waiter, pathMgr StaticPodPathManager, cfg *kubeadmapi.InitConfiguration, etcdUpgrade bool, oldEtcdClient, newEtcdClient etcdutil.ClusterInterrogator) error { recoverManifests := map[string]string{} - var isTLSUpgrade bool var isExternalEtcd bool beforePodHashMap, err := waiter.WaitForStaticPodControlPlaneHashes(cfg.NodeRegistration.Name) @@ -442,16 +416,11 @@ func StaticPodControlPlane(client clientset.Interface, waiter apiclient.Waiter, // etcd upgrade is done prior to other control plane components if !isExternalEtcd && etcdUpgrade { - previousEtcdHasTLS := oldEtcdClient.HasTLS() - // set the TLS upgrade flag for all components - isTLSUpgrade = !previousEtcdHasTLS - if isTLSUpgrade { - fmt.Printf("[upgrade/etcd] Upgrading to TLS for %s\n", constants.Etcd) - } + fmt.Printf("[upgrade/etcd] Upgrading to TLS for %s\n", constants.Etcd) // Perform etcd upgrade using common to all control plane components function - fatal, err := performEtcdStaticPodUpgrade(client, waiter, pathMgr, cfg, recoverManifests, isTLSUpgrade, oldEtcdClient, newEtcdClient) + fatal, err := performEtcdStaticPodUpgrade(client, waiter, pathMgr, cfg, recoverManifests, oldEtcdClient, newEtcdClient) if err != nil { if fatal { return err @@ -468,7 +437,7 @@ func StaticPodControlPlane(client clientset.Interface, waiter apiclient.Waiter, } for _, component := range constants.MasterComponents { - if err = upgradeComponent(component, waiter, pathMgr, cfg, beforePodHashMap[component], recoverManifests, isTLSUpgrade); err != nil { + if err = upgradeComponent(component, waiter, pathMgr, cfg, beforePodHashMap[component], recoverManifests); err != nil { return err } } diff --git a/cmd/kubeadm/app/phases/upgrade/staticpods_test.go b/cmd/kubeadm/app/phases/upgrade/staticpods_test.go index 9f58c369da2..81f7bc6fcf4 100644 --- a/cmd/kubeadm/app/phases/upgrade/staticpods_test.go +++ b/cmd/kubeadm/app/phases/upgrade/staticpods_test.go @@ -38,11 +38,11 @@ import ( controlplanephase "k8s.io/kubernetes/cmd/kubeadm/app/phases/controlplane" etcdphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/etcd" "k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient" + certstestutil "k8s.io/kubernetes/cmd/kubeadm/app/util/certs" configutil "k8s.io/kubernetes/cmd/kubeadm/app/util/config" etcdutil "k8s.io/kubernetes/cmd/kubeadm/app/util/etcd" "k8s.io/kubernetes/cmd/kubeadm/app/util/pkiutil" testutil "k8s.io/kubernetes/cmd/kubeadm/test" - certstestutil "k8s.io/kubernetes/cmd/kubeadm/test/certs" ) const ( @@ -228,13 +228,9 @@ func (spm *fakeStaticPodPathManager) CleanupDirs() error { type fakeTLSEtcdClient struct{ TLS bool } -func (c fakeTLSEtcdClient) HasTLS() bool { - return c.TLS -} - func (c fakeTLSEtcdClient) ClusterAvailable() (bool, error) { return true, nil } -func (c fakeTLSEtcdClient) WaitForClusterAvailable(delay time.Duration, retries int, retryInterval time.Duration) (bool, error) { +func (c fakeTLSEtcdClient) WaitForClusterAvailable(retries int, retryInterval time.Duration) (bool, error) { return true, nil } @@ -263,14 +259,9 @@ func (c fakeTLSEtcdClient) AddMember(name string, peerAddrs string) ([]etcdutil. type fakePodManifestEtcdClient struct{ ManifestDir, CertificatesDir string } -func (c fakePodManifestEtcdClient) HasTLS() bool { - hasTLS, _ := etcdutil.PodManifestsHaveTLS(c.ManifestDir) - return hasTLS -} - func (c fakePodManifestEtcdClient) ClusterAvailable() (bool, error) { return true, nil } -func (c fakePodManifestEtcdClient) WaitForClusterAvailable(delay time.Duration, retries int, retryInterval time.Duration) (bool, error) { +func (c fakePodManifestEtcdClient) WaitForClusterAvailable(retries int, retryInterval time.Duration) (bool, error) { return true, nil } @@ -421,116 +412,117 @@ func TestStaticPodControlPlane(t *testing.T) { } for _, rt := range tests { - waiter := NewFakeStaticPodWaiter(rt.waitErrsToReturn) - pathMgr, err := NewFakeStaticPodPathManager(rt.moveFileFunc) - if err != nil { - t.Fatalf("couldn't run NewFakeStaticPodPathManager: %v", err) - } - defer os.RemoveAll(pathMgr.(*fakeStaticPodPathManager).KubernetesDir()) - constants.KubernetesDir = pathMgr.(*fakeStaticPodPathManager).KubernetesDir() - - tempCertsDir, err := ioutil.TempDir("", "kubeadm-certs") - if err != nil { - t.Fatalf("couldn't create temporary certificates directory: %v", err) - } - defer os.RemoveAll(tempCertsDir) - tmpEtcdDataDir, err := ioutil.TempDir("", "kubeadm-etcd-data") - if err != nil { - t.Fatalf("couldn't create temporary etcd data directory: %v", err) - } - defer os.RemoveAll(tmpEtcdDataDir) - - oldcfg, err := getConfig("v1.12.0", tempCertsDir, tmpEtcdDataDir) - if err != nil { - t.Fatalf("couldn't create config: %v", err) - } - - tree, err := certsphase.GetCertsWithoutEtcd().AsMap().CertTree() - if err != nil { - t.Fatalf("couldn't get cert tree: %v", err) - } - - if err := tree.CreateTree(oldcfg); err != nil { - t.Fatalf("couldn't get create cert tree: %v", err) - } - - t.Logf("Wrote certs to %s\n", oldcfg.CertificatesDir) - - // Initialize the directory with v1.7 manifests; should then be upgraded to v1.8 using the method - err = controlplanephase.CreateInitStaticPodManifestFiles(pathMgr.RealManifestDir(), oldcfg) - if err != nil { - t.Fatalf("couldn't run CreateInitStaticPodManifestFiles: %v", err) - } - err = etcdphase.CreateLocalEtcdStaticPodManifestFile(pathMgr.RealManifestDir(), oldcfg) - if err != nil { - t.Fatalf("couldn't run CreateLocalEtcdStaticPodManifestFile: %v", err) - } - // Get a hash of the v1.7 API server manifest to compare later (was the file re-written) - oldHash, err := getAPIServerHash(pathMgr.RealManifestDir()) - if err != nil { - t.Fatalf("couldn't read temp file: %v", err) - } - - newcfg, err := getConfig("v1.13.0", tempCertsDir, tmpEtcdDataDir) - if err != nil { - t.Fatalf("couldn't create config: %v", err) - } - - // create the kubeadm etcd certs - caCert, caKey, err := certsphase.KubeadmCertEtcdCA.CreateAsCA(newcfg) - if err != nil { - t.Fatalf("couldn't create new CA certificate: %v", err) - } - for _, cert := range []*certsphase.KubeadmCert{ - &certsphase.KubeadmCertEtcdServer, - &certsphase.KubeadmCertEtcdPeer, - &certsphase.KubeadmCertEtcdHealthcheck, - &certsphase.KubeadmCertEtcdAPIClient, - } { - if err := cert.CreateFromCA(newcfg, caCert, caKey); err != nil { - t.Fatalf("couldn't create certificate %s: %v", cert.Name, err) + t.Run(rt.description, func(t *testing.T) { + waiter := NewFakeStaticPodWaiter(rt.waitErrsToReturn) + pathMgr, err := NewFakeStaticPodPathManager(rt.moveFileFunc) + if err != nil { + t.Fatalf("couldn't run NewFakeStaticPodPathManager: %v", err) } - } + defer os.RemoveAll(pathMgr.(*fakeStaticPodPathManager).KubernetesDir()) + constants.KubernetesDir = pathMgr.(*fakeStaticPodPathManager).KubernetesDir() - actualErr := StaticPodControlPlane( - nil, - waiter, - pathMgr, - newcfg, - true, - fakeTLSEtcdClient{ - TLS: false, - }, - fakePodManifestEtcdClient{ - ManifestDir: pathMgr.RealManifestDir(), - CertificatesDir: newcfg.CertificatesDir, - }, - ) - if (actualErr != nil) != rt.expectedErr { - t.Errorf( - "failed UpgradeStaticPodControlPlane\n%s\n\texpected error: %t\n\tgot: %t\n\tactual error: %v", - rt.description, - rt.expectedErr, - (actualErr != nil), - actualErr, + tempCertsDir, err := ioutil.TempDir("", "kubeadm-certs") + if err != nil { + t.Fatalf("couldn't create temporary certificates directory: %v", err) + } + defer os.RemoveAll(tempCertsDir) + tmpEtcdDataDir, err := ioutil.TempDir("", "kubeadm-etcd-data") + if err != nil { + t.Fatalf("couldn't create temporary etcd data directory: %v", err) + } + defer os.RemoveAll(tmpEtcdDataDir) + + oldcfg, err := getConfig(constants.MinimumControlPlaneVersion.String(), tempCertsDir, tmpEtcdDataDir) + if err != nil { + t.Fatalf("couldn't create config: %v", err) + } + + tree, err := certsphase.GetCertsWithoutEtcd().AsMap().CertTree() + if err != nil { + t.Fatalf("couldn't get cert tree: %v", err) + } + + if err := tree.CreateTree(oldcfg); err != nil { + t.Fatalf("couldn't get create cert tree: %v", err) + } + + t.Logf("Wrote certs to %s\n", oldcfg.CertificatesDir) + + // Initialize the directory with v1.7 manifests; should then be upgraded to v1.8 using the method + err = controlplanephase.CreateInitStaticPodManifestFiles(pathMgr.RealManifestDir(), oldcfg) + if err != nil { + t.Fatalf("couldn't run CreateInitStaticPodManifestFiles: %v", err) + } + err = etcdphase.CreateLocalEtcdStaticPodManifestFile(pathMgr.RealManifestDir(), oldcfg) + if err != nil { + t.Fatalf("couldn't run CreateLocalEtcdStaticPodManifestFile: %v", err) + } + // Get a hash of the v1.7 API server manifest to compare later (was the file re-written) + oldHash, err := getAPIServerHash(pathMgr.RealManifestDir()) + if err != nil { + t.Fatalf("couldn't read temp file: %v", err) + } + + newcfg, err := getConfig(constants.CurrentKubernetesVersion.String(), tempCertsDir, tmpEtcdDataDir) + if err != nil { + t.Fatalf("couldn't create config: %v", err) + } + + // create the kubeadm etcd certs + caCert, caKey, err := certsphase.KubeadmCertEtcdCA.CreateAsCA(newcfg) + if err != nil { + t.Fatalf("couldn't create new CA certificate: %v", err) + } + for _, cert := range []*certsphase.KubeadmCert{ + &certsphase.KubeadmCertEtcdServer, + &certsphase.KubeadmCertEtcdPeer, + &certsphase.KubeadmCertEtcdHealthcheck, + &certsphase.KubeadmCertEtcdAPIClient, + } { + if err := cert.CreateFromCA(newcfg, caCert, caKey); err != nil { + t.Fatalf("couldn't create certificate %s: %v", cert.Name, err) + } + } + + actualErr := StaticPodControlPlane( + nil, + waiter, + pathMgr, + newcfg, + true, + fakeTLSEtcdClient{ + TLS: false, + }, + fakePodManifestEtcdClient{ + ManifestDir: pathMgr.RealManifestDir(), + CertificatesDir: newcfg.CertificatesDir, + }, ) - } + if (actualErr != nil) != rt.expectedErr { + t.Errorf( + "failed UpgradeStaticPodControlPlane\n%s\n\texpected error: %t\n\tgot: %t\n\tactual error: %v", + rt.description, + rt.expectedErr, + (actualErr != nil), + actualErr, + ) + } - newHash, err := getAPIServerHash(pathMgr.RealManifestDir()) - if err != nil { - t.Fatalf("couldn't read temp file: %v", err) - } + newHash, err := getAPIServerHash(pathMgr.RealManifestDir()) + if err != nil { + t.Fatalf("couldn't read temp file: %v", err) + } - if (oldHash != newHash) != rt.manifestShouldChange { - t.Errorf( - "failed StaticPodControlPlane\n%s\n\texpected manifest change: %t\n\tgot: %t\n\tnewHash: %v", - rt.description, - rt.manifestShouldChange, - (oldHash != newHash), - newHash, - ) - } - return + if (oldHash != newHash) != rt.manifestShouldChange { + t.Errorf( + "failed StaticPodControlPlane\n%s\n\texpected manifest change: %t\n\tgot: %t\n\tnewHash: %v", + rt.description, + rt.manifestShouldChange, + (oldHash != newHash), + newHash, + ) + } + }) } } diff --git a/cmd/kubeadm/app/preflight/BUILD b/cmd/kubeadm/app/preflight/BUILD index 0c248791a57..39578e47cdc 100644 --- a/cmd/kubeadm/app/preflight/BUILD +++ b/cmd/kubeadm/app/preflight/BUILD @@ -46,6 +46,7 @@ go_test( deps = [ "//cmd/kubeadm/app/apis/kubeadm:go_default_library", "//cmd/kubeadm/app/apis/kubeadm/v1beta1:go_default_library", + "//cmd/kubeadm/app/constants:go_default_library", "//cmd/kubeadm/app/util/runtime:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library", "//vendor/github.com/pkg/errors:go_default_library", diff --git a/cmd/kubeadm/app/preflight/checks.go b/cmd/kubeadm/app/preflight/checks.go index a077722c70b..30de7209c1e 100644 --- a/cmd/kubeadm/app/preflight/checks.go +++ b/cmd/kubeadm/app/preflight/checks.go @@ -616,7 +616,7 @@ func (kubever KubeletVersionCheck) Check() (warnings, errorList []error) { return nil, []error{errors.Wrap(err, "couldn't get kubelet version")} } if kubeletVersion.LessThan(kubeadmconstants.MinimumKubeletVersion) { - return nil, []error{errors.Errorf("Kubelet version %q is lower than kubadm can support. Please upgrade kubelet", kubeletVersion)} + return nil, []error{errors.Errorf("Kubelet version %q is lower than kubeadm can support. Please upgrade kubelet", kubeletVersion)} } if kubever.KubernetesVersion != "" { diff --git a/cmd/kubeadm/app/preflight/checks_test.go b/cmd/kubeadm/app/preflight/checks_test.go index 8d1b3d881f3..3ec7a790598 100644 --- a/cmd/kubeadm/app/preflight/checks_test.go +++ b/cmd/kubeadm/app/preflight/checks_test.go @@ -18,6 +18,7 @@ package preflight import ( "bytes" + "fmt" "io/ioutil" "strings" "testing" @@ -31,6 +32,7 @@ import ( "k8s.io/apimachinery/pkg/util/sets" kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" kubeadmapiv1beta1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta1" + "k8s.io/kubernetes/cmd/kubeadm/app/constants" utilruntime "k8s.io/kubernetes/cmd/kubeadm/app/util/runtime" "k8s.io/utils/exec" fakeexec "k8s.io/utils/exec/testing" @@ -647,43 +649,43 @@ func TestKubeletVersionCheck(t *testing.T) { expectErrors bool expectWarnings bool }{ - {"v1.13.2", "", false, false}, // check minimally supported version when there is no information about control plane - {"v1.11.3", "v1.11.8", true, false}, // too old kubelet (older than kubeadmconstants.MinimumKubeletVersion), should fail. - {"v1.12.0", "v1.12.5", false, false}, // kubelet within same major.minor as control plane - {"v1.12.5", "v1.12.1", false, false}, // kubelet is newer, but still within same major.minor as control plane - {"v1.12.0", "v1.13.1", false, false}, // kubelet is lower than control plane, but newer than minimally supported - {"v1.13.0-alpha.1", "v1.12.1", true, false}, // kubelet is newer (development build) than control plane, should fail. - {"v1.13.0", "v1.12.5", true, false}, // kubelet is newer (release) than control plane, should fail. + {"v" + constants.CurrentKubernetesVersion.WithPatch(2).String(), "", false, false}, // check minimally supported version when there is no information about control plane + {"v1.11.3", "v1.11.8", true, false}, // too old kubelet (older than kubeadmconstants.MinimumKubeletVersion), should fail. + {"v" + constants.MinimumKubeletVersion.String(), constants.MinimumControlPlaneVersion.WithPatch(5).String(), false, false}, // kubelet within same major.minor as control plane + {"v" + constants.MinimumKubeletVersion.WithPatch(5).String(), constants.MinimumControlPlaneVersion.WithPatch(1).String(), false, false}, // kubelet is newer, but still within same major.minor as control plane + {"v" + constants.MinimumKubeletVersion.String(), constants.CurrentKubernetesVersion.WithPatch(1).String(), false, false}, // kubelet is lower than control plane, but newer than minimally supported + {"v" + constants.CurrentKubernetesVersion.WithPreRelease("alpha.1").String(), constants.MinimumControlPlaneVersion.WithPatch(1).String(), true, false}, // kubelet is newer (development build) than control plane, should fail. + {"v" + constants.CurrentKubernetesVersion.String(), constants.MinimumControlPlaneVersion.WithPatch(5).String(), true, false}, // kubelet is newer (release) than control plane, should fail. } for _, tc := range cases { - fcmd := fakeexec.FakeCmd{ - CombinedOutputScript: []fakeexec.FakeCombinedOutputAction{ - func() ([]byte, error) { return []byte("Kubernetes " + tc.kubeletVersion), nil }, - }, - } - fexec := &fakeexec.FakeExec{ - CommandScript: []fakeexec.FakeCommandAction{ - func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) }, - }, - } + t.Run(tc.kubeletVersion, func(t *testing.T) { + fcmd := fakeexec.FakeCmd{ + CombinedOutputScript: []fakeexec.FakeCombinedOutputAction{ + func() ([]byte, error) { return []byte("Kubernetes " + tc.kubeletVersion), nil }, + }, + } + fexec := &fakeexec.FakeExec{ + CommandScript: []fakeexec.FakeCommandAction{ + func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) }, + }, + } - check := KubeletVersionCheck{KubernetesVersion: tc.k8sVersion, exec: fexec} - warnings, errors := check.Check() - - switch { - case warnings != nil && !tc.expectWarnings: - t.Errorf("KubeletVersionCheck: unexpected warnings for kubelet version %q and Kubernetes version %q. Warnings: %v", tc.kubeletVersion, tc.k8sVersion, warnings) - case warnings == nil && tc.expectWarnings: - t.Errorf("KubeletVersionCheck: expected warnings for kubelet version %q and Kubernetes version %q but got nothing", tc.kubeletVersion, tc.k8sVersion) - case errors != nil && !tc.expectErrors: - t.Errorf("KubeletVersionCheck: unexpected errors for kubelet version %q and Kubernetes version %q. errors: %v", tc.kubeletVersion, tc.k8sVersion, errors) - case errors == nil && tc.expectErrors: - t.Errorf("KubeletVersionCheck: expected errors for kubelet version %q and Kubernetes version %q but got nothing", tc.kubeletVersion, tc.k8sVersion) - } + check := KubeletVersionCheck{KubernetesVersion: tc.k8sVersion, exec: fexec} + warnings, errors := check.Check() + switch { + case warnings != nil && !tc.expectWarnings: + t.Errorf("KubeletVersionCheck: unexpected warnings for kubelet version %q and Kubernetes version %q. Warnings: %v", tc.kubeletVersion, tc.k8sVersion, warnings) + case warnings == nil && tc.expectWarnings: + t.Errorf("KubeletVersionCheck: expected warnings for kubelet version %q and Kubernetes version %q but got nothing", tc.kubeletVersion, tc.k8sVersion) + case errors != nil && !tc.expectErrors: + t.Errorf("KubeletVersionCheck: unexpected errors for kubelet version %q and Kubernetes version %q. errors: %v", tc.kubeletVersion, tc.k8sVersion, errors) + case errors == nil && tc.expectErrors: + t.Errorf("KubeletVersionCheck: expected errors for kubelet version %q and Kubernetes version %q but got nothing", tc.kubeletVersion, tc.k8sVersion) + } + }) } - } func TestSetHasItemOrAll(t *testing.T) { @@ -701,15 +703,17 @@ func TestSetHasItemOrAll(t *testing.T) { } for _, rt := range tests { - result := setHasItemOrAll(rt.ignoreSet, rt.testString) - if result != rt.expectedResult { - t.Errorf( - "setHasItemOrAll: expected: %v actual: %v (arguments: %q, %q)", - rt.expectedResult, result, - rt.ignoreSet, - rt.testString, - ) - } + t.Run(rt.testString, func(t *testing.T) { + result := setHasItemOrAll(rt.ignoreSet, rt.testString) + if result != rt.expectedResult { + t.Errorf( + "setHasItemOrAll: expected: %v actual: %v (arguments: %q, %q)", + rt.expectedResult, result, + rt.ignoreSet, + rt.testString, + ) + } + }) } } @@ -789,12 +793,14 @@ func TestNumCPUCheck(t *testing.T) { } for _, rt := range tests { - warnings, errors := NumCPUCheck{NumCPU: rt.numCPU}.Check() - if len(warnings) != rt.numWarnings { - t.Errorf("expected %d warning(s) but got %d: %q", rt.numWarnings, len(warnings), warnings) - } - if len(errors) != rt.numErrors { - t.Errorf("expected %d warning(s) but got %d: %q", rt.numErrors, len(errors), errors) - } + t.Run(fmt.Sprintf("number of CPUs: %d", rt.numCPU), func(t *testing.T) { + warnings, errors := NumCPUCheck{NumCPU: rt.numCPU}.Check() + if len(warnings) != rt.numWarnings { + t.Errorf("expected %d warning(s) but got %d: %q", rt.numWarnings, len(warnings), warnings) + } + if len(errors) != rt.numErrors { + t.Errorf("expected %d warning(s) but got %d: %q", rt.numErrors, len(errors), errors) + } + }) } } diff --git a/cmd/kubeadm/app/preflight/utils_test.go b/cmd/kubeadm/app/preflight/utils_test.go index 608f841c567..b6f46ff8e58 100644 --- a/cmd/kubeadm/app/preflight/utils_test.go +++ b/cmd/kubeadm/app/preflight/utils_test.go @@ -40,26 +40,26 @@ func TestGetKubeletVersion(t *testing.T) { } for _, tc := range cases { - fcmd := fakeexec.FakeCmd{ - CombinedOutputScript: []fakeexec.FakeCombinedOutputAction{ - func() ([]byte, error) { return []byte(tc.output), tc.err }, - }, - } - fexec := &fakeexec.FakeExec{ - CommandScript: []fakeexec.FakeCommandAction{ - func(cmd string, args ...string) utilsexec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) }, - }, - } - ver, err := GetKubeletVersion(fexec) - switch { - case err != nil && tc.valid: - t.Errorf("GetKubeletVersion: unexpected error for %q. Error: %v", tc.output, err) - case err == nil && !tc.valid: - t.Errorf("GetKubeletVersion: error expected for key %q, but result is %q", tc.output, ver) - case ver != nil && ver.String() != tc.expected: - t.Errorf("GetKubeletVersion: unexpected version result for key %q. Expected: %q Actual: %q", tc.output, tc.expected, ver) - } - + t.Run(tc.output, func(t *testing.T) { + fcmd := fakeexec.FakeCmd{ + CombinedOutputScript: []fakeexec.FakeCombinedOutputAction{ + func() ([]byte, error) { return []byte(tc.output), tc.err }, + }, + } + fexec := &fakeexec.FakeExec{ + CommandScript: []fakeexec.FakeCommandAction{ + func(cmd string, args ...string) utilsexec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) }, + }, + } + ver, err := GetKubeletVersion(fexec) + switch { + case err != nil && tc.valid: + t.Errorf("GetKubeletVersion: unexpected error for %q. Error: %v", tc.output, err) + case err == nil && !tc.valid: + t.Errorf("GetKubeletVersion: error expected for key %q, but result is %q", tc.output, ver) + case ver != nil && ver.String() != tc.expected: + t.Errorf("GetKubeletVersion: unexpected version result for key %q. Expected: %q Actual: %q", tc.output, tc.expected, ver) + } + }) } - } diff --git a/cmd/kubeadm/app/util/BUILD b/cmd/kubeadm/app/util/BUILD index becafa093b2..7356f887c09 100644 --- a/cmd/kubeadm/app/util/BUILD +++ b/cmd/kubeadm/app/util/BUILD @@ -80,6 +80,7 @@ filegroup( ":package-srcs", "//cmd/kubeadm/app/util/apiclient:all-srcs", "//cmd/kubeadm/app/util/audit:all-srcs", + "//cmd/kubeadm/app/util/certs:all-srcs", "//cmd/kubeadm/app/util/config:all-srcs", "//cmd/kubeadm/app/util/dryrun:all-srcs", "//cmd/kubeadm/app/util/etcd:all-srcs", diff --git a/cmd/kubeadm/app/util/apiclient/clientbacked_dryrun.go b/cmd/kubeadm/app/util/apiclient/clientbacked_dryrun.go index a79080ee45d..a0673c52856 100644 --- a/cmd/kubeadm/app/util/apiclient/clientbacked_dryrun.go +++ b/cmd/kubeadm/app/util/apiclient/clientbacked_dryrun.go @@ -20,6 +20,8 @@ import ( "encoding/json" "fmt" + "github.com/pkg/errors" + apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -29,8 +31,6 @@ import ( "k8s.io/client-go/rest" core "k8s.io/client-go/testing" "k8s.io/client-go/tools/clientcmd" - - "github.com/pkg/errors" ) // ClientBackedDryRunGetter implements the DryRunGetter interface for use in NewDryRunClient() and proxies all GET and LIST requests to the backing API server reachable via rest.Config diff --git a/cmd/kubeadm/app/util/apiclient/dryrunclient_test.go b/cmd/kubeadm/app/util/apiclient/dryrunclient_test.go index d484c376a8f..7ef41c17585 100644 --- a/cmd/kubeadm/app/util/apiclient/dryrunclient_test.go +++ b/cmd/kubeadm/app/util/apiclient/dryrunclient_test.go @@ -29,28 +29,33 @@ import ( func TestLogDryRunAction(t *testing.T) { var tests = []struct { + name string action core.Action expectedBytes []byte buf *bytes.Buffer }{ { + name: "action GET on services", action: core.NewGetAction(schema.GroupVersionResource{Version: "v1", Resource: "services"}, "default", "kubernetes"), expectedBytes: []byte(`[dryrun] Would perform action GET on resource "services" in API group "core/v1" [dryrun] Resource name: "kubernetes" `), }, { + name: "action GET on clusterrolebindings", action: core.NewRootGetAction(schema.GroupVersionResource{Group: rbac.GroupName, Version: rbac.SchemeGroupVersion.Version, Resource: "clusterrolebindings"}, "system:node"), expectedBytes: []byte(`[dryrun] Would perform action GET on resource "clusterrolebindings" in API group "rbac.authorization.k8s.io/v1" [dryrun] Resource name: "system:node" `), }, { + name: "action LIST on services", action: core.NewListAction(schema.GroupVersionResource{Version: "v1", Resource: "services"}, schema.GroupVersionKind{Version: "v1", Kind: "Service"}, "default", metav1.ListOptions{}), expectedBytes: []byte(`[dryrun] Would perform action LIST on resource "services" in API group "core/v1" `), }, { + name: "action CREATE on services", action: core.NewCreateAction(schema.GroupVersionResource{Version: "v1", Resource: "services"}, "default", &v1.Service{ ObjectMeta: metav1.ObjectMeta{ Name: "foo", @@ -72,6 +77,7 @@ func TestLogDryRunAction(t *testing.T) { `), }, { + name: "action PATCH on nodes", action: core.NewPatchAction(schema.GroupVersionResource{Version: "v1", Resource: "nodes"}, "default", "my-node", "application/strategic-merge-patch+json", []byte(`{"spec":{"taints":[{"key": "foo", "value": "bar"}]}}`)), expectedBytes: []byte(`[dryrun] Would perform action PATCH on resource "nodes" in API group "core/v1" [dryrun] Resource name: "my-node" @@ -80,6 +86,7 @@ func TestLogDryRunAction(t *testing.T) { `), }, { + name: "action DELETE on pods", action: core.NewDeleteAction(schema.GroupVersionResource{Version: "v1", Resource: "pods"}, "default", "my-pod"), expectedBytes: []byte(`[dryrun] Would perform action DELETE on resource "pods" in API group "core/v1" [dryrun] Resource name: "my-pod" @@ -87,16 +94,18 @@ func TestLogDryRunAction(t *testing.T) { }, } for _, rt := range tests { - rt.buf = bytes.NewBufferString("") - logDryRunAction(rt.action, rt.buf, DefaultMarshalFunc) - actualBytes := rt.buf.Bytes() + t.Run(rt.name, func(t *testing.T) { + rt.buf = bytes.NewBufferString("") + logDryRunAction(rt.action, rt.buf, DefaultMarshalFunc) + actualBytes := rt.buf.Bytes() - if !bytes.Equal(actualBytes, rt.expectedBytes) { - t.Errorf( - "failed LogDryRunAction:\n\texpected bytes: %q\n\t actual: %q", - rt.expectedBytes, - actualBytes, - ) - } + if !bytes.Equal(actualBytes, rt.expectedBytes) { + t.Errorf( + "failed LogDryRunAction:\n\texpected bytes: %q\n\t actual: %q", + rt.expectedBytes, + actualBytes, + ) + } + }) } } diff --git a/cmd/kubeadm/app/util/apiclient/idempotency.go b/cmd/kubeadm/app/util/apiclient/idempotency.go index 450c4bd426d..02727c5a54c 100644 --- a/cmd/kubeadm/app/util/apiclient/idempotency.go +++ b/cmd/kubeadm/app/util/apiclient/idempotency.go @@ -21,6 +21,7 @@ import ( "fmt" "github.com/pkg/errors" + apps "k8s.io/api/apps/v1" "k8s.io/api/core/v1" rbac "k8s.io/api/rbac/v1" diff --git a/cmd/kubeadm/app/util/apiclient/idempotency_test.go b/cmd/kubeadm/app/util/apiclient/idempotency_test.go index 986eabdad4d..1564c7bcc29 100644 --- a/cmd/kubeadm/app/util/apiclient/idempotency_test.go +++ b/cmd/kubeadm/app/util/apiclient/idempotency_test.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package apiclient_test +package apiclient import ( "testing" @@ -22,7 +22,6 @@ import ( "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes/fake" - "k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient" kubeletapis "k8s.io/kubernetes/pkg/kubelet/apis" ) @@ -68,8 +67,10 @@ func TestPatchNodeNonErrorCases(t *testing.T) { if err != nil { t.Fatalf("failed to create node to fake client: %v", err) } - conditionFunction := apiclient.PatchNodeOnce(client, tc.lookupName, func(node *v1.Node) { - node.Name = "testNewNode" + conditionFunction := PatchNodeOnce(client, tc.lookupName, func(node *v1.Node) { + node.Annotations = map[string]string{ + "updatedBy": "test", + } }) success, err := conditionFunction() if err != nil { diff --git a/cmd/kubeadm/app/util/apiclient/init_dryrun_test.go b/cmd/kubeadm/app/util/apiclient/init_dryrun_test.go index d5f89dd2b76..3b82c84a8f9 100644 --- a/cmd/kubeadm/app/util/apiclient/init_dryrun_test.go +++ b/cmd/kubeadm/app/util/apiclient/init_dryrun_test.go @@ -32,54 +32,63 @@ func TestHandleGetAction(t *testing.T) { idr := NewInitDryRunGetter(masterName, serviceSubnet) var tests = []struct { + name string action core.GetActionImpl expectedHandled bool expectedObjectJSON []byte expectedErr bool }{ { + name: "get default services", action: core.NewGetAction(schema.GroupVersionResource{Version: "v1", Resource: "services"}, "default", "kubernetes"), expectedHandled: true, expectedObjectJSON: []byte(`{"metadata":{"name":"kubernetes","namespace":"default","creationTimestamp":null,"labels":{"component":"apiserver","provider":"kubernetes"}},"spec":{"ports":[{"name":"https","port":443,"targetPort":6443}],"clusterIP":"10.96.0.1"},"status":{"loadBalancer":{}}}`), expectedErr: false, }, { + name: "get nodes", action: core.NewRootGetAction(schema.GroupVersionResource{Version: "v1", Resource: "nodes"}, masterName), expectedHandled: true, expectedObjectJSON: []byte(`{"metadata":{"name":"master-foo","creationTimestamp":null,"labels":{"kubernetes.io/hostname":"master-foo"}},"spec":{},"status":{"daemonEndpoints":{"kubeletEndpoint":{"Port":0}},"nodeInfo":{"machineID":"","systemUUID":"","bootID":"","kernelVersion":"","osImage":"","containerRuntimeVersion":"","kubeletVersion":"","kubeProxyVersion":"","operatingSystem":"","architecture":""}}}`), expectedErr: false, }, { + name: "get clusterrolebinings", action: core.NewRootGetAction(schema.GroupVersionResource{Group: rbac.GroupName, Version: rbac.SchemeGroupVersion.Version, Resource: "clusterrolebindings"}, "system:node"), expectedHandled: true, expectedObjectJSON: []byte(``), expectedErr: true, // we expect a NotFound error here }, { + name: "get kube-system secret bootstrap-token-abcdef", action: core.NewGetAction(schema.GroupVersionResource{Version: "v1", Resource: "secrets"}, "kube-system", "bootstrap-token-abcdef"), expectedHandled: true, expectedObjectJSON: []byte(``), expectedErr: true, // we expect a NotFound error here }, { // an ask for a kubernetes service in the _kube-system_ ns should not be answered + name: "get kube-system services", action: core.NewGetAction(schema.GroupVersionResource{Version: "v1", Resource: "services"}, "kube-system", "kubernetes"), expectedHandled: false, expectedObjectJSON: []byte(``), expectedErr: false, }, { // an ask for an other service than kubernetes should not be answered + name: "get default my-other-service", action: core.NewGetAction(schema.GroupVersionResource{Version: "v1", Resource: "services"}, "default", "my-other-service"), expectedHandled: false, expectedObjectJSON: []byte(``), expectedErr: false, }, { // an ask for an other node than the master should not be answered + name: "get other-node", action: core.NewRootGetAction(schema.GroupVersionResource{Version: "v1", Resource: "nodes"}, "other-node"), expectedHandled: false, expectedObjectJSON: []byte(``), expectedErr: false, }, { // an ask for a secret in any other ns than kube-system should not be answered + name: "get default secret bootstrap-token-abcdef", action: core.NewGetAction(schema.GroupVersionResource{Version: "v1", Resource: "secrets"}, "default", "bootstrap-token-abcdef"), expectedHandled: false, expectedObjectJSON: []byte(``), @@ -87,40 +96,42 @@ func TestHandleGetAction(t *testing.T) { }, } for _, rt := range tests { - handled, obj, actualErr := idr.HandleGetAction(rt.action) - objBytes := []byte(``) - if obj != nil { - var err error - objBytes, err = json.Marshal(obj) - if err != nil { - t.Fatalf("couldn't marshal returned object") + t.Run(rt.name, func(t *testing.T) { + handled, obj, actualErr := idr.HandleGetAction(rt.action) + objBytes := []byte(``) + if obj != nil { + var err error + objBytes, err = json.Marshal(obj) + if err != nil { + t.Fatalf("couldn't marshal returned object") + } } - } - if handled != rt.expectedHandled { - t.Errorf( - "failed HandleGetAction:\n\texpected handled: %t\n\t actual: %t %v", - rt.expectedHandled, - handled, - rt.action, - ) - } + if handled != rt.expectedHandled { + t.Errorf( + "failed HandleGetAction:\n\texpected handled: %t\n\t actual: %t %v", + rt.expectedHandled, + handled, + rt.action, + ) + } - if !bytes.Equal(objBytes, rt.expectedObjectJSON) { - t.Errorf( - "failed HandleGetAction:\n\texpected object: %q\n\t actual: %q", - rt.expectedObjectJSON, - objBytes, - ) - } + if !bytes.Equal(objBytes, rt.expectedObjectJSON) { + t.Errorf( + "failed HandleGetAction:\n\texpected object: %q\n\t actual: %q", + rt.expectedObjectJSON, + objBytes, + ) + } - if (actualErr != nil) != rt.expectedErr { - t.Errorf( - "failed HandleGetAction:\n\texpected error: %t\n\t actual: %t %v", - rt.expectedErr, - (actualErr != nil), - rt.action, - ) - } + if (actualErr != nil) != rt.expectedErr { + t.Errorf( + "failed HandleGetAction:\n\texpected error: %t\n\t actual: %t %v", + rt.expectedErr, + (actualErr != nil), + rt.action, + ) + } + }) } } diff --git a/cmd/kubeadm/app/util/apiclient/wait.go b/cmd/kubeadm/app/util/apiclient/wait.go index b05d7b3dc03..91aee17be20 100644 --- a/cmd/kubeadm/app/util/apiclient/wait.go +++ b/cmd/kubeadm/app/util/apiclient/wait.go @@ -23,6 +23,7 @@ import ( "time" "github.com/pkg/errors" + "k8s.io/api/core/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" diff --git a/cmd/kubeadm/app/util/arguments_test.go b/cmd/kubeadm/app/util/arguments_test.go index fd8c724983d..48c93318e9e 100644 --- a/cmd/kubeadm/app/util/arguments_test.go +++ b/cmd/kubeadm/app/util/arguments_test.go @@ -24,11 +24,13 @@ import ( func TestBuildArgumentListFromMap(t *testing.T) { var tests = []struct { + name string base map[string]string overrides map[string]string expected []string }{ - { // override an argument from the base + { + name: "override an argument from the base", base: map[string]string{ "admission-control": "NamespaceLifecycle", "insecure-bind-address": "127.0.0.1", @@ -43,7 +45,8 @@ func TestBuildArgumentListFromMap(t *testing.T) { "--insecure-bind-address=127.0.0.1", }, }, - { // add an argument that is not in base + { + name: "add an argument that is not in base", base: map[string]string{ "insecure-bind-address": "127.0.0.1", "allow-privileged": "true", @@ -57,7 +60,8 @@ func TestBuildArgumentListFromMap(t *testing.T) { "--insecure-bind-address=127.0.0.1", }, }, - { // allow empty strings in base + { + name: "allow empty strings in base", base: map[string]string{ "insecure-bind-address": "127.0.0.1", "allow-privileged": "true", @@ -73,7 +77,8 @@ func TestBuildArgumentListFromMap(t *testing.T) { "--something-that-allows-empty-string=", }, }, - { // allow empty strings in overrides + { + name: "allow empty strings in overrides", base: map[string]string{ "insecure-bind-address": "127.0.0.1", "allow-privileged": "true", @@ -93,20 +98,23 @@ func TestBuildArgumentListFromMap(t *testing.T) { } for _, rt := range tests { - actual := BuildArgumentListFromMap(rt.base, rt.overrides) - if !reflect.DeepEqual(actual, rt.expected) { - t.Errorf("failed BuildArgumentListFromMap:\nexpected:\n%v\nsaw:\n%v", rt.expected, actual) - } + t.Run(rt.name, func(t *testing.T) { + actual := BuildArgumentListFromMap(rt.base, rt.overrides) + if !reflect.DeepEqual(actual, rt.expected) { + t.Errorf("failed BuildArgumentListFromMap:\nexpected:\n%v\nsaw:\n%v", rt.expected, actual) + } + }) } } func TestParseArgumentListToMap(t *testing.T) { var tests = []struct { + name string args []string expectedMap map[string]string }{ { - // normal case + name: "normal case", args: []string{ "--admission-control=NamespaceLifecycle,LimitRanger", "--insecure-bind-address=127.0.0.1", @@ -119,7 +127,7 @@ func TestParseArgumentListToMap(t *testing.T) { }, }, { - // test that feature-gates is working + name: "test that feature-gates is working", args: []string{ "--admission-control=NamespaceLifecycle,LimitRanger", "--insecure-bind-address=127.0.0.1", @@ -134,7 +142,7 @@ func TestParseArgumentListToMap(t *testing.T) { }, }, { - // test that a binary can be the first arg + name: "test that a binary can be the first arg", args: []string{ "kube-apiserver", "--admission-control=NamespaceLifecycle,LimitRanger", @@ -152,21 +160,24 @@ func TestParseArgumentListToMap(t *testing.T) { } for _, rt := range tests { - actualMap := ParseArgumentListToMap(rt.args) - if !reflect.DeepEqual(actualMap, rt.expectedMap) { - t.Errorf("failed ParseArgumentListToMap:\nexpected:\n%v\nsaw:\n%v", rt.expectedMap, actualMap) - } + t.Run(rt.name, func(t *testing.T) { + actualMap := ParseArgumentListToMap(rt.args) + if !reflect.DeepEqual(actualMap, rt.expectedMap) { + t.Errorf("failed ParseArgumentListToMap:\nexpected:\n%v\nsaw:\n%v", rt.expectedMap, actualMap) + } + }) } } func TestReplaceArgument(t *testing.T) { var tests = []struct { + name string args []string mutateFunc func(map[string]string) map[string]string expectedArgs []string }{ { - // normal case + name: "normal case", args: []string{ "kube-apiserver", "--admission-control=NamespaceLifecycle,LimitRanger", @@ -185,7 +196,7 @@ func TestReplaceArgument(t *testing.T) { }, }, { - // normal case + name: "another normal case", args: []string{ "kube-apiserver", "--admission-control=NamespaceLifecycle,LimitRanger", @@ -207,21 +218,24 @@ func TestReplaceArgument(t *testing.T) { } for _, rt := range tests { - actualArgs := ReplaceArgument(rt.args, rt.mutateFunc) - sort.Strings(actualArgs) - sort.Strings(rt.expectedArgs) - if !reflect.DeepEqual(actualArgs, rt.expectedArgs) { - t.Errorf("failed ReplaceArgument:\nexpected:\n%v\nsaw:\n%v", rt.expectedArgs, actualArgs) - } + t.Run(rt.name, func(t *testing.T) { + actualArgs := ReplaceArgument(rt.args, rt.mutateFunc) + sort.Strings(actualArgs) + sort.Strings(rt.expectedArgs) + if !reflect.DeepEqual(actualArgs, rt.expectedArgs) { + t.Errorf("failed ReplaceArgument:\nexpected:\n%v\nsaw:\n%v", rt.expectedArgs, actualArgs) + } + }) } } func TestRoundtrip(t *testing.T) { var tests = []struct { + name string args []string }{ { - // normal case + name: "normal case", args: []string{ "--admission-control=NamespaceLifecycle,LimitRanger", "--insecure-bind-address=127.0.0.1", @@ -229,7 +243,7 @@ func TestRoundtrip(t *testing.T) { }, }, { - // test that feature-gates is working + name: "test that feature-gates is working", args: []string{ "--admission-control=NamespaceLifecycle,LimitRanger", "--insecure-bind-address=127.0.0.1", @@ -240,86 +254,89 @@ func TestRoundtrip(t *testing.T) { } for _, rt := range tests { - // These two methods should be each other's opposite functions, test that by chaining the methods and see if you get the same result back - actual := BuildArgumentListFromMap(ParseArgumentListToMap(rt.args), map[string]string{}) - sort.Strings(actual) - sort.Strings(rt.args) + t.Run(rt.name, func(t *testing.T) { + // These two methods should be each other's opposite functions, test that by chaining the methods and see if you get the same result back + actual := BuildArgumentListFromMap(ParseArgumentListToMap(rt.args), map[string]string{}) + sort.Strings(actual) + sort.Strings(rt.args) - if !reflect.DeepEqual(actual, rt.args) { - t.Errorf("failed TestRoundtrip:\nexpected:\n%v\nsaw:\n%v", rt.args, actual) - } + if !reflect.DeepEqual(actual, rt.args) { + t.Errorf("failed TestRoundtrip:\nexpected:\n%v\nsaw:\n%v", rt.args, actual) + } + }) } } func TestParseArgument(t *testing.T) { var tests = []struct { + name string arg string expectedKey string expectedVal string expectedErr bool }{ { - // cannot be empty + name: "arg cannot be empty", arg: "", expectedErr: true, }, { - // must contain -- and = + name: "arg must contain -- and =", arg: "a", expectedErr: true, }, { - // must contain -- and = + name: "arg must contain -- and =", arg: "a-z", expectedErr: true, }, { - // must contain -- + name: "arg must contain --", arg: "a=b", expectedErr: true, }, { - // must contain a key + name: "arg must contain a key", arg: "--=b", expectedErr: true, }, { - // can contain key but no value + name: "arg can contain key but no value", arg: "--a=", expectedKey: "a", expectedVal: "", expectedErr: false, }, { - // simple case + name: "simple case", arg: "--a=b", expectedKey: "a", expectedVal: "b", expectedErr: false, }, { - // keys/values with '-' should be supported + name: "keys/values with '-' should be supported", arg: "--very-long-flag-name=some-value", expectedKey: "very-long-flag-name", expectedVal: "some-value", expectedErr: false, }, { - // numbers should be handled correctly + name: "numbers should be handled correctly", arg: "--some-number=0.2", expectedKey: "some-number", expectedVal: "0.2", expectedErr: false, }, { - // lists should be handled correctly + name: "lists should be handled correctly", arg: "--admission-control=foo,bar,baz", expectedKey: "admission-control", expectedVal: "foo,bar,baz", expectedErr: false, }, { - // more than one '=' should be allowed + name: "more than one '=' should be allowed", arg: "--feature-gates=EnableFoo=true,EnableBar=false", expectedKey: "feature-gates", expectedVal: "EnableFoo=true,EnableBar=false", @@ -328,12 +345,14 @@ func TestParseArgument(t *testing.T) { } for _, rt := range tests { - key, val, actual := parseArgument(rt.arg) - if (actual != nil) != rt.expectedErr { - t.Errorf("failed parseArgument:\nexpected error:\n%t\nsaw error:\n%v", rt.expectedErr, actual) - } - if (key != rt.expectedKey) || (val != rt.expectedVal) { - t.Errorf("failed parseArgument:\nexpected key: %s\nsaw key: %s\nexpected value: %s\nsaw value: %s", rt.expectedKey, key, rt.expectedVal, val) - } + t.Run(rt.name, func(t *testing.T) { + key, val, actual := parseArgument(rt.arg) + if (actual != nil) != rt.expectedErr { + t.Errorf("failed parseArgument:\nexpected error:\n%t\nsaw error:\n%v", rt.expectedErr, actual) + } + if (key != rt.expectedKey) || (val != rt.expectedVal) { + t.Errorf("failed parseArgument:\nexpected key: %s\nsaw key: %s\nexpected value: %s\nsaw value: %s", rt.expectedKey, key, rt.expectedVal, val) + } + }) } } diff --git a/cmd/kubeadm/test/certs/BUILD b/cmd/kubeadm/app/util/certs/BUILD similarity index 89% rename from cmd/kubeadm/test/certs/BUILD rename to cmd/kubeadm/app/util/certs/BUILD index 2bd48fc0e10..d3007e29a79 100644 --- a/cmd/kubeadm/test/certs/BUILD +++ b/cmd/kubeadm/app/util/certs/BUILD @@ -8,7 +8,7 @@ load( go_library( name = "go_default_library", srcs = ["util.go"], - importpath = "k8s.io/kubernetes/cmd/kubeadm/test/certs", + importpath = "k8s.io/kubernetes/cmd/kubeadm/app/util/certs", deps = [ "//cmd/kubeadm/app/util/pkiutil:go_default_library", "//staging/src/k8s.io/client-go/util/cert:go_default_library", diff --git a/cmd/kubeadm/test/certs/util.go b/cmd/kubeadm/app/util/certs/util.go similarity index 100% rename from cmd/kubeadm/test/certs/util.go rename to cmd/kubeadm/app/util/certs/util.go diff --git a/cmd/kubeadm/app/util/config/cluster.go b/cmd/kubeadm/app/util/config/cluster.go index d20c046a5b1..22147cf7eec 100644 --- a/cmd/kubeadm/app/util/config/cluster.go +++ b/cmd/kubeadm/app/util/config/cluster.go @@ -25,6 +25,7 @@ import ( "strings" "github.com/pkg/errors" + apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" diff --git a/cmd/kubeadm/app/util/config/cluster_test.go b/cmd/kubeadm/app/util/config/cluster_test.go index 5605ca6046a..1fcc7c72c58 100644 --- a/cmd/kubeadm/app/util/config/cluster_test.go +++ b/cmd/kubeadm/app/util/config/cluster_test.go @@ -34,7 +34,7 @@ import ( "k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient" ) -var k8sVersionString = "v1.12.0" +var k8sVersionString = kubeadmconstants.MinimumControlPlaneVersion.String() var k8sVersion = version.MustParseGeneric(k8sVersionString) var nodeName = "mynode" var cfgFiles = map[string][]byte{ diff --git a/cmd/kubeadm/app/util/config/initconfiguration.go b/cmd/kubeadm/app/util/config/initconfiguration.go index e425e0cdb63..eec7e28c6a1 100644 --- a/cmd/kubeadm/app/util/config/initconfiguration.go +++ b/cmd/kubeadm/app/util/config/initconfiguration.go @@ -54,10 +54,7 @@ func SetInitDynamicDefaults(cfg *kubeadmapi.InitConfiguration) error { if err := SetAPIEndpointDynamicDefaults(&cfg.LocalAPIEndpoint); err != nil { return err } - if err := SetClusterDynamicDefaults(&cfg.ClusterConfiguration, cfg.LocalAPIEndpoint.AdvertiseAddress, cfg.LocalAPIEndpoint.BindPort); err != nil { - return err - } - return nil + return SetClusterDynamicDefaults(&cfg.ClusterConfiguration, cfg.LocalAPIEndpoint.AdvertiseAddress, cfg.LocalAPIEndpoint.BindPort) } // SetBootstrapTokensDynamicDefaults checks and sets configuration values for the BootstrapTokens object diff --git a/cmd/kubeadm/app/util/config/joinconfiguration.go b/cmd/kubeadm/app/util/config/joinconfiguration.go index 168de0b509f..aa4d653075b 100644 --- a/cmd/kubeadm/app/util/config/joinconfiguration.go +++ b/cmd/kubeadm/app/util/config/joinconfiguration.go @@ -41,11 +41,7 @@ func SetJoinDynamicDefaults(cfg *kubeadmapi.JoinConfiguration) error { return err } - if err := SetJoinControlPlaneDefaults(cfg.ControlPlane); err != nil { - return err - } - - return nil + return SetJoinControlPlaneDefaults(cfg.ControlPlane) } // SetJoinControlPlaneDefaults checks and sets configuration values for the JoinControlPlane object diff --git a/cmd/kubeadm/app/util/dryrun/dryrun.go b/cmd/kubeadm/app/util/dryrun/dryrun.go index 4f09f0a0bb1..aec1584e378 100644 --- a/cmd/kubeadm/app/util/dryrun/dryrun.go +++ b/cmd/kubeadm/app/util/dryrun/dryrun.go @@ -24,7 +24,7 @@ import ( "time" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/util/errors" + errorsutil "k8s.io/apimachinery/pkg/util/errors" "k8s.io/kubernetes/cmd/kubeadm/app/constants" "k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient" ) @@ -76,7 +76,7 @@ func PrintDryRunFiles(files []FileToPrint, w io.Writer) error { fmt.Fprintf(w, "[dryrun] Would write file %q with content:\n", outputFilePath) apiclient.PrintBytesWithLinePrefix(w, fileBytes, "\t") } - return errors.NewAggregate(errs) + return errorsutil.NewAggregate(errs) } // Waiter is an implementation of apiclient.Waiter that should be used for dry-running diff --git a/cmd/kubeadm/app/util/endpoint.go b/cmd/kubeadm/app/util/endpoint.go index 8760aec6b0b..62746bf17db 100644 --- a/cmd/kubeadm/app/util/endpoint.go +++ b/cmd/kubeadm/app/util/endpoint.go @@ -95,7 +95,7 @@ func ParseHostPort(hostport string) (string, string, error) { // if port is defined, parse and validate it if port != "" { if _, err := ParsePort(port); err != nil { - return "", "", errors.New("port must be a valid number between 1 and 65535, inclusive") + return "", "", errors.Errorf("hostport %s: port %s must be a valid number between 1 and 65535, inclusive", hostport, port) } } @@ -109,7 +109,7 @@ func ParseHostPort(hostport string) (string, string, error) { return host, port, nil } - return "", "", errors.New("host must be a valid IP address or a valid RFC-1123 DNS subdomain") + return "", "", errors.Errorf("hostport %s: host '%s' must be a valid IP address or a valid RFC-1123 DNS subdomain", hostport, host) } // ParsePort parses a string representing a TCP port. diff --git a/cmd/kubeadm/app/util/endpoint_test.go b/cmd/kubeadm/app/util/endpoint_test.go index 21b5931ba77..c8412d07764 100644 --- a/cmd/kubeadm/app/util/endpoint_test.go +++ b/cmd/kubeadm/app/util/endpoint_test.go @@ -197,19 +197,21 @@ func TestGetMasterEndpoint(t *testing.T) { } for _, rt := range tests { - actualEndpoint, actualError := GetMasterEndpoint(rt.cfg) + t.Run(rt.name, func(t *testing.T) { + actualEndpoint, actualError := GetMasterEndpoint(rt.cfg) - if (actualError != nil) && !rt.expectedError { - t.Errorf("%s unexpected failure: %v", rt.name, actualError) - continue - } else if (actualError == nil) && rt.expectedError { - t.Errorf("%s passed when expected to fail", rt.name) - continue - } + if (actualError != nil) && !rt.expectedError { + t.Errorf("%s unexpected failure: %v", rt.name, actualError) + return + } else if (actualError == nil) && rt.expectedError { + t.Errorf("%s passed when expected to fail", rt.name) + return + } - if actualEndpoint != rt.expectedEndpoint { - t.Errorf("%s returned invalid endpoint %s, expected %s", rt.name, actualEndpoint, rt.expectedEndpoint) - } + if actualEndpoint != rt.expectedEndpoint { + t.Errorf("%s returned invalid endpoint %s, expected %s", rt.name, actualEndpoint, rt.expectedEndpoint) + } + }) } } @@ -316,24 +318,26 @@ func TestParseHostPort(t *testing.T) { } for _, rt := range tests { - actualHost, actualPort, actualError := ParseHostPort(rt.hostport) + t.Run(rt.name, func(t *testing.T) { + actualHost, actualPort, actualError := ParseHostPort(rt.hostport) - if (actualError != nil) && !rt.expectedError { - t.Errorf("%s unexpected failure: %v", rt.name, actualError) - continue - } else if (actualError == nil) && rt.expectedError { - t.Errorf("%s passed when expected to fail", rt.name) - continue - } + if (actualError != nil) && !rt.expectedError { + t.Errorf("%s unexpected failure: %v", rt.name, actualError) + return + } else if (actualError == nil) && rt.expectedError { + t.Errorf("%s passed when expected to fail", rt.name) + return + } - if actualHost != rt.expectedHost { - t.Errorf("%s returned invalid host %s, expected %s", rt.name, actualHost, rt.expectedHost) - continue - } + if actualHost != rt.expectedHost { + t.Errorf("%s returned invalid host %s, expected %s", rt.name, actualHost, rt.expectedHost) + return + } - if actualPort != rt.expectedPort { - t.Errorf("%s returned invalid port %s, expected %s", rt.name, actualPort, rt.expectedPort) - } + if actualPort != rt.expectedPort { + t.Errorf("%s returned invalid port %s, expected %s", rt.name, actualPort, rt.expectedPort) + } + }) } } @@ -368,18 +372,20 @@ func TestParsePort(t *testing.T) { } for _, rt := range tests { - actualPort, actualError := ParsePort(rt.port) + t.Run(rt.name, func(t *testing.T) { + actualPort, actualError := ParsePort(rt.port) - if (actualError != nil) && !rt.expectedError { - t.Errorf("%s unexpected failure: %v", rt.name, actualError) - continue - } else if (actualError == nil) && rt.expectedError { - t.Errorf("%s passed when expected to fail", rt.name) - continue - } + if (actualError != nil) && !rt.expectedError { + t.Errorf("%s unexpected failure: %v", rt.name, actualError) + return + } else if (actualError == nil) && rt.expectedError { + t.Errorf("%s passed when expected to fail", rt.name) + return + } - if actualPort != rt.expectedPort { - t.Errorf("%s returned invalid port %d, expected %d", rt.name, actualPort, rt.expectedPort) - } + if actualPort != rt.expectedPort { + t.Errorf("%s returned invalid port %d, expected %d", rt.name, actualPort, rt.expectedPort) + } + }) } } diff --git a/cmd/kubeadm/app/util/error.go b/cmd/kubeadm/app/util/error.go index 4eaf984fd4e..e026f71ebc1 100644 --- a/cmd/kubeadm/app/util/error.go +++ b/cmd/kubeadm/app/util/error.go @@ -21,7 +21,7 @@ import ( "os" "strings" - utilerrors "k8s.io/apimachinery/pkg/util/errors" + errorsutil "k8s.io/apimachinery/pkg/util/errors" ) const ( @@ -69,7 +69,7 @@ func checkErr(err error, handleErr func(string, int)) { return case preflightError: handleErr(err.Error(), PreFlightExitCode) - case utilerrors.Aggregate: + case errorsutil.Aggregate: handleErr(err.Error(), ValidationExitCode) default: diff --git a/cmd/kubeadm/app/util/error_test.go b/cmd/kubeadm/app/util/error_test.go index 2e19ffa46a2..5532ae866c5 100644 --- a/cmd/kubeadm/app/util/error_test.go +++ b/cmd/kubeadm/app/util/error_test.go @@ -31,25 +31,28 @@ func TestCheckErr(t *testing.T) { codeReturned = code } - var tokenTest = []struct { + var tests = []struct { + name string e error expected int }{ - {nil, 0}, - {errors.New(""), DefaultErrorExitCode}, - {&pferror{}, PreFlightExitCode}, + {"error is nil", nil, 0}, + {"empty error", errors.New(""), DefaultErrorExitCode}, + {"preflight error", &pferror{}, PreFlightExitCode}, } - for _, rt := range tokenTest { - codeReturned = 0 - checkErr(rt.e, errHandle) - if codeReturned != rt.expected { - t.Errorf( - "failed checkErr:\n\texpected: %d\n\t actual: %d", - rt.expected, - codeReturned, - ) - } + for _, rt := range tests { + t.Run(rt.name, func(t *testing.T) { + codeReturned = 0 + checkErr(rt.e, errHandle) + if codeReturned != rt.expected { + t.Errorf( + "failed checkErr:\n\texpected: %d\n\t actual: %d", + rt.expected, + codeReturned, + ) + } + }) } } @@ -58,10 +61,12 @@ func TestFormatErrMsg(t *testing.T) { errMsg2 := "specified version to upgrade to v1.9.0-alpha.3 is higher than the kubeadm version v1.9.0-alpha.1.3121+84178212527295-dirty. Upgrade kubeadm first using the tool you used to install kubeadm" testCases := []struct { + name string errs []error expect string }{ { + name: "two errors", errs: []error{ errors.New(errMsg1), errors.New(errMsg2), @@ -69,6 +74,7 @@ func TestFormatErrMsg(t *testing.T) { expect: "\t- " + errMsg1 + "\n" + "\t- " + errMsg2 + "\n", }, { + name: "one error", errs: []error{ errors.New(errMsg1), }, @@ -77,9 +83,11 @@ func TestFormatErrMsg(t *testing.T) { } for _, testCase := range testCases { - got := FormatErrMsg(testCase.errs) - if got != testCase.expect { - t.Errorf("FormatErrMsg error, expect: %v, got: %v", testCase.expect, got) - } + t.Run(testCase.name, func(t *testing.T) { + got := FormatErrMsg(testCase.errs) + if got != testCase.expect { + t.Errorf("FormatErrMsg error, expect: %v, got: %v", testCase.expect, got) + } + }) } } diff --git a/cmd/kubeadm/app/util/etcd/BUILD b/cmd/kubeadm/app/util/etcd/BUILD index adf2ff4f1b3..3168a0c50e3 100644 --- a/cmd/kubeadm/app/util/etcd/BUILD +++ b/cmd/kubeadm/app/util/etcd/BUILD @@ -9,7 +9,6 @@ go_library( "//cmd/kubeadm/app/apis/kubeadm:go_default_library", "//cmd/kubeadm/app/constants:go_default_library", "//cmd/kubeadm/app/util/config:go_default_library", - "//cmd/kubeadm/app/util/staticpod:go_default_library", "//staging/src/k8s.io/client-go/kubernetes:go_default_library", "//vendor/github.com/coreos/etcd/clientv3:go_default_library", "//vendor/github.com/coreos/etcd/pkg/transport:go_default_library", @@ -25,7 +24,6 @@ go_test( deps = [ "//cmd/kubeadm/app/apis/kubeadm:go_default_library", "//cmd/kubeadm/app/constants:go_default_library", - "//cmd/kubeadm/test:go_default_library", ], ) diff --git a/cmd/kubeadm/app/util/etcd/etcd.go b/cmd/kubeadm/app/util/etcd/etcd.go index 5fccce82a37..ef0ac4bd7c7 100644 --- a/cmd/kubeadm/app/util/etcd/etcd.go +++ b/cmd/kubeadm/app/util/etcd/etcd.go @@ -34,7 +34,6 @@ import ( kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" "k8s.io/kubernetes/cmd/kubeadm/app/constants" "k8s.io/kubernetes/cmd/kubeadm/app/util/config" - "k8s.io/kubernetes/cmd/kubeadm/app/util/staticpod" ) // ClusterInterrogator is an interface to get etcd cluster related information @@ -43,8 +42,7 @@ type ClusterInterrogator interface { GetClusterStatus() (map[string]*clientv3.StatusResponse, error) GetClusterVersions() (map[string]string, error) GetVersion() (string, error) - HasTLS() bool - WaitForClusterAvailable(delay time.Duration, retries int, retryInterval time.Duration) (bool, error) + WaitForClusterAvailable(retries int, retryInterval time.Duration) (bool, error) Sync() error AddMember(name string, peerAddrs string) ([]Member, error) } @@ -55,46 +53,6 @@ type Client struct { TLS *tls.Config } -// HasTLS returns true if etcd is configured for TLS -func (c Client) HasTLS() bool { - return c.TLS != nil -} - -// PodManifestsHaveTLS reads the etcd staticpod manifest from disk and returns false if the TLS flags -// are missing from the command list. If all the flags are present it returns true. -func PodManifestsHaveTLS(ManifestDir string) (bool, error) { - etcdPodPath := constants.GetStaticPodFilepath(constants.Etcd, ManifestDir) - etcdPod, err := staticpod.ReadStaticPodFromDisk(etcdPodPath) - if err != nil { - return false, errors.Wrap(err, "failed to check if etcd pod implements TLS") - } - - tlsFlags := []string{ - "--cert-file=", - "--key-file=", - "--trusted-ca-file=", - "--client-cert-auth=", - "--peer-cert-file=", - "--peer-key-file=", - "--peer-trusted-ca-file=", - "--peer-client-cert-auth=", - } -FlagLoop: - for _, flag := range tlsFlags { - for _, container := range etcdPod.Spec.Containers { - for _, arg := range container.Command { - if strings.Contains(arg, flag) { - continue FlagLoop - } - } - } - // flag not found in any container - return false, nil - } - // all flags were found in container args; pod fully implements TLS - return true, nil -} - // New creates a new EtcdCluster client func New(endpoints []string, ca, cert, key string) (*Client, error) { client := Client{Endpoints: endpoints} @@ -119,53 +77,8 @@ func New(endpoints []string, ca, cert, key string) (*Client, error) { // the kubeadm-config ConfigMap in kube-system namespace. // Once created, the client synchronizes client's endpoints with the known endpoints from the etcd membership API (reality check). func NewFromCluster(client clientset.Interface, certificatesDir string) (*Client, error) { - - // Kubeadm v1.13 should manage v1.12 clusters and v1.13 clusters - // v1.12 clusters can be have etcd listening on localhost only (if the cluster was created with kubeadm v1.12) - // or etcd listening on localhost and API server advertise address (if the cluster was created with kubeadm v1.13). - // The first case should be dropped in v1.14 when support for v1.12 clusters can be removed from the codebase. - - // Detect which type of etcd we are dealing with - // Please note that this test can be executed only on master nodes during upgrades; - // For nodes where we are joining a new control plane node instead we should tolerate that the etcd manifest does not - // exists and try to connect to etcd using API server advertise address; as described above this will lead to a know isse - // for cluster created with v1.12, but a documented workaround will be provided - oldManifest := false - klog.V(1).Infoln("checking etcd manifest") - - etcdManifestFile := constants.GetStaticPodFilepath(constants.Etcd, constants.GetStaticPodDirectory()) - etcdPod, err := staticpod.ReadStaticPodFromDisk(etcdManifestFile) - if err == nil { - etcdContainer := etcdPod.Spec.Containers[0] - for _, arg := range etcdContainer.Command { - if arg == "--listen-client-urls=https://127.0.0.1:2379" { - klog.V(1).Infoln("etcd manifest created by kubeadm v1.12") - oldManifest = true - } - } - - // if etcd is listening on localhost only - if oldManifest == true { - // etcd cluster has a single member "by design" - endpoints := []string{fmt.Sprintf("localhost:%d", constants.EtcdListenClientPort)} - - etcdClient, err := New( - endpoints, - filepath.Join(certificatesDir, constants.EtcdCACertName), - filepath.Join(certificatesDir, constants.EtcdHealthcheckClientCertName), - filepath.Join(certificatesDir, constants.EtcdHealthcheckClientKeyName), - ) - if err != nil { - return nil, errors.Wrapf(err, "error creating etcd client for %v endpoint", endpoints) - } - - return etcdClient, nil - } - } - - // etcd is listening on localhost and API server advertise address, and - // the etcd cluster can have more than one etcd members, so it is necessary to get the - // list of endpoints from kubeadm cluster status before connecting + // etcd is listening the API server advertise address on each control-plane node + // so it is necessary to get the list of endpoints from kubeadm cluster status before connecting // Gets the cluster status clusterStatus, err := config.GetClusterStatus(client) @@ -196,12 +109,13 @@ func NewFromCluster(client clientset.Interface, certificatesDir string) (*Client if err != nil { return nil, errors.Wrap(err, "error syncing endpoints with etc") } + klog.V(1).Infof("update etcd endpoints: %s", strings.Join(etcdClient.Endpoints, ",")) return etcdClient, nil } // Sync synchronizes client's endpoints with the known endpoints from the etcd membership. -func (c Client) Sync() error { +func (c *Client) Sync() error { cli, err := clientv3.New(clientv3.Config{ Endpoints: c.Endpoints, DialTimeout: 20 * time.Second, @@ -334,10 +248,8 @@ func (c Client) GetClusterStatus() (map[string]*clientv3.StatusResponse, error) return clusterStatus, nil } -// WaitForClusterAvailable returns true if all endpoints in the cluster are available after an initial delay and retry attempts, an error is returned otherwise -func (c Client) WaitForClusterAvailable(delay time.Duration, retries int, retryInterval time.Duration) (bool, error) { - fmt.Printf("[util/etcd] Waiting %v for initial delay\n", delay) - time.Sleep(delay) +// WaitForClusterAvailable returns true if all endpoints in the cluster are available after retry attempts, an error is returned otherwise +func (c Client) WaitForClusterAvailable(retries int, retryInterval time.Duration) (bool, error) { for i := 0; i < retries; i++ { if i > 0 { fmt.Printf("[util/etcd] Waiting %v until next retry\n", retryInterval) diff --git a/cmd/kubeadm/app/util/etcd/etcd_test.go b/cmd/kubeadm/app/util/etcd/etcd_test.go index efd8f896a77..f9728131d5c 100644 --- a/cmd/kubeadm/app/util/etcd/etcd_test.go +++ b/cmd/kubeadm/app/util/etcd/etcd_test.go @@ -18,253 +18,13 @@ package etcd import ( "fmt" - "io/ioutil" - "os" - "path/filepath" "strconv" "testing" kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" "k8s.io/kubernetes/cmd/kubeadm/app/constants" - testutil "k8s.io/kubernetes/cmd/kubeadm/test" ) -const ( - secureEtcdPod = `# generated by kubeadm v1.10.0 -apiVersion: v1 -kind: Pod -metadata: - annotations: - scheduler.alpha.kubernetes.io/critical-pod: "" - creationTimestamp: null - labels: - component: etcd - tier: control-plane - name: etcd - namespace: kube-system -spec: - containers: - - command: - - etcd - - --advertise-client-urls=https://127.0.0.1:2379 - - --data-dir=/var/lib/etcd - - --peer-key-file=/etc/kubernetes/pki/etcd/peer.key - - --peer-trusted-ca-file=/etc/kubernetes/pki/etcd/ca.crt - - --listen-client-urls=https://127.0.0.1:2379 - - --peer-client-cert-auth=true - - --cert-file=/etc/kubernetes/pki/etcd/server.crt - - --key-file=/etc/kubernetes/pki/etcd/server.key - - --trusted-ca-file=/etc/kubernetes/pki/etcd/ca.crt - - --peer-cert-file=/etc/kubernetes/pki/etcd/peer.crt - - --client-cert-auth=true - image: k8s.gcr.io/etcd-amd64:3.1.12 - livenessProbe: - exec: - command: - - /bin/sh - - -ec - - ETCDCTL_API=3 etcdctl --endpoints=127.0.0.1:2379 --cacert=/etc/kubernetes/pki/etcd/ca.crt - --cert=/etc/kubernetes/pki/etcd/healthcheck-client.crt --key=/etc/kubernetes/pki/etcd/healthcheck-client.key - get foo - failureThreshold: 8 - initialDelaySeconds: 15 - timeoutSeconds: 15 - name: etcd - resources: {} - volumeMounts: - - mountPath: /var/lib/etcd - name: etcd-data - - mountPath: /etc/kubernetes/pki/etcd - name: etcd-certs - hostNetwork: true - volumes: - - hostPath: - path: /var/lib/etcd - type: DirectoryOrCreate - name: etcd-data - - hostPath: - path: /etc/kubernetes/pki/etcd - type: DirectoryOrCreate - name: etcd-certs -status: {} -` - secureExposedEtcdPod = ` -apiVersion: v1 -kind: Pod -metadata: - annotations: - scheduler.alpha.kubernetes.io/critical-pod: "" - creationTimestamp: null - labels: - component: etcd - tier: control-plane - name: etcd - namespace: kube-system -spec: - containers: - - command: - - etcd - - --advertise-client-urls=https://10.0.5.5:2379 - - --data-dir=/var/lib/etcd - - --peer-key-file=/etc/kubernetes/pki/etcd/peer.key - - --peer-trusted-ca-file=/etc/kubernetes/pki/etcd/ca.crt - - --listen-client-urls=https://[::0:0]:2379 - - --peer-client-cert-auth=true - - --cert-file=/etc/kubernetes/pki/etcd/server.crt - - --key-file=/etc/kubernetes/pki/etcd/server.key - - --trusted-ca-file=/etc/kubernetes/pki/etcd/ca.crt - - --peer-cert-file=/etc/kubernetes/pki/etcd/peer.crt - - --client-cert-auth=true - image: k8s.gcr.io/etcd-amd64:3.1.12 - livenessProbe: - exec: - command: - - /bin/sh - - -ec - - ETCDCTL_API=3 etcdctl --endpoints=https://[::1]:2379 --cacert=/etc/kubernetes/pki/etcd/ca.crt - --cert=/etc/kubernetes/pki/etcd/healthcheck-client.crt --key=/etc/kubernetes/pki/etcd/healthcheck-client.key - get foo - failureThreshold: 8 - initialDelaySeconds: 15 - timeoutSeconds: 15 - name: etcd - resources: {} - volumeMounts: - - mountPath: /var/lib/etcd - name: etcd-data - - mountPath: /etc/kubernetes/pki/etcd - name: etcd-certs - hostNetwork: true - volumes: - - hostPath: - path: /var/lib/etcd - type: DirectoryOrCreate - name: etcd-data - - hostPath: - path: /etc/kubernetes/pki/etcd - type: DirectoryOrCreate - name: etcd-certs -status: {} -` - insecureEtcdPod = `# generated by kubeadm v1.9.6 -apiVersion: v1 -kind: Pod -metadata: - annotations: - scheduler.alpha.kubernetes.io/critical-pod: "" - creationTimestamp: null - labels: - component: etcd - tier: control-plane - name: etcd - namespace: kube-system -spec: - containers: - - command: - - etcd - - --listen-client-urls=http://127.0.0.1:2379 - - --advertise-client-urls=http://127.0.0.1:2379 - - --data-dir=/var/lib/etcd - image: gcr.io/google_containers/etcd-amd64:3.1.11 - livenessProbe: - failureThreshold: 8 - httpGet: - host: 127.0.0.1 - path: /health - port: 2379 - scheme: HTTP - initialDelaySeconds: 15 - timeoutSeconds: 15 - name: etcd - resources: {} - volumeMounts: - - mountPath: /var/lib/etcd - name: etcd - hostNetwork: true - volumes: - - hostPath: - path: /var/lib/etcd - type: DirectoryOrCreate - name: etcd -status: {} -` - invalidPod = `---{ broken yaml @@@` -) - -func TestPodManifestHasTLS(t *testing.T) { - tests := []struct { - description string - podYaml string - hasTLS bool - expectErr bool - writeManifest bool - }{ - { - description: "secure etcd returns true", - podYaml: secureEtcdPod, - hasTLS: true, - writeManifest: true, - expectErr: false, - }, - { - description: "secure exposed etcd returns true", - podYaml: secureExposedEtcdPod, - hasTLS: true, - writeManifest: true, - expectErr: false, - }, - { - description: "insecure etcd returns false", - podYaml: insecureEtcdPod, - hasTLS: false, - writeManifest: true, - expectErr: false, - }, - { - description: "invalid pod fails to unmarshal", - podYaml: invalidPod, - hasTLS: false, - writeManifest: true, - expectErr: true, - }, - { - description: "non-existent file returns error", - podYaml: ``, - hasTLS: false, - writeManifest: false, - expectErr: true, - }, - } - - for _, rt := range tests { - tmpdir := testutil.SetupTempDir(t) - defer os.RemoveAll(tmpdir) - - manifestPath := filepath.Join(tmpdir, "etcd.yaml") - if rt.writeManifest { - err := ioutil.WriteFile(manifestPath, []byte(rt.podYaml), 0644) - if err != nil { - t.Fatalf("Failed to write pod manifest\n%s\n\tfatal error: %v", rt.description, err) - } - } - - hasTLS, actualErr := PodManifestsHaveTLS(tmpdir) - if (actualErr != nil) != rt.expectErr { - t.Errorf( - "PodManifestHasTLS failed\n%s\n\texpected error: %t\n\tgot: %t\n\tactual error: %v", - rt.description, - rt.expectErr, - (actualErr != nil), - actualErr, - ) - } - - if hasTLS != rt.hasTLS { - t.Errorf("PodManifestHasTLS failed\n%s\n\texpected hasTLS: %t\n\tgot: %t", rt.description, rt.hasTLS, hasTLS) - } - } -} - func TestCheckConfigurationIsHA(t *testing.T) { var tests = []struct { name string diff --git a/cmd/kubeadm/app/util/kubeconfig/kubeconfig_test.go b/cmd/kubeadm/app/util/kubeconfig/kubeconfig_test.go index dc9879148cb..569419864ee 100644 --- a/cmd/kubeadm/app/util/kubeconfig/kubeconfig_test.go +++ b/cmd/kubeadm/app/util/kubeconfig/kubeconfig_test.go @@ -81,56 +81,62 @@ type configClientWithToken struct { func TestCreateWithCerts(t *testing.T) { var createBasicTest = []struct { + name string cc configClient ccWithCerts configClientWithCerts expected string }{ - {configClient{}, configClientWithCerts{}, ""}, - {configClient{clusterName: "kubernetes"}, configClientWithCerts{}, ""}, + {"empty config", configClient{}, configClientWithCerts{}, ""}, + {"clusterName kubernetes", configClient{clusterName: "kubernetes"}, configClientWithCerts{}, ""}, } for _, rt := range createBasicTest { - cwc := CreateWithCerts( - rt.cc.serverURL, - rt.cc.clusterName, - rt.cc.userName, - rt.cc.caCert, - rt.ccWithCerts.clientKey, - rt.ccWithCerts.clientCert, - ) - if cwc.Kind != rt.expected { - t.Errorf( - "failed CreateWithCerts:\n\texpected: %s\n\t actual: %s", - rt.expected, - cwc.Kind, + t.Run(rt.name, func(t *testing.T) { + cwc := CreateWithCerts( + rt.cc.serverURL, + rt.cc.clusterName, + rt.cc.userName, + rt.cc.caCert, + rt.ccWithCerts.clientKey, + rt.ccWithCerts.clientCert, ) - } + if cwc.Kind != rt.expected { + t.Errorf( + "failed CreateWithCerts:\n\texpected: %s\n\t actual: %s", + rt.expected, + cwc.Kind, + ) + } + }) } } func TestCreateWithToken(t *testing.T) { var createBasicTest = []struct { + name string cc configClient ccWithToken configClientWithToken expected string }{ - {configClient{}, configClientWithToken{}, ""}, - {configClient{clusterName: "kubernetes"}, configClientWithToken{}, ""}, + {"empty config", configClient{}, configClientWithToken{}, ""}, + {"clusterName kubernetes", configClient{clusterName: "kubernetes"}, configClientWithToken{}, ""}, } for _, rt := range createBasicTest { - cwc := CreateWithToken( - rt.cc.serverURL, - rt.cc.clusterName, - rt.cc.userName, - rt.cc.caCert, - rt.ccWithToken.token, - ) - if cwc.Kind != rt.expected { - t.Errorf( - "failed CreateWithToken:\n\texpected: %s\n\t actual: %s", - rt.expected, - cwc.Kind, + t.Run(rt.name, func(t *testing.T) { + cwc := CreateWithToken( + rt.cc.serverURL, + rt.cc.clusterName, + rt.cc.userName, + rt.cc.caCert, + rt.ccWithToken.token, ) - } + if cwc.Kind != rt.expected { + t.Errorf( + "failed CreateWithToken:\n\texpected: %s\n\t actual: %s", + rt.expected, + cwc.Kind, + ) + } + }) } } @@ -152,29 +158,31 @@ func TestWriteKubeconfigToDisk(t *testing.T) { {"test2", configClient{clusterName: "kubernetes", userName: "user2", serverURL: "localhost:8080"}, configClientWithToken{token: "cba"}, nil, []byte(configOut2)}, } for _, rt := range writeConfig { - c := CreateWithToken( - rt.cc.serverURL, - rt.cc.clusterName, - rt.cc.userName, - rt.cc.caCert, - rt.ccWithToken.token, - ) - configPath := fmt.Sprintf("%s/etc/kubernetes/%s.conf", tmpdir, rt.name) - err := WriteToDisk(configPath, c) - if err != rt.expected { - t.Errorf( - "failed WriteToDisk with an error:\n\texpected: %s\n\t actual: %s", - rt.expected, - err, + t.Run(rt.name, func(t *testing.T) { + c := CreateWithToken( + rt.cc.serverURL, + rt.cc.clusterName, + rt.cc.userName, + rt.cc.caCert, + rt.ccWithToken.token, ) - } - newFile, _ := ioutil.ReadFile(configPath) - if !bytes.Equal(newFile, rt.file) { - t.Errorf( - "failed WriteToDisk config write:\n\texpected: %s\n\t actual: %s", - rt.file, - newFile, - ) - } + configPath := fmt.Sprintf("%s/etc/kubernetes/%s.conf", tmpdir, rt.name) + err := WriteToDisk(configPath, c) + if err != rt.expected { + t.Errorf( + "failed WriteToDisk with an error:\n\texpected: %s\n\t actual: %s", + rt.expected, + err, + ) + } + newFile, _ := ioutil.ReadFile(configPath) + if !bytes.Equal(newFile, rt.file) { + t.Errorf( + "failed WriteToDisk config write:\n\texpected: %s\n\t actual: %s", + rt.file, + newFile, + ) + } + }) } } diff --git a/cmd/kubeadm/app/util/marshal.go b/cmd/kubeadm/app/util/marshal.go index d38dce75f2f..5fca9950ad3 100644 --- a/cmd/kubeadm/app/util/marshal.go +++ b/cmd/kubeadm/app/util/marshal.go @@ -21,13 +21,13 @@ import ( "bytes" "io" - pkgerrors "github.com/pkg/errors" + "github.com/pkg/errors" "sigs.k8s.io/yaml" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/serializer" - "k8s.io/apimachinery/pkg/util/errors" + errorsutil "k8s.io/apimachinery/pkg/util/errors" utilyaml "k8s.io/apimachinery/pkg/util/yaml" clientsetscheme "k8s.io/client-go/kubernetes/scheme" "k8s.io/kubernetes/cmd/kubeadm/app/constants" @@ -45,7 +45,7 @@ func MarshalToYamlForCodecs(obj runtime.Object, gv schema.GroupVersion, codecs s mediaType := "application/yaml" info, ok := runtime.SerializerInfoForMediaType(codecs.SupportedMediaTypes(), mediaType) if !ok { - return []byte{}, pkgerrors.Errorf("unsupported media type %q", mediaType) + return []byte{}, errors.Errorf("unsupported media type %q", mediaType) } encoder := codecs.EncoderForVersion(info.Serializer, gv) @@ -64,7 +64,7 @@ func UnmarshalFromYamlForCodecs(buffer []byte, gv schema.GroupVersion, codecs se mediaType := "application/yaml" info, ok := runtime.SerializerInfoForMediaType(codecs.SupportedMediaTypes(), mediaType) if !ok { - return nil, pkgerrors.Errorf("unsupported media type %q", mediaType) + return nil, errors.Errorf("unsupported media type %q", mediaType) } decoder := codecs.DecoderToVersion(info.Serializer, gv) @@ -97,12 +97,12 @@ func SplitYAMLDocuments(yamlBytes []byte) (map[schema.GroupVersionKind][]byte, e } // Require TypeMeta information to be present if len(typeMetaInfo.APIVersion) == 0 || len(typeMetaInfo.Kind) == 0 { - errs = append(errs, pkgerrors.New("invalid configuration: kind and apiVersion is mandatory information that needs to be specified in all YAML documents")) + errs = append(errs, errors.New("invalid configuration: kind and apiVersion is mandatory information that needs to be specified in all YAML documents")) continue } // Check whether the kind has been registered before. If it has, throw an error if known := knownKinds[typeMetaInfo.Kind]; known { - errs = append(errs, pkgerrors.Errorf("invalid configuration: kind %q is specified twice in YAML file", typeMetaInfo.Kind)) + errs = append(errs, errors.Errorf("invalid configuration: kind %q is specified twice in YAML file", typeMetaInfo.Kind)) continue } knownKinds[typeMetaInfo.Kind] = true @@ -110,7 +110,7 @@ func SplitYAMLDocuments(yamlBytes []byte) (map[schema.GroupVersionKind][]byte, e // Build a GroupVersionKind object from the deserialized TypeMeta object gv, err := schema.ParseGroupVersion(typeMetaInfo.APIVersion) if err != nil { - errs = append(errs, pkgerrors.Wrap(err, "unable to parse apiVersion")) + errs = append(errs, errors.Wrap(err, "unable to parse apiVersion")) continue } gvk := gv.WithKind(typeMetaInfo.Kind) @@ -118,7 +118,7 @@ func SplitYAMLDocuments(yamlBytes []byte) (map[schema.GroupVersionKind][]byte, e // Save the mapping between the gvk and the bytes that object consists of gvkmap[gvk] = b } - if err := errors.NewAggregate(errs); err != nil { + if err := errorsutil.NewAggregate(errs); err != nil { return nil, err } return gvkmap, nil diff --git a/cmd/kubeadm/app/util/pkiutil/pki_helpers.go b/cmd/kubeadm/app/util/pkiutil/pki_helpers.go index 20cc1ce309b..64b80af3d26 100644 --- a/cmd/kubeadm/app/util/pkiutil/pki_helpers.go +++ b/cmd/kubeadm/app/util/pkiutil/pki_helpers.go @@ -459,12 +459,12 @@ func EncodeCSRPEM(csr *x509.CertificateRequest) []byte { func parseCSRPEM(pemCSR []byte) (*x509.CertificateRequest, error) { block, _ := pem.Decode(pemCSR) if block == nil { - return nil, fmt.Errorf("data doesn't contain a valid certificate request") + return nil, errors.New("data doesn't contain a valid certificate request") } if block.Type != certutil.CertificateRequestBlockType { var block *pem.Block - return nil, fmt.Errorf("expected block type %q, but PEM had type %v", certutil.CertificateRequestBlockType, block.Type) + return nil, errors.Errorf("expected block type %q, but PEM had type %v", certutil.CertificateRequestBlockType, block.Type) } return x509.ParseCertificateRequest(block.Bytes) @@ -480,7 +480,7 @@ func CertificateRequestFromFile(file string) (*x509.CertificateRequest, error) { csr, err := parseCSRPEM(pemBlock) if err != nil { - return nil, fmt.Errorf("error reading certificate request file %s: %v", file, err) + return nil, errors.Wrapf(err, "error reading certificate request file %s", file) } return csr, nil } diff --git a/cmd/kubeadm/app/util/pkiutil/pki_helpers_test.go b/cmd/kubeadm/app/util/pkiutil/pki_helpers_test.go index ae8f224bf9e..307048b0614 100644 --- a/cmd/kubeadm/app/util/pkiutil/pki_helpers_test.go +++ b/cmd/kubeadm/app/util/pkiutil/pki_helpers_test.go @@ -70,40 +70,43 @@ func TestNewCertificateAuthority(t *testing.T) { func TestNewCertAndKey(t *testing.T) { var tests = []struct { + name string caKeySize int expected bool }{ { - // RSA key too small + name: "RSA key too small", caKeySize: 128, expected: false, }, { - // Should succeed + name: "Should succeed", caKeySize: 2048, expected: true, }, } for _, rt := range tests { - caKey, err := rsa.GenerateKey(rand.Reader, rt.caKeySize) - if err != nil { - t.Fatalf("Couldn't create rsa Private Key") - } - caCert := &x509.Certificate{} - config := &certutil.Config{ - CommonName: "test", - Organization: []string{"test"}, - Usages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}, - } - _, _, actual := NewCertAndKey(caCert, caKey, config) - if (actual == nil) != rt.expected { - t.Errorf( - "failed NewCertAndKey:\n\texpected: %t\n\t actual: %t", - rt.expected, - (actual == nil), - ) - } + t.Run(rt.name, func(t *testing.T) { + caKey, err := rsa.GenerateKey(rand.Reader, rt.caKeySize) + if err != nil { + t.Fatalf("Couldn't create rsa Private Key") + } + caCert := &x509.Certificate{} + config := &certutil.Config{ + CommonName: "test", + Organization: []string{"test"}, + Usages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}, + } + _, _, actual := NewCertAndKey(caCert, caKey, config) + if (actual == nil) != rt.expected { + t.Errorf( + "failed NewCertAndKey:\n\texpected: %t\n\t actual: %t", + rt.expected, + (actual == nil), + ) + } + }) } } @@ -111,10 +114,12 @@ func TestHasServerAuth(t *testing.T) { caCert, caKey, _ := NewCertificateAuthority(&certutil.Config{CommonName: "kubernetes"}) var tests = []struct { + name string config certutil.Config expected bool }{ { + name: "has ServerAuth", config: certutil.Config{ CommonName: "test", Usages: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, @@ -122,6 +127,7 @@ func TestHasServerAuth(t *testing.T) { expected: true, }, { + name: "doesn't have ServerAuth", config: certutil.Config{ CommonName: "test", Usages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}, @@ -131,18 +137,20 @@ func TestHasServerAuth(t *testing.T) { } for _, rt := range tests { - cert, _, err := NewCertAndKey(caCert, caKey, &rt.config) - if err != nil { - t.Fatalf("Couldn't create cert: %v", err) - } - actual := HasServerAuth(cert) - if actual != rt.expected { - t.Errorf( - "failed HasServerAuth:\n\texpected: %t\n\t actual: %t", - rt.expected, - actual, - ) - } + t.Run(rt.name, func(t *testing.T) { + cert, _, err := NewCertAndKey(caCert, caKey, &rt.config) + if err != nil { + t.Fatalf("Couldn't create cert: %v", err) + } + actual := HasServerAuth(cert) + if actual != rt.expected { + t.Errorf( + "failed HasServerAuth:\n\texpected: %t\n\t actual: %t", + rt.expected, + actual, + ) + } + }) } } @@ -245,30 +253,35 @@ func TestCertOrKeyExist(t *testing.T) { } var tests = []struct { + desc string path string name string expected bool }{ { + desc: "empty path and name", path: "", name: "", expected: false, }, { + desc: "valid path and name", path: tmpdir, name: "foo", expected: true, }, } for _, rt := range tests { - actual := CertOrKeyExist(rt.path, rt.name) - if actual != rt.expected { - t.Errorf( - "failed CertOrKeyExist:\n\texpected: %t\n\t actual: %t", - rt.expected, - actual, - ) - } + t.Run(rt.name, func(t *testing.T) { + actual := CertOrKeyExist(rt.path, rt.name) + if actual != rt.expected { + t.Errorf( + "failed CertOrKeyExist:\n\texpected: %t\n\t actual: %t", + rt.expected, + actual, + ) + } + }) } } @@ -295,30 +308,35 @@ func TestTryLoadCertAndKeyFromDisk(t *testing.T) { } var tests = []struct { + desc string path string name string expected bool }{ { + desc: "empty path and name", path: "", name: "", expected: false, }, { + desc: "valid path and name", path: tmpdir, name: "foo", expected: true, }, } for _, rt := range tests { - _, _, actual := TryLoadCertAndKeyFromDisk(rt.path, rt.name) - if (actual == nil) != rt.expected { - t.Errorf( - "failed TryLoadCertAndKeyFromDisk:\n\texpected: %t\n\t actual: %t", - rt.expected, - (actual == nil), - ) - } + t.Run(rt.desc, func(t *testing.T) { + _, _, actual := TryLoadCertAndKeyFromDisk(rt.path, rt.name) + if (actual == nil) != rt.expected { + t.Errorf( + "failed TryLoadCertAndKeyFromDisk:\n\texpected: %t\n\t actual: %t", + rt.expected, + (actual == nil), + ) + } + }) } } @@ -345,30 +363,35 @@ func TestTryLoadCertFromDisk(t *testing.T) { } var tests = []struct { + desc string path string name string expected bool }{ { + desc: "empty path and name", path: "", name: "", expected: false, }, { + desc: "valid path and name", path: tmpdir, name: "foo", expected: true, }, } for _, rt := range tests { - _, actual := TryLoadCertFromDisk(rt.path, rt.name) - if (actual == nil) != rt.expected { - t.Errorf( - "failed TryLoadCertAndKeyFromDisk:\n\texpected: %t\n\t actual: %t", - rt.expected, - (actual == nil), - ) - } + t.Run(rt.desc, func(t *testing.T) { + _, actual := TryLoadCertFromDisk(rt.path, rt.name) + if (actual == nil) != rt.expected { + t.Errorf( + "failed TryLoadCertAndKeyFromDisk:\n\texpected: %t\n\t actual: %t", + rt.expected, + (actual == nil), + ) + } + }) } } @@ -395,30 +418,35 @@ func TestTryLoadKeyFromDisk(t *testing.T) { } var tests = []struct { + desc string path string name string expected bool }{ { + desc: "empty path and name", path: "", name: "", expected: false, }, { + desc: "valid path and name", path: tmpdir, name: "foo", expected: true, }, } for _, rt := range tests { - _, actual := TryLoadKeyFromDisk(rt.path, rt.name) - if (actual == nil) != rt.expected { - t.Errorf( - "failed TryLoadCertAndKeyFromDisk:\n\texpected: %t\n\t actual: %t", - rt.expected, - (actual == nil), - ) - } + t.Run(rt.desc, func(t *testing.T) { + _, actual := TryLoadKeyFromDisk(rt.path, rt.name) + if (actual == nil) != rt.expected { + t.Errorf( + "failed TryLoadCertAndKeyFromDisk:\n\texpected: %t\n\t actual: %t", + rt.expected, + (actual == nil), + ) + } + }) } } @@ -463,12 +491,14 @@ func TestPathForCSR(t *testing.T) { func TestGetAPIServerAltNames(t *testing.T) { var tests = []struct { + desc string name string cfg *kubeadmapi.InitConfiguration expectedDNSNames []string expectedIPAddresses []string }{ { + desc: "empty name", name: "", cfg: &kubeadmapi.InitConfiguration{ LocalAPIEndpoint: kubeadmapi.APIEndpoint{AdvertiseAddress: "1.2.3.4"}, @@ -485,6 +515,7 @@ func TestGetAPIServerAltNames(t *testing.T) { expectedIPAddresses: []string{"10.96.0.1", "1.2.3.4", "10.1.245.94", "10.1.245.95"}, }, { + desc: "ControlPlaneEndpoint IP", name: "ControlPlaneEndpoint IP", cfg: &kubeadmapi.InitConfiguration{ LocalAPIEndpoint: kubeadmapi.APIEndpoint{AdvertiseAddress: "1.2.3.4"}, @@ -503,38 +534,40 @@ func TestGetAPIServerAltNames(t *testing.T) { } for _, rt := range tests { - altNames, err := GetAPIServerAltNames(rt.cfg) - if err != nil { - t.Fatalf("failed calling GetAPIServerAltNames: %s: %v", rt.name, err) - } + t.Run(rt.desc, func(t *testing.T) { + altNames, err := GetAPIServerAltNames(rt.cfg) + if err != nil { + t.Fatalf("failed calling GetAPIServerAltNames: %s: %v", rt.name, err) + } - for _, DNSName := range rt.expectedDNSNames { - found := false - for _, val := range altNames.DNSNames { - if val == DNSName { - found = true - break + for _, DNSName := range rt.expectedDNSNames { + found := false + for _, val := range altNames.DNSNames { + if val == DNSName { + found = true + break + } + } + + if !found { + t.Errorf("%s: altNames does not contain DNSName %s but %v", rt.name, DNSName, altNames.DNSNames) } } - if !found { - t.Errorf("%s: altNames does not contain DNSName %s but %v", rt.name, DNSName, altNames.DNSNames) - } - } + for _, IPAddress := range rt.expectedIPAddresses { + found := false + for _, val := range altNames.IPs { + if val.Equal(net.ParseIP(IPAddress)) { + found = true + break + } + } - for _, IPAddress := range rt.expectedIPAddresses { - found := false - for _, val := range altNames.IPs { - if val.Equal(net.ParseIP(IPAddress)) { - found = true - break + if !found { + t.Errorf("%s: altNames does not contain IPAddress %s but %v", rt.name, IPAddress, altNames.IPs) } } - - if !found { - t.Errorf("%s: altNames does not contain IPAddress %s but %v", rt.name, IPAddress, altNames.IPs) - } - } + }) } } @@ -569,32 +602,36 @@ func TestGetEtcdAltNames(t *testing.T) { expectedDNSNames := []string{"myNode", "localhost", proxy} for _, DNSName := range expectedDNSNames { - found := false - for _, val := range altNames.DNSNames { - if val == DNSName { - found = true - break + t.Run(DNSName, func(t *testing.T) { + found := false + for _, val := range altNames.DNSNames { + if val == DNSName { + found = true + break + } } - } - if !found { - t.Errorf("altNames does not contain DNSName %s", DNSName) - } + if !found { + t.Errorf("altNames does not contain DNSName %s", DNSName) + } + }) } expectedIPAddresses := []string{"1.2.3.4", "127.0.0.1", net.IPv6loopback.String(), proxyIP} for _, IPAddress := range expectedIPAddresses { - found := false - for _, val := range altNames.IPs { - if val.Equal(net.ParseIP(IPAddress)) { - found = true - break + t.Run(IPAddress, func(t *testing.T) { + found := false + for _, val := range altNames.IPs { + if val.Equal(net.ParseIP(IPAddress)) { + found = true + break + } } - } - if !found { - t.Errorf("altNames does not contain IPAddress %s", IPAddress) - } + if !found { + t.Errorf("altNames does not contain IPAddress %s", IPAddress) + } + }) } } @@ -627,31 +664,33 @@ func TestGetEtcdPeerAltNames(t *testing.T) { expectedDNSNames := []string{hostname, proxy} for _, DNSName := range expectedDNSNames { - found := false - for _, val := range altNames.DNSNames { - if val == DNSName { - found = true - break + t.Run(DNSName, func(t *testing.T) { + found := false + for _, val := range altNames.DNSNames { + if val == DNSName { + found = true + break + } } - } - if !found { - t.Errorf("altNames does not contain DNSName %s", DNSName) - } - } - - expectedIPAddresses := []string{advertiseIP, proxyIP} - for _, IPAddress := range expectedIPAddresses { - found := false - for _, val := range altNames.IPs { - if val.Equal(net.ParseIP(IPAddress)) { - found = true - break + if !found { + t.Errorf("altNames does not contain DNSName %s", DNSName) } - } - if !found { - t.Errorf("altNames does not contain IPAddress %s", IPAddress) - } + expectedIPAddresses := []string{advertiseIP, proxyIP} + for _, IPAddress := range expectedIPAddresses { + found := false + for _, val := range altNames.IPs { + if val.Equal(net.ParseIP(IPAddress)) { + found = true + break + } + } + + if !found { + t.Errorf("altNames does not contain IPAddress %s", IPAddress) + } + } + }) } } diff --git a/cmd/kubeadm/app/util/runtime/runtime.go b/cmd/kubeadm/app/util/runtime/runtime.go index 2b5915b307e..bbf51978d94 100644 --- a/cmd/kubeadm/app/util/runtime/runtime.go +++ b/cmd/kubeadm/app/util/runtime/runtime.go @@ -21,9 +21,9 @@ import ( goruntime "runtime" "strings" - pkgerrors "github.com/pkg/errors" + "github.com/pkg/errors" - "k8s.io/apimachinery/pkg/util/errors" + errorsutil "k8s.io/apimachinery/pkg/util/errors" kubeadmapiv1beta1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta1" utilsexec "k8s.io/utils/exec" ) @@ -69,7 +69,7 @@ func NewContainerRuntime(execer utilsexec.Interface, criSocket string) (Containe } if _, err := execer.LookPath(toolName); err != nil { - return nil, pkgerrors.Wrapf(err, "%s is required for container runtime", toolName) + return nil, errors.Wrapf(err, "%s is required for container runtime", toolName) } return runtime, nil @@ -88,7 +88,7 @@ func (runtime *DockerRuntime) IsDocker() bool { // IsRunning checks if runtime is running func (runtime *CRIRuntime) IsRunning() error { if out, err := runtime.exec.Command("crictl", "-r", runtime.criSocket, "info").CombinedOutput(); err != nil { - return pkgerrors.Wrapf(err, "container runtime is not running: output: %s, error", string(out)) + return errors.Wrapf(err, "container runtime is not running: output: %s, error", string(out)) } return nil } @@ -96,7 +96,7 @@ func (runtime *CRIRuntime) IsRunning() error { // IsRunning checks if runtime is running func (runtime *DockerRuntime) IsRunning() error { if out, err := runtime.exec.Command("docker", "info").CombinedOutput(); err != nil { - return pkgerrors.Wrapf(err, "container runtime is not running: output: %s, error", string(out)) + return errors.Wrapf(err, "container runtime is not running: output: %s, error", string(out)) } return nil } @@ -105,7 +105,7 @@ func (runtime *DockerRuntime) IsRunning() error { func (runtime *CRIRuntime) ListKubeContainers() ([]string, error) { out, err := runtime.exec.Command("crictl", "-r", runtime.criSocket, "pods", "-q").CombinedOutput() if err != nil { - return nil, pkgerrors.Wrapf(err, "output: %s, error", string(out)) + return nil, errors.Wrapf(err, "output: %s, error", string(out)) } pods := []string{} for _, pod := range strings.Fields(string(out)) { @@ -127,15 +127,15 @@ func (runtime *CRIRuntime) RemoveContainers(containers []string) error { out, err := runtime.exec.Command("crictl", "-r", runtime.criSocket, "stopp", container).CombinedOutput() if err != nil { // don't stop on errors, try to remove as many containers as possible - errs = append(errs, pkgerrors.Wrapf(err, "failed to stop running pod %s: output: %s, error", container, string(out))) + errs = append(errs, errors.Wrapf(err, "failed to stop running pod %s: output: %s, error", container, string(out))) } else { out, err = runtime.exec.Command("crictl", "-r", runtime.criSocket, "rmp", container).CombinedOutput() if err != nil { - errs = append(errs, pkgerrors.Wrapf(err, "failed to remove running container %s: output: %s, error", container, string(out))) + errs = append(errs, errors.Wrapf(err, "failed to remove running container %s: output: %s, error", container, string(out))) } } } - return errors.NewAggregate(errs) + return errorsutil.NewAggregate(errs) } // RemoveContainers removes running containers @@ -145,17 +145,17 @@ func (runtime *DockerRuntime) RemoveContainers(containers []string) error { out, err := runtime.exec.Command("docker", "rm", "--force", "--volumes", container).CombinedOutput() if err != nil { // don't stop on errors, try to remove as many containers as possible - errs = append(errs, pkgerrors.Wrapf(err, "failed to remove running container %s: output: %s, error", container, string(out))) + errs = append(errs, errors.Wrapf(err, "failed to remove running container %s: output: %s, error", container, string(out))) } } - return errors.NewAggregate(errs) + return errorsutil.NewAggregate(errs) } // PullImage pulls the image func (runtime *CRIRuntime) PullImage(image string) error { out, err := runtime.exec.Command("crictl", "-r", runtime.criSocket, "pull", image).CombinedOutput() if err != nil { - return pkgerrors.Wrapf(err, "output: %s, error", string(out)) + return errors.Wrapf(err, "output: %s, error", string(out)) } return nil } @@ -164,7 +164,7 @@ func (runtime *CRIRuntime) PullImage(image string) error { func (runtime *DockerRuntime) PullImage(image string) error { out, err := runtime.exec.Command("docker", "pull", image).CombinedOutput() if err != nil { - return pkgerrors.Wrapf(err, "output: %s, error", string(out)) + return errors.Wrapf(err, "output: %s, error", string(out)) } return nil } diff --git a/cmd/kubeadm/app/util/staticpod/utils_test.go b/cmd/kubeadm/app/util/staticpod/utils_test.go index 3aa91bc558d..d9449a60edf 100644 --- a/cmd/kubeadm/app/util/staticpod/utils_test.go +++ b/cmd/kubeadm/app/util/staticpod/utils_test.go @@ -166,27 +166,29 @@ func TestComponentProbe(t *testing.T) { }, } for _, rt := range tests { - actual := ComponentProbe(rt.cfg, rt.component, rt.port, rt.path, rt.scheme) - if actual.Handler.HTTPGet.Host != rt.expected { - t.Errorf("%s test case failed:\n\texpected: %s\n\t actual: %s", - rt.name, rt.expected, - actual.Handler.HTTPGet.Host) - } - if actual.Handler.HTTPGet.Port != intstr.FromInt(rt.port) { - t.Errorf("%s test case failed:\n\texpected: %v\n\t actual: %v", - rt.name, rt.port, - actual.Handler.HTTPGet.Port) - } - if actual.Handler.HTTPGet.Path != rt.path { - t.Errorf("%s test case failed:\n\texpected: %s\n\t actual: %s", - rt.name, rt.path, - actual.Handler.HTTPGet.Path) - } - if actual.Handler.HTTPGet.Scheme != rt.scheme { - t.Errorf("%s test case failed:\n\texpected: %v\n\t actual: %v", - rt.name, rt.scheme, - actual.Handler.HTTPGet.Scheme) - } + t.Run(rt.name, func(t *testing.T) { + actual := ComponentProbe(rt.cfg, rt.component, rt.port, rt.path, rt.scheme) + if actual.Handler.HTTPGet.Host != rt.expected { + t.Errorf("%s test case failed:\n\texpected: %s\n\t actual: %s", + rt.name, rt.expected, + actual.Handler.HTTPGet.Host) + } + if actual.Handler.HTTPGet.Port != intstr.FromInt(rt.port) { + t.Errorf("%s test case failed:\n\texpected: %v\n\t actual: %v", + rt.name, rt.port, + actual.Handler.HTTPGet.Port) + } + if actual.Handler.HTTPGet.Path != rt.path { + t.Errorf("%s test case failed:\n\texpected: %s\n\t actual: %s", + rt.name, rt.path, + actual.Handler.HTTPGet.Path) + } + if actual.Handler.HTTPGet.Scheme != rt.scheme { + t.Errorf("%s test case failed:\n\texpected: %v\n\t actual: %v", + rt.name, rt.scheme, + actual.Handler.HTTPGet.Scheme) + } + }) } } @@ -330,16 +332,18 @@ func TestEtcdProbe(t *testing.T) { }, } for _, rt := range tests { - // TODO: Make EtcdProbe accept a ClusterConfiguration object instead of InitConfiguration - initcfg := &kubeadmapi.InitConfiguration{ - ClusterConfiguration: *rt.cfg, - } - actual := EtcdProbe(initcfg, rt.component, rt.port, rt.certsDir, rt.cacert, rt.cert, rt.key) - if actual.Handler.Exec.Command[2] != rt.expected { - t.Errorf("%s test case failed:\n\texpected: %s\n\t actual: %s", - rt.name, rt.expected, - actual.Handler.Exec.Command[2]) - } + t.Run(rt.name, func(t *testing.T) { + // TODO: Make EtcdProbe accept a ClusterConfiguration object instead of InitConfiguration + initcfg := &kubeadmapi.InitConfiguration{ + ClusterConfiguration: *rt.cfg, + } + actual := EtcdProbe(initcfg, rt.component, rt.port, rt.certsDir, rt.cacert, rt.cert, rt.key) + if actual.Handler.Exec.Command[2] != rt.expected { + t.Errorf("%s test case failed:\n\texpected: %s\n\t actual: %s", + rt.name, rt.expected, + actual.Handler.Exec.Command[2]) + } + }) } } @@ -376,15 +380,17 @@ func TestComponentPod(t *testing.T) { } for _, rt := range tests { - c := v1.Container{Name: rt.name} - actual := ComponentPod(c, map[string]v1.Volume{}) - if !reflect.DeepEqual(rt.expected, actual) { - t.Errorf( - "failed componentPod:\n\texpected: %v\n\t actual: %v", - rt.expected, - actual, - ) - } + t.Run(rt.name, func(t *testing.T) { + c := v1.Container{Name: rt.name} + actual := ComponentPod(c, map[string]v1.Volume{}) + if !reflect.DeepEqual(rt.expected, actual) { + t.Errorf( + "failed componentPod:\n\texpected: %v\n\t actual: %v", + rt.expected, + actual, + ) + } + }) } } @@ -413,14 +419,16 @@ func TestNewVolume(t *testing.T) { } for _, rt := range tests { - actual := NewVolume(rt.name, rt.path, rt.pathType) - if !reflect.DeepEqual(actual, rt.expected) { - t.Errorf( - "failed newVolume:\n\texpected: %v\n\t actual: %v", - rt.expected, - actual, - ) - } + t.Run(rt.name, func(t *testing.T) { + actual := NewVolume(rt.name, rt.path, rt.pathType) + if !reflect.DeepEqual(actual, rt.expected) { + t.Errorf( + "failed newVolume:\n\texpected: %v\n\t actual: %v", + rt.expected, + actual, + ) + } + }) } } @@ -454,14 +462,16 @@ func TestNewVolumeMount(t *testing.T) { } for _, rt := range tests { - actual := NewVolumeMount(rt.name, rt.path, rt.ro) - if !reflect.DeepEqual(actual, rt.expected) { - t.Errorf( - "failed newVolumeMount:\n\texpected: %v\n\t actual: %v", - rt.expected, - actual, - ) - } + t.Run(rt.name, func(t *testing.T) { + actual := NewVolumeMount(rt.name, rt.path, rt.ro) + if !reflect.DeepEqual(actual, rt.expected) { + t.Errorf( + "failed newVolumeMount:\n\texpected: %v\n\t actual: %v", + rt.expected, + actual, + ) + } + }) } } func TestVolumeMapToSlice(t *testing.T) { @@ -508,11 +518,13 @@ func TestVolumeMountMapToSlice(t *testing.T) { func TestGetExtraParameters(t *testing.T) { var tests = []struct { + name string overrides map[string]string defaults map[string]string expected []string }{ { + name: "with admission-control default NamespaceLifecycle", overrides: map[string]string{ "admission-control": "NamespaceLifecycle,LimitRanger", }, @@ -528,6 +540,7 @@ func TestGetExtraParameters(t *testing.T) { }, }, { + name: "without admission-control default", overrides: map[string]string{ "admission-control": "NamespaceLifecycle,LimitRanger", }, @@ -544,12 +557,14 @@ func TestGetExtraParameters(t *testing.T) { } for _, rt := range tests { - actual := GetExtraParameters(rt.overrides, rt.defaults) - sort.Strings(actual) - sort.Strings(rt.expected) - if !reflect.DeepEqual(actual, rt.expected) { - t.Errorf("failed getExtraParameters:\nexpected:\n%v\nsaw:\n%v", rt.expected, actual) - } + t.Run(rt.name, func(t *testing.T) { + actual := GetExtraParameters(rt.overrides, rt.defaults) + sort.Strings(actual) + sort.Strings(rt.expected) + if !reflect.DeepEqual(actual, rt.expected) { + t.Errorf("failed getExtraParameters:\nexpected:\n%v\nsaw:\n%v", rt.expected, actual) + } + }) } } @@ -599,27 +614,29 @@ func TestReadStaticPodFromDisk(t *testing.T) { } for _, rt := range tests { - tmpdir := testutil.SetupTempDir(t) - defer os.RemoveAll(tmpdir) + t.Run(rt.description, func(t *testing.T) { + tmpdir := testutil.SetupTempDir(t) + defer os.RemoveAll(tmpdir) - manifestPath := filepath.Join(tmpdir, "pod.yaml") - if rt.writeManifest { - err := ioutil.WriteFile(manifestPath, []byte(rt.podYaml), 0644) - if err != nil { - t.Fatalf("Failed to write pod manifest\n%s\n\tfatal error: %v", rt.description, err) + manifestPath := filepath.Join(tmpdir, "pod.yaml") + if rt.writeManifest { + err := ioutil.WriteFile(manifestPath, []byte(rt.podYaml), 0644) + if err != nil { + t.Fatalf("Failed to write pod manifest\n%s\n\tfatal error: %v", rt.description, err) + } } - } - _, actualErr := ReadStaticPodFromDisk(manifestPath) - if (actualErr != nil) != rt.expectErr { - t.Errorf( - "ReadStaticPodFromDisk failed\n%s\n\texpected error: %t\n\tgot: %t\n\tactual error: %v", - rt.description, - rt.expectErr, - (actualErr != nil), - actualErr, - ) - } + _, actualErr := ReadStaticPodFromDisk(manifestPath) + if (actualErr != nil) != rt.expectErr { + t.Errorf( + "ReadStaticPodFromDisk failed\n%s\n\texpected error: %t\n\tgot: %t\n\tactual error: %v", + rt.description, + rt.expectErr, + (actualErr != nil), + actualErr, + ) + } + }) } } @@ -657,38 +674,40 @@ func TestManifestFilesAreEqual(t *testing.T) { } for _, rt := range tests { - tmpdir := testutil.SetupTempDir(t) - defer os.RemoveAll(tmpdir) + t.Run(rt.description, func(t *testing.T) { + tmpdir := testutil.SetupTempDir(t) + defer os.RemoveAll(tmpdir) - // write 2 manifests - for i := 0; i < 2; i++ { - if rt.podYamls[i] != "" { - manifestPath := filepath.Join(tmpdir, strconv.Itoa(i)+".yaml") - err := ioutil.WriteFile(manifestPath, []byte(rt.podYamls[i]), 0644) - if err != nil { - t.Fatalf("Failed to write manifest file\n%s\n\tfatal error: %v", rt.description, err) + // write 2 manifests + for i := 0; i < 2; i++ { + if rt.podYamls[i] != "" { + manifestPath := filepath.Join(tmpdir, strconv.Itoa(i)+".yaml") + err := ioutil.WriteFile(manifestPath, []byte(rt.podYamls[i]), 0644) + if err != nil { + t.Fatalf("Failed to write manifest file\n%s\n\tfatal error: %v", rt.description, err) + } } } - } - // compare them - result, actualErr := ManifestFilesAreEqual(filepath.Join(tmpdir, "0.yaml"), filepath.Join(tmpdir, "1.yaml")) - if result != rt.expectedResult { - t.Errorf( - "ManifestFilesAreEqual failed\n%s\nexpected result: %t\nactual result: %t", - rt.description, - rt.expectedResult, - result, - ) - } - if (actualErr != nil) != rt.expectErr { - t.Errorf( - "ManifestFilesAreEqual failed\n%s\n\texpected error: %t\n\tgot: %t\n\tactual error: %v", - rt.description, - rt.expectErr, - (actualErr != nil), - actualErr, - ) - } + // compare them + result, actualErr := ManifestFilesAreEqual(filepath.Join(tmpdir, "0.yaml"), filepath.Join(tmpdir, "1.yaml")) + if result != rt.expectedResult { + t.Errorf( + "ManifestFilesAreEqual failed\n%s\nexpected result: %t\nactual result: %t", + rt.description, + rt.expectedResult, + result, + ) + } + if (actualErr != nil) != rt.expectErr { + t.Errorf( + "ManifestFilesAreEqual failed\n%s\n\texpected error: %t\n\tgot: %t\n\tactual error: %v", + rt.description, + rt.expectErr, + (actualErr != nil), + actualErr, + ) + } + }) } } diff --git a/cmd/kubeadm/app/util/system/cgroup_validator_test.go b/cmd/kubeadm/app/util/system/cgroup_validator_test.go index c8f8275085d..b9de6abd4b0 100644 --- a/cmd/kubeadm/app/util/system/cgroup_validator_test.go +++ b/cmd/kubeadm/app/util/system/cgroup_validator_test.go @@ -45,12 +45,13 @@ func TestValidateCgroupSubsystem(t *testing.T) { err: false, }, } { - err := v.validateCgroupSubsystems(cgroupSpec, test.subsystems) - if !test.err { - assert.Nil(t, err, "%q: Expect error not to occur with cgroup", desc) - } else { - assert.NotNil(t, err, "%q: Expect error to occur with docker info", desc) - } - + t.Run(desc, func(t *testing.T) { + err := v.validateCgroupSubsystems(cgroupSpec, test.subsystems) + if !test.err { + assert.Nil(t, err, "%q: Expect error not to occur with cgroup", desc) + } else { + assert.NotNil(t, err, "%q: Expect error to occur with docker info", desc) + } + }) } } diff --git a/cmd/kubeadm/app/util/system/docker_validator_test.go b/cmd/kubeadm/app/util/system/docker_validator_test.go index 19b7e9adf37..28993486643 100644 --- a/cmd/kubeadm/app/util/system/docker_validator_test.go +++ b/cmd/kubeadm/app/util/system/docker_validator_test.go @@ -32,72 +32,84 @@ func TestValidateDockerInfo(t *testing.T) { GraphDriver: []string{"driver_1", "driver_2"}, } for _, test := range []struct { + name string info types.Info err bool warn bool }{ { + name: "unsupported Docker version 1.10.1", info: types.Info{Driver: "driver_1", ServerVersion: "1.10.1"}, err: true, warn: false, }, { + name: "unsupported driver", info: types.Info{Driver: "bad_driver", ServerVersion: "1.11.1"}, err: true, warn: false, }, { + name: "valid Docker version 1.11.1", info: types.Info{Driver: "driver_1", ServerVersion: "1.11.1"}, err: false, warn: false, }, { + name: "valid Docker version 1.12.1", info: types.Info{Driver: "driver_2", ServerVersion: "1.12.1"}, err: false, warn: false, }, { + name: "valid Docker version 1.13.1", info: types.Info{Driver: "driver_2", ServerVersion: "1.13.1"}, err: false, warn: false, }, { + name: "valid Docker version 17.03.0-ce", info: types.Info{Driver: "driver_2", ServerVersion: "17.03.0-ce"}, err: false, warn: false, }, { + name: "valid Docker version 17.06.0-ce", info: types.Info{Driver: "driver_2", ServerVersion: "17.06.0-ce"}, err: false, warn: false, }, { + name: "valid Docker version 17.09.0-ce", info: types.Info{Driver: "driver_2", ServerVersion: "17.09.0-ce"}, err: false, warn: false, }, { + name: "valid Docker version 18.06.0-ce", info: types.Info{Driver: "driver_2", ServerVersion: "18.06.0-ce"}, err: false, warn: false, }, { + name: "Docker version 18.09.0 is not in the list of validated versions", info: types.Info{Driver: "driver_2", ServerVersion: "18.09.0"}, err: false, warn: true, }, } { - warn, err := v.validateDockerInfo(spec, test.info) - if !test.err { - assert.Nil(t, err, "Expect error not to occur with docker info %+v", test.info) - } else { - assert.NotNil(t, err, "Expect error to occur with docker info %+v", test.info) - } - if !test.warn { - assert.Nil(t, warn, "Expect error not to occur with docker info %+v", test.info) - } else { - assert.NotNil(t, warn, "Expect error to occur with docker info %+v", test.info) - } - + t.Run(test.name, func(t *testing.T) { + warn, err := v.validateDockerInfo(spec, test.info) + if !test.err { + assert.Nil(t, err, "Expect error not to occur with docker info %+v", test.info) + } else { + assert.NotNil(t, err, "Expect error to occur with docker info %+v", test.info) + } + if !test.warn { + assert.Nil(t, warn, "Expect error not to occur with docker info %+v", test.info) + } else { + assert.NotNil(t, warn, "Expect error to occur with docker info %+v", test.info) + } + }) } } diff --git a/cmd/kubeadm/app/util/system/kernel_validator.go b/cmd/kubeadm/app/util/system/kernel_validator.go index 36ecd20dbdb..869464a165c 100644 --- a/cmd/kubeadm/app/util/system/kernel_validator.go +++ b/cmd/kubeadm/app/util/system/kernel_validator.go @@ -29,10 +29,10 @@ import ( "regexp" "strings" - pkgerrors "github.com/pkg/errors" - "k8s.io/klog" + "github.com/pkg/errors" - "k8s.io/apimachinery/pkg/util/errors" + errorsutil "k8s.io/apimachinery/pkg/util/errors" + "k8s.io/klog" ) var _ Validator = &KernelValidator{} @@ -66,7 +66,7 @@ func (k *KernelValidator) Validate(spec SysSpec) (error, error) { helper := KernelValidatorHelperImpl{} release, err := helper.GetKernelReleaseVersion() if err != nil { - return nil, pkgerrors.Wrap(err, "failed to get kernel release") + return nil, errors.Wrap(err, "failed to get kernel release") } k.kernelRelease = release var errs []error @@ -75,7 +75,7 @@ func (k *KernelValidator) Validate(spec SysSpec) (error, error) { if len(spec.KernelSpec.Required) > 0 || len(spec.KernelSpec.Forbidden) > 0 || len(spec.KernelSpec.Optional) > 0 { errs = append(errs, k.validateKernelConfig(spec.KernelSpec)) } - return nil, errors.NewAggregate(errs) + return nil, errorsutil.NewAggregate(errs) } // validateKernelVersion validates the kernel version. @@ -89,14 +89,14 @@ func (k *KernelValidator) validateKernelVersion(kSpec KernelSpec) error { } } k.Reporter.Report("KERNEL_VERSION", k.kernelRelease, bad) - return pkgerrors.Errorf("unsupported kernel release: %s", k.kernelRelease) + return errors.Errorf("unsupported kernel release: %s", k.kernelRelease) } // validateKernelConfig validates the kernel configurations. func (k *KernelValidator) validateKernelConfig(kSpec KernelSpec) error { allConfig, err := k.getKernelConfig() if err != nil { - return pkgerrors.Wrap(err, "failed to parse kernel config") + return errors.Wrap(err, "failed to parse kernel config") } return k.validateCachedKernelConfig(allConfig, kSpec) } @@ -165,7 +165,7 @@ func (k *KernelValidator) validateCachedKernelConfig(allConfig map[string]kConfi validateOpt(config, forbidden) } if len(badConfigs) > 0 { - return pkgerrors.Errorf("unexpected kernel config: %s", strings.Join(badConfigs, " ")) + return errors.Errorf("unexpected kernel config: %s", strings.Join(badConfigs, " ")) } return nil } @@ -220,14 +220,14 @@ func (k *KernelValidator) getKernelConfigReader() (io.Reader, error) { // config module and check again. output, err := exec.Command(modprobeCmd, configsModule).CombinedOutput() if err != nil { - return nil, pkgerrors.Wrapf(err, "unable to load kernel module: %q, output: %q, err", + return nil, errors.Wrapf(err, "unable to load kernel module: %q, output: %q, err", configsModule, output) } // Unload the kernel config module to make sure the validation have no side effect. defer exec.Command(modprobeCmd, "-r", configsModule).Run() loadModule = true } - return nil, pkgerrors.Errorf("no config path in %v is available", possibePaths) + return nil, errors.Errorf("no config path in %v is available", possibePaths) } // getKernelConfig gets kernel config from kernel config file and convert kernel config to internal type. diff --git a/cmd/kubeadm/app/util/system/kernel_validator_test.go b/cmd/kubeadm/app/util/system/kernel_validator_test.go index 92daad28c69..e1cfedb5cf6 100644 --- a/cmd/kubeadm/app/util/system/kernel_validator_test.go +++ b/cmd/kubeadm/app/util/system/kernel_validator_test.go @@ -33,40 +33,45 @@ func TestValidateKernelVersion(t *testing.T) { // not the DefaultSysSpec. The DefaultSysSpec should be tested with node e2e. testRegex := []string{`3\.[1-9][0-9].*`, `4\..*`} for _, test := range []struct { + name string version string err bool }{ - // first version regex matches { + name: "3.19.9-99-test first version regex matches", version: "3.19.9-99-test", err: false, }, - // one of version regexes matches { + name: "4.4.14+ one of version regexes matches", version: "4.4.14+", err: false, }, - // no version regex matches { + name: "2.0.0 no version regex matches", version: "2.0.0", err: true, }, { + name: "5.0.0 no version regex matches", version: "5.0.0", err: true, }, { + name: "3.9.0 no version regex matches", version: "3.9.0", err: true, }, } { - v.kernelRelease = test.version - err := v.validateKernelVersion(KernelSpec{Versions: testRegex}) - if !test.err { - assert.Nil(t, err, "Expect error not to occur with kernel version %q", test.version) - } else { - assert.NotNil(t, err, "Expect error to occur with kenrel version %q", test.version) - } + t.Run(test.name, func(t *testing.T) { + v.kernelRelease = test.version + err := v.validateKernelVersion(KernelSpec{Versions: testRegex}) + if !test.err { + assert.Nil(t, err, "Expect error not to occur with kernel version %q", test.version) + } else { + assert.NotNil(t, err, "Expect error to occur with kenrel version %q", test.version) + } + }) } } @@ -82,13 +87,13 @@ func TestValidateCachedKernelConfig(t *testing.T) { {Name: "FORBIDDEN_2", Aliases: []string{"ALIASE_FORBIDDEN_2"}}, }, } - for c, test := range []struct { + for _, test := range []struct { desc string config map[string]kConfigOption err bool }{ { - desc: "meet all required configurations should not report error.", + desc: "meet all required configurations should not report error", config: map[string]kConfigOption{ "REQUIRED_1": builtIn, "REQUIRED_2": asModule, @@ -96,7 +101,7 @@ func TestValidateCachedKernelConfig(t *testing.T) { err: false, }, { - desc: "one required configuration disabled should report error.", + desc: "one required configuration disabled should report error", config: map[string]kConfigOption{ "REQUIRED_1": leftOut, "REQUIRED_2": builtIn, @@ -104,14 +109,14 @@ func TestValidateCachedKernelConfig(t *testing.T) { err: true, }, { - desc: "one required configuration missing should report error.", + desc: "one required configuration missing should report error", config: map[string]kConfigOption{ "REQUIRED_1": builtIn, }, err: true, }, { - desc: "alias of required configuration should not report error.", + desc: "alias of required configuration should not report error", config: map[string]kConfigOption{ "REQUIRED_1": builtIn, "ALIASE_REQUIRED_2": asModule, @@ -119,7 +124,7 @@ func TestValidateCachedKernelConfig(t *testing.T) { err: false, }, { - desc: "optional configuration set or not should not report error.", + desc: "optional configuration set or not should not report error", config: map[string]kConfigOption{ "REQUIRED_1": builtIn, "REQUIRED_2": asModule, @@ -128,7 +133,7 @@ func TestValidateCachedKernelConfig(t *testing.T) { err: false, }, { - desc: "forbidden configuration disabled should not report error.", + desc: "forbidden configuration disabled should not report error", config: map[string]kConfigOption{ "REQUIRED_1": builtIn, "REQUIRED_2": asModule, @@ -137,7 +142,7 @@ func TestValidateCachedKernelConfig(t *testing.T) { err: false, }, { - desc: "forbidden configuration built-in should report error.", + desc: "forbidden configuration built-in should report error", config: map[string]kConfigOption{ "REQUIRED_1": builtIn, "REQUIRED_2": asModule, @@ -146,7 +151,7 @@ func TestValidateCachedKernelConfig(t *testing.T) { err: true, }, { - desc: "forbidden configuration built as module should report error.", + desc: "forbidden configuration built as module should report error", config: map[string]kConfigOption{ "REQUIRED_1": builtIn, "REQUIRED_2": asModule, @@ -155,7 +160,7 @@ func TestValidateCachedKernelConfig(t *testing.T) { err: true, }, { - desc: "alias of forbidden configuration should report error.", + desc: "alias of forbidden configuration should report error", config: map[string]kConfigOption{ "REQUIRED_1": builtIn, "REQUIRED_2": asModule, @@ -164,18 +169,19 @@ func TestValidateCachedKernelConfig(t *testing.T) { err: true, }, } { - t.Logf("TestCase #%d %s", c, test.desc) - // Add kernel config prefix. - for k, v := range test.config { - delete(test.config, k) - test.config[kConfigPrefix+k] = v - } - err := v.validateCachedKernelConfig(test.config, testKernelSpec) - if !test.err { - assert.Nil(t, err, "Expect error not to occur with kernel config %q", test.config) - } else { - assert.NotNil(t, err, "Expect error to occur with kenrel config %q", test.config) - } + t.Run(test.desc, func(t *testing.T) { + // Add kernel config prefix. + for k, v := range test.config { + delete(test.config, k) + test.config[kConfigPrefix+k] = v + } + err := v.validateCachedKernelConfig(test.config, testKernelSpec) + if !test.err { + assert.Nil(t, err, "Expect error not to occur with kernel config %q", test.config) + } else { + assert.NotNil(t, err, "Expect error to occur with kenrel config %q", test.config) + } + }) } } diff --git a/cmd/kubeadm/app/util/system/os_validator_test.go b/cmd/kubeadm/app/util/system/os_validator_test.go index f4338f74a75..6c325025922 100644 --- a/cmd/kubeadm/app/util/system/os_validator_test.go +++ b/cmd/kubeadm/app/util/system/os_validator_test.go @@ -44,11 +44,13 @@ func TestValidateOS(t *testing.T) { err: true, }, } { - err := v.validateOS(test.os, specOS) - if !test.err { - assert.Nil(t, err, "Expect error not to occur with os %q", test.os) - } else { - assert.NotNil(t, err, "Expect error to occur with os %q", test.os) - } + t.Run(test.os, func(t *testing.T) { + err := v.validateOS(test.os, specOS) + if !test.err { + assert.Nil(t, err, "Expect error not to occur with os %q", test.os) + } else { + assert.NotNil(t, err, "Expect error to occur with os %q", test.os) + } + }) } } diff --git a/cmd/kubeadm/app/util/system/package_validator.go b/cmd/kubeadm/app/util/system/package_validator.go index 820c68e6c2b..18fb9777eef 100644 --- a/cmd/kubeadm/app/util/system/package_validator.go +++ b/cmd/kubeadm/app/util/system/package_validator.go @@ -22,10 +22,10 @@ import ( "os/exec" "strings" - "k8s.io/apimachinery/pkg/util/errors" - "github.com/blang/semver" - pkgerrors "github.com/pkg/errors" + "github.com/pkg/errors" + + errorsutil "k8s.io/apimachinery/pkg/util/errors" "k8s.io/klog" ) @@ -46,7 +46,7 @@ func newPackageManager() (packageManager, error) { if m, ok := newDPKG(); ok { return m, nil } - return nil, pkgerrors.New("failed to find package manager") + return nil, errors.New("failed to find package manager") } // dpkg implements packageManager. It uses "dpkg-query" to retrieve package @@ -65,14 +65,14 @@ func newDPKG() (packageManager, bool) { // getPackageVersion returns the upstream package version for the package given // the packageName, and an error if no such package exists. -func (_ dpkg) getPackageVersion(packageName string) (string, error) { +func (dpkg) getPackageVersion(packageName string) (string, error) { output, err := exec.Command("dpkg-query", "--show", "--showformat='${Version}'", packageName).Output() if err != nil { - return "", pkgerrors.Wrap(err, "dpkg-query failed") + return "", errors.Wrap(err, "dpkg-query failed") } version := extractUpstreamVersion(string(output)) if version == "" { - return "", pkgerrors.New("no version information") + return "", errors.New("no version information") } return version, nil } @@ -86,23 +86,23 @@ type packageValidator struct { } // Name returns the name of the package validator. -func (self *packageValidator) Name() string { +func (validator *packageValidator) Name() string { return "package" } // Validate checks packages and their versions against the spec using the // package manager on the running machine, and returns an error on any // package/version mismatch. -func (self *packageValidator) Validate(spec SysSpec) (error, error) { +func (validator *packageValidator) Validate(spec SysSpec) (error, error) { if len(spec.PackageSpecs) == 0 { return nil, nil } var err error - if self.kernelRelease, err = getKernelRelease(); err != nil { + if validator.kernelRelease, err = getKernelRelease(); err != nil { return nil, err } - if self.osDistro, err = getOSDistro(); err != nil { + if validator.osDistro, err = getOSDistro(); err != nil { return nil, err } @@ -110,17 +110,17 @@ func (self *packageValidator) Validate(spec SysSpec) (error, error) { if err != nil { return nil, err } - specs := applyPackageSpecOverride(spec.PackageSpecs, spec.PackageSpecOverrides, self.osDistro) - return self.validate(specs, manager) + specs := applyPackageSpecOverride(spec.PackageSpecs, spec.PackageSpecOverrides, validator.osDistro) + return validator.validate(specs, manager) } // Validate checks packages and their versions against the packageSpecs using // the packageManager, and returns an error on any package/version mismatch. -func (self *packageValidator) validate(packageSpecs []PackageSpec, manager packageManager) (error, error) { +func (validator *packageValidator) validate(packageSpecs []PackageSpec, manager packageManager) (error, error) { var errs []error for _, spec := range packageSpecs { // Substitute variables in package name. - packageName := resolvePackageName(spec.Name, self.kernelRelease) + packageName := resolvePackageName(spec.Name, validator.kernelRelease) nameWithVerRange := fmt.Sprintf("%s (%s)", packageName, spec.VersionRange) @@ -129,14 +129,14 @@ func (self *packageValidator) validate(packageSpecs []PackageSpec, manager packa if err != nil { klog.V(1).Infof("Failed to get the version for the package %q: %s\n", packageName, err) errs = append(errs, err) - self.reporter.Report(nameWithVerRange, "not installed", bad) + validator.reporter.Report(nameWithVerRange, "not installed", bad) continue } // Version requirement will not be enforced if version range is // not specified in the spec. if spec.VersionRange == "" { - self.reporter.Report(packageName, version, good) + validator.reporter.Report(packageName, version, good) continue } @@ -147,25 +147,25 @@ func (self *packageValidator) validate(packageSpecs []PackageSpec, manager packa if err != nil { klog.Errorf("Failed to convert %q to semantic version: %s\n", version, err) errs = append(errs, err) - self.reporter.Report(nameWithVerRange, "internal error", bad) + validator.reporter.Report(nameWithVerRange, "internal error", bad) continue } versionRange := semver.MustParseRange(toSemVerRange(spec.VersionRange)) if versionRange(sv) { - self.reporter.Report(nameWithVerRange, version, good) + validator.reporter.Report(nameWithVerRange, version, good) } else { - errs = append(errs, pkgerrors.Errorf("package \"%s %s\" does not meet the spec \"%s (%s)\"", packageName, sv, packageName, spec.VersionRange)) - self.reporter.Report(nameWithVerRange, version, bad) + errs = append(errs, errors.Errorf("package \"%s %s\" does not meet the spec \"%s (%s)\"", packageName, sv, packageName, spec.VersionRange)) + validator.reporter.Report(nameWithVerRange, version, bad) } } - return nil, errors.NewAggregate(errs) + return nil, errorsutil.NewAggregate(errs) } // getKernelRelease returns the kernel release of the local machine. func getKernelRelease() (string, error) { output, err := exec.Command("uname", "-r").Output() if err != nil { - return "", pkgerrors.Wrap(err, "failed to get kernel release") + return "", errors.Wrap(err, "failed to get kernel release") } return strings.TrimSpace(string(output)), nil } @@ -175,7 +175,7 @@ func getOSDistro() (string, error) { f := "/etc/lsb-release" b, err := ioutil.ReadFile(f) if err != nil { - return "", pkgerrors.Wrapf(err, "failed to read %q", f) + return "", errors.Wrapf(err, "failed to read %q", f) } content := string(b) switch { @@ -186,7 +186,7 @@ func getOSDistro() (string, error) { case strings.Contains(content, "CoreOS"): return "coreos", nil default: - return "", pkgerrors.Errorf("failed to get OS distro: %s", content) + return "", errors.Errorf("failed to get OS distro: %s", content) } } diff --git a/cmd/kubeadm/app/util/system/package_validator_test.go b/cmd/kubeadm/app/util/system/package_validator_test.go index 3387a454a68..c88956a6327 100644 --- a/cmd/kubeadm/app/util/system/package_validator_test.go +++ b/cmd/kubeadm/app/util/system/package_validator_test.go @@ -17,6 +17,7 @@ limitations under the License. package system import ( + "fmt" "reflect" "testing" @@ -49,10 +50,12 @@ func TestExtractUpstreamVersion(t *testing.T) { expected: "1.0.6", }, } { - got := extractUpstreamVersion(test.input) - if test.expected != got { - t.Errorf("extractUpstreamVersion(%q) = %q, want %q", test.input, got, test.expected) - } + t.Run(fmt.Sprintf("input:%s,expected:%s", test.input, test.expected), func(t *testing.T) { + got := extractUpstreamVersion(test.input) + if test.expected != got { + t.Errorf("extractUpstreamVersion(%q) = %q, want %q", test.input, got, test.expected) + } + }) } } @@ -106,10 +109,12 @@ func TestToSemVer(t *testing.T) { expected: "8.0.95", }, } { - got := toSemVer(test.input) - if test.expected != got { - t.Errorf("toSemVer(%q) = %q, want %q", test.input, got, test.expected) - } + t.Run(fmt.Sprintf("input:%s,expected:%s", test.input, test.expected), func(t *testing.T) { + got := toSemVer(test.input) + if test.expected != got { + t.Errorf("toSemVer(%q) = %q, want %q", test.input, got, test.expected) + } + }) } } @@ -143,10 +148,12 @@ func TestToSemVerRange(t *testing.T) { expected: ">1.x || >3.1.0 !4.2.x", }, } { - got := toSemVerRange(test.input) - if test.expected != got { - t.Errorf("toSemVerRange(%q) = %q, want %q", test.input, got, test.expected) - } + t.Run(fmt.Sprintf("input:%s,expected:%s", test.input, test.expected), func(t *testing.T) { + got := toSemVerRange(test.input) + if test.expected != got { + t.Errorf("toSemVerRange(%q) = %q, want %q", test.input, got, test.expected) + } + }) } } @@ -209,32 +216,37 @@ func TestValidatePackageVersion(t *testing.T) { }, }, } { - _, err := v.validate(test.specs, manager) - if test.err == nil && err != nil { - t.Errorf("%s: v.validate(): err = %s", test.desc, err) - } - if test.err != nil { - if err == nil { - t.Errorf("%s: v.validate() is expected to fail.", test.desc) - } else if test.err.Error() != err.Error() { - t.Errorf("%s: v.validate(): err = %q, want = %q", test.desc, err, test.err) + t.Run(test.desc, func(t *testing.T) { + _, err := v.validate(test.specs, manager) + if test.err == nil && err != nil { + t.Errorf("%s: v.validate(): err = %s", test.desc, err) } - } + if test.err != nil { + if err == nil { + t.Errorf("%s: v.validate() is expected to fail.", test.desc) + } else if test.err.Error() != err.Error() { + t.Errorf("%s: v.validate(): err = %q, want = %q", test.desc, err, test.err) + } + } + }) } } func TestApplyPackageOverride(t *testing.T) { for _, test := range []struct { + name string overrides []PackageSpecOverride osDistro string specs []PackageSpec expected []PackageSpec }{ { + name: "foo>=1.0", specs: []PackageSpec{{Name: "foo", VersionRange: ">=1.0"}}, expected: []PackageSpec{{Name: "foo", VersionRange: ">=1.0"}}, }, { + name: "ubuntu:foo>=1.0/bar>=2.0", osDistro: "ubuntu", overrides: []PackageSpecOverride{ { @@ -247,6 +259,7 @@ func TestApplyPackageOverride(t *testing.T) { expected: []PackageSpec{{Name: "bar", VersionRange: ">=2.0"}}, }, { + name: "ubuntu:foo>=1.0/debian:foo", osDistro: "ubuntu", overrides: []PackageSpecOverride{ { @@ -258,9 +271,11 @@ func TestApplyPackageOverride(t *testing.T) { expected: []PackageSpec{{Name: "foo", VersionRange: ">=1.0"}}, }, } { - got := applyPackageSpecOverride(test.specs, test.overrides, test.osDistro) - if !reflect.DeepEqual(test.expected, got) { - t.Errorf("applyPackageSpecOverride(%+v, %+v, %s) = %+v, want = %+v", test.specs, test.overrides, test.osDistro, got, test.expected) - } + t.Run(test.name, func(t *testing.T) { + got := applyPackageSpecOverride(test.specs, test.overrides, test.osDistro) + if !reflect.DeepEqual(test.expected, got) { + t.Errorf("applyPackageSpecOverride(%+v, %+v, %s) = %+v, want = %+v", test.specs, test.overrides, test.osDistro, got, test.expected) + } + }) } } diff --git a/cmd/kubeadm/app/util/system/validators.go b/cmd/kubeadm/app/util/system/validators.go index c1f1c15ae45..01daa0f3676 100644 --- a/cmd/kubeadm/app/util/system/validators.go +++ b/cmd/kubeadm/app/util/system/validators.go @@ -18,7 +18,8 @@ package system import ( "fmt" - "k8s.io/apimachinery/pkg/util/errors" + + errorsutil "k8s.io/apimachinery/pkg/util/errors" ) // Validator is the interface for all validators. @@ -46,7 +47,7 @@ func Validate(spec SysSpec, validators []Validator) (error, error) { errs = append(errs, err) warns = append(warns, warn) } - return errors.NewAggregate(warns), errors.NewAggregate(errs) + return errorsutil.NewAggregate(warns), errorsutil.NewAggregate(errs) } // ValidateSpec uses all default validators to validate the system and writes to stdout. diff --git a/cmd/kubeadm/app/util/template_test.go b/cmd/kubeadm/app/util/template_test.go index 6f795e469a8..c6d3def0669 100644 --- a/cmd/kubeadm/app/util/template_test.go +++ b/cmd/kubeadm/app/util/template_test.go @@ -30,13 +30,14 @@ const ( func TestParseTemplate(t *testing.T) { var tmplTests = []struct { + name string template string data interface{} output string errExpected bool }{ - // should parse a valid template and set the right values { + name: "should parse a valid template and set the right values", template: validTmpl, data: struct{ ImageRepository, Arch string }{ ImageRepository: "k8s.gcr.io", @@ -45,8 +46,8 @@ func TestParseTemplate(t *testing.T) { output: validTmplOut, errExpected: false, }, - // should noop if there aren't any {{ .foo }} present { + name: "should noop if there aren't any {{ .foo }} present", template: doNothing, data: struct{ ImageRepository, Arch string }{ ImageRepository: "k8s.gcr.io", @@ -55,15 +56,15 @@ func TestParseTemplate(t *testing.T) { output: doNothing, errExpected: false, }, - // invalid syntax, passing nil { + name: "invalid syntax, passing nil", template: invalidTmpl1, data: nil, output: "", errExpected: true, }, - // invalid syntax { + name: "invalid syntax", template: invalidTmpl2, data: struct{}{}, output: "", @@ -71,20 +72,22 @@ func TestParseTemplate(t *testing.T) { }, } for _, tt := range tmplTests { - outbytes, err := ParseTemplate(tt.template, tt.data) - if tt.errExpected != (err != nil) { - t.Errorf( - "failed TestParseTemplate:\n\texpected err: %t\n\t actual: %s", - tt.errExpected, - err, - ) - } - if tt.output != string(outbytes) { - t.Errorf( - "failed TestParseTemplate:\n\texpected bytes: %s\n\t actual: %s", - tt.output, - outbytes, - ) - } + t.Run(tt.name, func(t *testing.T) { + outbytes, err := ParseTemplate(tt.template, tt.data) + if tt.errExpected != (err != nil) { + t.Errorf( + "failed TestParseTemplate:\n\texpected err: %t\n\t actual: %s", + tt.errExpected, + err, + ) + } + if tt.output != string(outbytes) { + t.Errorf( + "failed TestParseTemplate:\n\texpected bytes: %s\n\t actual: %s", + tt.output, + outbytes, + ) + } + }) } } diff --git a/cmd/kubeadm/app/util/version.go b/cmd/kubeadm/app/util/version.go index 4da6ce48aef..198e6d9d6b1 100644 --- a/cmd/kubeadm/app/util/version.go +++ b/cmd/kubeadm/app/util/version.go @@ -17,7 +17,6 @@ limitations under the License. package util import ( - "errors" "fmt" "io/ioutil" "net/http" @@ -25,7 +24,8 @@ import ( "strings" "time" - pkgerrors "github.com/pkg/errors" + "github.com/pkg/errors" + netutil "k8s.io/apimachinery/pkg/util/net" versionutil "k8s.io/apimachinery/pkg/util/version" "k8s.io/klog" @@ -79,9 +79,11 @@ func KubernetesReleaseVersion(version string) (string, error) { // kubeReleaseLabelRegex matches labels such as: latest, latest-1, latest-1.10 if kubeReleaseLabelRegex.MatchString(versionLabel) { - var clientVersion string // Try to obtain a client version. - clientVersion, _ = kubeadmVersion(pkgversion.Get().String()) + // pkgversion.Get().String() should always return a correct version added by the golang + // linker and the build system. The version can still be missing when doing unit tests + // on individual packages. + clientVersion, clientVersionErr := kubeadmVersion(pkgversion.Get().String()) // Fetch version from the internet. url := fmt.Sprintf("%s/%s.txt", bucketURL, versionLabel) body, err := fetchFromURL(url, getReleaseVersionTimeout) @@ -95,6 +97,12 @@ func KubernetesReleaseVersion(version string) (string, error) { klog.Infof("falling back to the local client version: %s", clientVersion) return KubernetesReleaseVersion(clientVersion) } + + if clientVersionErr != nil { + klog.Warningf("could not obtain client version; using remote version: %s", body) + return KubernetesReleaseVersion(body) + } + // both the client and the remote version are obtained; validate them and pick a stable version body, err = validateStableVersion(body, clientVersion) if err != nil { @@ -103,7 +111,7 @@ func KubernetesReleaseVersion(version string) (string, error) { // Re-validate received version and return. return KubernetesReleaseVersion(body) } - return "", pkgerrors.Errorf("version %q doesn't match patterns for neither semantic version nor labels (stable, latest, ...)", version) + return "", errors.Errorf("version %q doesn't match patterns for neither semantic version nor labels (stable, latest, ...)", version) } // KubernetesVersionToImageTag is helper function that replaces all @@ -144,7 +152,7 @@ func splitVersion(version string) (string, string, error) { var urlSuffix string subs := kubeBucketPrefixes.FindAllStringSubmatch(version, 1) if len(subs) != 1 || len(subs[0]) != 4 { - return "", "", pkgerrors.Errorf("invalid version %q", version) + return "", "", errors.Errorf("invalid version %q", version) } switch { @@ -164,12 +172,12 @@ func fetchFromURL(url string, timeout time.Duration) (string, error) { client := &http.Client{Timeout: timeout, Transport: netutil.SetOldTransportDefaults(&http.Transport{})} resp, err := client.Get(url) if err != nil { - return "", pkgerrors.Errorf("unable to get URL %q: %s", url, err.Error()) + return "", errors.Errorf("unable to get URL %q: %s", url, err.Error()) } defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) if err != nil { - return "", pkgerrors.Errorf("unable to read content of URL %q: %s", url, err.Error()) + return "", errors.Errorf("unable to read content of URL %q: %s", url, err.Error()) } bodyString := strings.TrimSpace(string(body)) @@ -184,7 +192,7 @@ func fetchFromURL(url string, timeout time.Duration) (string, error) { func kubeadmVersion(info string) (string, error) { v, err := versionutil.ParseSemantic(info) if err != nil { - return "", pkgerrors.Wrap(err, "kubeadm version error") + return "", errors.Wrap(err, "kubeadm version error") } // There is no utility in versionutil to get the version without the metadata, // so this needs some manual formatting. @@ -216,18 +224,13 @@ func kubeadmVersion(info string) (string, error) { // This is done to conform with "stable-X" and only allow remote versions from // the same Patch level release. func validateStableVersion(remoteVersion, clientVersion string) (string, error) { - if clientVersion == "" { - klog.Infof("could not obtain client version; using remote version: %s", remoteVersion) - return remoteVersion, nil - } - verRemote, err := versionutil.ParseGeneric(remoteVersion) if err != nil { - return "", pkgerrors.Wrap(err, "remote version error") + return "", errors.Wrap(err, "remote version error") } verClient, err := versionutil.ParseGeneric(clientVersion) if err != nil { - return "", pkgerrors.Wrap(err, "client version error") + return "", errors.Wrap(err, "client version error") } // If the remote Major version is bigger or if the Major versions are the same, // but the remote Minor is bigger use the client version release. This handles Major bumps too. diff --git a/cmd/kubeadm/app/util/version_test.go b/cmd/kubeadm/app/util/version_test.go index 3444d6c0a22..f40f261338b 100644 --- a/cmd/kubeadm/app/util/version_test.go +++ b/cmd/kubeadm/app/util/version_test.go @@ -17,6 +17,7 @@ limitations under the License. package util import ( + "fmt" "net/http" "net/http/httptest" "path" @@ -48,14 +49,16 @@ func TestValidVersion(t *testing.T) { "v1.6.1+coreos.0", } for _, s := range validVersions { - ver, err := KubernetesReleaseVersion(s) - t.Log("Valid: ", s, ver, err) - if err != nil { - t.Errorf("KubernetesReleaseVersion unexpected error for version %q: %v", s, err) - } - if ver != s { - t.Errorf("KubernetesReleaseVersion should return same valid version string. %q != %q", s, ver) - } + t.Run(s, func(t *testing.T) { + ver, err := KubernetesReleaseVersion(s) + t.Log("Valid: ", s, ver, err) + if err != nil { + t.Errorf("KubernetesReleaseVersion unexpected error for version %q: %v", s, err) + } + if ver != s { + t.Errorf("KubernetesReleaseVersion should return same valid version string. %q != %q", s, ver) + } + }) } } @@ -68,14 +71,16 @@ func TestInvalidVersion(t *testing.T) { "something1.2", } for _, s := range invalidVersions { - ver, err := KubernetesReleaseVersion(s) - t.Log("Invalid: ", s, ver, err) - if err == nil { - t.Errorf("KubernetesReleaseVersion error expected for version %q, but returned successfully", s) - } - if ver != "" { - t.Errorf("KubernetesReleaseVersion should return empty string in case of error. Returned %q for version %q", ver, s) - } + t.Run(s, func(t *testing.T) { + ver, err := KubernetesReleaseVersion(s) + t.Log("Invalid: ", s, ver, err) + if err == nil { + t.Errorf("KubernetesReleaseVersion error expected for version %q, but returned successfully", s) + } + if ver != "" { + t.Errorf("KubernetesReleaseVersion should return empty string in case of error. Returned %q for version %q", ver, s) + } + }) } } @@ -86,14 +91,16 @@ func TestValidConvenientForUserVersion(t *testing.T) { "1.6.1_coreos.0", } for _, s := range validVersions { - ver, err := KubernetesReleaseVersion(s) - t.Log("Valid: ", s, ver, err) - if err != nil { - t.Errorf("KubernetesReleaseVersion unexpected error for version %q: %v", s, err) - } - if ver != "v"+s { - t.Errorf("KubernetesReleaseVersion should return semantic version string. %q vs. %q", s, ver) - } + t.Run(s, func(t *testing.T) { + ver, err := KubernetesReleaseVersion(s) + t.Log("Valid: ", s, ver, err) + if err != nil { + t.Errorf("KubernetesReleaseVersion unexpected error for version %q: %v", s, err) + } + if ver != "v"+s { + t.Errorf("KubernetesReleaseVersion should return semantic version string. %q vs. %q", s, ver) + } + }) } } @@ -128,16 +135,18 @@ func TestVersionFromNetwork(t *testing.T) { kubeReleaseBucketURL = server.URL for k, v := range cases { - ver, err := KubernetesReleaseVersion(k) - t.Logf("Key: %q. Result: %q, Error: %v", k, ver, err) - switch { - case err != nil && !v.ErrorExpected: - t.Errorf("KubernetesReleaseVersion: unexpected error for %q. Error: %v", k, err) - case err == nil && v.ErrorExpected: - t.Errorf("KubernetesReleaseVersion: error expected for key %q, but result is %q", k, ver) - case ver != v.Expected: - t.Errorf("KubernetesReleaseVersion: unexpected result for key %q. Expected: %q Actual: %q", k, v.Expected, ver) - } + t.Run(k, func(t *testing.T) { + ver, err := KubernetesReleaseVersion(k) + t.Logf("Key: %q. Result: %q, Error: %v", k, ver, err) + switch { + case err != nil && !v.ErrorExpected: + t.Errorf("KubernetesReleaseVersion: unexpected error for %q. Error: %+v", k, err) + case err == nil && v.ErrorExpected: + t.Errorf("KubernetesReleaseVersion: error expected for key %q, but result is %q", k, ver) + case ver != v.Expected: + t.Errorf("KubernetesReleaseVersion: unexpected result for key %q. Expected: %q Actual: %q", k, v.Expected, ver) + } + }) } } @@ -158,11 +167,13 @@ func TestVersionToTag(t *testing.T) { } for _, tc := range cases { - tag := KubernetesVersionToImageTag(tc.input) - t.Logf("KubernetesVersionToImageTag: Input: %q. Result: %q. Expected: %q", tc.input, tag, tc.expected) - if tag != tc.expected { - t.Errorf("failed KubernetesVersionToImageTag: Input: %q. Result: %q. Expected: %q", tc.input, tag, tc.expected) - } + t.Run(fmt.Sprintf("input:%s/expected:%s", tc.input, tc.expected), func(t *testing.T) { + tag := KubernetesVersionToImageTag(tc.input) + t.Logf("KubernetesVersionToImageTag: Input: %q. Result: %q. Expected: %q", tc.input, tag, tc.expected) + if tag != tc.expected { + t.Errorf("failed KubernetesVersionToImageTag: Input: %q. Result: %q. Expected: %q", tc.input, tag, tc.expected) + } + }) } } @@ -194,18 +205,19 @@ func TestSplitVersion(t *testing.T) { kubeReleaseBucketURL = "https://dl.k8s.io" for _, tc := range cases { - bucket, label, err := splitVersion(tc.input) - switch { - case err != nil && tc.valid: - t.Errorf("splitVersion: unexpected error for %q. Error: %v", tc.input, err) - case err == nil && !tc.valid: - t.Errorf("splitVersion: error expected for key %q, but result is %q, %q", tc.input, bucket, label) - case bucket != tc.bucket: - t.Errorf("splitVersion: unexpected bucket result for key %q. Expected: %q Actual: %q", tc.input, tc.bucket, bucket) - case label != tc.label: - t.Errorf("splitVersion: unexpected label result for key %q. Expected: %q Actual: %q", tc.input, tc.label, label) - } - + t.Run(fmt.Sprintf("input:%s/label:%s", tc.input, tc.label), func(t *testing.T) { + bucket, label, err := splitVersion(tc.input) + switch { + case err != nil && tc.valid: + t.Errorf("splitVersion: unexpected error for %q. Error: %v", tc.input, err) + case err == nil && !tc.valid: + t.Errorf("splitVersion: error expected for key %q, but result is %q, %q", tc.input, bucket, label) + case bucket != tc.bucket: + t.Errorf("splitVersion: unexpected bucket result for key %q. Expected: %q Actual: %q", tc.input, tc.bucket, bucket) + case label != tc.label: + t.Errorf("splitVersion: unexpected label result for key %q. Expected: %q Actual: %q", tc.input, tc.label, label) + } + }) } } @@ -227,13 +239,14 @@ func TestKubernetesIsCIVersion(t *testing.T) { } for _, tc := range cases { - result := KubernetesIsCIVersion(tc.input) - t.Logf("KubernetesIsCIVersion: Input: %q. Result: %v. Expected: %v", tc.input, result, tc.expected) - if result != tc.expected { - t.Errorf("failed KubernetesIsCIVersion: Input: %q. Result: %v. Expected: %v", tc.input, result, tc.expected) - } + t.Run(fmt.Sprintf("input:%s/expected:%t", tc.input, tc.expected), func(t *testing.T) { + result := KubernetesIsCIVersion(tc.input) + t.Logf("KubernetesIsCIVersion: Input: %q. Result: %v. Expected: %v", tc.input, result, tc.expected) + if result != tc.expected { + t.Errorf("failed KubernetesIsCIVersion: Input: %q. Result: %v. Expected: %v", tc.input, result, tc.expected) + } + }) } - } // Validate KubernetesReleaseVersion but with bucket prefixes @@ -258,16 +271,18 @@ func TestCIBuildVersion(t *testing.T) { } for _, tc := range cases { - ver, err := KubernetesReleaseVersion(tc.input) - t.Logf("Input: %q. Result: %q, Error: %v", tc.input, ver, err) - switch { - case err != nil && tc.valid: - t.Errorf("KubernetesReleaseVersion: unexpected error for input %q. Error: %v", tc.input, err) - case err == nil && !tc.valid: - t.Errorf("KubernetesReleaseVersion: error expected for input %q, but result is %q", tc.input, ver) - case ver != tc.expected: - t.Errorf("KubernetesReleaseVersion: unexpected result for input %q. Expected: %q Actual: %q", tc.input, tc.expected, ver) - } + t.Run(fmt.Sprintf("input:%s/expected:%s", tc.input, tc.expected), func(t *testing.T) { + ver, err := KubernetesReleaseVersion(tc.input) + t.Logf("Input: %q. Result: %q, Error: %v", tc.input, ver, err) + switch { + case err != nil && tc.valid: + t.Errorf("KubernetesReleaseVersion: unexpected error for input %q. Error: %v", tc.input, err) + case err == nil && !tc.valid: + t.Errorf("KubernetesReleaseVersion: error expected for input %q, but result is %q", tc.input, ver) + case ver != tc.expected: + t.Errorf("KubernetesReleaseVersion: unexpected result for input %q. Expected: %q Actual: %q", tc.input, tc.expected, ver) + } + }) } } @@ -284,10 +299,12 @@ func TestNormalizedBuildVersionVersion(t *testing.T) { } for _, tc := range cases { - output := normalizedBuildVersion(tc.input) - if output != tc.expected { - t.Errorf("normalizedBuildVersion: unexpected output %q for input %q. Expected: %q", output, tc.input, tc.expected) - } + t.Run(fmt.Sprintf("input:%s/expected:%s", tc.input, tc.expected), func(t *testing.T) { + output := normalizedBuildVersion(tc.input) + if output != tc.expected { + t.Errorf("normalizedBuildVersion: unexpected output %q for input %q. Expected: %q", output, tc.input, tc.expected) + } + }) } } @@ -421,10 +438,10 @@ func TestValidateStableVersion(t *testing.T) { output: "v1.11.0", }, { - name: "valid: client version is empty; use remote version", + name: "invalid: client version is empty", remoteVersion: "v1.12.1", clientVersion: "", - output: "v1.12.1", + expectedError: true, }, { name: "invalid: error parsing the remote version", diff --git a/cmd/kubeadm/test/BUILD b/cmd/kubeadm/test/BUILD index 2c6fc05940a..53a4ff8911d 100644 --- a/cmd/kubeadm/test/BUILD +++ b/cmd/kubeadm/test/BUILD @@ -13,9 +13,9 @@ go_library( "//cmd/kubeadm/app/apis/kubeadm:go_default_library", "//cmd/kubeadm/app/apis/kubeadm/v1beta1:go_default_library", "//cmd/kubeadm/app/constants:go_default_library", + "//cmd/kubeadm/app/util/certs:go_default_library", "//cmd/kubeadm/app/util/config:go_default_library", "//cmd/kubeadm/app/util/pkiutil:go_default_library", - "//cmd/kubeadm/test/certs:go_default_library", "//vendor/github.com/renstrom/dedent:go_default_library", ], ) @@ -31,7 +31,6 @@ filegroup( name = "all-srcs", srcs = [ ":package-srcs", - "//cmd/kubeadm/test/certs:all-srcs", "//cmd/kubeadm/test/cmd:all-srcs", "//cmd/kubeadm/test/kubeconfig:all-srcs", ], diff --git a/cmd/kubeadm/test/cmd/BUILD b/cmd/kubeadm/test/cmd/BUILD index fa944de0efd..50ed3737ada 100644 --- a/cmd/kubeadm/test/cmd/BUILD +++ b/cmd/kubeadm/test/cmd/BUILD @@ -33,6 +33,7 @@ go_test( "skip", ], deps = [ + "//cmd/kubeadm/app/constants:go_default_library", "//cmd/kubeadm/app/phases/certs:go_default_library", "//cmd/kubeadm/app/util/pkiutil:go_default_library", "//cmd/kubeadm/test:go_default_library", diff --git a/cmd/kubeadm/test/cmd/completion_test.go b/cmd/kubeadm/test/cmd/completion_test.go index b7e46ac478d..95fe79d8924 100644 --- a/cmd/kubeadm/test/cmd/completion_test.go +++ b/cmd/kubeadm/test/cmd/completion_test.go @@ -27,23 +27,26 @@ func TestCmdCompletion(t *testing.T) { } var tests = []struct { + name string args string expected bool }{ - {"", false}, // shell not specified - {"foo", false}, // unsupported shell type + {"shell not expected", "", false}, + {"unsupported shell type", "foo", false}, } for _, rt := range tests { - _, _, actual := RunCmd(kubeadmPath, "completion", rt.args) - if (actual == nil) != rt.expected { - t.Errorf( - "failed CmdCompletion running 'kubeadm completion %s' with an error: %v\n\texpected: %t\n\t actual: %t", - rt.args, - actual, - rt.expected, - (actual == nil), - ) - } + t.Run(rt.name, func(t *testing.T) { + _, _, actual := RunCmd(kubeadmPath, "completion", rt.args) + if (actual == nil) != rt.expected { + t.Errorf( + "failed CmdCompletion running 'kubeadm completion %s' with an error: %v\n\texpected: %t\n\t actual: %t", + rt.args, + actual, + rt.expected, + (actual == nil), + ) + } + }) } } diff --git a/cmd/kubeadm/test/cmd/init_test.go b/cmd/kubeadm/test/cmd/init_test.go index 282ec83527b..780d50a8ca7 100644 --- a/cmd/kubeadm/test/cmd/init_test.go +++ b/cmd/kubeadm/test/cmd/init_test.go @@ -23,6 +23,7 @@ import ( "github.com/pkg/errors" "github.com/renstrom/dedent" + "k8s.io/kubernetes/cmd/kubeadm/app/constants" "k8s.io/kubernetes/cmd/kubeadm/app/phases/certs" "k8s.io/kubernetes/cmd/kubeadm/app/util/pkiutil" testutil "k8s.io/kubernetes/cmd/kubeadm/test" @@ -102,7 +103,7 @@ func TestCmdInitKubernetesVersion(t *testing.T) { }, { name: "valid version is accepted", - args: "--kubernetes-version=1.12.0", + args: "--kubernetes-version=" + constants.CurrentKubernetesVersion.String(), expected: true, }, } diff --git a/cmd/kubeadm/test/cmd/join_test.go b/cmd/kubeadm/test/cmd/join_test.go index 556ba7bfefb..54b59901f3c 100644 --- a/cmd/kubeadm/test/cmd/join_test.go +++ b/cmd/kubeadm/test/cmd/join_test.go @@ -32,26 +32,29 @@ func TestCmdJoinConfig(t *testing.T) { } var initTest = []struct { + name string args string expected bool }{ - {"--config=foobar", false}, - {"--config=/does/not/exist/foo/bar", false}, + {"config", "--config=foobar", false}, + {"config path", "--config=/does/not/exist/foo/bar", false}, } kubeadmPath := getKubeadmPath() for _, rt := range initTest { - _, _, actual := RunCmd(kubeadmPath, "join", rt.args, "--ignore-preflight-errors=all") - if (actual == nil) != rt.expected { - t.Errorf( - "failed CmdJoinConfig running 'kubeadm join %s' with an error: %v\n\texpected: %t\n\t actual: %t", - rt.args, - actual, - rt.expected, - (actual == nil), - ) - } - kubeadmReset() + t.Run(rt.name, func(t *testing.T) { + _, _, actual := RunCmd(kubeadmPath, "join", rt.args, "--ignore-preflight-errors=all") + if (actual == nil) != rt.expected { + t.Errorf( + "failed CmdJoinConfig running 'kubeadm join %s' with an error: %v\n\texpected: %t\n\t actual: %t", + rt.args, + actual, + rt.expected, + (actual == nil), + ) + } + kubeadmReset() + }) } } @@ -62,26 +65,29 @@ func TestCmdJoinDiscoveryFile(t *testing.T) { } var initTest = []struct { + name string args string expected bool }{ - {"--discovery-file=foobar", false}, - {"--discovery-file=file:wrong", false}, + {"valid discovery file", "--discovery-file=foobar", false}, + {"invalid discovery file", "--discovery-file=file:wrong", false}, } kubeadmPath := getKubeadmPath() for _, rt := range initTest { - _, _, actual := RunCmd(kubeadmPath, "join", rt.args, "--ignore-preflight-errors=all") - if (actual == nil) != rt.expected { - t.Errorf( - "failed CmdJoinDiscoveryFile running 'kubeadm join %s' with an error: %v\n\texpected: %t\n\t actual: %t", - rt.args, - actual, - rt.expected, - (actual == nil), - ) - } - kubeadmReset() + t.Run(rt.name, func(t *testing.T) { + _, _, actual := RunCmd(kubeadmPath, "join", rt.args, "--ignore-preflight-errors=all") + if (actual == nil) != rt.expected { + t.Errorf( + "failed CmdJoinDiscoveryFile running 'kubeadm join %s' with an error: %v\n\texpected: %t\n\t actual: %t", + rt.args, + actual, + rt.expected, + (actual == nil), + ) + } + kubeadmReset() + }) } } @@ -92,26 +98,29 @@ func TestCmdJoinDiscoveryToken(t *testing.T) { } var initTest = []struct { + name string args string expected bool }{ - {"--discovery-token=foobar", false}, - {"--discovery-token=token://asdf:asdf", false}, + {"valid discovery token", "--discovery-token=foobar", false}, + {"valid discovery token url", "--discovery-token=token://asdf:asdf", false}, } kubeadmPath := getKubeadmPath() for _, rt := range initTest { - _, _, actual := RunCmd(kubeadmPath, "join", rt.args, "--ignore-preflight-errors=all") - if (actual == nil) != rt.expected { - t.Errorf( - "failed CmdJoinDiscoveryToken running 'kubeadm join %s' with an error: %v\n\texpected: %t\n\t actual: %t", - rt.args, - actual, - rt.expected, - (actual == nil), - ) - } - kubeadmReset() + t.Run(rt.name, func(t *testing.T) { + _, _, actual := RunCmd(kubeadmPath, "join", rt.args, "--ignore-preflight-errors=all") + if (actual == nil) != rt.expected { + t.Errorf( + "failed CmdJoinDiscoveryToken running 'kubeadm join %s' with an error: %v\n\texpected: %t\n\t actual: %t", + rt.args, + actual, + rt.expected, + (actual == nil), + ) + } + kubeadmReset() + }) } } @@ -122,25 +131,28 @@ func TestCmdJoinNodeName(t *testing.T) { } var initTest = []struct { + name string args string expected bool }{ - {"--node-name=foobar", false}, + {"valid node name", "--node-name=foobar", false}, } kubeadmPath := getKubeadmPath() for _, rt := range initTest { - _, _, actual := RunCmd(kubeadmPath, "join", rt.args, "--ignore-preflight-errors=all") - if (actual == nil) != rt.expected { - t.Errorf( - "failed CmdJoinNodeName running 'kubeadm join %s' with an error: %v\n\texpected: %t\n\t actual: %t", - rt.args, - actual, - rt.expected, - (actual == nil), - ) - } - kubeadmReset() + t.Run(rt.name, func(t *testing.T) { + _, _, actual := RunCmd(kubeadmPath, "join", rt.args, "--ignore-preflight-errors=all") + if (actual == nil) != rt.expected { + t.Errorf( + "failed CmdJoinNodeName running 'kubeadm join %s' with an error: %v\n\texpected: %t\n\t actual: %t", + rt.args, + actual, + rt.expected, + (actual == nil), + ) + } + kubeadmReset() + }) } } @@ -151,26 +163,29 @@ func TestCmdJoinTLSBootstrapToken(t *testing.T) { } var initTest = []struct { + name string args string expected bool }{ - {"--tls-bootstrap-token=foobar", false}, - {"--tls-bootstrap-token=token://asdf:asdf", false}, + {"valid bootstrap token", "--tls-bootstrap-token=foobar", false}, + {"valid bootstrap token url", "--tls-bootstrap-token=token://asdf:asdf", false}, } kubeadmPath := getKubeadmPath() for _, rt := range initTest { - _, _, actual := RunCmd(kubeadmPath, "join", rt.args, "--ignore-preflight-errors=all") - if (actual == nil) != rt.expected { - t.Errorf( - "failed CmdJoinTLSBootstrapToken running 'kubeadm join %s' with an error: %v\n\texpected: %t\n\t actual: %t", - rt.args, - actual, - rt.expected, - (actual == nil), - ) - } - kubeadmReset() + t.Run(rt.name, func(t *testing.T) { + _, _, actual := RunCmd(kubeadmPath, "join", rt.args, "--ignore-preflight-errors=all") + if (actual == nil) != rt.expected { + t.Errorf( + "failed CmdJoinTLSBootstrapToken running 'kubeadm join %s' with an error: %v\n\texpected: %t\n\t actual: %t", + rt.args, + actual, + rt.expected, + (actual == nil), + ) + } + kubeadmReset() + }) } } @@ -181,26 +196,29 @@ func TestCmdJoinToken(t *testing.T) { } var initTest = []struct { + name string args string expected bool }{ - {"--token=foobar", false}, - {"--token=token://asdf:asdf", false}, + {"valid token", "--token=foobar", false}, + {"valid token url", "--token=token://asdf:asdf", false}, } kubeadmPath := getKubeadmPath() for _, rt := range initTest { - _, _, actual := RunCmd(kubeadmPath, "join", rt.args, "--ignore-preflight-errors=all") - if (actual == nil) != rt.expected { - t.Errorf( - "failed CmdJoinToken running 'kubeadm join %s' with an error: %v\n\texpected: %t\n\t actual: %t", - rt.args, - actual, - rt.expected, - (actual == nil), - ) - } - kubeadmReset() + t.Run(rt.name, func(t *testing.T) { + _, _, actual := RunCmd(kubeadmPath, "join", rt.args, "--ignore-preflight-errors=all") + if (actual == nil) != rt.expected { + t.Errorf( + "failed CmdJoinToken running 'kubeadm join %s' with an error: %v\n\texpected: %t\n\t actual: %t", + rt.args, + actual, + rt.expected, + (actual == nil), + ) + } + kubeadmReset() + }) } } @@ -212,25 +230,28 @@ func TestCmdJoinBadArgs(t *testing.T) { kubeadmPath := getKubeadmPath() var initTest = []struct { + name string args string expected bool }{ - {"--discovery-token=abcdef.1234567890123456 --discovery-file=file:///tmp/foo.bar", false}, // DiscoveryToken, DiscoveryFile can't both be set - {"", false}, // DiscoveryToken or DiscoveryFile must be set + {"discovery-token and discovery-file can't both be set", "--discovery-token=abcdef.1234567890123456 --discovery-file=file:///tmp/foo.bar", false}, // DiscoveryToken, DiscoveryFile can't both be set + {"discovery-token or discovery-file must be set", "", false}, // DiscoveryToken or DiscoveryFile must be set } for _, rt := range initTest { - _, _, actual := RunCmd(kubeadmPath, "join", rt.args, "--ignore-preflight-errors=all") - if (actual == nil) != rt.expected { - t.Errorf( - "failed CmdJoinBadArgs 'kubeadm join %s' with an error: %v\n\texpected: %t\n\t actual: %t", - rt.args, - actual, - rt.expected, - (actual == nil), - ) - } - kubeadmReset() + t.Run(rt.name, func(t *testing.T) { + _, _, actual := RunCmd(kubeadmPath, "join", rt.args, "--ignore-preflight-errors=all") + if (actual == nil) != rt.expected { + t.Errorf( + "failed CmdJoinBadArgs 'kubeadm join %s' with an error: %v\n\texpected: %t\n\t actual: %t", + rt.args, + actual, + rt.expected, + (actual == nil), + ) + } + kubeadmReset() + }) } } @@ -241,24 +262,27 @@ func TestCmdJoinArgsMixed(t *testing.T) { } var initTest = []struct { + name string args string expected bool }{ - {"--discovery-token=abcdef.1234567890abcdef --config=/etc/kubernetes/kubeadm.config", false}, + {"discovery-token and config", "--discovery-token=abcdef.1234567890abcdef --config=/etc/kubernetes/kubeadm.config", false}, } kubeadmPath := getKubeadmPath() for _, rt := range initTest { - _, _, actual := RunCmd(kubeadmPath, "join", rt.args, "--ignore-preflight-errors=all") - if (actual == nil) != rt.expected { - t.Errorf( - "failed CmdJoinArgsMixed running 'kubeadm join %s' with an error: %v\n\texpected: %t\n\t actual: %t", - rt.args, - actual, - rt.expected, - (actual == nil), - ) - } - kubeadmReset() + t.Run(rt.name, func(t *testing.T) { + _, _, actual := RunCmd(kubeadmPath, "join", rt.args, "--ignore-preflight-errors=all") + if (actual == nil) != rt.expected { + t.Errorf( + "failed CmdJoinArgsMixed running 'kubeadm join %s' with an error: %v\n\texpected: %t\n\t actual: %t", + rt.args, + actual, + rt.expected, + (actual == nil), + ) + } + kubeadmReset() + }) } } diff --git a/cmd/kubeadm/test/cmd/token_test.go b/cmd/kubeadm/test/cmd/token_test.go index b1506798d14..f24b936c6c1 100644 --- a/cmd/kubeadm/test/cmd/token_test.go +++ b/cmd/kubeadm/test/cmd/token_test.go @@ -90,25 +90,28 @@ func TestCmdTokenDelete(t *testing.T) { } var tests = []struct { + name string args string expected bool }{ - {"", false}, // no token provided - {"foobar", false}, // invalid token + {"no token provided", "", false}, + {"invalid token", "foobar", false}, } kubeadmPath := getKubeadmPath() for _, rt := range tests { - _, _, actual := RunCmd(kubeadmPath, "token", "delete", rt.args) - if (actual == nil) != rt.expected { - t.Errorf( - "failed CmdTokenDelete running 'kubeadm token %s' with an error: %v\n\texpected: %t\n\t actual: %t", - rt.args, - actual, - rt.expected, - (actual == nil), - ) - } - kubeadmReset() + t.Run(rt.name, func(t *testing.T) { + _, _, actual := RunCmd(kubeadmPath, "token", "delete", rt.args) + if (actual == nil) != rt.expected { + t.Errorf( + "failed CmdTokenDelete running 'kubeadm token %s' with an error: %v\n\texpected: %t\n\t actual: %t", + rt.args, + actual, + rt.expected, + (actual == nil), + ) + } + kubeadmReset() + }) } } diff --git a/cmd/kubeadm/test/cmd/version_test.go b/cmd/kubeadm/test/cmd/version_test.go index 345c0edabfc..320bb48249c 100644 --- a/cmd/kubeadm/test/cmd/version_test.go +++ b/cmd/kubeadm/test/cmd/version_test.go @@ -40,37 +40,40 @@ func TestCmdVersion(t *testing.T) { } var versionTest = []struct { + name string args string regex string expected bool }{ - {"--output=valid", "", false}, - {"--output=short", ShortExpectedRegex, true}, - {"", NormalExpectedRegex, true}, + {"invalid output option", "--output=valid", "", false}, + {"short output", "--output=short", ShortExpectedRegex, true}, + {"default output", "", NormalExpectedRegex, true}, } kubeadmPath := getKubeadmPath() for _, rt := range versionTest { - stdout, _, actual := RunCmd(kubeadmPath, "version", rt.args) - if (actual == nil) != rt.expected { - t.Errorf( - "failed CmdVersion running 'kubeadm version %s' with an error: %v\n\texpected: %t\n\t actual: %t", - rt.args, - actual, - rt.expected, - (actual == nil), - ) - } + t.Run(rt.name, func(t *testing.T) { + stdout, _, actual := RunCmd(kubeadmPath, "version", rt.args) + if (actual == nil) != rt.expected { + t.Errorf( + "failed CmdVersion running 'kubeadm version %s' with an error: %v\n\texpected: %t\n\t actual: %t", + rt.args, + actual, + rt.expected, + (actual == nil), + ) + } - if rt.expected { - matched, err := regexp.MatchString(rt.regex, stdout) - if err != nil { - t.Fatalf("encountered an error while trying to match 'kubeadm version %s' stdout: %v", rt.args, err) + if rt.expected { + matched, err := regexp.MatchString(rt.regex, stdout) + if err != nil { + t.Fatalf("encountered an error while trying to match 'kubeadm version %s' stdout: %v", rt.args, err) + } + if !matched { + t.Errorf("'kubeadm version %s' stdout did not match expected regex; wanted: [%q], got: [%s]", rt.args, rt.regex, stdout) + } } - if !matched { - t.Errorf("'kubeadm version %s' stdout did not match expected regex; wanted: [%q], got: [%s]", rt.args, rt.regex, stdout) - } - } + }) } } @@ -81,52 +84,55 @@ func TestCmdVersionOutputJsonOrYaml(t *testing.T) { } var versionTest = []struct { + name string args string format string expected bool }{ - {"--output=json", "json", true}, - {"--output=yaml", "yaml", true}, + {"json output", "--output=json", "json", true}, + {"yaml output", "--output=yaml", "yaml", true}, } kubeadmPath := getKubeadmPath() for _, rt := range versionTest { - stdout, _, actual := RunCmd(kubeadmPath, "version", rt.args) - if (actual == nil) != rt.expected { - t.Errorf( - "failed CmdVersion running 'kubeadm version %s' with an error: %v\n\texpected: %t\n\t actual: %t", - rt.args, - actual, - rt.expected, - (actual == nil), - ) - } - - if rt.expected { - var obj interface{} - switch rt.format { - case "json": - err := json.Unmarshal([]byte(stdout), &obj) - if err != nil { - t.Errorf("failed to parse json from 'kubeadm version %s': %s", rt.args, err) - } - case "yaml": - err := yaml.Unmarshal([]byte(stdout), &obj) - if err != nil { - t.Errorf("failed to parse yaml from 'kubeadm version %s': %s", rt.args, err) - } + t.Run(rt.name, func(t *testing.T) { + stdout, _, actual := RunCmd(kubeadmPath, "version", rt.args) + if (actual == nil) != rt.expected { + t.Errorf( + "failed CmdVersion running 'kubeadm version %s' with an error: %v\n\texpected: %t\n\t actual: %t", + rt.args, + actual, + rt.expected, + (actual == nil), + ) } - m := obj.(map[string]interface{}) - if m["clientVersion"] == nil { - t.Errorf("failed to get the information of clientVersion from 'kubeadm version %s'", rt.args) - } - info := m["clientVersion"].(map[string]interface{}) - for _, key := range VersionInfo { - if len(info[key].(string)) == 0 { - t.Errorf("failed to get the information of %s from 'kubeadm version %s'", key, rt.args) + if rt.expected { + var obj interface{} + switch rt.format { + case "json": + err := json.Unmarshal([]byte(stdout), &obj) + if err != nil { + t.Errorf("failed to parse json from 'kubeadm version %s': %s", rt.args, err) + } + case "yaml": + err := yaml.Unmarshal([]byte(stdout), &obj) + if err != nil { + t.Errorf("failed to parse yaml from 'kubeadm version %s': %s", rt.args, err) + } + } + + m := obj.(map[string]interface{}) + if m["clientVersion"] == nil { + t.Errorf("failed to get the information of clientVersion from 'kubeadm version %s'", rt.args) + } + info := m["clientVersion"].(map[string]interface{}) + for _, key := range VersionInfo { + if len(info[key].(string)) == 0 { + t.Errorf("failed to get the information of %s from 'kubeadm version %s'", key, rt.args) + } } } - } + }) } } diff --git a/cmd/kubeadm/test/kubeconfig/BUILD b/cmd/kubeadm/test/kubeconfig/BUILD index 7b6e9eeba1d..792e593e136 100644 --- a/cmd/kubeadm/test/kubeconfig/BUILD +++ b/cmd/kubeadm/test/kubeconfig/BUILD @@ -10,7 +10,7 @@ go_library( srcs = ["util.go"], importpath = "k8s.io/kubernetes/cmd/kubeadm/test/kubeconfig", deps = [ - "//cmd/kubeadm/test/certs:go_default_library", + "//cmd/kubeadm/app/util/certs:go_default_library", "//staging/src/k8s.io/client-go/tools/clientcmd/api:go_default_library", ], ) diff --git a/cmd/kubeadm/test/kubeconfig/util.go b/cmd/kubeadm/test/kubeconfig/util.go index daad6892282..51092a79d7e 100644 --- a/cmd/kubeadm/test/kubeconfig/util.go +++ b/cmd/kubeadm/test/kubeconfig/util.go @@ -22,7 +22,7 @@ import ( "testing" clientcmdapi "k8s.io/client-go/tools/clientcmd/api" - certstestutil "k8s.io/kubernetes/cmd/kubeadm/test/certs" + certstestutil "k8s.io/kubernetes/cmd/kubeadm/app/util/certs" ) // AssertKubeConfigCurrentCluster is a utility function for kubeadm testing that asserts if the CurrentCluster in diff --git a/cmd/kubeadm/test/util.go b/cmd/kubeadm/test/util.go index 471aa7633e8..0bbe47a53f5 100644 --- a/cmd/kubeadm/test/util.go +++ b/cmd/kubeadm/test/util.go @@ -17,6 +17,7 @@ limitations under the License. package test import ( + "fmt" "html/template" "io/ioutil" "os" @@ -28,9 +29,9 @@ import ( kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" kubeadmapiv1beta1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta1" kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants" + certtestutil "k8s.io/kubernetes/cmd/kubeadm/app/util/certs" configutil "k8s.io/kubernetes/cmd/kubeadm/app/util/config" "k8s.io/kubernetes/cmd/kubeadm/app/util/pkiutil" - certtestutil "k8s.io/kubernetes/cmd/kubeadm/test/certs" ) // SetupTempDir is a utility function for kubeadm testing, that creates a temporary directory @@ -54,7 +55,7 @@ func SetupInitConfigurationFile(t *testing.T, tmpdir string, cfg *kubeadmapi.Ini t.Fatalf("Couldn't create cfgDir") } - cfgTemplate := template.Must(template.New("init").Parse(dedent.Dedent(` + cfgTemplate := template.Must(template.New("init").Parse(dedent.Dedent(fmt.Sprintf(` apiVersion: kubeadm.k8s.io/v1beta1 kind: InitConfiguration apiEndpoint: @@ -66,8 +67,8 @@ func SetupInitConfigurationFile(t *testing.T, tmpdir string, cfg *kubeadmapi.Ini apiVersion: kubeadm.k8s.io/v1beta1 kind: ClusterConfiguration certificatesDir: {{.CertificatesDir}} - kubernetesVersion: v1.12.0 - `))) + kubernetesVersion: %s + `, kubeadmconstants.MinimumControlPlaneVersion)))) f, err := os.Create(cfgPath) if err != nil { diff --git a/cmd/kubelet/app/BUILD b/cmd/kubelet/app/BUILD index 309d7d07e0b..59e5a936053 100644 --- a/cmd/kubelet/app/BUILD +++ b/cmd/kubelet/app/BUILD @@ -8,8 +8,22 @@ load( go_test( name = "go_default_test", - srcs = ["server_test.go"], + srcs = [ + "server_bootstrap_test.go", + "server_test.go", + ], embed = [":go_default_library"], + deps = [ + "//staging/src/k8s.io/api/certificates/v1beta1:go_default_library", + "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + "//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library", + "//staging/src/k8s.io/apimachinery/pkg/types:go_default_library", + "//staging/src/k8s.io/client-go/rest:go_default_library", + "//staging/src/k8s.io/client-go/util/cert:go_default_library", + "//vendor/github.com/cloudflare/cfssl/config:go_default_library", + "//vendor/github.com/cloudflare/cfssl/signer:go_default_library", + "//vendor/github.com/cloudflare/cfssl/signer/local:go_default_library", + ], ) go_library( @@ -113,6 +127,7 @@ go_library( "//staging/src/k8s.io/client-go/kubernetes:go_default_library", "//staging/src/k8s.io/client-go/kubernetes/typed/authentication/v1beta1:go_default_library", "//staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1beta1:go_default_library", + "//staging/src/k8s.io/client-go/kubernetes/typed/certificates/v1beta1:go_default_library", "//staging/src/k8s.io/client-go/kubernetes/typed/core/v1:go_default_library", "//staging/src/k8s.io/client-go/rest:go_default_library", "//staging/src/k8s.io/client-go/tools/clientcmd:go_default_library", diff --git a/cmd/kubelet/app/server.go b/cmd/kubelet/app/server.go index 8be78808e4a..c84979fd617 100644 --- a/cmd/kubelet/app/server.go +++ b/cmd/kubelet/app/server.go @@ -50,6 +50,7 @@ import ( "k8s.io/apiserver/pkg/util/flag" "k8s.io/client-go/dynamic" clientset "k8s.io/client-go/kubernetes" + certificatesclient "k8s.io/client-go/kubernetes/typed/certificates/v1beta1" v1core "k8s.io/client-go/kubernetes/typed/core/v1" restclient "k8s.io/client-go/rest" "k8s.io/client-go/tools/clientcmd" @@ -537,66 +538,39 @@ func run(s *options.KubeletServer, kubeDeps *kubelet.Dependencies, stopCh <-chan return err } - if s.BootstrapKubeconfig != "" { - if err := bootstrap.LoadClientCert(s.KubeConfig, s.BootstrapKubeconfig, s.CertDirectory, nodeName); err != nil { - return err - } - } - // if in standalone mode, indicate as much by setting all clients to nil - if standaloneMode { + switch { + case standaloneMode: kubeDeps.KubeClient = nil kubeDeps.DynamicKubeClient = nil kubeDeps.EventClient = nil kubeDeps.HeartbeatClient = nil klog.Warningf("standalone mode, no API client") - } else if kubeDeps.KubeClient == nil || kubeDeps.EventClient == nil || kubeDeps.HeartbeatClient == nil || kubeDeps.DynamicKubeClient == nil { - // initialize clients if not standalone mode and any of the clients are not provided - var kubeClient clientset.Interface - var eventClient v1core.EventsGetter - var heartbeatClient clientset.Interface - var dynamicKubeClient dynamic.Interface - clientConfig, err := createAPIServerClientConfig(s) - if err != nil { - return fmt.Errorf("invalid kubeconfig: %v", err) - } - - var clientCertificateManager certificate.Manager - if s.RotateCertificates && utilfeature.DefaultFeatureGate.Enabled(features.RotateKubeletClientCertificate) { - clientCertificateManager, err = kubeletcertificate.NewKubeletClientCertificateManager(s.CertDirectory, nodeName, clientConfig.CertData, clientConfig.KeyData, clientConfig.CertFile, clientConfig.KeyFile) - if err != nil { - return err - } - } - // we set exitAfter to five minutes because we use this client configuration to request new certs - if we are unable - // to request new certs, we will be unable to continue normal operation. Exiting the process allows a wrapper - // or the bootstrapping credentials to potentially lay down new initial config. - closeAllConns, err := kubeletcertificate.UpdateTransport(wait.NeverStop, clientConfig, clientCertificateManager, 5*time.Minute) + case kubeDeps.KubeClient == nil, kubeDeps.EventClient == nil, kubeDeps.HeartbeatClient == nil, kubeDeps.DynamicKubeClient == nil: + clientConfig, closeAllConns, err := buildKubeletClientConfig(s, nodeName) if err != nil { return err } + kubeDeps.OnHeartbeatFailure = closeAllConns - kubeClient, err = clientset.NewForConfig(clientConfig) + kubeDeps.KubeClient, err = clientset.NewForConfig(clientConfig) if err != nil { - klog.Warningf("New kubeClient from clientConfig error: %v", err) - } else if kubeClient.CertificatesV1beta1() != nil && clientCertificateManager != nil { - klog.V(2).Info("Starting client certificate rotation.") - clientCertificateManager.SetCertificateSigningRequestClient(kubeClient.CertificatesV1beta1().CertificateSigningRequests()) - clientCertificateManager.Start() + return fmt.Errorf("failed to initialize kubelet client: %v", err) } - dynamicKubeClient, err = dynamic.NewForConfig(clientConfig) + + kubeDeps.DynamicKubeClient, err = dynamic.NewForConfig(clientConfig) if err != nil { - klog.Warningf("Failed to initialize dynamic KubeClient: %v", err) + return fmt.Errorf("failed to initialize kubelet dynamic client: %v", err) } // make a separate client for events eventClientConfig := *clientConfig eventClientConfig.QPS = float32(s.EventRecordQPS) eventClientConfig.Burst = int(s.EventBurst) - eventClient, err = v1core.NewForConfig(&eventClientConfig) + kubeDeps.EventClient, err = v1core.NewForConfig(&eventClientConfig) if err != nil { - klog.Warningf("Failed to create API Server client for Events: %v", err) + return fmt.Errorf("failed to initialize kubelet event client: %v", err) } // make a separate client for heartbeat with throttling disabled and a timeout attached @@ -610,28 +584,18 @@ func run(s *options.KubeletServer, kubeDeps *kubelet.Dependencies, stopCh <-chan } } heartbeatClientConfig.QPS = float32(-1) - heartbeatClient, err = clientset.NewForConfig(&heartbeatClientConfig) + kubeDeps.HeartbeatClient, err = clientset.NewForConfig(&heartbeatClientConfig) if err != nil { - klog.Warningf("Failed to create API Server client for heartbeat: %v", err) + return fmt.Errorf("failed to initialize kubelet heartbeat client: %v", err) } - // csiClient works with CRDs that support json only - clientConfig.ContentType = "application/json" - csiClient, err := csiclientset.NewForConfig(clientConfig) + // CRDs are JSON only, and client renegotiation for streaming is not correct as per #67803 + csiClientConfig := restclient.CopyConfig(clientConfig) + csiClientConfig.ContentType = "application/json" + kubeDeps.CSIClient, err = csiclientset.NewForConfig(csiClientConfig) if err != nil { - klog.Warningf("Failed to create CSI API client: %v", err) + return fmt.Errorf("failed to initialize kubelet storage client: %v", err) } - - kubeDeps.KubeClient = kubeClient - kubeDeps.DynamicKubeClient = dynamicKubeClient - if heartbeatClient != nil { - kubeDeps.HeartbeatClient = heartbeatClient - kubeDeps.OnHeartbeatFailure = closeAllConns - } - if eventClient != nil { - kubeDeps.EventClient = eventClient - } - kubeDeps.CSIClient = csiClient } // If the kubelet config controller is available, and dynamic config is enabled, start the config and status sync loops @@ -771,6 +735,118 @@ func run(s *options.KubeletServer, kubeDeps *kubelet.Dependencies, stopCh <-chan return nil } +// buildKubeletClientConfig constructs the appropriate client config for the kubelet depending on whether +// bootstrapping is enabled or client certificate rotation is enabled. +func buildKubeletClientConfig(s *options.KubeletServer, nodeName types.NodeName) (*restclient.Config, func(), error) { + if s.RotateCertificates && utilfeature.DefaultFeatureGate.Enabled(features.RotateKubeletClientCertificate) { + // Rules for client rotation and the handling of kube config files: + // + // 1. If the client provides only a kubeconfig file, we must use that as the initial client + // kubeadm needs the initial data in the kubeconfig to be placed into the cert store + // 2. If the client provides only an initial bootstrap kubeconfig file, we must create a + // kubeconfig file at the target location that points to the cert store, but until + // the file is present the client config will have no certs + // 3. If the client provides both and the kubeconfig is valid, we must ignore the bootstrap + // kubeconfig. + // 4. If the client provides both and the kubeconfig is expired or otherwise invalid, we must + // replace the kubeconfig with a new file that points to the cert dir + // + // The desired configuration for bootstrapping is to use a bootstrap kubeconfig and to have + // the kubeconfig file be managed by this process. For backwards compatibility with kubeadm, + // which provides a high powered kubeconfig on the master with cert/key data, we must + // bootstrap the cert manager with the contents of the initial client config. + + klog.Infof("Client rotation is on, will bootstrap in background") + certConfig, clientConfig, err := bootstrap.LoadClientConfig(s.KubeConfig, s.BootstrapKubeconfig, s.CertDirectory) + if err != nil { + return nil, nil, err + } + + clientCertificateManager, err := buildClientCertificateManager(certConfig, clientConfig, s.CertDirectory, nodeName) + if err != nil { + return nil, nil, err + } + + // the rotating transport will use the cert from the cert manager instead of these files + transportConfig := restclient.AnonymousClientConfig(clientConfig) + kubeClientConfigOverrides(s, transportConfig) + + // we set exitAfter to five minutes because we use this client configuration to request new certs - if we are unable + // to request new certs, we will be unable to continue normal operation. Exiting the process allows a wrapper + // or the bootstrapping credentials to potentially lay down new initial config. + closeAllConns, err := kubeletcertificate.UpdateTransport(wait.NeverStop, transportConfig, clientCertificateManager, 5*time.Minute) + if err != nil { + return nil, nil, err + } + + klog.V(2).Info("Starting client certificate rotation.") + clientCertificateManager.Start() + + return transportConfig, closeAllConns, nil + } + + if len(s.BootstrapKubeconfig) > 0 { + if err := bootstrap.LoadClientCert(s.KubeConfig, s.BootstrapKubeconfig, s.CertDirectory, nodeName); err != nil { + return nil, nil, err + } + } + + clientConfig, err := clientcmd.NewNonInteractiveDeferredLoadingClientConfig( + &clientcmd.ClientConfigLoadingRules{ExplicitPath: s.KubeConfig}, + &clientcmd.ConfigOverrides{}, + ).ClientConfig() + if err != nil { + return nil, nil, fmt.Errorf("invalid kubeconfig: %v", err) + } + + kubeClientConfigOverrides(s, clientConfig) + + return clientConfig, nil, nil +} + +// buildClientCertificateManager creates a certificate manager that will use certConfig to request a client certificate +// if no certificate is available, or the most recent clientConfig (which is assumed to point to the cert that the manager will +// write out). +func buildClientCertificateManager(certConfig, clientConfig *restclient.Config, certDir string, nodeName types.NodeName) (certificate.Manager, error) { + newClientFn := func(current *tls.Certificate) (certificatesclient.CertificateSigningRequestInterface, error) { + // If we have a valid certificate, use that to fetch CSRs. Otherwise use the bootstrap + // credentials. In the future it would be desirable to change the behavior of bootstrap + // to always fall back to the external bootstrap credentials when such credentials are + // provided by a fundamental trust system like cloud VM identity or an HSM module. + config := certConfig + if current != nil { + config = clientConfig + } + client, err := clientset.NewForConfig(config) + if err != nil { + return nil, err + } + return client.CertificatesV1beta1().CertificateSigningRequests(), nil + } + + return kubeletcertificate.NewKubeletClientCertificateManager( + certDir, + nodeName, + + // this preserves backwards compatibility with kubeadm which passes + // a high powered certificate to the kubelet as --kubeconfig and expects + // it to be rotated out immediately + clientConfig.CertData, + clientConfig.KeyData, + + clientConfig.CertFile, + clientConfig.KeyFile, + newClientFn, + ) +} + +func kubeClientConfigOverrides(s *options.KubeletServer, clientConfig *restclient.Config) { + clientConfig.ContentType = s.ContentType + // Override kubeconfig qps/burst settings from flags + clientConfig.QPS = float32(s.KubeAPIQPS) + clientConfig.Burst = int(s.KubeAPIBurst) +} + // getNodeName returns the node name according to the cloud provider // if cloud provider is specified. Otherwise, returns the hostname of the node. func getNodeName(cloud cloudprovider.Interface, hostname string) (types.NodeName, error) { @@ -859,39 +935,6 @@ func InitializeTLS(kf *options.KubeletFlags, kc *kubeletconfiginternal.KubeletCo return tlsOptions, nil } -func kubeconfigClientConfig(s *options.KubeletServer) (*restclient.Config, error) { - return clientcmd.NewNonInteractiveDeferredLoadingClientConfig( - &clientcmd.ClientConfigLoadingRules{ExplicitPath: s.KubeConfig}, - &clientcmd.ConfigOverrides{}, - ).ClientConfig() -} - -// createClientConfig creates a client configuration from the command line arguments. -// If --kubeconfig is explicitly set, it will be used. -func createClientConfig(s *options.KubeletServer) (*restclient.Config, error) { - if s.BootstrapKubeconfig != "" || len(s.KubeConfig) > 0 { - return kubeconfigClientConfig(s) - } else { - return nil, fmt.Errorf("createClientConfig called in standalone mode") - } -} - -// createAPIServerClientConfig generates a client.Config from command line flags -// via createClientConfig and then injects chaos into the configuration via addChaosToClientConfig. -func createAPIServerClientConfig(s *options.KubeletServer) (*restclient.Config, error) { - clientConfig, err := createClientConfig(s) - if err != nil { - return nil, err - } - - clientConfig.ContentType = s.ContentType - // Override kubeconfig qps/burst settings from flags - clientConfig.QPS = float32(s.KubeAPIQPS) - clientConfig.Burst = int(s.KubeAPIBurst) - - return clientConfig, nil -} - // RunKubelet is responsible for setting up and running a kubelet. It is used in three different applications: // 1 Integration tests // 2 Kubelet binary diff --git a/cmd/kubelet/app/server_bootstrap_test.go b/cmd/kubelet/app/server_bootstrap_test.go new file mode 100644 index 00000000000..c59029fae86 --- /dev/null +++ b/cmd/kubelet/app/server_bootstrap_test.go @@ -0,0 +1,377 @@ +/* +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 app + +import ( + "crypto/ecdsa" + "crypto/elliptic" + "crypto/rand" + "crypto/x509" + "crypto/x509/pkix" + "encoding/json" + "encoding/pem" + "io/ioutil" + "math/big" + "net/http" + "net/http/httptest" + "os" + "path/filepath" + "sync" + "testing" + "time" + + cfsslconfig "github.com/cloudflare/cfssl/config" + cfsslsigner "github.com/cloudflare/cfssl/signer" + cfssllocal "github.com/cloudflare/cfssl/signer/local" + + certapi "k8s.io/api/certificates/v1beta1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/types" + restclient "k8s.io/client-go/rest" + certutil "k8s.io/client-go/util/cert" +) + +// Test_buildClientCertificateManager validates that we can build a local client cert +// manager that will use the bootstrap client until we get a valid cert, then use our +// provided identity on subsequent requests. +func Test_buildClientCertificateManager(t *testing.T) { + testDir, err := ioutil.TempDir("", "kubeletcert") + if err != nil { + t.Fatal(err) + } + defer func() { os.RemoveAll(testDir) }() + + serverPrivateKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + if err != nil { + t.Fatal(err) + } + serverCA, err := certutil.NewSelfSignedCACert(certutil.Config{ + CommonName: "the-test-framework", + }, serverPrivateKey) + if err != nil { + t.Fatal(err) + } + server := &csrSimulator{ + t: t, + serverPrivateKey: serverPrivateKey, + serverCA: serverCA, + } + s := httptest.NewServer(server) + defer s.Close() + + config1 := &restclient.Config{ + UserAgent: "FirstClient", + Host: s.URL, + } + config2 := &restclient.Config{ + UserAgent: "SecondClient", + Host: s.URL, + } + + nodeName := types.NodeName("test") + m, err := buildClientCertificateManager(config1, config2, testDir, nodeName) + if err != nil { + t.Fatal(err) + } + defer m.Stop() + r := m.(rotater) + + // get an expired CSR (simulating historical output) + server.backdate = 2 * time.Hour + server.expectUserAgent = "FirstClient" + ok, err := r.RotateCerts() + if !ok || err != nil { + t.Fatalf("unexpected rotation err: %t %v", ok, err) + } + if cert := m.Current(); cert != nil { + t.Fatalf("Unexpected cert, should be expired: %#v", cert) + } + fi := getFileInfo(testDir) + if len(fi) != 2 { + t.Fatalf("Unexpected directory contents: %#v", fi) + } + + // if m.Current() == nil, then we try again and get a valid + // client + server.backdate = 0 + server.expectUserAgent = "FirstClient" + if ok, err := r.RotateCerts(); !ok || err != nil { + t.Fatalf("unexpected rotation err: %t %v", ok, err) + } + if cert := m.Current(); cert == nil { + t.Fatalf("Unexpected cert, should be valid: %#v", cert) + } + fi = getFileInfo(testDir) + if len(fi) != 2 { + t.Fatalf("Unexpected directory contents: %#v", fi) + } + + // if m.Current() != nil, then we should use the second client + server.expectUserAgent = "SecondClient" + if ok, err := r.RotateCerts(); !ok || err != nil { + t.Fatalf("unexpected rotation err: %t %v", ok, err) + } + if cert := m.Current(); cert == nil { + t.Fatalf("Unexpected cert, should be valid: %#v", cert) + } + fi = getFileInfo(testDir) + if len(fi) != 2 { + t.Fatalf("Unexpected directory contents: %#v", fi) + } +} + +func Test_buildClientCertificateManager_populateCertDir(t *testing.T) { + testDir, err := ioutil.TempDir("", "kubeletcert") + if err != nil { + t.Fatal(err) + } + defer func() { os.RemoveAll(testDir) }() + + // when no cert is provided, write nothing to disk + config1 := &restclient.Config{ + UserAgent: "FirstClient", + Host: "http://localhost", + } + config2 := &restclient.Config{ + UserAgent: "SecondClient", + Host: "http://localhost", + } + nodeName := types.NodeName("test") + if _, err := buildClientCertificateManager(config1, config2, testDir, nodeName); err != nil { + t.Fatal(err) + } + fi := getFileInfo(testDir) + if len(fi) != 0 { + t.Fatalf("Unexpected directory contents: %#v", fi) + } + + // an invalid cert should be ignored + config2.CertData = []byte("invalid contents") + config2.KeyData = []byte("invalid contents") + if _, err := buildClientCertificateManager(config1, config2, testDir, nodeName); err == nil { + t.Fatal("unexpected non error") + } + fi = getFileInfo(testDir) + if len(fi) != 0 { + t.Fatalf("Unexpected directory contents: %#v", fi) + } + + // an expired client certificate should be written to disk, because the cert manager can + // use config1 to refresh it and the cert manager won't return it for clients. + config2.CertData, config2.KeyData = genClientCert(t, time.Now().Add(-2*time.Hour), time.Now().Add(-time.Hour)) + if _, err := buildClientCertificateManager(config1, config2, testDir, nodeName); err != nil { + t.Fatal(err) + } + fi = getFileInfo(testDir) + if len(fi) != 2 { + t.Fatalf("Unexpected directory contents: %#v", fi) + } + + // a valid, non-expired client certificate should be written to disk + config2.CertData, config2.KeyData = genClientCert(t, time.Now().Add(-time.Hour), time.Now().Add(24*time.Hour)) + if _, err := buildClientCertificateManager(config1, config2, testDir, nodeName); err != nil { + t.Fatal(err) + } + fi = getFileInfo(testDir) + if len(fi) != 2 { + t.Fatalf("Unexpected directory contents: %#v", fi) + } + +} + +func getFileInfo(dir string) map[string]os.FileInfo { + fi := make(map[string]os.FileInfo) + filepath.Walk(dir, func(path string, info os.FileInfo, err error) error { + if path == dir { + return nil + } + fi[path] = info + if !info.IsDir() { + os.Remove(path) + } + return nil + }) + return fi +} + +type rotater interface { + RotateCerts() (bool, error) +} + +func getCSR(req *http.Request) (*certapi.CertificateSigningRequest, error) { + if req.Body == nil { + return nil, nil + } + body, err := ioutil.ReadAll(req.Body) + if err != nil { + return nil, err + } + csr := &certapi.CertificateSigningRequest{} + if err := json.Unmarshal(body, csr); err != nil { + return nil, err + } + return csr, nil +} + +func mustMarshal(obj interface{}) []byte { + data, err := json.Marshal(obj) + if err != nil { + panic(err) + } + return data +} + +type csrSimulator struct { + t *testing.T + + serverPrivateKey *ecdsa.PrivateKey + serverCA *x509.Certificate + backdate time.Duration + + expectUserAgent string + + lock sync.Mutex + csr *certapi.CertificateSigningRequest +} + +func (s *csrSimulator) ServeHTTP(w http.ResponseWriter, req *http.Request) { + s.lock.Lock() + defer s.lock.Unlock() + t := s.t + + t.Logf("Request %s %s %s", req.Method, req.URL, req.UserAgent()) + + if len(s.expectUserAgent) > 0 && req.UserAgent() != s.expectUserAgent { + t.Errorf("Unexpected user agent: %s", req.UserAgent()) + } + + switch { + case req.Method == "POST" && req.URL.Path == "/apis/certificates.k8s.io/v1beta1/certificatesigningrequests": + csr, err := getCSR(req) + if err != nil { + t.Fatal(err) + } + if csr.Name == "" { + csr.Name = "test-csr" + } + + csr.UID = types.UID("1") + csr.ResourceVersion = "1" + data := mustMarshal(csr) + w.Header().Set("Content-Type", "application/json") + w.Write(data) + + csr = csr.DeepCopy() + csr.ResourceVersion = "2" + var usages []string + for _, usage := range csr.Spec.Usages { + usages = append(usages, string(usage)) + } + policy := &cfsslconfig.Signing{ + Default: &cfsslconfig.SigningProfile{ + Usage: usages, + Expiry: time.Hour, + ExpiryString: time.Hour.String(), + Backdate: s.backdate, + }, + } + cfs, err := cfssllocal.NewSigner(s.serverPrivateKey, s.serverCA, cfsslsigner.DefaultSigAlgo(s.serverPrivateKey), policy) + if err != nil { + t.Fatal(err) + } + csr.Status.Certificate, err = cfs.Sign(cfsslsigner.SignRequest{ + Request: string(csr.Spec.Request), + }) + if err != nil { + t.Fatal(err) + } + csr.Status.Conditions = []certapi.CertificateSigningRequestCondition{ + {Type: certapi.CertificateApproved}, + } + s.csr = csr + + case req.Method == "GET" && req.URL.Path == "/apis/certificates.k8s.io/v1beta1/certificatesigningrequests" && req.URL.RawQuery == "fieldSelector=metadata.name%3Dtest-csr&limit=500": + if s.csr == nil { + t.Fatalf("no csr") + } + csr := s.csr.DeepCopy() + + data := mustMarshal(&certapi.CertificateSigningRequestList{ + ListMeta: metav1.ListMeta{ + ResourceVersion: "2", + }, + Items: []certapi.CertificateSigningRequest{ + *csr, + }, + }) + w.Header().Set("Content-Type", "application/json") + w.Write(data) + + case req.Method == "GET" && req.URL.Path == "/apis/certificates.k8s.io/v1beta1/certificatesigningrequests" && req.URL.RawQuery == "fieldSelector=metadata.name%3Dtest-csr&resourceVersion=2&watch=true": + if s.csr == nil { + t.Fatalf("no csr") + } + csr := s.csr.DeepCopy() + + data := mustMarshal(&metav1.WatchEvent{ + Type: "ADDED", + Object: runtime.RawExtension{ + Raw: mustMarshal(csr), + }, + }) + w.Header().Set("Content-Type", "application/json") + w.Write(data) + + default: + t.Fatalf("unexpected request: %s %s", req.Method, req.URL) + } +} + +// genClientCert generates an x509 certificate for testing. Certificate and key +// are returned in PEM encoding. +func genClientCert(t *testing.T, from, to time.Time) ([]byte, []byte) { + key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + if err != nil { + t.Fatal(err) + } + keyRaw, err := x509.MarshalECPrivateKey(key) + if err != nil { + t.Fatal(err) + } + serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128) + serialNumber, err := rand.Int(rand.Reader, serialNumberLimit) + if err != nil { + t.Fatal(err) + } + cert := &x509.Certificate{ + SerialNumber: serialNumber, + Subject: pkix.Name{Organization: []string{"Acme Co"}}, + NotBefore: from, + NotAfter: to, + + KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, + ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}, + BasicConstraintsValid: true, + } + certRaw, err := x509.CreateCertificate(rand.Reader, cert, cert, key.Public(), key) + if err != nil { + t.Fatal(err) + } + return pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: certRaw}), + pem.EncodeToMemory(&pem.Block{Type: "PRIVATE KEY", Bytes: keyRaw}) +} diff --git a/docs/.generated_docs b/docs/.generated_docs index 89a63ed631d..7c97583e830 100644 --- a/docs/.generated_docs +++ b/docs/.generated_docs @@ -127,7 +127,6 @@ docs/man/man1/kubeadm-config-images-list.1 docs/man/man1/kubeadm-config-images-pull.1 docs/man/man1/kubeadm-config-images.1 docs/man/man1/kubeadm-config-migrate.1 -docs/man/man1/kubeadm-config-print-default.1 docs/man/man1/kubeadm-config-print-init-defaults.1 docs/man/man1/kubeadm-config-print-join-defaults.1 docs/man/man1/kubeadm-config-print.1 diff --git a/docs/api-reference/coordination.k8s.io/v1/definitions.html b/docs/api-reference/coordination.k8s.io/v1/definitions.html new file mode 100755 index 00000000000..db0511f3708 --- /dev/null +++ b/docs/api-reference/coordination.k8s.io/v1/definitions.html @@ -0,0 +1,1430 @@ + + + + + + +Top Level API Objects + + + + +
+
+

Top Level API Objects

+
+
+ +
+
+
+
+

Definitions

+
+
+

v1.APIResourceList

+
+

APIResourceList is a list of APIResource, it is used to expose the name of the resources supported in a specific group and version, and if the resource is namespaced.

+
+ +++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameDescriptionRequiredSchemaDefault

kind

Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds

false

string

apiVersion

APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources

false

string

groupVersion

groupVersion is the group and version this APIResourceList is for.

true

string

resources

resources contains the name of the resources and if they are namespaced.

true

v1.APIResource array

+ +
+
+

v1.Patch

+
+

Patch is provided to give a concrete name and type to the Kubernetes PATCH request body.

+
+
+
+

v1.DeleteOptions

+
+

DeleteOptions may be provided when deleting an API object.

+
+ +++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameDescriptionRequiredSchemaDefault

kind

Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds

false

string

apiVersion

APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources

false

string

gracePeriodSeconds

The duration in seconds before the object should be deleted. Value must be non-negative integer. The value zero indicates delete immediately. If this value is nil, the default grace period for the specified type will be used. Defaults to a per object value if not specified. zero means delete immediately.

false

integer (int64)

preconditions

Must be fulfilled before a deletion is carried out. If not possible, a 409 Conflict status will be returned.

false

v1.Preconditions

orphanDependents

Deprecated: please use the PropagationPolicy, this field will be deprecated in 1.7. Should the dependent objects be orphaned. If true/false, the "orphan" finalizer will be added to/removed from the object’s finalizers list. Either this field or PropagationPolicy may be set, but not both.

false

boolean

false

propagationPolicy

Whether and how garbage collection will be performed. Either this field or OrphanDependents may be set, but not both. The default policy is decided by the existing finalizer set in the metadata.finalizers and the resource-specific default policy. Acceptable values are: Orphan - orphan the dependents; Background - allow the garbage collector to delete the dependents in the background; Foreground - a cascading policy that deletes all dependents in the foreground.

false

v1.DeletionPropagation

dryRun

When present, indicates that modifications should not be persisted. An invalid or unrecognized dryRun directive will result in an error response and no further processing of the request. Valid values are: - All: all dry run stages will be processed

false

string array

+ +
+
+

v1.ListMeta

+
+

ListMeta describes metadata that synthetic resources must have, including lists and various status objects. A resource may have only one of {ObjectMeta, ListMeta}.

+
+ +++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameDescriptionRequiredSchemaDefault

selfLink

selfLink is a URL representing this object. Populated by the system. Read-only.

false

string

resourceVersion

String that identifies the server’s internal version of this object that can be used by clients to determine when objects have changed. Value must be treated as opaque by clients and passed unmodified back to the server. Populated by the system. Read-only. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#concurrency-control-and-consistency

false

string

continue

continue may be set if the user set a limit on the number of items returned, and indicates that the server has more data available. The value is opaque and may be used to issue another request to the endpoint that served this list to retrieve the next set of available objects. Continuing a consistent list may not be possible if the server configuration has changed or more than a few minutes have passed. The resourceVersion field returned when using this continue value will be identical to the value in the first response, unless you have received this token from an error message.

false

string

+ +
+
+

v1.StatusDetails

+
+

StatusDetails is a set of additional properties that MAY be set by the server to provide additional information about a response. The Reason field of a Status object defines what attributes will be set. Clients must ignore fields that do not match the defined type of each attribute, and should assume that any attribute may be empty, invalid, or under defined.

+
+ +++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameDescriptionRequiredSchemaDefault

name

The name attribute of the resource associated with the status StatusReason (when there is a single name which can be described).

false

string

group

The group attribute of the resource associated with the status StatusReason.

false

string

kind

The kind attribute of the resource associated with the status StatusReason. On some operations may differ from the requested resource Kind. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds

false

string

uid

UID of the resource. (when there is a single resource which can be described). More info: http://kubernetes.io/docs/user-guide/identifiers#uids

false

string

causes

The Causes array includes more details associated with the StatusReason failure. Not all StatusReasons may provide detailed causes.

false

v1.StatusCause array

retryAfterSeconds

If specified, the time in seconds before the operation should be retried. Some errors may indicate the client must take an alternate action - for those errors this field may indicate how long to wait before taking the alternate action.

false

integer (int32)

+ +
+
+

v1.Preconditions

+
+

Preconditions must be fulfilled before an operation (update, delete, etc.) is carried out.

+
+ +++++++ + + + + + + + + + + + + + + + + + + +
NameDescriptionRequiredSchemaDefault

uid

Specifies the target UID.

false

types.UID

+ +
+
+

v1.Initializers

+
+

Initializers tracks the progress of initialization.

+
+ +++++++ + + + + + + + + + + + + + + + + + + + + + + + + + +
NameDescriptionRequiredSchemaDefault

pending

Pending is a list of initializers that must execute in order before this object is visible. When the last pending initializer is removed, and no failing result is set, the initializers struct will be set to nil and the object is considered as initialized and visible to all clients.

true

v1.Initializer array

result

If result is set with the Failure field, the object will be persisted to storage and then deleted, ensuring that other clients can observe the deletion.

false

v1.Status

+ +
+
+

v1.Initializer

+
+

Initializer is information about an initializer that has not yet completed.

+
+ +++++++ + + + + + + + + + + + + + + + + + + +
NameDescriptionRequiredSchemaDefault

name

name of the process that is responsible for initializing this object.

true

string

+ +
+
+

v1.Status

+
+

Status is a return value for calls that don’t return other objects.

+
+ +++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameDescriptionRequiredSchemaDefault

kind

Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds

false

string

apiVersion

APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources

false

string

metadata

Standard list metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds

false

v1.ListMeta

status

Status of the operation. One of: "Success" or "Failure". More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status

false

string

message

A human-readable description of the status of this operation.

false

string

reason

A machine-readable description of why this operation is in the "Failure" status. If this value is empty there is no information available. A Reason clarifies an HTTP status code but does not override it.

false

string

details

Extended data associated with the reason. Each reason may define its own extended details. This field is optional and the data returned is not guaranteed to conform to any schema except that defined by the reason type.

false

v1.StatusDetails

code

Suggested HTTP return code for this status, 0 if not set.

false

integer (int32)

+ +
+
+

v1.WatchEvent

+ +++++++ + + + + + + + + + + + + + + + + + + + + + + + + + +
NameDescriptionRequiredSchemaDefault

type

true

string

object

true

string

+ +
+
+

v1.ObjectMeta

+
+

ObjectMeta is metadata that all persisted resources must have, which includes all objects users must create.

+
+ +++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameDescriptionRequiredSchemaDefault

name

Name must be unique within a namespace. Is required when creating resources, although some resources may allow a client to request the generation of an appropriate name automatically. Name is primarily intended for creation idempotence and configuration definition. Cannot be updated. More info: http://kubernetes.io/docs/user-guide/identifiers#names

false

string

generateName

GenerateName is an optional prefix, used by the server, to generate a unique name ONLY IF the Name field has not been provided. If this field is used, the name returned to the client will be different than the name passed. This value will also be combined with a unique suffix. The provided value has the same validation rules as the Name field, and may be truncated by the length of the suffix required to make the value unique on the server.
+
+If this field is specified and the generated name exists, the server will NOT return a 409 - instead, it will either return 201 Created or 500 with Reason ServerTimeout indicating a unique name could not be found in the time allotted, and the client should retry (optionally after the time indicated in the Retry-After header).
+
+Applied only if Name is not specified. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#idempotency

false

string

namespace

Namespace defines the space within each name must be unique. An empty namespace is equivalent to the "default" namespace, but "default" is the canonical representation. Not all objects are required to be scoped to a namespace - the value of this field for those objects will be empty.
+
+Must be a DNS_LABEL. Cannot be updated. More info: http://kubernetes.io/docs/user-guide/namespaces

false

string

selfLink

SelfLink is a URL representing this object. Populated by the system. Read-only.

false

string

uid

UID is the unique in time and space value for this object. It is typically generated by the server on successful creation of a resource and is not allowed to change on PUT operations.
+
+Populated by the system. Read-only. More info: http://kubernetes.io/docs/user-guide/identifiers#uids

false

string

resourceVersion

An opaque value that represents the internal version of this object that can be used by clients to determine when objects have changed. May be used for optimistic concurrency, change detection, and the watch operation on a resource or set of resources. Clients must treat these values as opaque and passed unmodified back to the server. They may only be valid for a particular resource or set of resources.
+
+Populated by the system. Read-only. Value must be treated as opaque by clients and . More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#concurrency-control-and-consistency

false

string

generation

A sequence number representing a specific generation of the desired state. Populated by the system. Read-only.

false

integer (int64)

creationTimestamp

CreationTimestamp is a timestamp representing the server time when this object was created. It is not guaranteed to be set in happens-before order across separate operations. Clients may not set this value. It is represented in RFC3339 form and is in UTC.
+
+Populated by the system. Read-only. Null for lists. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata

false

string

deletionTimestamp

DeletionTimestamp is RFC 3339 date and time at which this resource will be deleted. This field is set by the server when a graceful deletion is requested by the user, and is not directly settable by a client. The resource is expected to be deleted (no longer visible from resource lists, and not reachable by name) after the time in this field, once the finalizers list is empty. As long as the finalizers list contains items, deletion is blocked. Once the deletionTimestamp is set, this value may not be unset or be set further into the future, although it may be shortened or the resource may be deleted prior to this time. For example, a user may request that a pod is deleted in 30 seconds. The Kubelet will react by sending a graceful termination signal to the containers in the pod. After that 30 seconds, the Kubelet will send a hard termination signal (SIGKILL) to the container and after cleanup, remove the pod from the API. In the presence of network partitions, this object may still exist after this timestamp, until an administrator or automated process can determine the resource is fully terminated. If not set, graceful deletion of the object has not been requested.
+
+Populated by the system when a graceful deletion is requested. Read-only. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata

false

string

deletionGracePeriodSeconds

Number of seconds allowed for this object to gracefully terminate before it will be removed from the system. Only set when deletionTimestamp is also set. May only be shortened. Read-only.

false

integer (int64)

labels

Map of string keys and values that can be used to organize and categorize (scope and select) objects. May match selectors of replication controllers and services. More info: http://kubernetes.io/docs/user-guide/labels

false

object

annotations

Annotations is an unstructured key value map stored with a resource that may be set by external tools to store and retrieve arbitrary metadata. They are not queryable and should be preserved when modifying objects. More info: http://kubernetes.io/docs/user-guide/annotations

false

object

ownerReferences

List of objects depended by this object. If ALL objects in the list have been deleted, this object will be garbage collected. If this object is managed by a controller, then an entry in this list will point to this controller, with the controller field set to true. There cannot be more than one managing controller.

false

v1.OwnerReference array

initializers

An initializer is a controller which enforces some system invariant at object creation time. This field is a list of initializers that have not yet acted on this object. If nil or empty, this object has been completely initialized. Otherwise, the object is considered uninitialized and is hidden (in list/watch and get calls) from clients that haven’t explicitly asked to observe uninitialized objects.
+
+When an object is created, the system will populate this list with the current set of initializers. Only privileged users may set or modify this list. Once it is empty, it may not be modified further by any user.

false

v1.Initializers

finalizers

Must be empty before the object is deleted from the registry. Each entry is an identifier for the responsible component that will remove the entry from the list. If the deletionTimestamp of the object is non-nil, entries in this list can only be removed.

false

string array

clusterName

The name of the cluster which the object belongs to. This is used to distinguish resources with same name and namespace in different clusters. This field is not set anywhere right now and apiserver is going to ignore it if set in create or update request.

false

string

+ +
+
+

v1.OwnerReference

+
+

OwnerReference contains enough information to let you identify an owning object. An owning object must be in the same namespace as the dependent, or be cluster-scoped, so there is no namespace field.

+
+ +++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameDescriptionRequiredSchemaDefault

apiVersion

API version of the referent.

true

string

kind

Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds

true

string

name

Name of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#names

true

string

uid

UID of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#uids

true

string

controller

If true, this reference points to the managing controller.

false

boolean

false

blockOwnerDeletion

If true, AND if the owner has the "foregroundDeletion" finalizer, then the owner cannot be deleted from the key-value store until this reference is removed. Defaults to false. To set this field, a user needs "delete" permission of the owner, otherwise 422 (Unprocessable Entity) will be returned.

false

boolean

false

+ +
+
+

v1.LeaseSpec

+
+

LeaseSpec is a specification of a Lease.

+
+ +++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameDescriptionRequiredSchemaDefault

holderIdentity

holderIdentity contains the identity of the holder of a current lease.

false

string

leaseDurationSeconds

leaseDurationSeconds is a duration that candidates for a lease need to wait to force acquire it. This is measure against time of last observed RenewTime.

false

integer (int32)

acquireTime

acquireTime is a time when the current lease was acquired.

false

string

renewTime

renewTime is a time when the current holder of a lease has last updated the lease.

false

string

leaseTransitions

leaseTransitions is the number of transitions of a lease between holders.

false

integer (int32)

+ +
+
+

v1.APIResource

+
+

APIResource specifies the name of a resource and whether it is namespaced.

+
+ +++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameDescriptionRequiredSchemaDefault

name

name is the plural name of the resource.

true

string

singularName

singularName is the singular name of the resource. This allows clients to handle plural and singular opaquely. The singularName is more correct for reporting status on a single item and both singular and plural are allowed from the kubectl CLI interface.

true

string

namespaced

namespaced indicates if a resource is namespaced or not.

true

boolean

false

group

group is the preferred group of the resource. Empty implies the group of the containing resource list. For subresources, this may have a different value, for example: Scale".

false

string

version

version is the preferred version of the resource. Empty implies the version of the containing resource list For subresources, this may have a different value, for example: v1 (while inside a v1beta1 version of the core resource’s group)".

false

string

kind

kind is the kind for the resource (e.g. Foo is the kind for a resource foo)

true

string

verbs

verbs is a list of supported kube verbs (this includes get, list, watch, create, update, patch, delete, deletecollection, and proxy)

true

string array

shortNames

shortNames is a list of suggested short names of the resource.

false

string array

categories

categories is a list of the grouped resources this resource belongs to (e.g. all)

false

string array

+ +
+
+

types.UID

+ +
+
+

v1.LeaseList

+
+

LeaseList is a list of Lease objects.

+
+ +++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameDescriptionRequiredSchemaDefault

kind

Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds

false

string

apiVersion

APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources

false

string

metadata

Standard list metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata

false

v1.ListMeta

items

Items is a list of schema objects.

true

v1.Lease array

+ +
+
+

v1.Lease

+
+

Lease defines a lease concept.

+
+ +++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameDescriptionRequiredSchemaDefault

kind

Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds

false

string

apiVersion

APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources

false

string

metadata

More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata

false

v1.ObjectMeta

spec

Specification of the Lease. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status

false

v1.LeaseSpec

+ +
+
+

v1.StatusCause

+
+

StatusCause provides more information about an api.Status failure, including cases when multiple errors are encountered.

+
+ +++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameDescriptionRequiredSchemaDefault

reason

A machine-readable description of the cause of the error. If this value is empty there is no information available.

false

string

message

A human-readable description of the cause of the error. This field may be presented as-is to a reader.

false

string

field

The field of the resource that has caused this error, as named by its JSON serialization. May include dot and postfix notation for nested attributes. Arrays are zero-indexed. Fields may appear more than once in an array of causes due to fields having multiple errors. Optional.
+
+Examples:
+ "name" - the field "name" on the current resource
+ "items[0].name" - the field "name" on the first array entry in "items"

false

string

+ +
+
+

v1.DeletionPropagation

+ +
+
+

any

+
+

Represents an untyped JSON map - see the description of the field for more info about the structure of this object.

+
+
+
+
+
+ + + \ No newline at end of file diff --git a/docs/api-reference/coordination.k8s.io/v1/operations.html b/docs/api-reference/coordination.k8s.io/v1/operations.html new file mode 100755 index 00000000000..b892e384a3d --- /dev/null +++ b/docs/api-reference/coordination.k8s.io/v1/operations.html @@ -0,0 +1,2263 @@ + + + + + + +Operations + + + + +
+
+

Operations

+
+
+

get available resources

+
+
+
GET /apis/coordination.k8s.io/v1
+
+
+
+

Responses

+ +++++ + + + + + + + + + + + + + + +
HTTP CodeDescriptionSchema

default

success

v1.APIResourceList

+ +
+
+

Consumes

+
+
    +
  • +

    application/json

    +
  • +
  • +

    application/yaml

    +
  • +
  • +

    application/vnd.kubernetes.protobuf

    +
  • +
+
+
+
+

Produces

+
+
    +
  • +

    application/json

    +
  • +
  • +

    application/yaml

    +
  • +
  • +

    application/vnd.kubernetes.protobuf

    +
  • +
+
+
+
+

Tags

+
+
    +
  • +

    apiscoordination.k8s.iov1

    +
  • +
+
+
+
+
+

list or watch objects of kind Lease

+
+
+
GET /apis/coordination.k8s.io/v1/leases
+
+
+
+

Parameters

+ ++++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
TypeNameDescriptionRequiredSchemaDefault

QueryParameter

pretty

If true, then the output is pretty printed.

false

string

QueryParameter

labelSelector

A selector to restrict the list of returned objects by their labels. Defaults to everything.

false

string

QueryParameter

fieldSelector

A selector to restrict the list of returned objects by their fields. Defaults to everything.

false

string

QueryParameter

includeUninitialized

If true, partially initialized resources are included in the response.

false

boolean

QueryParameter

watch

Watch for changes to the described resources and return them as a stream of add, update, and remove notifications. Specify resourceVersion.

false

boolean

QueryParameter

resourceVersion

When specified with a watch call, shows changes that occur after that particular version of a resource. Defaults to changes from the beginning of history. When specified for list: - if unset, then the result is returned from remote storage based on quorum-read flag; - if it’s 0, then we simply return what we currently have in cache, no guarantee; - if set to non zero, then the result is at least as fresh as given rv.

false

string

QueryParameter

timeoutSeconds

Timeout for the list/watch call. This limits the duration of the call, regardless of any activity or inactivity.

false

integer (int32)

QueryParameter

limit

limit is a maximum number of responses to return for a list call. If more items exist, the server will set the continue field on the list metadata to a value that can be used with the same initial query to retrieve the next set of results. Setting a limit may return fewer than the requested amount of items (up to zero items) in the event all requested objects are filtered out and clients should only use the presence of the continue field to determine whether more results are available. Servers may choose not to support the limit argument and will return all of the available results. If limit is specified and the continue field is empty, clients may assume that no more results are available. This field is not supported if watch is true. +

The server guarantees that the objects returned when using continue will be identical to issuing a single list call without a limit - that is, no objects created, modified, or deleted after the first request is issued will be included in any subsequent continued requests. This is sometimes referred to as a consistent snapshot, and ensures that a client that is using limit to receive smaller chunks of a very large result can ensure they see all possible objects. If objects are updated during a chunked list the version of the object that was present at the time the first list result was calculated is returned.

false

integer (int32)

QueryParameter

continue

The continue option should be set when retrieving more results from the server. Since this value is server defined, clients may only use the continue value from a previous query result with identical query parameters (except for the value of continue) and the server may reject a continue value it does not recognize. If the specified continue value is no longer valid whether due to expiration (generally five to fifteen minutes) or a configuration change on the server, the server will respond with a 410 ResourceExpired error together with a continue token. If the client needs a consistent list, it must restart their list without the continue field. Otherwise, the client may send another list request with the token received with the 410 error, the server will respond with a list starting from the next key, but from the latest snapshot, which is inconsistent from the previous list results - objects that are created, modified, or deleted after the first list request will be included in the response, as long as their keys are after the "next key". +

This field is not supported when watch is true. Clients may start a watch from the last resourceVersion value returned by the server and not miss any modifications.

false

string

+ +
+
+

Responses

+ +++++ + + + + + + + + + + + + + + +
HTTP CodeDescriptionSchema

200

success

v1.LeaseList

+ +
+
+

Consumes

+
+
    +
  • +

    /

    +
  • +
+
+
+
+

Produces

+
+
    +
  • +

    application/json

    +
  • +
  • +

    application/yaml

    +
  • +
  • +

    application/vnd.kubernetes.protobuf

    +
  • +
  • +

    application/json;stream=watch

    +
  • +
  • +

    application/vnd.kubernetes.protobuf;stream=watch

    +
  • +
+
+
+
+

Tags

+
+
    +
  • +

    apiscoordination.k8s.iov1

    +
  • +
+
+
+
+
+

list or watch objects of kind Lease

+
+
+
GET /apis/coordination.k8s.io/v1/namespaces/{namespace}/leases
+
+
+
+

Parameters

+ ++++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
TypeNameDescriptionRequiredSchemaDefault

QueryParameter

pretty

If true, then the output is pretty printed.

false

string

QueryParameter

labelSelector

A selector to restrict the list of returned objects by their labels. Defaults to everything.

false

string

QueryParameter

fieldSelector

A selector to restrict the list of returned objects by their fields. Defaults to everything.

false

string

QueryParameter

includeUninitialized

If true, partially initialized resources are included in the response.

false

boolean

QueryParameter

watch

Watch for changes to the described resources and return them as a stream of add, update, and remove notifications. Specify resourceVersion.

false

boolean

QueryParameter

resourceVersion

When specified with a watch call, shows changes that occur after that particular version of a resource. Defaults to changes from the beginning of history. When specified for list: - if unset, then the result is returned from remote storage based on quorum-read flag; - if it’s 0, then we simply return what we currently have in cache, no guarantee; - if set to non zero, then the result is at least as fresh as given rv.

false

string

QueryParameter

timeoutSeconds

Timeout for the list/watch call. This limits the duration of the call, regardless of any activity or inactivity.

false

integer (int32)

QueryParameter

limit

limit is a maximum number of responses to return for a list call. If more items exist, the server will set the continue field on the list metadata to a value that can be used with the same initial query to retrieve the next set of results. Setting a limit may return fewer than the requested amount of items (up to zero items) in the event all requested objects are filtered out and clients should only use the presence of the continue field to determine whether more results are available. Servers may choose not to support the limit argument and will return all of the available results. If limit is specified and the continue field is empty, clients may assume that no more results are available. This field is not supported if watch is true. +

The server guarantees that the objects returned when using continue will be identical to issuing a single list call without a limit - that is, no objects created, modified, or deleted after the first request is issued will be included in any subsequent continued requests. This is sometimes referred to as a consistent snapshot, and ensures that a client that is using limit to receive smaller chunks of a very large result can ensure they see all possible objects. If objects are updated during a chunked list the version of the object that was present at the time the first list result was calculated is returned.

false

integer (int32)

QueryParameter

continue

The continue option should be set when retrieving more results from the server. Since this value is server defined, clients may only use the continue value from a previous query result with identical query parameters (except for the value of continue) and the server may reject a continue value it does not recognize. If the specified continue value is no longer valid whether due to expiration (generally five to fifteen minutes) or a configuration change on the server, the server will respond with a 410 ResourceExpired error together with a continue token. If the client needs a consistent list, it must restart their list without the continue field. Otherwise, the client may send another list request with the token received with the 410 error, the server will respond with a list starting from the next key, but from the latest snapshot, which is inconsistent from the previous list results - objects that are created, modified, or deleted after the first list request will be included in the response, as long as their keys are after the "next key". +

This field is not supported when watch is true. Clients may start a watch from the last resourceVersion value returned by the server and not miss any modifications.

false

string

PathParameter

namespace

object name and auth scope, such as for teams and projects

true

string

+ +
+
+

Responses

+ +++++ + + + + + + + + + + + + + + +
HTTP CodeDescriptionSchema

200

success

v1.LeaseList

+ +
+
+

Consumes

+
+
    +
  • +

    /

    +
  • +
+
+
+
+

Produces

+
+
    +
  • +

    application/json

    +
  • +
  • +

    application/yaml

    +
  • +
  • +

    application/vnd.kubernetes.protobuf

    +
  • +
  • +

    application/json;stream=watch

    +
  • +
  • +

    application/vnd.kubernetes.protobuf;stream=watch

    +
  • +
+
+
+
+

Tags

+
+
    +
  • +

    apiscoordination.k8s.iov1

    +
  • +
+
+
+
+
+

delete collection of Lease

+
+
+
DELETE /apis/coordination.k8s.io/v1/namespaces/{namespace}/leases
+
+
+
+

Parameters

+ ++++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
TypeNameDescriptionRequiredSchemaDefault

QueryParameter

pretty

If true, then the output is pretty printed.

false

string

QueryParameter

labelSelector

A selector to restrict the list of returned objects by their labels. Defaults to everything.

false

string

QueryParameter

fieldSelector

A selector to restrict the list of returned objects by their fields. Defaults to everything.

false

string

QueryParameter

includeUninitialized

If true, partially initialized resources are included in the response.

false

boolean

QueryParameter

watch

Watch for changes to the described resources and return them as a stream of add, update, and remove notifications. Specify resourceVersion.

false

boolean

QueryParameter

resourceVersion

When specified with a watch call, shows changes that occur after that particular version of a resource. Defaults to changes from the beginning of history. When specified for list: - if unset, then the result is returned from remote storage based on quorum-read flag; - if it’s 0, then we simply return what we currently have in cache, no guarantee; - if set to non zero, then the result is at least as fresh as given rv.

false

string

QueryParameter

timeoutSeconds

Timeout for the list/watch call. This limits the duration of the call, regardless of any activity or inactivity.

false

integer (int32)

QueryParameter

limit

limit is a maximum number of responses to return for a list call. If more items exist, the server will set the continue field on the list metadata to a value that can be used with the same initial query to retrieve the next set of results. Setting a limit may return fewer than the requested amount of items (up to zero items) in the event all requested objects are filtered out and clients should only use the presence of the continue field to determine whether more results are available. Servers may choose not to support the limit argument and will return all of the available results. If limit is specified and the continue field is empty, clients may assume that no more results are available. This field is not supported if watch is true. +

The server guarantees that the objects returned when using continue will be identical to issuing a single list call without a limit - that is, no objects created, modified, or deleted after the first request is issued will be included in any subsequent continued requests. This is sometimes referred to as a consistent snapshot, and ensures that a client that is using limit to receive smaller chunks of a very large result can ensure they see all possible objects. If objects are updated during a chunked list the version of the object that was present at the time the first list result was calculated is returned.

false

integer (int32)

QueryParameter

continue

The continue option should be set when retrieving more results from the server. Since this value is server defined, clients may only use the continue value from a previous query result with identical query parameters (except for the value of continue) and the server may reject a continue value it does not recognize. If the specified continue value is no longer valid whether due to expiration (generally five to fifteen minutes) or a configuration change on the server, the server will respond with a 410 ResourceExpired error together with a continue token. If the client needs a consistent list, it must restart their list without the continue field. Otherwise, the client may send another list request with the token received with the 410 error, the server will respond with a list starting from the next key, but from the latest snapshot, which is inconsistent from the previous list results - objects that are created, modified, or deleted after the first list request will be included in the response, as long as their keys are after the "next key". +

This field is not supported when watch is true. Clients may start a watch from the last resourceVersion value returned by the server and not miss any modifications.

false

string

PathParameter

namespace

object name and auth scope, such as for teams and projects

true

string

+ +
+
+

Responses

+ +++++ + + + + + + + + + + + + + + +
HTTP CodeDescriptionSchema

200

success

v1.Status

+ +
+
+

Consumes

+
+
    +
  • +

    /

    +
  • +
+
+
+
+

Produces

+
+
    +
  • +

    application/json

    +
  • +
  • +

    application/yaml

    +
  • +
  • +

    application/vnd.kubernetes.protobuf

    +
  • +
+
+
+
+

Tags

+
+
    +
  • +

    apiscoordination.k8s.iov1

    +
  • +
+
+
+
+
+

create a Lease

+
+
+
POST /apis/coordination.k8s.io/v1/namespaces/{namespace}/leases
+
+
+
+

Parameters

+ ++++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
TypeNameDescriptionRequiredSchemaDefault

QueryParameter

pretty

If true, then the output is pretty printed.

false

string

BodyParameter

body

true

v1.Lease

QueryParameter

dryRun

When present, indicates that modifications should not be persisted. An invalid or unrecognized dryRun directive will result in an error response and no further processing of the request. Valid values are: - All: all dry run stages will be processed

false

string

QueryParameter

includeUninitialized

If IncludeUninitialized is specified, the object may be returned without completing initialization.

false

boolean

PathParameter

namespace

object name and auth scope, such as for teams and projects

true

string

+ +
+
+

Responses

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + +
HTTP CodeDescriptionSchema

202

Accepted

v1.Lease

200

success

v1.Lease

201

Created

v1.Lease

+ +
+
+

Consumes

+
+
    +
  • +

    /

    +
  • +
+
+
+
+

Produces

+
+
    +
  • +

    application/json

    +
  • +
  • +

    application/yaml

    +
  • +
  • +

    application/vnd.kubernetes.protobuf

    +
  • +
+
+
+
+

Tags

+
+
    +
  • +

    apiscoordination.k8s.iov1

    +
  • +
+
+
+
+
+

read the specified Lease

+
+
+
GET /apis/coordination.k8s.io/v1/namespaces/{namespace}/leases/{name}
+
+
+
+

Parameters

+ ++++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
TypeNameDescriptionRequiredSchemaDefault

QueryParameter

pretty

If true, then the output is pretty printed.

false

string

QueryParameter

export

Should this value be exported. Export strips fields that a user can not specify.

false

boolean

QueryParameter

exact

Should the export be exact. Exact export maintains cluster-specific fields like Namespace.

false

boolean

PathParameter

namespace

object name and auth scope, such as for teams and projects

true

string

PathParameter

name

name of the Lease

true

string

+ +
+
+

Responses

+ +++++ + + + + + + + + + + + + + + +
HTTP CodeDescriptionSchema

200

success

v1.Lease

+ +
+
+

Consumes

+
+
    +
  • +

    /

    +
  • +
+
+
+
+

Produces

+
+
    +
  • +

    application/json

    +
  • +
  • +

    application/yaml

    +
  • +
  • +

    application/vnd.kubernetes.protobuf

    +
  • +
+
+
+
+

Tags

+
+
    +
  • +

    apiscoordination.k8s.iov1

    +
  • +
+
+
+
+
+

replace the specified Lease

+
+
+
PUT /apis/coordination.k8s.io/v1/namespaces/{namespace}/leases/{name}
+
+
+
+

Parameters

+ ++++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
TypeNameDescriptionRequiredSchemaDefault

QueryParameter

pretty

If true, then the output is pretty printed.

false

string

BodyParameter

body

true

v1.Lease

QueryParameter

dryRun

When present, indicates that modifications should not be persisted. An invalid or unrecognized dryRun directive will result in an error response and no further processing of the request. Valid values are: - All: all dry run stages will be processed

false

string

PathParameter

namespace

object name and auth scope, such as for teams and projects

true

string

PathParameter

name

name of the Lease

true

string

+ +
+
+

Responses

+ +++++ + + + + + + + + + + + + + + + + + + + +
HTTP CodeDescriptionSchema

200

success

v1.Lease

201

Created

v1.Lease

+ +
+
+

Consumes

+
+
    +
  • +

    /

    +
  • +
+
+
+
+

Produces

+
+
    +
  • +

    application/json

    +
  • +
  • +

    application/yaml

    +
  • +
  • +

    application/vnd.kubernetes.protobuf

    +
  • +
+
+
+
+

Tags

+
+
    +
  • +

    apiscoordination.k8s.iov1

    +
  • +
+
+
+
+
+

delete a Lease

+
+
+
DELETE /apis/coordination.k8s.io/v1/namespaces/{namespace}/leases/{name}
+
+
+
+

Parameters

+ ++++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
TypeNameDescriptionRequiredSchemaDefault

QueryParameter

pretty

If true, then the output is pretty printed.

false

string

BodyParameter

body

false

v1.DeleteOptions

QueryParameter

gracePeriodSeconds

The duration in seconds before the object should be deleted. Value must be non-negative integer. The value zero indicates delete immediately. If this value is nil, the default grace period for the specified type will be used. Defaults to a per object value if not specified. zero means delete immediately.

false

integer (int32)

QueryParameter

orphanDependents

Deprecated: please use the PropagationPolicy, this field will be deprecated in 1.7. Should the dependent objects be orphaned. If true/false, the "orphan" finalizer will be added to/removed from the object’s finalizers list. Either this field or PropagationPolicy may be set, but not both.

false

boolean

QueryParameter

propagationPolicy

Whether and how garbage collection will be performed. Either this field or OrphanDependents may be set, but not both. The default policy is decided by the existing finalizer set in the metadata.finalizers and the resource-specific default policy. Acceptable values are: Orphan - orphan the dependents; Background - allow the garbage collector to delete the dependents in the background; Foreground - a cascading policy that deletes all dependents in the foreground.

false

string

QueryParameter

dryRun

When present, indicates that modifications should not be persisted. An invalid or unrecognized dryRun directive will result in an error response and no further processing of the request. Valid values are: - All: all dry run stages will be processed

false

string

PathParameter

namespace

object name and auth scope, such as for teams and projects

true

string

PathParameter

name

name of the Lease

true

string

+ +
+
+

Responses

+ +++++ + + + + + + + + + + + + + + + + + + + +
HTTP CodeDescriptionSchema

202

Accepted

v1.Status

200

success

v1.Status

+ +
+
+

Consumes

+
+
    +
  • +

    /

    +
  • +
+
+
+
+

Produces

+
+
    +
  • +

    application/json

    +
  • +
  • +

    application/yaml

    +
  • +
  • +

    application/vnd.kubernetes.protobuf

    +
  • +
+
+
+
+

Tags

+
+
    +
  • +

    apiscoordination.k8s.iov1

    +
  • +
+
+
+
+
+

partially update the specified Lease

+
+
+
PATCH /apis/coordination.k8s.io/v1/namespaces/{namespace}/leases/{name}
+
+
+
+

Parameters

+ ++++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
TypeNameDescriptionRequiredSchemaDefault

QueryParameter

pretty

If true, then the output is pretty printed.

false

string

BodyParameter

body

true

v1.Patch

QueryParameter

dryRun

When present, indicates that modifications should not be persisted. An invalid or unrecognized dryRun directive will result in an error response and no further processing of the request. Valid values are: - All: all dry run stages will be processed

false

string

PathParameter

namespace

object name and auth scope, such as for teams and projects

true

string

PathParameter

name

name of the Lease

true

string

+ +
+
+

Responses

+ +++++ + + + + + + + + + + + + + + +
HTTP CodeDescriptionSchema

200

success

v1.Lease

+ +
+
+

Consumes

+
+
    +
  • +

    application/json-patch+json

    +
  • +
  • +

    application/merge-patch+json

    +
  • +
  • +

    application/strategic-merge-patch+json

    +
  • +
+
+
+
+

Produces

+
+
    +
  • +

    application/json

    +
  • +
  • +

    application/yaml

    +
  • +
  • +

    application/vnd.kubernetes.protobuf

    +
  • +
+
+
+
+

Tags

+
+
    +
  • +

    apiscoordination.k8s.iov1

    +
  • +
+
+
+
+
+

watch individual changes to a list of Lease. deprecated: use the watch parameter with a list operation instead.

+
+
+
GET /apis/coordination.k8s.io/v1/watch/leases
+
+
+
+

Parameters

+ ++++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
TypeNameDescriptionRequiredSchemaDefault

QueryParameter

pretty

If true, then the output is pretty printed.

false

string

QueryParameter

labelSelector

A selector to restrict the list of returned objects by their labels. Defaults to everything.

false

string

QueryParameter

fieldSelector

A selector to restrict the list of returned objects by their fields. Defaults to everything.

false

string

QueryParameter

includeUninitialized

If true, partially initialized resources are included in the response.

false

boolean

QueryParameter

watch

Watch for changes to the described resources and return them as a stream of add, update, and remove notifications. Specify resourceVersion.

false

boolean

QueryParameter

resourceVersion

When specified with a watch call, shows changes that occur after that particular version of a resource. Defaults to changes from the beginning of history. When specified for list: - if unset, then the result is returned from remote storage based on quorum-read flag; - if it’s 0, then we simply return what we currently have in cache, no guarantee; - if set to non zero, then the result is at least as fresh as given rv.

false

string

QueryParameter

timeoutSeconds

Timeout for the list/watch call. This limits the duration of the call, regardless of any activity or inactivity.

false

integer (int32)

QueryParameter

limit

limit is a maximum number of responses to return for a list call. If more items exist, the server will set the continue field on the list metadata to a value that can be used with the same initial query to retrieve the next set of results. Setting a limit may return fewer than the requested amount of items (up to zero items) in the event all requested objects are filtered out and clients should only use the presence of the continue field to determine whether more results are available. Servers may choose not to support the limit argument and will return all of the available results. If limit is specified and the continue field is empty, clients may assume that no more results are available. This field is not supported if watch is true. +

The server guarantees that the objects returned when using continue will be identical to issuing a single list call without a limit - that is, no objects created, modified, or deleted after the first request is issued will be included in any subsequent continued requests. This is sometimes referred to as a consistent snapshot, and ensures that a client that is using limit to receive smaller chunks of a very large result can ensure they see all possible objects. If objects are updated during a chunked list the version of the object that was present at the time the first list result was calculated is returned.

false

integer (int32)

QueryParameter

continue

The continue option should be set when retrieving more results from the server. Since this value is server defined, clients may only use the continue value from a previous query result with identical query parameters (except for the value of continue) and the server may reject a continue value it does not recognize. If the specified continue value is no longer valid whether due to expiration (generally five to fifteen minutes) or a configuration change on the server, the server will respond with a 410 ResourceExpired error together with a continue token. If the client needs a consistent list, it must restart their list without the continue field. Otherwise, the client may send another list request with the token received with the 410 error, the server will respond with a list starting from the next key, but from the latest snapshot, which is inconsistent from the previous list results - objects that are created, modified, or deleted after the first list request will be included in the response, as long as their keys are after the "next key". +

This field is not supported when watch is true. Clients may start a watch from the last resourceVersion value returned by the server and not miss any modifications.

false

string

+ +
+
+

Responses

+ +++++ + + + + + + + + + + + + + + +
HTTP CodeDescriptionSchema

200

success

v1.WatchEvent

+ +
+
+

Consumes

+
+
    +
  • +

    /

    +
  • +
+
+
+
+

Produces

+
+
    +
  • +

    application/json

    +
  • +
  • +

    application/yaml

    +
  • +
  • +

    application/vnd.kubernetes.protobuf

    +
  • +
  • +

    application/json;stream=watch

    +
  • +
  • +

    application/vnd.kubernetes.protobuf;stream=watch

    +
  • +
+
+
+
+

Tags

+
+
    +
  • +

    apiscoordination.k8s.iov1

    +
  • +
+
+
+
+
+

watch individual changes to a list of Lease. deprecated: use the watch parameter with a list operation instead.

+
+
+
GET /apis/coordination.k8s.io/v1/watch/namespaces/{namespace}/leases
+
+
+
+

Parameters

+ ++++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
TypeNameDescriptionRequiredSchemaDefault

QueryParameter

pretty

If true, then the output is pretty printed.

false

string

QueryParameter

labelSelector

A selector to restrict the list of returned objects by their labels. Defaults to everything.

false

string

QueryParameter

fieldSelector

A selector to restrict the list of returned objects by their fields. Defaults to everything.

false

string

QueryParameter

includeUninitialized

If true, partially initialized resources are included in the response.

false

boolean

QueryParameter

watch

Watch for changes to the described resources and return them as a stream of add, update, and remove notifications. Specify resourceVersion.

false

boolean

QueryParameter

resourceVersion

When specified with a watch call, shows changes that occur after that particular version of a resource. Defaults to changes from the beginning of history. When specified for list: - if unset, then the result is returned from remote storage based on quorum-read flag; - if it’s 0, then we simply return what we currently have in cache, no guarantee; - if set to non zero, then the result is at least as fresh as given rv.

false

string

QueryParameter

timeoutSeconds

Timeout for the list/watch call. This limits the duration of the call, regardless of any activity or inactivity.

false

integer (int32)

QueryParameter

limit

limit is a maximum number of responses to return for a list call. If more items exist, the server will set the continue field on the list metadata to a value that can be used with the same initial query to retrieve the next set of results. Setting a limit may return fewer than the requested amount of items (up to zero items) in the event all requested objects are filtered out and clients should only use the presence of the continue field to determine whether more results are available. Servers may choose not to support the limit argument and will return all of the available results. If limit is specified and the continue field is empty, clients may assume that no more results are available. This field is not supported if watch is true. +

The server guarantees that the objects returned when using continue will be identical to issuing a single list call without a limit - that is, no objects created, modified, or deleted after the first request is issued will be included in any subsequent continued requests. This is sometimes referred to as a consistent snapshot, and ensures that a client that is using limit to receive smaller chunks of a very large result can ensure they see all possible objects. If objects are updated during a chunked list the version of the object that was present at the time the first list result was calculated is returned.

false

integer (int32)

QueryParameter

continue

The continue option should be set when retrieving more results from the server. Since this value is server defined, clients may only use the continue value from a previous query result with identical query parameters (except for the value of continue) and the server may reject a continue value it does not recognize. If the specified continue value is no longer valid whether due to expiration (generally five to fifteen minutes) or a configuration change on the server, the server will respond with a 410 ResourceExpired error together with a continue token. If the client needs a consistent list, it must restart their list without the continue field. Otherwise, the client may send another list request with the token received with the 410 error, the server will respond with a list starting from the next key, but from the latest snapshot, which is inconsistent from the previous list results - objects that are created, modified, or deleted after the first list request will be included in the response, as long as their keys are after the "next key". +

This field is not supported when watch is true. Clients may start a watch from the last resourceVersion value returned by the server and not miss any modifications.

false

string

PathParameter

namespace

object name and auth scope, such as for teams and projects

true

string

+ +
+
+

Responses

+ +++++ + + + + + + + + + + + + + + +
HTTP CodeDescriptionSchema

200

success

v1.WatchEvent

+ +
+
+

Consumes

+
+
    +
  • +

    /

    +
  • +
+
+
+
+

Produces

+
+
    +
  • +

    application/json

    +
  • +
  • +

    application/yaml

    +
  • +
  • +

    application/vnd.kubernetes.protobuf

    +
  • +
  • +

    application/json;stream=watch

    +
  • +
  • +

    application/vnd.kubernetes.protobuf;stream=watch

    +
  • +
+
+
+
+

Tags

+
+
    +
  • +

    apiscoordination.k8s.iov1

    +
  • +
+
+
+
+
+

watch changes to an object of kind Lease. deprecated: use the watch parameter with a list operation instead, filtered to a single item with the fieldSelector parameter.

+
+
+
GET /apis/coordination.k8s.io/v1/watch/namespaces/{namespace}/leases/{name}
+
+
+
+

Parameters

+ ++++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
TypeNameDescriptionRequiredSchemaDefault

QueryParameter

pretty

If true, then the output is pretty printed.

false

string

QueryParameter

labelSelector

A selector to restrict the list of returned objects by their labels. Defaults to everything.

false

string

QueryParameter

fieldSelector

A selector to restrict the list of returned objects by their fields. Defaults to everything.

false

string

QueryParameter

includeUninitialized

If true, partially initialized resources are included in the response.

false

boolean

QueryParameter

watch

Watch for changes to the described resources and return them as a stream of add, update, and remove notifications. Specify resourceVersion.

false

boolean

QueryParameter

resourceVersion

When specified with a watch call, shows changes that occur after that particular version of a resource. Defaults to changes from the beginning of history. When specified for list: - if unset, then the result is returned from remote storage based on quorum-read flag; - if it’s 0, then we simply return what we currently have in cache, no guarantee; - if set to non zero, then the result is at least as fresh as given rv.

false

string

QueryParameter

timeoutSeconds

Timeout for the list/watch call. This limits the duration of the call, regardless of any activity or inactivity.

false

integer (int32)

QueryParameter

limit

limit is a maximum number of responses to return for a list call. If more items exist, the server will set the continue field on the list metadata to a value that can be used with the same initial query to retrieve the next set of results. Setting a limit may return fewer than the requested amount of items (up to zero items) in the event all requested objects are filtered out and clients should only use the presence of the continue field to determine whether more results are available. Servers may choose not to support the limit argument and will return all of the available results. If limit is specified and the continue field is empty, clients may assume that no more results are available. This field is not supported if watch is true. +

The server guarantees that the objects returned when using continue will be identical to issuing a single list call without a limit - that is, no objects created, modified, or deleted after the first request is issued will be included in any subsequent continued requests. This is sometimes referred to as a consistent snapshot, and ensures that a client that is using limit to receive smaller chunks of a very large result can ensure they see all possible objects. If objects are updated during a chunked list the version of the object that was present at the time the first list result was calculated is returned.

false

integer (int32)

QueryParameter

continue

The continue option should be set when retrieving more results from the server. Since this value is server defined, clients may only use the continue value from a previous query result with identical query parameters (except for the value of continue) and the server may reject a continue value it does not recognize. If the specified continue value is no longer valid whether due to expiration (generally five to fifteen minutes) or a configuration change on the server, the server will respond with a 410 ResourceExpired error together with a continue token. If the client needs a consistent list, it must restart their list without the continue field. Otherwise, the client may send another list request with the token received with the 410 error, the server will respond with a list starting from the next key, but from the latest snapshot, which is inconsistent from the previous list results - objects that are created, modified, or deleted after the first list request will be included in the response, as long as their keys are after the "next key". +

This field is not supported when watch is true. Clients may start a watch from the last resourceVersion value returned by the server and not miss any modifications.

false

string

PathParameter

namespace

object name and auth scope, such as for teams and projects

true

string

PathParameter

name

name of the Lease

true

string

+ +
+
+

Responses

+ +++++ + + + + + + + + + + + + + + +
HTTP CodeDescriptionSchema

200

success

v1.WatchEvent

+ +
+
+

Consumes

+
+
    +
  • +

    /

    +
  • +
+
+
+
+

Produces

+
+
    +
  • +

    application/json

    +
  • +
  • +

    application/yaml

    +
  • +
  • +

    application/vnd.kubernetes.protobuf

    +
  • +
  • +

    application/json;stream=watch

    +
  • +
  • +

    application/vnd.kubernetes.protobuf;stream=watch

    +
  • +
+
+
+
+

Tags

+
+
    +
  • +

    apiscoordination.k8s.iov1

    +
  • +
+
+
+
+
+
+
+ + + \ No newline at end of file diff --git a/docs/man/man1/kubeadm-config-print-default.1 b/docs/man/man1/kubeadm-config-print-default.1 deleted file mode 100644 index b6fd7a0f989..00000000000 --- a/docs/man/man1/kubeadm-config-print-default.1 +++ /dev/null @@ -1,3 +0,0 @@ -This file is autogenerated, but we've stopped checking such files into the -repository to reduce the need for rebases. Please run hack/generate-docs.sh to -populate this file. diff --git a/hack/.golint_failures b/hack/.golint_failures index 8dab82504d8..b7d0181f745 100644 --- a/hack/.golint_failures +++ b/hack/.golint_failures @@ -1,4 +1,3 @@ - cluster/images/etcd-version-monitor cmd/cloud-controller-manager/app/apis/config/v1alpha1 cmd/hyperkube @@ -47,6 +46,7 @@ pkg/apis/certificates pkg/apis/certificates/v1beta1 pkg/apis/certificates/validation pkg/apis/coordination +pkg/apis/coordination/v1 pkg/apis/coordination/v1beta1 pkg/apis/core pkg/apis/core/helper @@ -88,7 +88,6 @@ pkg/apis/storage/v1beta1/util pkg/auth/authorizer/abac pkg/capabilities pkg/cloudprovider/providers/fake -pkg/cloudprovider/providers/gce/cloud pkg/cloudprovider/providers/photon pkg/cloudprovider/providers/vsphere pkg/cloudprovider/providers/vsphere/vclib @@ -137,15 +136,12 @@ pkg/kubeapiserver/options pkg/kubectl pkg/kubectl/apps pkg/kubectl/cmd/annotate -pkg/kubectl/cmd/apiresources pkg/kubectl/cmd/apply pkg/kubectl/cmd/attach -pkg/kubectl/cmd/auth pkg/kubectl/cmd/autoscale pkg/kubectl/cmd/certificates pkg/kubectl/cmd/clusterinfo pkg/kubectl/cmd/completion -pkg/kubectl/cmd/config pkg/kubectl/cmd/convert pkg/kubectl/cmd/cp pkg/kubectl/cmd/create @@ -175,9 +171,7 @@ pkg/kubectl/cmd/taint pkg/kubectl/cmd/testing pkg/kubectl/cmd/top pkg/kubectl/cmd/util -pkg/kubectl/cmd/util/editor pkg/kubectl/cmd/util/openapi -pkg/kubectl/cmd/util/sanity pkg/kubectl/cmd/version pkg/kubectl/cmd/wait pkg/kubectl/describe/versioned @@ -366,7 +360,6 @@ pkg/serviceaccount pkg/ssh pkg/util/bandwidth pkg/util/config -pkg/util/configz pkg/util/ebtables pkg/util/env pkg/util/file @@ -448,6 +441,7 @@ staging/src/k8s.io/api/batch/v1 staging/src/k8s.io/api/batch/v1beta1 staging/src/k8s.io/api/batch/v2alpha1 staging/src/k8s.io/api/certificates/v1beta1 +staging/src/k8s.io/api/coordination/v1 staging/src/k8s.io/api/coordination/v1beta1 staging/src/k8s.io/api/core/v1 staging/src/k8s.io/api/events/v1beta1 @@ -522,7 +516,6 @@ staging/src/k8s.io/apimachinery/pkg/util/runtime staging/src/k8s.io/apimachinery/pkg/util/sets/types staging/src/k8s.io/apimachinery/pkg/util/strategicpatch staging/src/k8s.io/apimachinery/pkg/util/uuid -staging/src/k8s.io/apimachinery/pkg/util/validation staging/src/k8s.io/apimachinery/pkg/util/wait staging/src/k8s.io/apimachinery/pkg/util/yaml staging/src/k8s.io/apimachinery/pkg/watch @@ -694,6 +687,7 @@ staging/src/k8s.io/metrics/pkg/client/custom_metrics/fake staging/src/k8s.io/metrics/pkg/client/custom_metrics/scheme staging/src/k8s.io/metrics/pkg/client/external_metrics staging/src/k8s.io/metrics/pkg/client/external_metrics/fake +staging/src/k8s.io/node-api/pkg/apis/node/v1alpha1 staging/src/k8s.io/sample-apiserver/pkg/admission/plugin/banflunder staging/src/k8s.io/sample-apiserver/pkg/admission/wardleinitializer staging/src/k8s.io/sample-apiserver/pkg/apis/wardle diff --git a/hack/godep-save.sh b/hack/godep-save.sh index 4b30e5d0bec..e278072d002 100755 --- a/hack/godep-save.sh +++ b/hack/godep-save.sh @@ -63,6 +63,7 @@ REQUIRED_BINS=( "github.com/bazelbuild/bazel-gazelle/cmd/gazelle" "github.com/kubernetes/repo-infra/kazel" "k8s.io/kube-openapi/cmd/openapi-gen" + "golang.org/x/lint/golint" "./..." ) diff --git a/hack/import-restrictions.yaml b/hack/import-restrictions.yaml index 9e56ad61c68..1ffa5ef0966 100644 --- a/hack/import-restrictions.yaml +++ b/hack/import-restrictions.yaml @@ -27,6 +27,7 @@ - k8s.io/api/core/v1 - k8s.io/cli-runtime/pkg/genericclioptions/printers - k8s.io/cli-runtime/pkg/genericclioptions/resource + - k8s.io/cli-runtime/pkg/kustomize/k8sdeps - baseImportPath: "./vendor/k8s.io/apimachinery/" allowedImports: @@ -172,6 +173,12 @@ - k8s.io/client-go - k8s.io/klog +- baseImportPath: "./vendor/k8s.io/node-api/" + allowedImports: + - k8s.io/apimachinery + - k8s.io/client-go + - k8s.io/node-api + - baseImportPath: "./vendor/k8s.io/csi-api/" allowedImports: - k8s.io/api diff --git a/hack/jenkins/benchmark-dockerized.sh b/hack/jenkins/benchmark-dockerized.sh index 4171cf6510d..1b86e6521e0 100755 --- a/hack/jenkins/benchmark-dockerized.sh +++ b/hack/jenkins/benchmark-dockerized.sh @@ -39,9 +39,9 @@ retry go get github.com/cespare/prettybench export KUBE_RACE=" " # Disable coverage report export KUBE_COVER="n" -export ARTIFACTS_DIR=${WORKSPACE}/_artifacts +export ARTIFACTS=${ARTIFACTS:-"${WORKSPACE}/artifacts"} -mkdir -p "${ARTIFACTS_DIR}" +mkdir -p "${ARTIFACTS}" cd /go/src/k8s.io/kubernetes ./hack/install-etcd.sh @@ -49,5 +49,5 @@ cd /go/src/k8s.io/kubernetes # Run the benchmark tests and pretty-print the results into a separate file. make test-integration WHAT="$*" KUBE_TEST_ARGS="-run='XXX' -bench=. -benchmem" \ | tee \ - >(prettybench -no-passthrough > ${ARTIFACTS_DIR}/BenchmarkResults.txt) \ - >(go run test/integration/benchmark/jsonify/main.go ${ARTIFACTS_DIR}/BenchmarkResults_benchmark_$(date -u +%Y-%m-%dT%H:%M:%SZ).json || cat > /dev/null) + >(prettybench -no-passthrough > ${ARTIFACTS}/BenchmarkResults.txt) \ + >(go run test/integration/benchmark/jsonify/main.go ${ARTIFACTS}/BenchmarkResults_benchmark_$(date -u +%Y-%m-%dT%H:%M:%SZ).json || cat > /dev/null) diff --git a/hack/jenkins/gotest.sh b/hack/jenkins/gotest.sh index cc298ccaa49..7b6778290b8 100755 --- a/hack/jenkins/gotest.sh +++ b/hack/jenkins/gotest.sh @@ -36,8 +36,10 @@ go get -u github.com/jstemmer/go-junit-report # Enable the Go race detector. export KUBE_RACE=-race -# Produce a JUnit-style XML test report for Jenkins. -export KUBE_JUNIT_REPORT_DIR=${WORKSPACE}/_artifacts +# Set artifacts directory +export ARTIFACTS=${ARTIFACTS:-"${WORKSPACE}/artifacts"} +# Produce a JUnit-style XML test report +export KUBE_JUNIT_REPORT_DIR="${ARTIFACTS}" # Save the verbose stdout as well. export KUBE_KEEP_VERBOSE_TEST_OUTPUT=y diff --git a/hack/jenkins/test-dockerized.sh b/hack/jenkins/test-dockerized.sh index 48f8306ce5b..df29a6f693d 100755 --- a/hack/jenkins/test-dockerized.sh +++ b/hack/jenkins/test-dockerized.sh @@ -39,15 +39,16 @@ retry go get github.com/jstemmer/go-junit-report export KUBE_RACE=-race # Disable coverage report export KUBE_COVER="n" -# Produce a JUnit-style XML test report for Jenkins. -export KUBE_JUNIT_REPORT_DIR=${WORKSPACE}/artifacts -export ARTIFACTS_DIR=${WORKSPACE}/artifacts +# Set artifacts directory +export ARTIFACTS=${ARTIFACTS:-"${WORKSPACE}/artifacts"} +# Produce a JUnit-style XML test report +export KUBE_JUNIT_REPORT_DIR="${ARTIFACTS}" # Save the verbose stdout as well. export KUBE_KEEP_VERBOSE_TEST_OUTPUT=y export KUBE_INTEGRATION_TEST_MAX_CONCURRENCY=4 export LOG_LEVEL=4 -cd /go/src/k8s.io/kubernetes +cd "${GOPATH}/src/k8s.io/kubernetes" make generated_files go install ./cmd/... diff --git a/hack/jenkins/verify-dockerized.sh b/hack/jenkins/verify-dockerized.sh index a15c811aa02..4182d85aac1 100755 --- a/hack/jenkins/verify-dockerized.sh +++ b/hack/jenkins/verify-dockerized.sh @@ -31,13 +31,13 @@ retry() { export PATH=${GOPATH}/bin:${PWD}/third_party/etcd:/usr/local/go/bin:${PATH} -# Produce a JUnit-style XML test report -export KUBE_JUNIT_REPORT_DIR=${WORKSPACE}/artifacts # Set artifacts directory -export ARTIFACTS_DIR=${WORKSPACE}/artifacts +export ARTIFACTS=${ARTIFACTS:-"${WORKSPACE}/artifacts"} +# Produce a JUnit-style XML test report +export KUBE_JUNIT_REPORT_DIR="${ARTIFACTS}" export LOG_LEVEL=4 -cd /go/src/k8s.io/kubernetes +cd "${GOPATH}/src/k8s.io/kubernetes" make verify diff --git a/hack/lib/etcd.sh b/hack/lib/etcd.sh index 33d8e07a988..5423d246c52 100755 --- a/hack/lib/etcd.sh +++ b/hack/lib/etcd.sh @@ -16,7 +16,7 @@ # A set of helpers for starting/running etcd for tests -ETCD_VERSION=${ETCD_VERSION:-3.2.24} +ETCD_VERSION=${ETCD_VERSION:-3.3.10} ETCD_HOST=${ETCD_HOST:-127.0.0.1} ETCD_PORT=${ETCD_PORT:-2379} export KUBE_INTEGRATION_ETCD_URL="http://${ETCD_HOST}:${ETCD_PORT}" @@ -70,8 +70,8 @@ kube::etcd::start() { # Start etcd ETCD_DIR=${ETCD_DIR:-$(mktemp -d 2>/dev/null || mktemp -d -t test-etcd.XXXXXX)} - if [[ -d "${ARTIFACTS_DIR:-}" ]]; then - ETCD_LOGFILE="${ARTIFACTS_DIR}/etcd.$(uname -n).$(id -un).log.DEBUG.$(date +%Y%m%d-%H%M%S).$$" + if [[ -d "${ARTIFACTS:-}" ]]; then + ETCD_LOGFILE="${ARTIFACTS}/etcd.$(uname -n).$(id -un).log.DEBUG.$(date +%Y%m%d-%H%M%S).$$" else ETCD_LOGFILE=${ETCD_LOGFILE:-"/dev/null"} fi diff --git a/hack/lib/init.sh b/hack/lib/init.sh index 2a676f804a0..64849d3af4d 100755 --- a/hack/lib/init.sh +++ b/hack/lib/init.sh @@ -59,9 +59,9 @@ v1 \ admissionregistration.k8s.io/v1alpha1 \ admissionregistration.k8s.io/v1beta1 \ admission.k8s.io/v1beta1 \ +apps/v1 \ apps/v1beta1 \ apps/v1beta2 \ -apps/v1 \ auditregistration.k8s.io/v1alpha1 \ authentication.k8s.io/v1 \ authentication.k8s.io/v1beta1 \ @@ -75,6 +75,7 @@ batch/v1beta1 \ batch/v2alpha1 \ certificates.k8s.io/v1beta1 \ coordination.k8s.io/v1beta1 \ +coordination.k8s.io/v1 \ extensions/v1beta1 \ events.k8s.io/v1beta1 \ imagepolicy.k8s.io/v1alpha1 \ diff --git a/hack/lib/util.sh b/hack/lib/util.sh index ccecdcfa880..68b5c6bd653 100755 --- a/hack/lib/util.sh +++ b/hack/lib/util.sh @@ -456,10 +456,8 @@ kube::util::ensure_godep_version() { # Otherwise, install forked godep kube::log::status "Installing godep version ${godep_target_version}" - # Run in hermetic GOPATH - kube::golang::setup_env - go install k8s.io/kubernetes/third_party/forked/godep - export KUBE_GODEP="${KUBE_GOPATH}/bin/godep" + GOBIN="${KUBE_OUTPUT_BINPATH}" go install k8s.io/kubernetes/third_party/forked/godep + export KUBE_GODEP="${KUBE_OUTPUT_BINPATH}/godep" kube::log::status "Installed ${KUBE_GODEP}" # Verify that the installed godep from fork is what we expect diff --git a/hack/local-up-cluster.sh b/hack/local-up-cluster.sh index b137b776f9d..cbd5341c661 100755 --- a/hack/local-up-cluster.sh +++ b/hack/local-up-cluster.sh @@ -483,6 +483,7 @@ function generate_certs { kube::util::create_client_certkey "${CONTROLPLANE_SUDO}" "${CERT_DIR}" 'client-ca' controller system:kube-controller-manager kube::util::create_client_certkey "${CONTROLPLANE_SUDO}" "${CERT_DIR}" 'client-ca' scheduler system:kube-scheduler kube::util::create_client_certkey "${CONTROLPLANE_SUDO}" "${CERT_DIR}" 'client-ca' admin system:admin system:masters + kube::util::create_client_certkey "${CONTROLPLANE_SUDO}" "${CERT_DIR}" 'client-ca' kube-apiserver kube-apiserver # Create matching certificates for kube-aggregator kube::util::create_serving_certkey "${CONTROLPLANE_SUDO}" "${CERT_DIR}" "server-ca" kube-aggregator api.kube-public.svc "localhost" ${API_HOST_IP} @@ -573,6 +574,8 @@ function start_apiserver { --vmodule="${LOG_SPEC}" \ --cert-dir="${CERT_DIR}" \ --client-ca-file="${CERT_DIR}/client-ca.crt" \ + --kubelet-client-certificate="${CERT_DIR}/client-kube-apiserver.crt" \ + --kubelet-client-key="${CERT_DIR}/client-kube-apiserver.key" \ --service-account-key-file="${SERVICE_ACCOUNT_KEY}" \ --service-account-lookup="${SERVICE_ACCOUNT_LOOKUP}" \ --enable-admission-plugins="${ENABLE_ADMISSION_PLUGINS}" \ @@ -616,6 +619,9 @@ function start_apiserver { AUTH_ARGS="--client-key=${CERT_DIR}/client-admin.key --client-certificate=${CERT_DIR}/client-admin.crt" fi + # Grant apiserver permission to speak to the kubelet + ${KUBECTL} --kubeconfig "${CERT_DIR}/admin.kubeconfig" create clusterrolebinding kube-apiserver-kubelet-admin --clusterrole=system:kubelet-api-admin --user=kube-apiserver + ${CONTROLPLANE_SUDO} cp "${CERT_DIR}/admin.kubeconfig" "${CERT_DIR}/admin-kube-aggregator.kubeconfig" ${CONTROLPLANE_SUDO} chown $(whoami) "${CERT_DIR}/admin-kube-aggregator.kubeconfig" ${KUBECTL} config set-cluster local-up-cluster --kubeconfig="${CERT_DIR}/admin-kube-aggregator.kubeconfig" --server="https://${API_HOST_IP}:31090" @@ -723,14 +729,16 @@ function start_kubelet { fi auth_args="" - if [[ -n "${KUBELET_AUTHORIZATION_WEBHOOK:-}" ]]; then + if [[ "${KUBELET_AUTHORIZATION_WEBHOOK:-}" != "false" ]]; then auth_args="${auth_args} --authorization-mode=Webhook" fi - if [[ -n "${KUBELET_AUTHENTICATION_WEBHOOK:-}" ]]; then + if [[ "${KUBELET_AUTHENTICATION_WEBHOOK:-}" != "false" ]]; then auth_args="${auth_args} --authentication-token-webhook" fi if [[ -n "${CLIENT_CA_FILE:-}" ]]; then auth_args="${auth_args} --client-ca-file=${CLIENT_CA_FILE}" + else + auth_args="${auth_args} --client-ca-file=${CERT_DIR}/client-ca.crt" fi cni_conf_dir_args="" diff --git a/hack/make-rules/test.sh b/hack/make-rules/test.sh index 3a64cdb404c..5aa1ad45a7f 100755 --- a/hack/make-rules/test.sh +++ b/hack/make-rules/test.sh @@ -120,6 +120,10 @@ KUBE_TEST_API_VERSIONS="${KUBE_TEST_API_VERSIONS:-${ALL_VERSIONS_CSV}}" # once we have multiple group supports # Create a junit-style XML test report in this directory if set. KUBE_JUNIT_REPORT_DIR=${KUBE_JUNIT_REPORT_DIR:-} +# If KUBE_JUNIT_REPORT_DIR is unset, and ARTIFACTS is set, then have them match. +if [[ -z "${KUBE_JUNIT_REPORT_DIR:-}" && -n "${ARTIFACTS:-}" ]]; then + export KUBE_JUNIT_REPORT_DIR="${ARTIFACTS}" +fi # Set to 'y' to keep the verbose stdout from tests when KUBE_JUNIT_REPORT_DIR is # set. KUBE_KEEP_VERBOSE_TEST_OUTPUT=${KUBE_KEEP_VERBOSE_TEST_OUTPUT:-n} diff --git a/hack/make-rules/verify.sh b/hack/make-rules/verify.sh index 7929264ce0c..b4b32edda7a 100755 --- a/hack/make-rules/verify.sh +++ b/hack/make-rules/verify.sh @@ -21,6 +21,11 @@ set -o pipefail KUBE_ROOT=$(dirname "${BASH_SOURCE}")/../.. source "${KUBE_ROOT}/hack/lib/util.sh" +# If KUBE_JUNIT_REPORT_DIR is unset, and ARTIFACTS is set, then have them match. +if [[ -z "${KUBE_JUNIT_REPORT_DIR:-}" && -n "${ARTIFACTS:-}" ]]; then + export KUBE_JUNIT_REPORT_DIR="${ARTIFACTS}" +fi + # include shell2junit library source "${KUBE_ROOT}/third_party/forked/shell2junit/sh2ju.sh" @@ -30,9 +35,25 @@ EXCLUDED_PATTERNS=( "verify-linkcheck.sh" # runs in separate Jenkins job once per day due to high network usage "verify-test-owners.sh" # TODO(rmmh): figure out how to avoid endless conflicts "verify-*-dockerized.sh" # Don't run any scripts that intended to be run dockerized - "verify-typecheck.sh" # runs in separate typecheck job ) +# Exclude typecheck in certain cases, if they're running in a separate job. +if [[ ${EXCLUDE_TYPECHECK:-} =~ ^[yY]$ ]]; then + EXCLUDED_PATTERNS+=( + "verify-typecheck.sh" # runs in separate typecheck job + ) +fi + + +# Exclude godep checks in certain cases, if they're running in a separate job. +if [[ ${EXCLUDE_GODEP:-} =~ ^[yY]$ ]]; then + EXCLUDED_PATTERNS+=( + "verify-godeps.sh" # runs in separate godeps job + "verify-staging-godeps.sh" # runs in separate godeps job + "verify-godep-licenses.sh" # runs in separate godeps job + ) +fi + # Only run whitelisted fast checks in quick mode. # These run in <10s each on enisoc's workstation, assuming that # `make` and `hack/godep-restore.sh` had already been run. diff --git a/hack/testdata/deployment-multicontainer-resources.yaml b/hack/testdata/deployment-multicontainer-resources.yaml index b36ace094b3..f574bcac000 100644 --- a/hack/testdata/deployment-multicontainer-resources.yaml +++ b/hack/testdata/deployment-multicontainer-resources.yaml @@ -1,4 +1,4 @@ -apiVersion: extensions/v1beta1 +apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment-resources diff --git a/hack/testdata/deployment-multicontainer.yaml b/hack/testdata/deployment-multicontainer.yaml index 117483957fd..47f0ceeb270 100644 --- a/hack/testdata/deployment-multicontainer.yaml +++ b/hack/testdata/deployment-multicontainer.yaml @@ -1,4 +1,4 @@ -apiVersion: extensions/v1beta1 +apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment diff --git a/hack/testdata/deployment-revision1.yaml b/hack/testdata/deployment-revision1.yaml index 2bcb8edea73..d60e08de2b0 100644 --- a/hack/testdata/deployment-revision1.yaml +++ b/hack/testdata/deployment-revision1.yaml @@ -1,4 +1,4 @@ -apiVersion: extensions/v1beta1 +apiVersion: apps/v1 kind: Deployment metadata: name: nginx diff --git a/hack/testdata/deployment-revision2.yaml b/hack/testdata/deployment-revision2.yaml index 1ed91c1375a..935e0e146d3 100644 --- a/hack/testdata/deployment-revision2.yaml +++ b/hack/testdata/deployment-revision2.yaml @@ -1,4 +1,4 @@ -apiVersion: extensions/v1beta1 +apiVersion: apps/v1 kind: Deployment metadata: name: nginx diff --git a/hack/testdata/deployment-with-UnixUserID.yaml b/hack/testdata/deployment-with-UnixUserID.yaml index ef69b33558c..cbfa76855a2 100644 --- a/hack/testdata/deployment-with-UnixUserID.yaml +++ b/hack/testdata/deployment-with-UnixUserID.yaml @@ -1,9 +1,14 @@ -apiVersion: extensions/v1beta1 +apiVersion: apps/v1 kind: Deployment metadata: name: deployment-with-unixuserid + labels: + app: nginx spec: replicas: 1 + selector: + matchLabels: + app: nginx template: metadata: labels: diff --git a/hack/testdata/diff/configmap.yaml b/hack/testdata/diff/configmap.yaml new file mode 100644 index 00000000000..be550449e83 --- /dev/null +++ b/hack/testdata/diff/configmap.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: test diff --git a/hack/testdata/diff/deployment.yaml b/hack/testdata/diff/deployment.yaml new file mode 100644 index 00000000000..0661df1be28 --- /dev/null +++ b/hack/testdata/diff/deployment.yaml @@ -0,0 +1,17 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: test +spec: + replicas: 3 + selector: + matchLabels: + name: test + template: + metadata: + labels: + name: test + spec: + containers: + - name: nginx + image: nginx diff --git a/hack/testdata/diff/pod.yaml b/hack/testdata/diff/pod.yaml new file mode 100644 index 00000000000..510ff2329e6 --- /dev/null +++ b/hack/testdata/diff/pod.yaml @@ -0,0 +1,8 @@ +apiVersion: v1 +kind: Pod +metadata: + name: test +spec: + containers: + - name: nginx + image: nginx diff --git a/hack/testdata/diff/secret.yaml b/hack/testdata/diff/secret.yaml new file mode 100644 index 00000000000..1c7de1855f9 --- /dev/null +++ b/hack/testdata/diff/secret.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +kind: Secret +metadata: + name: test diff --git a/hack/testdata/frontend-replicaset.yaml b/hack/testdata/frontend-replicaset.yaml index 878e10181ec..3dfeb9cb0a2 100644 --- a/hack/testdata/frontend-replicaset.yaml +++ b/hack/testdata/frontend-replicaset.yaml @@ -1,22 +1,18 @@ -apiVersion: extensions/v1beta1 +apiVersion: apps/v1 kind: ReplicaSet metadata: name: frontend - # these labels can be applied automatically - # from the labels in the pod template if not set - # labels: - # app: guestbook - # tier: frontend + labels: + app: guestbook + tier: frontend spec: # this replicas value is default # modify it according to your case replicas: 3 - # selector can be applied automatically - # from the labels in the pod template if not set - # selector: - # matchLabels: - # app: guestbook - # tier: frontend + selector: + matchLabels: + app: guestbook + tier: frontend template: metadata: labels: diff --git a/hack/testdata/initializer-deployments.yaml b/hack/testdata/initializer-deployments.yaml index 8564a874a3e..973a0a27636 100644 --- a/hack/testdata/initializer-deployments.yaml +++ b/hack/testdata/initializer-deployments.yaml @@ -1,4 +1,4 @@ -apiVersion: extensions/v1beta1 +apiVersion: apps/v1 kind: Deployment metadata: name: web diff --git a/hack/testdata/list.yaml b/hack/testdata/list.yaml index 1864e54e161..8e3bd5f3dfe 100644 --- a/hack/testdata/list.yaml +++ b/hack/testdata/list.yaml @@ -11,7 +11,7 @@ items: port: 80 selector: app: list-deployment-test -- apiVersion: extensions/v1beta1 +- apiVersion: apps/v1 kind: Deployment metadata: name: list-deployment-test @@ -19,6 +19,9 @@ items: app: list-deployment-test spec: replicas: 1 + selector: + matchLabels: + app: list-deployment-test template: metadata: labels: diff --git a/hack/testdata/recursive/deployment/deployment/nginx-broken.yaml b/hack/testdata/recursive/deployment/deployment/nginx-broken.yaml index 18c0d4ea7a2..c516dfdc8f4 100644 --- a/hack/testdata/recursive/deployment/deployment/nginx-broken.yaml +++ b/hack/testdata/recursive/deployment/deployment/nginx-broken.yaml @@ -1,4 +1,4 @@ -apiVersion: extensions/v1beta1 +apiVersion: apps/v1 ind: Deployment metadata: name: nginx2-deployment @@ -6,6 +6,9 @@ metadata: app: nginx2-deployment spec: replicas: 2 + selector: + matchLabels: + app: nginx2 template: metadata: labels: diff --git a/hack/testdata/recursive/deployment/deployment/nginx.yaml b/hack/testdata/recursive/deployment/deployment/nginx.yaml index f416d6c25cd..f4dde6d609d 100644 --- a/hack/testdata/recursive/deployment/deployment/nginx.yaml +++ b/hack/testdata/recursive/deployment/deployment/nginx.yaml @@ -1,4 +1,4 @@ -apiVersion: extensions/v1beta1 +apiVersion: apps/v1 kind: Deployment metadata: name: nginx1-deployment @@ -6,6 +6,9 @@ metadata: app: nginx1-deployment spec: replicas: 2 + selector: + matchLabels: + app: nginx1 template: metadata: labels: diff --git a/hack/testdata/recursive/deployment/nginx.yaml b/hack/testdata/recursive/deployment/nginx.yaml index 7988317f466..7c83f9654a6 100644 --- a/hack/testdata/recursive/deployment/nginx.yaml +++ b/hack/testdata/recursive/deployment/nginx.yaml @@ -1,4 +1,4 @@ -apiVersion: extensions/v1beta1 +apiVersion: apps/v1 kind: Deployment metadata: name: nginx0-deployment @@ -6,6 +6,9 @@ metadata: app: nginx0-deployment spec: replicas: 2 + selector: + matchLabels: + app: nginx0 template: metadata: labels: diff --git a/hack/testdata/redis-slave-replicaset.yaml b/hack/testdata/redis-slave-replicaset.yaml index 0948371e182..daa1507c556 100644 --- a/hack/testdata/redis-slave-replicaset.yaml +++ b/hack/testdata/redis-slave-replicaset.yaml @@ -1,23 +1,20 @@ -apiVersion: extensions/v1beta1 +apiVersion: apps/v1 kind: ReplicaSet metadata: name: redis-slave - # these labels can be applied automatically - # from the labels in the pod template if not set - # labels: - # app: redis - # role: slave - # tier: backend + labels: + app: redis + role: slave + tier: backend spec: # this replicas value is default # modify it according to your case replicas: 2 - # selector can be applied automatically - # from the labels in the pod template if not set - # selector: - # app: guestbook - # role: slave - # tier: backend + selector: + matchLabels: + app: redis + role: slave + tier: backend template: metadata: labels: diff --git a/hack/testdata/retainKeys/deployment/deployment-after.yaml b/hack/testdata/retainKeys/deployment/deployment-after.yaml index 15689a59959..656e4602d84 100644 --- a/hack/testdata/retainKeys/deployment/deployment-after.yaml +++ b/hack/testdata/retainKeys/deployment/deployment-after.yaml @@ -1,11 +1,16 @@ -apiVersion: extensions/v1beta1 +apiVersion: apps/v1 kind: Deployment metadata: name: test-deployment-retainkeys + labels: + app: nginx spec: strategy: type: Recreate replicas: 1 + selector: + matchLabels: + app: nginx template: metadata: labels: diff --git a/hack/testdata/retainKeys/deployment/deployment-before.yaml b/hack/testdata/retainKeys/deployment/deployment-before.yaml index e58a0c34a14..80e9f66224c 100644 --- a/hack/testdata/retainKeys/deployment/deployment-before.yaml +++ b/hack/testdata/retainKeys/deployment/deployment-before.yaml @@ -1,9 +1,14 @@ -apiVersion: extensions/v1beta1 +apiVersion: apps/v1 kind: Deployment metadata: name: test-deployment-retainkeys + labels: + app: nginx spec: replicas: 1 + selector: + matchLabels: + app: nginx template: metadata: labels: diff --git a/hack/testdata/rollingupdate-daemonset-rv2.yaml b/hack/testdata/rollingupdate-daemonset-rv2.yaml index b807e958dd2..f3023834c6a 100644 --- a/hack/testdata/rollingupdate-daemonset-rv2.yaml +++ b/hack/testdata/rollingupdate-daemonset-rv2.yaml @@ -1,8 +1,13 @@ -apiVersion: extensions/v1beta1 +apiVersion: apps/v1 kind: DaemonSet metadata: name: bind + labels: + service: bind spec: + selector: + matchLabels: + service: bind updateStrategy: type: RollingUpdate rollingUpdate: diff --git a/hack/testdata/rollingupdate-daemonset.yaml b/hack/testdata/rollingupdate-daemonset.yaml index 4bc77ed5bfe..d4ced8044a0 100644 --- a/hack/testdata/rollingupdate-daemonset.yaml +++ b/hack/testdata/rollingupdate-daemonset.yaml @@ -1,8 +1,13 @@ -apiVersion: extensions/v1beta1 +apiVersion: apps/v1 kind: DaemonSet metadata: name: bind + labels: + service: bind spec: + selector: + matchLabels: + service: bind updateStrategy: type: RollingUpdate rollingUpdate: diff --git a/hack/testdata/scale-deploy-1.yaml b/hack/testdata/scale-deploy-1.yaml index b1e6ee5a01e..91f1fa0d875 100644 --- a/hack/testdata/scale-deploy-1.yaml +++ b/hack/testdata/scale-deploy-1.yaml @@ -1,4 +1,4 @@ -apiVersion: extensions/v1beta1 +apiVersion: apps/v1 kind: Deployment metadata: labels: diff --git a/hack/testdata/scale-deploy-2.yaml b/hack/testdata/scale-deploy-2.yaml index dc954b5b5cd..e69847bf74b 100644 --- a/hack/testdata/scale-deploy-2.yaml +++ b/hack/testdata/scale-deploy-2.yaml @@ -1,4 +1,4 @@ -apiVersion: extensions/v1beta1 +apiVersion: apps/v1 kind: Deployment metadata: labels: diff --git a/hack/testdata/scale-deploy-3.yaml b/hack/testdata/scale-deploy-3.yaml index 63a7d759335..0eec827015e 100644 --- a/hack/testdata/scale-deploy-3.yaml +++ b/hack/testdata/scale-deploy-3.yaml @@ -1,4 +1,4 @@ -apiVersion: extensions/v1beta1 +apiVersion: apps/v1 kind: Deployment metadata: labels: diff --git a/hack/update-cloudprovider-gce.sh b/hack/update-cloudprovider-gce.sh deleted file mode 100755 index b35c429f8a9..00000000000 --- a/hack/update-cloudprovider-gce.sh +++ /dev/null @@ -1,38 +0,0 @@ -#!/usr/bin/env bash - -# Copyright 2018 The Kubernetes Authors. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -set -o errexit -set -o nounset -set -o pipefail - -KUBE_ROOT=$(dirname "${BASH_SOURCE}")/.. -source "${KUBE_ROOT}/hack/lib/init.sh" -GENERATOR="${KUBE_ROOT}/pkg/cloudprovider/providers/gce/cloud/gen/main.go" - -GEN_GO="${KUBE_ROOT}/pkg/cloudprovider/providers/gce/cloud/gen.go" -GEN_TEST_GO="${KUBE_ROOT}/pkg/cloudprovider/providers/gce/cloud/gen_test.go" - -kube::golang::setup_env - -TMPFILE=$(mktemp verify-cloudprovider-gce-XXXX) -trap "{ rm -f ${TMPFILE}; }" EXIT - -go run "${GENERATOR}" > ${TMPFILE} -mv "${TMPFILE}" "${GEN_GO}" -go run "${GENERATOR}" -mode test > ${TMPFILE} -mv "${TMPFILE}" "${GEN_TEST_GO}" - -exit 0 diff --git a/hack/update-codegen.sh b/hack/update-codegen.sh index 7c9edb94dd9..c2fbd79945f 100755 --- a/hack/update-codegen.sh +++ b/hack/update-codegen.sh @@ -114,3 +114,4 @@ CODEGEN_PKG=./vendor/k8s.io/code-generator vendor/k8s.io/apiextensions-apiserver CODEGEN_PKG=./vendor/k8s.io/code-generator vendor/k8s.io/metrics/hack/update-codegen.sh CODEGEN_PKG=./vendor/k8s.io/code-generator vendor/k8s.io/apiextensions-apiserver/examples/client-go/hack/update-codegen.sh CODEGEN_PKG=./vendor/k8s.io/code-generator vendor/k8s.io/csi-api/hack/update-codegen.sh +CODEGEN_PKG=./vendor/k8s.io/code-generator vendor/k8s.io/node-api/hack/update-codegen.sh diff --git a/hack/update-generated-protobuf-dockerized.sh b/hack/update-generated-protobuf-dockerized.sh index 612cfba3648..62950342943 100755 --- a/hack/update-generated-protobuf-dockerized.sh +++ b/hack/update-generated-protobuf-dockerized.sh @@ -68,6 +68,7 @@ PACKAGES=( k8s.io/api/rbac/v1 k8s.io/api/certificates/v1beta1 k8s.io/api/coordination/v1beta1 + k8s.io/api/coordination/v1 k8s.io/api/imagepolicy/v1alpha1 k8s.io/api/scheduling/v1alpha1 k8s.io/api/scheduling/v1beta1 diff --git a/hack/verify-cloudprovider-gce.sh b/hack/verify-cloudprovider-gce.sh deleted file mode 100755 index c6b3bd89af7..00000000000 --- a/hack/verify-cloudprovider-gce.sh +++ /dev/null @@ -1,49 +0,0 @@ -#!/usr/bin/env bash - -# Copyright 2018 The Kubernetes Authors. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -set -o errexit -set -o nounset -set -o pipefail - -KUBE_ROOT=$(dirname "${BASH_SOURCE}")/.. -source "${KUBE_ROOT}/hack/lib/init.sh" -GENERATOR="${KUBE_ROOT}/pkg/cloudprovider/providers/gce/cloud/gen/main.go" - -GEN_GO="${KUBE_ROOT}/pkg/cloudprovider/providers/gce/cloud/gen.go" -GEN_TEST_GO="${KUBE_ROOT}/pkg/cloudprovider/providers/gce/cloud/gen_test.go" - -kube::golang::setup_env - -TMPFILE=$(mktemp verify-cloudprovider-gce-XXXX) -trap "{ rm -f ${TMPFILE}; }" EXIT - -go run "${GENERATOR}" > ${TMPFILE} -if ! diff "${TMPFILE}" "${GEN_GO}"; then - echo "Generated file ${GEN_GO} needs to be updated (run hack/update-cloudprovider-gce.sh)" - echo - diff -u "${TMPFILE}" "${GEN_GO}" || true - exit 1 -fi - -go run "${GENERATOR}" -mode test > ${TMPFILE} -if ! diff "${TMPFILE}" "${GEN_TEST_GO}"; then - echo "Generated file ${GEN_TEST_GO} needs to be updated (run hack/update-cloudprovider-gce.sh)" - echo - diff -u "${TMPFILE}" "${GEN_TEST_GO}" || true - exit 1 -fi - -exit 0 diff --git a/hack/verify-codegen.sh b/hack/verify-codegen.sh index de031bb298e..9d02b382211 100755 --- a/hack/verify-codegen.sh +++ b/hack/verify-codegen.sh @@ -34,5 +34,6 @@ CODEGEN_PKG=./vendor/k8s.io/code-generator vendor/k8s.io/sample-controller/hack/ CODEGEN_PKG=./vendor/k8s.io/code-generator vendor/k8s.io/apiextensions-apiserver/hack/verify-codegen.sh CODEGEN_PKG=./vendor/k8s.io/code-generator vendor/k8s.io/metrics/hack/verify-codegen.sh CODEGEN_PKG=./vendor/k8s.io/code-generator vendor/k8s.io/csi-api/hack/verify-codegen.sh +CODEGEN_PKG=./vendor/k8s.io/code-generator vendor/k8s.io/node-api/hack/verify-codegen.sh "${KUBE_ROOT}/hack/update-codegen.sh" --verify-only diff --git a/hack/verify-godeps.sh b/hack/verify-godeps.sh index 2de2e6022c9..8fda624ca70 100755 --- a/hack/verify-godeps.sh +++ b/hack/verify-godeps.sh @@ -94,9 +94,9 @@ pushd "${KUBE_ROOT}" > /dev/null 2>&1 echo "(The above output can be saved as godepdiff.patch if you're not running this locally)" >&2 echo "(The patch file should also be exported as a build artifact if run through CI)" >&2 KEEP_TMP=true - if [[ -f godepdiff.patch && -d "${ARTIFACTS_DIR:-}" ]]; then + if [[ -f godepdiff.patch && -d "${ARTIFACTS:-}" ]]; then echo "Copying patch to artifacts.." - cp godepdiff.patch "${ARTIFACTS_DIR:-}/" + cp godepdiff.patch "${ARTIFACTS:-}/" fi ret=1 fi @@ -111,9 +111,9 @@ pushd "${KUBE_ROOT}" > /dev/null 2>&1 echo "(The above output can be saved as godepdiff.patch if you're not running this locally)" >&2 echo "(The patch file should also be exported as a build artifact if run through CI)" >&2 KEEP_TMP=true - if [[ -f vendordiff.patch && -d "${ARTIFACTS_DIR:-}" ]]; then + if [[ -f vendordiff.patch && -d "${ARTIFACTS:-}" ]]; then echo "Copying patch to artifacts.." - cp vendordiff.patch "${ARTIFACTS_DIR:-}/" + cp vendordiff.patch "${ARTIFACTS:-}/" fi ret=1 fi diff --git a/hack/verify-golint.sh b/hack/verify-golint.sh index 3e0c579f49c..d8c981f85b6 100755 --- a/hack/verify-golint.sh +++ b/hack/verify-golint.sh @@ -23,11 +23,15 @@ source "${KUBE_ROOT}/hack/lib/init.sh" kube::golang::verify_go_version -if ! which golint > /dev/null; then - echo 'Can not find golint, install with:' - echo 'go get -u golang.org/x/lint/golint' - exit 1 -fi + +# Ensure that we find the binaries we build before anything else. +export GOBIN="${KUBE_OUTPUT_BINPATH}" +PATH="${GOBIN}:${PATH}" + +# Install golint from vendor +echo 'installing golint from vendor' +go install k8s.io/kubernetes/vendor/golang.org/x/lint/golint + cd "${KUBE_ROOT}" diff --git a/pkg/api/persistentvolume/util.go b/pkg/api/persistentvolume/util.go index 298a38250f7..0d3a79889cd 100644 --- a/pkg/api/persistentvolume/util.go +++ b/pkg/api/persistentvolume/util.go @@ -25,13 +25,8 @@ import ( // DropDisabledFields removes disabled fields from the pv spec. // This should be called from PrepareForCreate/PrepareForUpdate for all resources containing a pv spec. func DropDisabledFields(pvSpec *api.PersistentVolumeSpec, oldPVSpec *api.PersistentVolumeSpec) { - if !utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) { - // TODO(liggitt): change this to only drop pvSpec.VolumeMode if (oldPVSpec == nil || oldPVSpec.VolumeMode == nil) - // Requires more coordinated changes to validation + if !utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) && !volumeModeInUse(oldPVSpec) { pvSpec.VolumeMode = nil - if oldPVSpec != nil { - oldPVSpec.VolumeMode = nil - } } if !utilfeature.DefaultFeatureGate.Enabled(features.CSIPersistentVolume) { @@ -41,3 +36,13 @@ func DropDisabledFields(pvSpec *api.PersistentVolumeSpec, oldPVSpec *api.Persist } } } + +func volumeModeInUse(oldPVSpec *api.PersistentVolumeSpec) bool { + if oldPVSpec == nil { + return false + } + if oldPVSpec.VolumeMode != nil { + return true + } + return false +} diff --git a/pkg/api/persistentvolume/util_test.go b/pkg/api/persistentvolume/util_test.go index 6ea33b5a38c..3b31f298c13 100644 --- a/pkg/api/persistentvolume/util_test.go +++ b/pkg/api/persistentvolume/util_test.go @@ -106,13 +106,12 @@ func TestDropDisabledFields(t *testing.T) { oldSpec: specWithMode(nil), expectOldSpec: specWithMode(nil), }, - // TODO: consider changing this case to preserve - "disabled block clears old and new on update when old pv did use block": { + "disabled block does not clear new on update when old pv did use block": { blockEnabled: false, newSpec: specWithMode(&modeBlock), - expectNewSpec: specWithMode(nil), + expectNewSpec: specWithMode(&modeBlock), oldSpec: specWithMode(&modeBlock), - expectOldSpec: specWithMode(nil), + expectOldSpec: specWithMode(&modeBlock), }, "enabled block preserves new": { diff --git a/pkg/api/persistentvolumeclaim/BUILD b/pkg/api/persistentvolumeclaim/BUILD index 3a72b78c8f0..e1b030325a0 100644 --- a/pkg/api/persistentvolumeclaim/BUILD +++ b/pkg/api/persistentvolumeclaim/BUILD @@ -37,6 +37,7 @@ go_test( deps = [ "//pkg/apis/core:go_default_library", "//pkg/features:go_default_library", + "//staging/src/k8s.io/apimachinery/pkg/util/diff:go_default_library", "//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library", "//staging/src/k8s.io/apiserver/pkg/util/feature/testing:go_default_library", ], diff --git a/pkg/api/persistentvolumeclaim/util.go b/pkg/api/persistentvolumeclaim/util.go index a6321d3404f..e55c02fa30d 100644 --- a/pkg/api/persistentvolumeclaim/util.go +++ b/pkg/api/persistentvolumeclaim/util.go @@ -22,10 +22,20 @@ import ( "k8s.io/kubernetes/pkg/features" ) -// DropDisabledAlphaFields removes disabled fields from the pvc spec. +// DropDisabledFields removes disabled fields from the pvc spec. // This should be called from PrepareForCreate/PrepareForUpdate for all resources containing a pvc spec. -func DropDisabledAlphaFields(pvcSpec *core.PersistentVolumeClaimSpec) { - if !utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) { +func DropDisabledFields(pvcSpec, oldPVCSpec *core.PersistentVolumeClaimSpec) { + if !utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) && !volumeModeInUse(oldPVCSpec) { pvcSpec.VolumeMode = nil } } + +func volumeModeInUse(oldPVCSpec *core.PersistentVolumeClaimSpec) bool { + if oldPVCSpec == nil { + return false + } + if oldPVCSpec.VolumeMode != nil { + return true + } + return false +} diff --git a/pkg/api/persistentvolumeclaim/util_test.go b/pkg/api/persistentvolumeclaim/util_test.go index 7bb61edd1dd..d5242c03a86 100644 --- a/pkg/api/persistentvolumeclaim/util_test.go +++ b/pkg/api/persistentvolumeclaim/util_test.go @@ -17,8 +17,11 @@ limitations under the License. package persistentvolumeclaim import ( + "fmt" + "reflect" "testing" + "k8s.io/apimachinery/pkg/util/diff" utilfeature "k8s.io/apiserver/pkg/util/feature" utilfeaturetesting "k8s.io/apiserver/pkg/util/feature/testing" "k8s.io/kubernetes/pkg/apis/core" @@ -28,33 +31,89 @@ import ( func TestDropAlphaPVCVolumeMode(t *testing.T) { vmode := core.PersistentVolumeFilesystem - // PersistentVolume with VolumeMode set - pvc := core.PersistentVolumeClaim{ - Spec: core.PersistentVolumeClaimSpec{ - AccessModes: []core.PersistentVolumeAccessMode{core.ReadWriteOnce}, - VolumeMode: &vmode, + pvcWithoutVolumeMode := func() *core.PersistentVolumeClaim { + return &core.PersistentVolumeClaim{ + Spec: core.PersistentVolumeClaimSpec{ + VolumeMode: nil, + }, + } + } + pvcWithVolumeMode := func() *core.PersistentVolumeClaim { + return &core.PersistentVolumeClaim{ + Spec: core.PersistentVolumeClaimSpec{ + VolumeMode: &vmode, + }, + } + } + + pvcInfo := []struct { + description string + hasVolumeMode bool + pvc func() *core.PersistentVolumeClaim + }{ + { + description: "pvc without VolumeMode", + hasVolumeMode: false, + pvc: pvcWithoutVolumeMode, + }, + { + description: "pvc with Filesystem VolumeMode", + hasVolumeMode: true, + pvc: pvcWithVolumeMode, + }, + { + description: "is nil", + hasVolumeMode: false, + pvc: func() *core.PersistentVolumeClaim { return nil }, }, } - // Enable alpha feature BlockVolume - defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, true)() - // now test dropping the fields - should not be dropped - DropDisabledAlphaFields(&pvc.Spec) + for _, enabled := range []bool{true, false} { + for _, oldpvcInfo := range pvcInfo { + for _, newpvcInfo := range pvcInfo { + oldpvcHasVolumeMode, oldpvc := oldpvcInfo.hasVolumeMode, oldpvcInfo.pvc() + newpvcHasVolumeMode, newpvc := newpvcInfo.hasVolumeMode, newpvcInfo.pvc() + if newpvc == nil { + continue + } - // check to make sure VolumeDevices is still present - // if featureset is set to true - if pvc.Spec.VolumeMode == nil { - t.Error("VolumeMode in pvc.Spec should not have been dropped based on feature-gate") - } + t.Run(fmt.Sprintf("feature enabled=%v, old pvc %v, new pvc %v", enabled, oldpvcInfo.description, newpvcInfo.description), func(t *testing.T) { + defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, enabled)() - // Disable alpha feature BlockVolume - defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, false)() - // now test dropping the fields - DropDisabledAlphaFields(&pvc.Spec) + var oldpvcSpec *core.PersistentVolumeClaimSpec + if oldpvc != nil { + oldpvcSpec = &oldpvc.Spec + } + DropDisabledFields(&newpvc.Spec, oldpvcSpec) - // check to make sure VolumeDevices is nil - // if featureset is set to false - if pvc.Spec.VolumeMode != nil { - t.Error("DropDisabledAlphaFields VolumeMode for pvc.Spec failed") + // old pvc should never be changed + if !reflect.DeepEqual(oldpvc, oldpvcInfo.pvc()) { + t.Errorf("old pvc changed: %v", diff.ObjectReflectDiff(oldpvc, oldpvcInfo.pvc())) + } + + switch { + case enabled || oldpvcHasVolumeMode: + // new pvc should not be changed if the feature is enabled, or if the old pvc had BlockVolume + if !reflect.DeepEqual(newpvc, newpvcInfo.pvc()) { + t.Errorf("new pvc changed: %v", diff.ObjectReflectDiff(newpvc, newpvcInfo.pvc())) + } + case newpvcHasVolumeMode: + // new pvc should be changed + if reflect.DeepEqual(newpvc, newpvcInfo.pvc()) { + t.Errorf("new pvc was not changed") + } + // new pvc should not have BlockVolume + if !reflect.DeepEqual(newpvc, pvcWithoutVolumeMode()) { + t.Errorf("new pvc had pvcBlockVolume: %v", diff.ObjectReflectDiff(newpvc, pvcWithoutVolumeMode())) + } + default: + // new pvc should not need to be changed + if !reflect.DeepEqual(newpvc, newpvcInfo.pvc()) { + t.Errorf("new pvc changed: %v", diff.ObjectReflectDiff(newpvc, newpvcInfo.pvc())) + } + } + }) + } + } } } diff --git a/pkg/api/pod/BUILD b/pkg/api/pod/BUILD index 2da65ee0c57..4bdc4c39d56 100644 --- a/pkg/api/pod/BUILD +++ b/pkg/api/pod/BUILD @@ -38,6 +38,8 @@ go_test( deps = [ "//pkg/apis/core:go_default_library", "//pkg/features:go_default_library", + "//staging/src/k8s.io/apimachinery/pkg/api/resource:go_default_library", + "//staging/src/k8s.io/apimachinery/pkg/util/diff:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/validation/field:go_default_library", "//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library", diff --git a/pkg/api/pod/util.go b/pkg/api/pod/util.go index d519c9a25ff..1c2c6a9fe0b 100644 --- a/pkg/api/pod/util.go +++ b/pkg/api/pod/util.go @@ -232,15 +232,17 @@ func UpdatePodCondition(status *api.PodStatus, condition *api.PodCondition) bool return !isEqual } -// DropDisabledAlphaFields removes disabled fields from the pod spec. +// DropDisabledFields removes disabled fields from the pod spec. // This should be called from PrepareForCreate/PrepareForUpdate for all resources containing a pod spec. -func DropDisabledAlphaFields(podSpec *api.PodSpec) { - if !utilfeature.DefaultFeatureGate.Enabled(features.PodPriority) { +func DropDisabledFields(podSpec, oldPodSpec *api.PodSpec) { + if !utilfeature.DefaultFeatureGate.Enabled(features.PodPriority) && !podPriorityInUse(oldPodSpec) { + // Set to nil pod's priority fields if the feature is disabled and the old pod + // does not specify any values for these fields. podSpec.Priority = nil podSpec.PriorityClassName = "" } - if !utilfeature.DefaultFeatureGate.Enabled(features.LocalStorageCapacityIsolation) { + if !utilfeature.DefaultFeatureGate.Enabled(features.LocalStorageCapacityIsolation) && !emptyDirSizeLimitInUse(oldPodSpec) { for i := range podSpec.Volumes { if podSpec.Volumes[i].EmptyDir != nil { podSpec.Volumes[i].EmptyDir.SizeLimit = nil @@ -248,21 +250,36 @@ func DropDisabledAlphaFields(podSpec *api.PodSpec) { } } - DropDisabledVolumeDevicesAlphaFields(podSpec) + if !utilfeature.DefaultFeatureGate.Enabled(features.VolumeSubpath) && !subpathInUse(oldPodSpec) { + // drop subpath from the pod if the feature is disabled and the old spec did not specify subpaths + for i := range podSpec.Containers { + for j := range podSpec.Containers[i].VolumeMounts { + podSpec.Containers[i].VolumeMounts[j].SubPath = "" + } + } + for i := range podSpec.InitContainers { + for j := range podSpec.InitContainers[i].VolumeMounts { + podSpec.InitContainers[i].VolumeMounts[j].SubPath = "" + } + } + } - DropDisabledRunAsGroupField(podSpec) + dropDisabledVolumeDevicesFields(podSpec, oldPodSpec) - if !utilfeature.DefaultFeatureGate.Enabled(features.RuntimeClass) && podSpec.RuntimeClassName != nil { + dropDisabledRunAsGroupField(podSpec, oldPodSpec) + + if !utilfeature.DefaultFeatureGate.Enabled(features.RuntimeClass) && !runtimeClassInUse(oldPodSpec) { + // Set RuntimeClassName to nil only if feature is disabled and it is not used podSpec.RuntimeClassName = nil } - DropDisabledProcMountField(podSpec) + dropDisabledProcMountField(podSpec, oldPodSpec) } -// DropDisabledRunAsGroupField removes disabled fields from PodSpec related +// dropDisabledRunAsGroupField removes disabled fields from PodSpec related // to RunAsGroup -func DropDisabledRunAsGroupField(podSpec *api.PodSpec) { - if !utilfeature.DefaultFeatureGate.Enabled(features.RunAsGroup) { +func dropDisabledRunAsGroupField(podSpec, oldPodSpec *api.PodSpec) { + if !utilfeature.DefaultFeatureGate.Enabled(features.RunAsGroup) && !runAsGroupInUse(oldPodSpec) { if podSpec.SecurityContext != nil { podSpec.SecurityContext.RunAsGroup = nil } @@ -279,28 +296,28 @@ func DropDisabledRunAsGroupField(podSpec *api.PodSpec) { } } -// DropDisabledProcMountField removes disabled fields from PodSpec related -// to ProcMount -func DropDisabledProcMountField(podSpec *api.PodSpec) { - if !utilfeature.DefaultFeatureGate.Enabled(features.ProcMountType) { - defProcMount := api.DefaultProcMount +// dropDisabledProcMountField removes disabled fields from PodSpec related +// to ProcMount only if it is not already used by the old spec +func dropDisabledProcMountField(podSpec, oldPodSpec *api.PodSpec) { + if !utilfeature.DefaultFeatureGate.Enabled(features.ProcMountType) && !procMountInUse(oldPodSpec) { + defaultProcMount := api.DefaultProcMount for i := range podSpec.Containers { if podSpec.Containers[i].SecurityContext != nil { - podSpec.Containers[i].SecurityContext.ProcMount = &defProcMount + podSpec.Containers[i].SecurityContext.ProcMount = &defaultProcMount } } for i := range podSpec.InitContainers { if podSpec.InitContainers[i].SecurityContext != nil { - podSpec.InitContainers[i].SecurityContext.ProcMount = &defProcMount + podSpec.InitContainers[i].SecurityContext.ProcMount = &defaultProcMount } } } } -// DropDisabledVolumeDevicesAlphaFields removes disabled fields from []VolumeDevice. +// dropDisabledVolumeDevicesFields removes disabled fields from []VolumeDevice if it has not been already populated. // This should be called from PrepareForCreate/PrepareForUpdate for all resources containing a VolumeDevice -func DropDisabledVolumeDevicesAlphaFields(podSpec *api.PodSpec) { - if !utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) { +func dropDisabledVolumeDevicesFields(podSpec, oldPodSpec *api.PodSpec) { + if !utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) && !volumeDevicesInUse(oldPodSpec) { for i := range podSpec.Containers { podSpec.Containers[i].VolumeDevices = nil } @@ -309,3 +326,128 @@ func DropDisabledVolumeDevicesAlphaFields(podSpec *api.PodSpec) { } } } + +// subpathInUse returns true if the pod spec is non-nil and has a volume mount that makes use of the subPath feature +func subpathInUse(podSpec *api.PodSpec) bool { + if podSpec == nil { + return false + } + for i := range podSpec.Containers { + for j := range podSpec.Containers[i].VolumeMounts { + if len(podSpec.Containers[i].VolumeMounts[j].SubPath) > 0 { + return true + } + } + } + for i := range podSpec.InitContainers { + for j := range podSpec.InitContainers[i].VolumeMounts { + if len(podSpec.InitContainers[i].VolumeMounts[j].SubPath) > 0 { + return true + } + } + } + return false +} + +// runtimeClassInUse returns true if the pod spec is non-nil and has a RuntimeClassName set +func runtimeClassInUse(podSpec *api.PodSpec) bool { + if podSpec == nil { + return false + } + if podSpec.RuntimeClassName != nil { + return true + } + return false +} + +// procMountInUse returns true if the pod spec is non-nil and has a SecurityContext's ProcMount field set +func procMountInUse(podSpec *api.PodSpec) bool { + if podSpec == nil { + return false + } + for i := range podSpec.Containers { + if podSpec.Containers[i].SecurityContext != nil { + if podSpec.Containers[i].SecurityContext.ProcMount != nil { + if *podSpec.Containers[i].SecurityContext.ProcMount != api.DefaultProcMount { + return true + } + } + } + } + for i := range podSpec.InitContainers { + if podSpec.InitContainers[i].SecurityContext != nil { + if podSpec.InitContainers[i].SecurityContext.ProcMount != nil { + if *podSpec.InitContainers[i].SecurityContext.ProcMount != api.DefaultProcMount { + return true + } + } + } + } + return false +} + +// podPriorityInUse returns true if the pod spec is non-nil and has Priority or PriorityClassName set. +func podPriorityInUse(podSpec *api.PodSpec) bool { + if podSpec == nil { + return false + } + if podSpec.Priority != nil || podSpec.PriorityClassName != "" { + return true + } + return false +} + +// emptyDirSizeLimitInUse returns true if any pod's EptyDir volumes use SizeLimit. +func emptyDirSizeLimitInUse(podSpec *api.PodSpec) bool { + if podSpec == nil { + return false + } + for i := range podSpec.Volumes { + if podSpec.Volumes[i].EmptyDir != nil { + if podSpec.Volumes[i].EmptyDir.SizeLimit != nil { + return true + } + } + } + return false +} + +// volumeDevicesInUse returns true if the pod spec is non-nil and has VolumeDevices set. +func volumeDevicesInUse(podSpec *api.PodSpec) bool { + if podSpec == nil { + return false + } + for i := range podSpec.Containers { + if podSpec.Containers[i].VolumeDevices != nil { + return true + } + } + for i := range podSpec.InitContainers { + if podSpec.InitContainers[i].VolumeDevices != nil { + return true + } + } + return false +} + +// runAsGroupInUse returns true if the pod spec is non-nil and has a SecurityContext's RunAsGroup field set +func runAsGroupInUse(podSpec *api.PodSpec) bool { + if podSpec == nil { + return false + } + + if podSpec.SecurityContext != nil && podSpec.SecurityContext.RunAsGroup != nil { + return true + } + for i := range podSpec.Containers { + if podSpec.Containers[i].SecurityContext != nil && podSpec.Containers[i].SecurityContext.RunAsGroup != nil { + return true + } + } + for i := range podSpec.InitContainers { + if podSpec.InitContainers[i].SecurityContext != nil && podSpec.InitContainers[i].SecurityContext.RunAsGroup != nil { + return true + } + } + return false +} diff --git a/pkg/api/pod/util_test.go b/pkg/api/pod/util_test.go index aaad55247dd..3125ec56345 100644 --- a/pkg/api/pod/util_test.go +++ b/pkg/api/pod/util_test.go @@ -17,10 +17,13 @@ limitations under the License. package pod import ( + "fmt" "reflect" "strings" "testing" + "k8s.io/apimachinery/pkg/api/resource" + "k8s.io/apimachinery/pkg/util/diff" "k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/validation/field" utilfeature "k8s.io/apiserver/pkg/util/feature" @@ -267,73 +270,785 @@ func TestPodConfigmaps(t *testing.T) { } func TestDropAlphaVolumeDevices(t *testing.T) { - testPod := api.Pod{ - Spec: api.PodSpec{ - RestartPolicy: api.RestartPolicyNever, - Containers: []api.Container{ - { - Name: "container1", - Image: "testimage", - VolumeDevices: []api.VolumeDevice{ - { - Name: "myvolume", - DevicePath: "/usr/test", + podWithVolumeDevices := func() *api.Pod { + return &api.Pod{ + Spec: api.PodSpec{ + RestartPolicy: api.RestartPolicyNever, + Containers: []api.Container{ + { + Name: "container1", + Image: "testimage", + VolumeDevices: []api.VolumeDevice{ + { + Name: "myvolume", + DevicePath: "/usr/test", + }, + }, + }, + }, + InitContainers: []api.Container{ + { + Name: "container1", + Image: "testimage", + VolumeDevices: []api.VolumeDevice{ + { + Name: "myvolume", + DevicePath: "/usr/test", + }, + }, + }, + }, + Volumes: []api.Volume{ + { + Name: "myvolume", + VolumeSource: api.VolumeSource{ + HostPath: &api.HostPathVolumeSource{ + Path: "/dev/xvdc", + }, }, }, }, }, - InitContainers: []api.Container{ - { - Name: "container1", - Image: "testimage", - VolumeDevices: []api.VolumeDevice{ - { - Name: "myvolume", - DevicePath: "/usr/test", - }, - }, - }, - }, - Volumes: []api.Volume{ - { - Name: "myvolume", - VolumeSource: api.VolumeSource{ - HostPath: &api.HostPathVolumeSource{ - Path: "/dev/xvdc", + } + } + podWithoutVolumeDevices := func() *api.Pod { + return &api.Pod{ + Spec: api.PodSpec{ + RestartPolicy: api.RestartPolicyNever, + Containers: []api.Container{ + { + Name: "container1", + Image: "testimage", + }, + }, + InitContainers: []api.Container{ + { + Name: "container1", + Image: "testimage", + }, + }, + Volumes: []api.Volume{ + { + Name: "myvolume", + VolumeSource: api.VolumeSource{ + HostPath: &api.HostPathVolumeSource{ + Path: "/dev/xvdc", + }, }, }, }, }, + } + } + + podInfo := []struct { + description string + hasVolumeDevices bool + pod func() *api.Pod + }{ + { + description: "has VolumeDevices", + hasVolumeDevices: true, + pod: podWithVolumeDevices, + }, + { + description: "does not have VolumeDevices", + hasVolumeDevices: false, + pod: podWithoutVolumeDevices, + }, + { + description: "is nil", + hasVolumeDevices: false, + pod: func() *api.Pod { return nil }, }, } - // Enable alpha feature BlockVolume - defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, true)() + for _, enabled := range []bool{true, false} { + for _, oldPodInfo := range podInfo { + for _, newPodInfo := range podInfo { + oldPodHasVolumeDevices, oldPod := oldPodInfo.hasVolumeDevices, oldPodInfo.pod() + newPodHasVolumeDevices, newPod := newPodInfo.hasVolumeDevices, newPodInfo.pod() + if newPod == nil { + continue + } - // now test dropping the fields - should not be dropped - DropDisabledAlphaFields(&testPod.Spec) + t.Run(fmt.Sprintf("feature enabled=%v, old pod %v, new pod %v", enabled, oldPodInfo.description, newPodInfo.description), func(t *testing.T) { + defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, enabled)() - // check to make sure VolumeDevices is still present - // if featureset is set to true - if testPod.Spec.Containers[0].VolumeDevices == nil { - t.Error("VolumeDevices in Container should not have been dropped based on feature-gate") - } - if testPod.Spec.InitContainers[0].VolumeDevices == nil { - t.Error("VolumeDevices in InitContainers should not have been dropped based on feature-gate") - } + var oldPodSpec *api.PodSpec + if oldPod != nil { + oldPodSpec = &oldPod.Spec + } + DropDisabledFields(&newPod.Spec, oldPodSpec) - // Disable alpha feature BlockVolume - defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, false)() + // old pod should never be changed + if !reflect.DeepEqual(oldPod, oldPodInfo.pod()) { + t.Errorf("old pod changed: %v", diff.ObjectReflectDiff(oldPod, oldPodInfo.pod())) + } - // now test dropping the fields - DropDisabledAlphaFields(&testPod.Spec) - - // check to make sure VolumeDevices is nil - // if featureset is set to false - if testPod.Spec.Containers[0].VolumeDevices != nil { - t.Error("DropDisabledAlphaFields for Containers failed") - } - if testPod.Spec.InitContainers[0].VolumeDevices != nil { - t.Error("DropDisabledAlphaFields for InitContainers failed") + switch { + case enabled || oldPodHasVolumeDevices: + // new pod should not be changed if the feature is enabled, or if the old pod had VolumeDevices + if !reflect.DeepEqual(newPod, newPodInfo.pod()) { + t.Errorf("new pod changed: %v", diff.ObjectReflectDiff(newPod, newPodInfo.pod())) + } + case newPodHasVolumeDevices: + // new pod should be changed + if reflect.DeepEqual(newPod, newPodInfo.pod()) { + t.Errorf("new pod was not changed") + } + // new pod should not have VolumeDevices + if !reflect.DeepEqual(newPod, podWithoutVolumeDevices()) { + t.Errorf("new pod had VolumeDevices: %v", diff.ObjectReflectDiff(newPod, podWithoutVolumeDevices())) + } + default: + // new pod should not need to be changed + if !reflect.DeepEqual(newPod, newPodInfo.pod()) { + t.Errorf("new pod changed: %v", diff.ObjectReflectDiff(newPod, newPodInfo.pod())) + } + } + }) + } + } + } +} + +func TestDropSubPath(t *testing.T) { + podWithSubpaths := func() *api.Pod { + return &api.Pod{ + Spec: api.PodSpec{ + RestartPolicy: api.RestartPolicyNever, + Containers: []api.Container{{Name: "container1", Image: "testimage", VolumeMounts: []api.VolumeMount{{Name: "a", SubPath: "foo"}, {Name: "a", SubPath: "foo2"}, {Name: "a", SubPath: "foo3"}}}}, + InitContainers: []api.Container{{Name: "container1", Image: "testimage", VolumeMounts: []api.VolumeMount{{Name: "a", SubPath: "foo"}, {Name: "a", SubPath: "foo2"}}}}, + Volumes: []api.Volume{{Name: "a", VolumeSource: api.VolumeSource{HostPath: &api.HostPathVolumeSource{Path: "/dev/xvdc"}}}}, + }, + } + } + podWithoutSubpaths := func() *api.Pod { + return &api.Pod{ + Spec: api.PodSpec{ + RestartPolicy: api.RestartPolicyNever, + Containers: []api.Container{{Name: "container1", Image: "testimage", VolumeMounts: []api.VolumeMount{{Name: "a", SubPath: ""}, {Name: "a", SubPath: ""}, {Name: "a", SubPath: ""}}}}, + InitContainers: []api.Container{{Name: "container1", Image: "testimage", VolumeMounts: []api.VolumeMount{{Name: "a", SubPath: ""}, {Name: "a", SubPath: ""}}}}, + Volumes: []api.Volume{{Name: "a", VolumeSource: api.VolumeSource{HostPath: &api.HostPathVolumeSource{Path: "/dev/xvdc"}}}}, + }, + } + } + + podInfo := []struct { + description string + hasSubpaths bool + pod func() *api.Pod + }{ + { + description: "has subpaths", + hasSubpaths: true, + pod: podWithSubpaths, + }, + { + description: "does not have subpaths", + hasSubpaths: false, + pod: podWithoutSubpaths, + }, + { + description: "is nil", + hasSubpaths: false, + pod: func() *api.Pod { return nil }, + }, + } + + for _, enabled := range []bool{true, false} { + for _, oldPodInfo := range podInfo { + for _, newPodInfo := range podInfo { + oldPodHasSubpaths, oldPod := oldPodInfo.hasSubpaths, oldPodInfo.pod() + newPodHasSubpaths, newPod := newPodInfo.hasSubpaths, newPodInfo.pod() + if newPod == nil { + continue + } + + t.Run(fmt.Sprintf("feature enabled=%v, old pod %v, new pod %v", enabled, oldPodInfo.description, newPodInfo.description), func(t *testing.T) { + defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.VolumeSubpath, enabled)() + + var oldPodSpec *api.PodSpec + if oldPod != nil { + oldPodSpec = &oldPod.Spec + } + DropDisabledFields(&newPod.Spec, oldPodSpec) + + // old pod should never be changed + if !reflect.DeepEqual(oldPod, oldPodInfo.pod()) { + t.Errorf("old pod changed: %v", diff.ObjectReflectDiff(oldPod, oldPodInfo.pod())) + } + + switch { + case enabled || oldPodHasSubpaths: + // new pod should not be changed if the feature is enabled, or if the old pod had subpaths + if !reflect.DeepEqual(newPod, newPodInfo.pod()) { + t.Errorf("new pod changed: %v", diff.ObjectReflectDiff(newPod, newPodInfo.pod())) + } + case newPodHasSubpaths: + // new pod should be changed + if reflect.DeepEqual(newPod, newPodInfo.pod()) { + t.Errorf("new pod was not changed") + } + // new pod should not have subpaths + if !reflect.DeepEqual(newPod, podWithoutSubpaths()) { + t.Errorf("new pod had subpaths: %v", diff.ObjectReflectDiff(newPod, podWithoutSubpaths())) + } + default: + // new pod should not need to be changed + if !reflect.DeepEqual(newPod, newPodInfo.pod()) { + t.Errorf("new pod changed: %v", diff.ObjectReflectDiff(newPod, newPodInfo.pod())) + } + } + }) + } + } + } +} + +func TestDropRuntimeClass(t *testing.T) { + runtimeClassName := "some_container_engine" + podWithoutRuntimeClass := func() *api.Pod { + return &api.Pod{ + Spec: api.PodSpec{ + RuntimeClassName: nil, + }, + } + } + podWithRuntimeClass := func() *api.Pod { + return &api.Pod{ + Spec: api.PodSpec{ + RuntimeClassName: &runtimeClassName, + }, + } + } + + podInfo := []struct { + description string + hasPodRuntimeClassName bool + pod func() *api.Pod + }{ + { + description: "pod Without RuntimeClassName", + hasPodRuntimeClassName: false, + pod: podWithoutRuntimeClass, + }, + { + description: "pod With RuntimeClassName", + hasPodRuntimeClassName: true, + pod: podWithRuntimeClass, + }, + { + description: "is nil", + hasPodRuntimeClassName: false, + pod: func() *api.Pod { return nil }, + }, + } + + for _, enabled := range []bool{true, false} { + for _, oldPodInfo := range podInfo { + for _, newPodInfo := range podInfo { + oldPodHasRuntimeClassName, oldPod := oldPodInfo.hasPodRuntimeClassName, oldPodInfo.pod() + newPodHasRuntimeClassName, newPod := newPodInfo.hasPodRuntimeClassName, newPodInfo.pod() + if newPod == nil { + continue + } + + t.Run(fmt.Sprintf("feature enabled=%v, old pod %v, new pod %v", enabled, oldPodInfo.description, newPodInfo.description), func(t *testing.T) { + defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.RuntimeClass, enabled)() + + var oldPodSpec *api.PodSpec + if oldPod != nil { + oldPodSpec = &oldPod.Spec + } + DropDisabledFields(&newPod.Spec, oldPodSpec) + + // old pod should never be changed + if !reflect.DeepEqual(oldPod, oldPodInfo.pod()) { + t.Errorf("old pod changed: %v", diff.ObjectReflectDiff(oldPod, oldPodInfo.pod())) + } + + switch { + case enabled || oldPodHasRuntimeClassName: + // new pod should not be changed if the feature is enabled, or if the old pod had RuntimeClass + if !reflect.DeepEqual(newPod, newPodInfo.pod()) { + t.Errorf("new pod changed: %v", diff.ObjectReflectDiff(newPod, newPodInfo.pod())) + } + case newPodHasRuntimeClassName: + // new pod should be changed + if reflect.DeepEqual(newPod, newPodInfo.pod()) { + t.Errorf("new pod was not changed") + } + // new pod should not have RuntimeClass + if !reflect.DeepEqual(newPod, podWithoutRuntimeClass()) { + t.Errorf("new pod had PodRuntimeClassName: %v", diff.ObjectReflectDiff(newPod, podWithoutRuntimeClass())) + } + default: + // new pod should not need to be changed + if !reflect.DeepEqual(newPod, newPodInfo.pod()) { + t.Errorf("new pod changed: %v", diff.ObjectReflectDiff(newPod, newPodInfo.pod())) + } + } + }) + } + } + } +} + +func TestDropProcMount(t *testing.T) { + procMount := api.UnmaskedProcMount + defaultProcMount := api.DefaultProcMount + podWithProcMount := func() *api.Pod { + return &api.Pod{ + Spec: api.PodSpec{ + RestartPolicy: api.RestartPolicyNever, + Containers: []api.Container{{Name: "container1", Image: "testimage", SecurityContext: &api.SecurityContext{ProcMount: &procMount}}}, + InitContainers: []api.Container{{Name: "container1", Image: "testimage", SecurityContext: &api.SecurityContext{ProcMount: &procMount}}}, + }, + } + } + podWithoutProcMount := func() *api.Pod { + return &api.Pod{ + Spec: api.PodSpec{ + RestartPolicy: api.RestartPolicyNever, + Containers: []api.Container{{Name: "container1", Image: "testimage", SecurityContext: &api.SecurityContext{ProcMount: &defaultProcMount}}}, + InitContainers: []api.Container{{Name: "container1", Image: "testimage", SecurityContext: &api.SecurityContext{ProcMount: &defaultProcMount}}}, + }, + } + } + + podInfo := []struct { + description string + hasProcMount bool + pod func() *api.Pod + }{ + { + description: "has ProcMount", + hasProcMount: true, + pod: podWithProcMount, + }, + { + description: "does not have ProcMount", + hasProcMount: false, + pod: podWithoutProcMount, + }, + { + description: "is nil", + hasProcMount: false, + pod: func() *api.Pod { return nil }, + }, + } + + for _, enabled := range []bool{true, false} { + for _, oldPodInfo := range podInfo { + for _, newPodInfo := range podInfo { + oldPodHasProcMount, oldPod := oldPodInfo.hasProcMount, oldPodInfo.pod() + newPodHasProcMount, newPod := newPodInfo.hasProcMount, newPodInfo.pod() + if newPod == nil { + continue + } + + t.Run(fmt.Sprintf("feature enabled=%v, old pod %v, new pod %v", enabled, oldPodInfo.description, newPodInfo.description), func(t *testing.T) { + defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ProcMountType, enabled)() + + var oldPodSpec *api.PodSpec + if oldPod != nil { + oldPodSpec = &oldPod.Spec + } + DropDisabledFields(&newPod.Spec, oldPodSpec) + + // old pod should never be changed + if !reflect.DeepEqual(oldPod, oldPodInfo.pod()) { + t.Errorf("old pod changed: %v", diff.ObjectReflectDiff(oldPod, oldPodInfo.pod())) + } + + switch { + case enabled || oldPodHasProcMount: + // new pod should not be changed if the feature is enabled, or if the old pod had ProcMount + if !reflect.DeepEqual(newPod, newPodInfo.pod()) { + t.Errorf("new pod changed: %v", diff.ObjectReflectDiff(newPod, newPodInfo.pod())) + } + case newPodHasProcMount: + // new pod should be changed + if reflect.DeepEqual(newPod, newPodInfo.pod()) { + t.Errorf("new pod was not changed") + } + // new pod should not have ProcMount + if !reflect.DeepEqual(newPod, podWithoutProcMount()) { + t.Errorf("new pod had ProcMount: %v", diff.ObjectReflectDiff(newPod, podWithoutProcMount())) + } + default: + // new pod should not need to be changed + if !reflect.DeepEqual(newPod, newPodInfo.pod()) { + t.Errorf("new pod changed: %v", diff.ObjectReflectDiff(newPod, newPodInfo.pod())) + } + } + }) + } + } + } +} + +func TestDropPodPriority(t *testing.T) { + podPriority := int32(1000) + podWithoutPriority := func() *api.Pod { + return &api.Pod{ + Spec: api.PodSpec{ + Priority: nil, + PriorityClassName: "", + }, + } + } + podWithPriority := func() *api.Pod { + return &api.Pod{ + Spec: api.PodSpec{ + Priority: &podPriority, + PriorityClassName: "", + }, + } + } + podWithPriorityClassOnly := func() *api.Pod { + return &api.Pod{ + Spec: api.PodSpec{ + Priority: nil, + PriorityClassName: "HighPriorityClass", + }, + } + } + podWithBothPriorityFields := func() *api.Pod { + return &api.Pod{ + Spec: api.PodSpec{ + Priority: &podPriority, + PriorityClassName: "HighPriorityClass", + }, + } + } + podInfo := []struct { + description string + hasPodPriority bool + pod func() *api.Pod + }{ + { + description: "pod With no PodPriority fields set", + hasPodPriority: false, + pod: podWithoutPriority, + }, + { + description: "feature disabled and pod With PodPriority field set but class name not set", + hasPodPriority: true, + pod: podWithPriority, + }, + { + description: "feature disabled and pod With PodPriority ClassName field set but PortPriority not set", + hasPodPriority: true, + pod: podWithPriorityClassOnly, + }, + { + description: "feature disabled and pod With both PodPriority ClassName and PodPriority fields set", + hasPodPriority: true, + pod: podWithBothPriorityFields, + }, + { + description: "is nil", + hasPodPriority: false, + pod: func() *api.Pod { return nil }, + }, + } + + for _, enabled := range []bool{true, false} { + for _, oldPodInfo := range podInfo { + for _, newPodInfo := range podInfo { + oldPodHasPodPriority, oldPod := oldPodInfo.hasPodPriority, oldPodInfo.pod() + newPodHasPodPriority, newPod := newPodInfo.hasPodPriority, newPodInfo.pod() + if newPod == nil { + continue + } + + t.Run(fmt.Sprintf("feature enabled=%v, old pod %v, new pod %v", enabled, oldPodInfo.description, newPodInfo.description), func(t *testing.T) { + defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.PodPriority, enabled)() + + var oldPodSpec *api.PodSpec + if oldPod != nil { + oldPodSpec = &oldPod.Spec + } + DropDisabledFields(&newPod.Spec, oldPodSpec) + + // old pod should never be changed + if !reflect.DeepEqual(oldPod, oldPodInfo.pod()) { + t.Errorf("old pod changed: %v", diff.ObjectReflectDiff(oldPod, oldPodInfo.pod())) + } + + switch { + case enabled || oldPodHasPodPriority: + // new pod should not be changed if the feature is enabled, or if the old pod had PodPriority + if !reflect.DeepEqual(newPod, newPodInfo.pod()) { + t.Errorf("new pod changed: %v", diff.ObjectReflectDiff(newPod, newPodInfo.pod())) + } + case newPodHasPodPriority: + // new pod should be changed + if reflect.DeepEqual(newPod, newPodInfo.pod()) { + t.Errorf("new pod was not changed") + } + // new pod should not have PodPriority + if !reflect.DeepEqual(newPod, podWithoutPriority()) { + t.Errorf("new pod had PodPriority: %v", diff.ObjectReflectDiff(newPod, podWithoutPriority())) + } + default: + // new pod should not need to be changed + if !reflect.DeepEqual(newPod, newPodInfo.pod()) { + t.Errorf("new pod changed: %v", diff.ObjectReflectDiff(newPod, newPodInfo.pod())) + } + } + }) + } + } + } +} + +func TestDropEmptyDirSizeLimit(t *testing.T) { + sizeLimit := resource.MustParse("1Gi") + podWithEmptyDirSizeLimit := func() *api.Pod { + return &api.Pod{ + Spec: api.PodSpec{ + RestartPolicy: api.RestartPolicyNever, + Volumes: []api.Volume{ + { + Name: "a", + VolumeSource: api.VolumeSource{ + EmptyDir: &api.EmptyDirVolumeSource{ + Medium: "memory", + SizeLimit: &sizeLimit, + }, + }, + }, + }, + }, + } + } + podWithoutEmptyDirSizeLimit := func() *api.Pod { + return &api.Pod{ + Spec: api.PodSpec{ + RestartPolicy: api.RestartPolicyNever, + Volumes: []api.Volume{ + { + Name: "a", + VolumeSource: api.VolumeSource{ + EmptyDir: &api.EmptyDirVolumeSource{ + Medium: "memory", + }, + }, + }, + }, + }, + } + } + + podInfo := []struct { + description string + hasEmptyDirSizeLimit bool + pod func() *api.Pod + }{ + { + description: "has EmptyDir Size Limit", + hasEmptyDirSizeLimit: true, + pod: podWithEmptyDirSizeLimit, + }, + { + description: "does not have EmptyDir Size Limit", + hasEmptyDirSizeLimit: false, + pod: podWithoutEmptyDirSizeLimit, + }, + { + description: "is nil", + hasEmptyDirSizeLimit: false, + pod: func() *api.Pod { return nil }, + }, + } + + for _, enabled := range []bool{true, false} { + for _, oldPodInfo := range podInfo { + for _, newPodInfo := range podInfo { + oldPodHasEmptyDirSizeLimit, oldPod := oldPodInfo.hasEmptyDirSizeLimit, oldPodInfo.pod() + newPodHasEmptyDirSizeLimit, newPod := newPodInfo.hasEmptyDirSizeLimit, newPodInfo.pod() + if newPod == nil { + continue + } + + t.Run(fmt.Sprintf("feature enabled=%v, old pod %v, new pod %v", enabled, oldPodInfo.description, newPodInfo.description), func(t *testing.T) { + defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.LocalStorageCapacityIsolation, enabled)() + + var oldPodSpec *api.PodSpec + if oldPod != nil { + oldPodSpec = &oldPod.Spec + } + DropDisabledFields(&newPod.Spec, oldPodSpec) + + // old pod should never be changed + if !reflect.DeepEqual(oldPod, oldPodInfo.pod()) { + t.Errorf("old pod changed: %v", diff.ObjectReflectDiff(oldPod, oldPodInfo.pod())) + } + + switch { + case enabled || oldPodHasEmptyDirSizeLimit: + // new pod should not be changed if the feature is enabled, or if the old pod had EmptyDir SizeLimit + if !reflect.DeepEqual(newPod, newPodInfo.pod()) { + t.Errorf("new pod changed: %v", diff.ObjectReflectDiff(newPod, newPodInfo.pod())) + } + case newPodHasEmptyDirSizeLimit: + // new pod should be changed + if reflect.DeepEqual(newPod, newPodInfo.pod()) { + t.Errorf("new pod was not changed") + } + // new pod should not have EmptyDir SizeLimit + if !reflect.DeepEqual(newPod, podWithoutEmptyDirSizeLimit()) { + t.Errorf("new pod had EmptyDir SizeLimit: %v", diff.ObjectReflectDiff(newPod, podWithoutEmptyDirSizeLimit())) + } + default: + // new pod should not need to be changed + if !reflect.DeepEqual(newPod, newPodInfo.pod()) { + t.Errorf("new pod changed: %v", diff.ObjectReflectDiff(newPod, newPodInfo.pod())) + } + } + }) + } + } + } +} + +func TestDropRunAsGroup(t *testing.T) { + group := func() *int64 { + testGroup := int64(1000) + return &testGroup + } + defaultProcMount := api.DefaultProcMount + defaultSecurityContext := func() *api.SecurityContext { + return &api.SecurityContext{ProcMount: &defaultProcMount} + } + securityContextWithRunAsGroup := func() *api.SecurityContext { + return &api.SecurityContext{ProcMount: &defaultProcMount, RunAsGroup: group()} + } + podWithoutRunAsGroup := func() *api.Pod { + return &api.Pod{ + Spec: api.PodSpec{ + RestartPolicy: api.RestartPolicyNever, + SecurityContext: &api.PodSecurityContext{}, + Containers: []api.Container{{Name: "container1", Image: "testimage", SecurityContext: defaultSecurityContext()}}, + InitContainers: []api.Container{{Name: "initContainer1", Image: "testimage", SecurityContext: defaultSecurityContext()}}, + }, + } + } + podWithRunAsGroupInPod := func() *api.Pod { + return &api.Pod{ + Spec: api.PodSpec{ + RestartPolicy: api.RestartPolicyNever, + SecurityContext: &api.PodSecurityContext{RunAsGroup: group()}, + Containers: []api.Container{{Name: "container1", Image: "testimage", SecurityContext: defaultSecurityContext()}}, + InitContainers: []api.Container{{Name: "initContainer1", Image: "testimage", SecurityContext: defaultSecurityContext()}}, + }, + } + } + podWithRunAsGroupInContainers := func() *api.Pod { + return &api.Pod{ + Spec: api.PodSpec{ + RestartPolicy: api.RestartPolicyNever, + SecurityContext: &api.PodSecurityContext{}, + Containers: []api.Container{{Name: "container1", Image: "testimage", SecurityContext: securityContextWithRunAsGroup()}}, + InitContainers: []api.Container{{Name: "initContainer1", Image: "testimage", SecurityContext: defaultSecurityContext()}}, + }, + } + } + podWithRunAsGroupInInitContainers := func() *api.Pod { + return &api.Pod{ + Spec: api.PodSpec{ + RestartPolicy: api.RestartPolicyNever, + SecurityContext: &api.PodSecurityContext{}, + Containers: []api.Container{{Name: "container1", Image: "testimage", SecurityContext: defaultSecurityContext()}}, + InitContainers: []api.Container{{Name: "initContainer1", Image: "testimage", SecurityContext: securityContextWithRunAsGroup()}}, + }, + } + } + + podInfo := []struct { + description string + hasRunAsGroup bool + pod func() *api.Pod + }{ + { + description: "have RunAsGroup in Pod", + hasRunAsGroup: true, + pod: podWithRunAsGroupInPod, + }, + { + description: "have RunAsGroup in Container", + hasRunAsGroup: true, + pod: podWithRunAsGroupInContainers, + }, + { + description: "have RunAsGroup in InitContainer", + hasRunAsGroup: true, + pod: podWithRunAsGroupInInitContainers, + }, + { + description: "does not have RunAsGroup", + hasRunAsGroup: false, + pod: podWithoutRunAsGroup, + }, + { + description: "is nil", + hasRunAsGroup: false, + pod: func() *api.Pod { return nil }, + }, + } + + for _, enabled := range []bool{true, false} { + for _, oldPodInfo := range podInfo { + for _, newPodInfo := range podInfo { + oldPodHasRunAsGroup, oldPod := oldPodInfo.hasRunAsGroup, oldPodInfo.pod() + newPodHasRunAsGroup, newPod := newPodInfo.hasRunAsGroup, newPodInfo.pod() + if newPod == nil { + continue + } + + t.Run(fmt.Sprintf("feature enabled=%v, old pod %v, new pod %v", enabled, oldPodInfo.description, newPodInfo.description), func(t *testing.T) { + defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.RunAsGroup, enabled)() + + var oldPodSpec *api.PodSpec + if oldPod != nil { + oldPodSpec = &oldPod.Spec + } + DropDisabledFields(&newPod.Spec, oldPodSpec) + + // old pod should never be changed + if !reflect.DeepEqual(oldPod, oldPodInfo.pod()) { + t.Errorf("old pod changed: %v", diff.ObjectReflectDiff(oldPod, oldPodInfo.pod())) + } + + switch { + case enabled || oldPodHasRunAsGroup: + // new pod should not be changed if the feature is enabled, or if the old pod had RunAsGroup + if !reflect.DeepEqual(newPod, newPodInfo.pod()) { + t.Errorf("new pod changed: %v", diff.ObjectReflectDiff(newPod, newPodInfo.pod())) + } + case newPodHasRunAsGroup: + // new pod should be changed + if reflect.DeepEqual(newPod, newPodInfo.pod()) { + t.Errorf("%v", oldPod) + t.Errorf("%v", newPod) + t.Errorf("new pod was not changed") + } + // new pod should not have RunAsGroup + if !reflect.DeepEqual(newPod, podWithoutRunAsGroup()) { + t.Errorf("new pod had RunAsGroup: %v", diff.ObjectReflectDiff(newPod, podWithoutRunAsGroup())) + } + default: + // new pod should not need to be changed + if !reflect.DeepEqual(newPod, newPodInfo.pod()) { + t.Errorf("new pod changed: %v", diff.ObjectReflectDiff(newPod, newPodInfo.pod())) + } + } + }) + } + } } } diff --git a/pkg/api/podsecuritypolicy/BUILD b/pkg/api/podsecuritypolicy/BUILD index 92c5c73c67b..0219cfc6b9f 100644 --- a/pkg/api/podsecuritypolicy/BUILD +++ b/pkg/api/podsecuritypolicy/BUILD @@ -38,6 +38,7 @@ go_test( "//pkg/apis/core:go_default_library", "//pkg/apis/policy:go_default_library", "//pkg/features:go_default_library", + "//staging/src/k8s.io/apimachinery/pkg/util/diff:go_default_library", "//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library", "//staging/src/k8s.io/apiserver/pkg/util/feature/testing:go_default_library", ], diff --git a/pkg/api/podsecuritypolicy/util.go b/pkg/api/podsecuritypolicy/util.go index 8c1f3511813..4aecb5a16ad 100644 --- a/pkg/api/podsecuritypolicy/util.go +++ b/pkg/api/podsecuritypolicy/util.go @@ -22,13 +22,26 @@ import ( "k8s.io/kubernetes/pkg/features" ) -// DropDisabledAlphaFields removes disabled fields from the pod security policy spec. +// DropDisabledFields removes disabled fields from the pod security policy spec. // This should be called from PrepareForCreate/PrepareForUpdate for all resources containing a od security policy spec. -func DropDisabledAlphaFields(pspSpec *policy.PodSecurityPolicySpec) { - if !utilfeature.DefaultFeatureGate.Enabled(features.ProcMountType) { +func DropDisabledFields(pspSpec, oldPSPSpec *policy.PodSecurityPolicySpec) { + if !utilfeature.DefaultFeatureGate.Enabled(features.ProcMountType) && !allowedProcMountTypesInUse(oldPSPSpec) { pspSpec.AllowedProcMountTypes = nil } - if !utilfeature.DefaultFeatureGate.Enabled(features.RunAsGroup) { + if !utilfeature.DefaultFeatureGate.Enabled(features.RunAsGroup) && (oldPSPSpec == nil || oldPSPSpec.RunAsGroup == nil) { pspSpec.RunAsGroup = nil } } + +func allowedProcMountTypesInUse(oldPSPSpec *policy.PodSecurityPolicySpec) bool { + if oldPSPSpec == nil { + return false + } + + if oldPSPSpec.AllowedProcMountTypes != nil { + return true + } + + return false + +} diff --git a/pkg/api/podsecuritypolicy/util_test.go b/pkg/api/podsecuritypolicy/util_test.go index 5fe4e52662f..7ec614c1719 100644 --- a/pkg/api/podsecuritypolicy/util_test.go +++ b/pkg/api/podsecuritypolicy/util_test.go @@ -17,8 +17,11 @@ limitations under the License. package podsecuritypolicy import ( + "fmt" + "reflect" "testing" + "k8s.io/apimachinery/pkg/util/diff" utilfeature "k8s.io/apiserver/pkg/util/feature" utilfeaturetesting "k8s.io/apiserver/pkg/util/feature/testing" api "k8s.io/kubernetes/pkg/apis/core" @@ -26,39 +29,161 @@ import ( "k8s.io/kubernetes/pkg/features" ) -func TestDropAlphaProcMountType(t *testing.T) { - // PodSecurityPolicy with AllowedProcMountTypes set - psp := policy.PodSecurityPolicy{ - Spec: policy.PodSecurityPolicySpec{ - AllowedProcMountTypes: []api.ProcMountType{api.UnmaskedProcMount}, +func TestDropAllowedProcMountTypes(t *testing.T) { + allowedProcMountTypes := []api.ProcMountType{api.UnmaskedProcMount} + scWithoutAllowedProcMountTypes := func() *policy.PodSecurityPolicySpec { + return &policy.PodSecurityPolicySpec{} + } + scWithAllowedProcMountTypes := func() *policy.PodSecurityPolicySpec { + return &policy.PodSecurityPolicySpec{ + AllowedProcMountTypes: allowedProcMountTypes, + } + } + + scInfo := []struct { + description string + hasAllowedProcMountTypes bool + sc func() *policy.PodSecurityPolicySpec + }{ + { + description: "PodSecurityPolicySpec Without AllowedProcMountTypes", + hasAllowedProcMountTypes: false, + sc: scWithoutAllowedProcMountTypes, + }, + { + description: "PodSecurityPolicySpec With AllowedProcMountTypes", + hasAllowedProcMountTypes: true, + sc: scWithAllowedProcMountTypes, + }, + { + description: "is nil", + hasAllowedProcMountTypes: false, + sc: func() *policy.PodSecurityPolicySpec { return nil }, }, } - // Enable alpha feature ProcMountType - defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ProcMountType, true)() + for _, enabled := range []bool{true, false} { + for _, oldPSPSpecInfo := range scInfo { + for _, newPSPSpecInfo := range scInfo { + oldPSPSpecHasAllowedProcMountTypes, oldPSPSpec := oldPSPSpecInfo.hasAllowedProcMountTypes, oldPSPSpecInfo.sc() + newPSPSpecHasAllowedProcMountTypes, newPSPSpec := newPSPSpecInfo.hasAllowedProcMountTypes, newPSPSpecInfo.sc() + if newPSPSpec == nil { + continue + } - // now test dropping the fields - should not be dropped - DropDisabledAlphaFields(&psp.Spec) + t.Run(fmt.Sprintf("feature enabled=%v, old PodSecurityPolicySpec %v, new PodSecurityPolicySpec %v", enabled, oldPSPSpecInfo.description, newPSPSpecInfo.description), func(t *testing.T) { + defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ProcMountType, enabled)() - // check to make sure AllowedProcMountTypes is still present - // if featureset is set to true - if utilfeature.DefaultFeatureGate.Enabled(features.ProcMountType) { - if psp.Spec.AllowedProcMountTypes == nil { - t.Error("AllowedProcMountTypes in pvc.Spec should not have been dropped based on feature-gate") - } - } + DropDisabledFields(newPSPSpec, oldPSPSpec) - // Disable alpha feature ProcMountType - defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ProcMountType, false)() + // old PodSecurityPolicySpec should never be changed + if !reflect.DeepEqual(oldPSPSpec, oldPSPSpecInfo.sc()) { + t.Errorf("old PodSecurityPolicySpec changed: %v", diff.ObjectReflectDiff(oldPSPSpec, oldPSPSpecInfo.sc())) + } - // now test dropping the fields - DropDisabledAlphaFields(&psp.Spec) - - // check to make sure AllowedProcMountTypes is nil - // if featureset is set to false - if utilfeature.DefaultFeatureGate.Enabled(features.ProcMountType) { - if psp.Spec.AllowedProcMountTypes != nil { - t.Error("DropDisabledAlphaFields AllowedProcMountTypes for psp.Spec failed") + switch { + case enabled || oldPSPSpecHasAllowedProcMountTypes: + // new PodSecurityPolicySpec should not be changed if the feature is enabled, or if the old PodSecurityPolicySpec had AllowedProcMountTypes + if !reflect.DeepEqual(newPSPSpec, newPSPSpecInfo.sc()) { + t.Errorf("new PodSecurityPolicySpec changed: %v", diff.ObjectReflectDiff(newPSPSpec, newPSPSpecInfo.sc())) + } + case newPSPSpecHasAllowedProcMountTypes: + // new PodSecurityPolicySpec should be changed + if reflect.DeepEqual(newPSPSpec, newPSPSpecInfo.sc()) { + t.Errorf("new PodSecurityPolicySpec was not changed") + } + // new PodSecurityPolicySpec should not have AllowedProcMountTypes + if !reflect.DeepEqual(newPSPSpec, scWithoutAllowedProcMountTypes()) { + t.Errorf("new PodSecurityPolicySpec had PodSecurityPolicySpecAllowedProcMountTypes: %v", diff.ObjectReflectDiff(newPSPSpec, scWithoutAllowedProcMountTypes())) + } + default: + // new PodSecurityPolicySpec should not need to be changed + if !reflect.DeepEqual(newPSPSpec, newPSPSpecInfo.sc()) { + t.Errorf("new PodSecurityPolicySpec changed: %v", diff.ObjectReflectDiff(newPSPSpec, newPSPSpecInfo.sc())) + } + } + }) + } + } + } +} + +func TestDropRunAsGroup(t *testing.T) { + group := func() *policy.RunAsGroupStrategyOptions { + return &policy.RunAsGroupStrategyOptions{} + } + scWithoutRunAsGroup := func() *policy.PodSecurityPolicySpec { + return &policy.PodSecurityPolicySpec{} + } + scWithRunAsGroup := func() *policy.PodSecurityPolicySpec { + return &policy.PodSecurityPolicySpec{ + RunAsGroup: group(), + } + } + scInfo := []struct { + description string + hasRunAsGroup bool + sc func() *policy.PodSecurityPolicySpec + }{ + { + description: "PodSecurityPolicySpec Without RunAsGroup", + hasRunAsGroup: false, + sc: scWithoutRunAsGroup, + }, + { + description: "PodSecurityPolicySpec With RunAsGroup", + hasRunAsGroup: true, + sc: scWithRunAsGroup, + }, + { + description: "is nil", + hasRunAsGroup: false, + sc: func() *policy.PodSecurityPolicySpec { return nil }, + }, + } + + for _, enabled := range []bool{true, false} { + for _, oldPSPSpecInfo := range scInfo { + for _, newPSPSpecInfo := range scInfo { + oldPSPSpecHasRunAsGroup, oldPSPSpec := oldPSPSpecInfo.hasRunAsGroup, oldPSPSpecInfo.sc() + newPSPSpecHasRunAsGroup, newPSPSpec := newPSPSpecInfo.hasRunAsGroup, newPSPSpecInfo.sc() + if newPSPSpec == nil { + continue + } + + t.Run(fmt.Sprintf("feature enabled=%v, old PodSecurityPolicySpec %v, new PodSecurityPolicySpec %v", enabled, oldPSPSpecInfo.description, newPSPSpecInfo.description), func(t *testing.T) { + defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.RunAsGroup, enabled)() + + DropDisabledFields(newPSPSpec, oldPSPSpec) + + // old PodSecurityPolicySpec should never be changed + if !reflect.DeepEqual(oldPSPSpec, oldPSPSpecInfo.sc()) { + t.Errorf("old PodSecurityPolicySpec changed: %v", diff.ObjectReflectDiff(oldPSPSpec, oldPSPSpecInfo.sc())) + } + + switch { + case enabled || oldPSPSpecHasRunAsGroup: + // new PodSecurityPolicySpec should not be changed if the feature is enabled, or if the old PodSecurityPolicySpec had RunAsGroup + if !reflect.DeepEqual(newPSPSpec, newPSPSpecInfo.sc()) { + t.Errorf("new PodSecurityPolicySpec changed: %v", diff.ObjectReflectDiff(newPSPSpec, newPSPSpecInfo.sc())) + } + case newPSPSpecHasRunAsGroup: + // new PodSecurityPolicySpec should be changed + if reflect.DeepEqual(newPSPSpec, newPSPSpecInfo.sc()) { + t.Errorf("new PodSecurityPolicySpec was not changed") + } + // new PodSecurityPolicySpec should not have RunAsGroup + if !reflect.DeepEqual(newPSPSpec, scWithoutRunAsGroup()) { + t.Errorf("new PodSecurityPolicySpec had RunAsGroup: %v", diff.ObjectReflectDiff(newPSPSpec, scWithoutRunAsGroup())) + } + default: + // new PodSecurityPolicySpec should not need to be changed + if !reflect.DeepEqual(newPSPSpec, newPSPSpecInfo.sc()) { + t.Errorf("new PodSecurityPolicySpec changed: %v", diff.ObjectReflectDiff(newPSPSpec, newPSPSpecInfo.sc())) + } + } + }) + } } } } diff --git a/pkg/apis/apps/v1/zz_generated.defaults.go b/pkg/apis/apps/v1/zz_generated.defaults.go index 4b541a3b15a..1c63c1917c4 100644 --- a/pkg/apis/apps/v1/zz_generated.defaults.go +++ b/pkg/apis/apps/v1/zz_generated.defaults.go @@ -136,6 +136,9 @@ func SetObjectDefaults_DaemonSet(in *v1.DaemonSet) { } } } + if a.SecurityContext != nil { + corev1.SetDefaults_SecurityContext(a.SecurityContext) + } } for i := range in.Spec.Template.Spec.Containers { a := &in.Spec.Template.Spec.Containers[i] @@ -178,6 +181,9 @@ func SetObjectDefaults_DaemonSet(in *v1.DaemonSet) { } } } + if a.SecurityContext != nil { + corev1.SetDefaults_SecurityContext(a.SecurityContext) + } } } @@ -283,6 +289,9 @@ func SetObjectDefaults_Deployment(in *v1.Deployment) { } } } + if a.SecurityContext != nil { + corev1.SetDefaults_SecurityContext(a.SecurityContext) + } } for i := range in.Spec.Template.Spec.Containers { a := &in.Spec.Template.Spec.Containers[i] @@ -325,6 +334,9 @@ func SetObjectDefaults_Deployment(in *v1.Deployment) { } } } + if a.SecurityContext != nil { + corev1.SetDefaults_SecurityContext(a.SecurityContext) + } } } @@ -430,6 +442,9 @@ func SetObjectDefaults_ReplicaSet(in *v1.ReplicaSet) { } } } + if a.SecurityContext != nil { + corev1.SetDefaults_SecurityContext(a.SecurityContext) + } } for i := range in.Spec.Template.Spec.Containers { a := &in.Spec.Template.Spec.Containers[i] @@ -472,6 +487,9 @@ func SetObjectDefaults_ReplicaSet(in *v1.ReplicaSet) { } } } + if a.SecurityContext != nil { + corev1.SetDefaults_SecurityContext(a.SecurityContext) + } } } @@ -577,6 +595,9 @@ func SetObjectDefaults_StatefulSet(in *v1.StatefulSet) { } } } + if a.SecurityContext != nil { + corev1.SetDefaults_SecurityContext(a.SecurityContext) + } } for i := range in.Spec.Template.Spec.Containers { a := &in.Spec.Template.Spec.Containers[i] @@ -619,6 +640,9 @@ func SetObjectDefaults_StatefulSet(in *v1.StatefulSet) { } } } + if a.SecurityContext != nil { + corev1.SetDefaults_SecurityContext(a.SecurityContext) + } } for i := range in.Spec.VolumeClaimTemplates { a := &in.Spec.VolumeClaimTemplates[i] diff --git a/pkg/apis/apps/v1beta1/zz_generated.defaults.go b/pkg/apis/apps/v1beta1/zz_generated.defaults.go index 656f61edc99..4a31e2e1699 100644 --- a/pkg/apis/apps/v1beta1/zz_generated.defaults.go +++ b/pkg/apis/apps/v1beta1/zz_generated.defaults.go @@ -132,6 +132,9 @@ func SetObjectDefaults_Deployment(in *v1beta1.Deployment) { } } } + if a.SecurityContext != nil { + v1.SetDefaults_SecurityContext(a.SecurityContext) + } } for i := range in.Spec.Template.Spec.Containers { a := &in.Spec.Template.Spec.Containers[i] @@ -174,6 +177,9 @@ func SetObjectDefaults_Deployment(in *v1beta1.Deployment) { } } } + if a.SecurityContext != nil { + v1.SetDefaults_SecurityContext(a.SecurityContext) + } } } @@ -279,6 +285,9 @@ func SetObjectDefaults_StatefulSet(in *v1beta1.StatefulSet) { } } } + if a.SecurityContext != nil { + v1.SetDefaults_SecurityContext(a.SecurityContext) + } } for i := range in.Spec.Template.Spec.Containers { a := &in.Spec.Template.Spec.Containers[i] @@ -321,6 +330,9 @@ func SetObjectDefaults_StatefulSet(in *v1beta1.StatefulSet) { } } } + if a.SecurityContext != nil { + v1.SetDefaults_SecurityContext(a.SecurityContext) + } } for i := range in.Spec.VolumeClaimTemplates { a := &in.Spec.VolumeClaimTemplates[i] diff --git a/pkg/apis/apps/v1beta2/zz_generated.defaults.go b/pkg/apis/apps/v1beta2/zz_generated.defaults.go index 713bcaa7819..847a56b0d08 100644 --- a/pkg/apis/apps/v1beta2/zz_generated.defaults.go +++ b/pkg/apis/apps/v1beta2/zz_generated.defaults.go @@ -136,6 +136,9 @@ func SetObjectDefaults_DaemonSet(in *v1beta2.DaemonSet) { } } } + if a.SecurityContext != nil { + v1.SetDefaults_SecurityContext(a.SecurityContext) + } } for i := range in.Spec.Template.Spec.Containers { a := &in.Spec.Template.Spec.Containers[i] @@ -178,6 +181,9 @@ func SetObjectDefaults_DaemonSet(in *v1beta2.DaemonSet) { } } } + if a.SecurityContext != nil { + v1.SetDefaults_SecurityContext(a.SecurityContext) + } } } @@ -283,6 +289,9 @@ func SetObjectDefaults_Deployment(in *v1beta2.Deployment) { } } } + if a.SecurityContext != nil { + v1.SetDefaults_SecurityContext(a.SecurityContext) + } } for i := range in.Spec.Template.Spec.Containers { a := &in.Spec.Template.Spec.Containers[i] @@ -325,6 +334,9 @@ func SetObjectDefaults_Deployment(in *v1beta2.Deployment) { } } } + if a.SecurityContext != nil { + v1.SetDefaults_SecurityContext(a.SecurityContext) + } } } @@ -430,6 +442,9 @@ func SetObjectDefaults_ReplicaSet(in *v1beta2.ReplicaSet) { } } } + if a.SecurityContext != nil { + v1.SetDefaults_SecurityContext(a.SecurityContext) + } } for i := range in.Spec.Template.Spec.Containers { a := &in.Spec.Template.Spec.Containers[i] @@ -472,6 +487,9 @@ func SetObjectDefaults_ReplicaSet(in *v1beta2.ReplicaSet) { } } } + if a.SecurityContext != nil { + v1.SetDefaults_SecurityContext(a.SecurityContext) + } } } @@ -577,6 +595,9 @@ func SetObjectDefaults_StatefulSet(in *v1beta2.StatefulSet) { } } } + if a.SecurityContext != nil { + v1.SetDefaults_SecurityContext(a.SecurityContext) + } } for i := range in.Spec.Template.Spec.Containers { a := &in.Spec.Template.Spec.Containers[i] @@ -619,6 +640,9 @@ func SetObjectDefaults_StatefulSet(in *v1beta2.StatefulSet) { } } } + if a.SecurityContext != nil { + v1.SetDefaults_SecurityContext(a.SecurityContext) + } } for i := range in.Spec.VolumeClaimTemplates { a := &in.Spec.VolumeClaimTemplates[i] diff --git a/pkg/apis/autoscaling/v2beta1/BUILD b/pkg/apis/autoscaling/v2beta1/BUILD index 47d21ddb94e..5fbc372b458 100644 --- a/pkg/apis/autoscaling/v2beta1/BUILD +++ b/pkg/apis/autoscaling/v2beta1/BUILD @@ -26,7 +26,10 @@ go_library( go_test( name = "go_default_test", - srcs = ["defaults_test.go"], + srcs = [ + "conversion_test.go", + "defaults_test.go", + ], embed = [":go_default_library"], deps = [ "//pkg/api/legacyscheme:go_default_library", @@ -37,6 +40,7 @@ go_test( "//staging/src/k8s.io/api/core/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/equality:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library", + "//vendor/github.com/stretchr/testify/assert:go_default_library", "//vendor/k8s.io/utils/pointer:go_default_library", ], ) diff --git a/pkg/apis/autoscaling/v2beta1/conversion.go b/pkg/apis/autoscaling/v2beta1/conversion.go index eebc1043053..142cf726493 100644 --- a/pkg/apis/autoscaling/v2beta1/conversion.go +++ b/pkg/apis/autoscaling/v2beta1/conversion.go @@ -185,8 +185,10 @@ func Convert_v2beta1_ObjectMetricSource_To_autoscaling_ObjectMetricSource(in *au } func Convert_autoscaling_PodsMetricSource_To_v2beta1_PodsMetricSource(in *autoscaling.PodsMetricSource, out *autoscalingv2beta1.PodsMetricSource, s conversion.Scope) error { - targetAverageValue := *in.Target.AverageValue - out.TargetAverageValue = targetAverageValue + if in.Target.AverageValue != nil { + targetAverageValue := *in.Target.AverageValue + out.TargetAverageValue = targetAverageValue + } out.MetricName = in.Metric.Name out.Selector = in.Metric.Selector @@ -247,8 +249,10 @@ func Convert_autoscaling_ObjectMetricStatus_To_v2beta1_ObjectMetricStatus(in *au } out.MetricName = in.Metric.Name out.Selector = in.Metric.Selector - currentAverageValue := *in.Current.AverageValue - out.AverageValue = ¤tAverageValue + if in.Current.AverageValue != nil { + currentAverageValue := *in.Current.AverageValue + out.AverageValue = ¤tAverageValue + } return nil } diff --git a/pkg/apis/autoscaling/v2beta1/conversion_test.go b/pkg/apis/autoscaling/v2beta1/conversion_test.go new file mode 100644 index 00000000000..4a1db1a1537 --- /dev/null +++ b/pkg/apis/autoscaling/v2beta1/conversion_test.go @@ -0,0 +1,84 @@ +/* +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 v2beta1 + +import ( + "testing" + + "github.com/stretchr/testify/assert" + + "k8s.io/api/autoscaling/v2beta1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/kubernetes/pkg/apis/autoscaling" +) + +// Testing nil pointer panic uncovered by #70806 +// TODO(yue9944882): Test nil/empty conversion across all resource types +func TestNilOrEmptyConversion(t *testing.T) { + scheme := runtime.NewScheme() + assert.NoError(t, addConversionFuncs(scheme)) + + testCases := []struct { + obj1 interface{} + obj2 interface{} + }{ + { + obj1: &autoscaling.ExternalMetricSource{}, + obj2: &v2beta1.ExternalMetricSource{}, + }, + { + obj1: &autoscaling.ExternalMetricStatus{}, + obj2: &v2beta1.ExternalMetricStatus{}, + }, + { + obj1: &autoscaling.PodsMetricSource{}, + obj2: &v2beta1.PodsMetricSource{}, + }, + { + obj1: &autoscaling.PodsMetricStatus{}, + obj2: &v2beta1.PodsMetricStatus{}, + }, + { + obj1: &autoscaling.ObjectMetricSource{}, + obj2: &v2beta1.ObjectMetricSource{}, + }, + { + obj1: &autoscaling.ObjectMetricStatus{}, + obj2: &v2beta1.ObjectMetricStatus{}, + }, + { + obj1: &autoscaling.ResourceMetricSource{}, + obj2: &v2beta1.ResourceMetricSource{}, + }, + { + obj1: &autoscaling.ResourceMetricStatus{}, + obj2: &v2beta1.ResourceMetricStatus{}, + }, + { + obj1: &autoscaling.HorizontalPodAutoscaler{}, + obj2: &v2beta1.HorizontalPodAutoscaler{}, + }, + { + obj1: &autoscaling.MetricTarget{}, + obj2: &v2beta1.CrossVersionObjectReference{}, + }, + } + for _, testCase := range testCases { + assert.NoError(t, scheme.Convert(testCase.obj1, testCase.obj2, nil)) + assert.NoError(t, scheme.Convert(testCase.obj2, testCase.obj1, nil)) + } +} diff --git a/pkg/apis/batch/v1/zz_generated.defaults.go b/pkg/apis/batch/v1/zz_generated.defaults.go index 201e3b22852..8c0f02b469c 100644 --- a/pkg/apis/batch/v1/zz_generated.defaults.go +++ b/pkg/apis/batch/v1/zz_generated.defaults.go @@ -130,6 +130,9 @@ func SetObjectDefaults_Job(in *v1.Job) { } } } + if a.SecurityContext != nil { + corev1.SetDefaults_SecurityContext(a.SecurityContext) + } } for i := range in.Spec.Template.Spec.Containers { a := &in.Spec.Template.Spec.Containers[i] @@ -172,6 +175,9 @@ func SetObjectDefaults_Job(in *v1.Job) { } } } + if a.SecurityContext != nil { + corev1.SetDefaults_SecurityContext(a.SecurityContext) + } } } diff --git a/pkg/apis/batch/v1beta1/zz_generated.defaults.go b/pkg/apis/batch/v1beta1/zz_generated.defaults.go index d90031c32aa..a9a1a5d0675 100644 --- a/pkg/apis/batch/v1beta1/zz_generated.defaults.go +++ b/pkg/apis/batch/v1beta1/zz_generated.defaults.go @@ -131,6 +131,9 @@ func SetObjectDefaults_CronJob(in *v1beta1.CronJob) { } } } + if a.SecurityContext != nil { + v1.SetDefaults_SecurityContext(a.SecurityContext) + } } for i := range in.Spec.JobTemplate.Spec.Template.Spec.Containers { a := &in.Spec.JobTemplate.Spec.Template.Spec.Containers[i] @@ -173,6 +176,9 @@ func SetObjectDefaults_CronJob(in *v1beta1.CronJob) { } } } + if a.SecurityContext != nil { + v1.SetDefaults_SecurityContext(a.SecurityContext) + } } } @@ -277,6 +283,9 @@ func SetObjectDefaults_JobTemplate(in *v1beta1.JobTemplate) { } } } + if a.SecurityContext != nil { + v1.SetDefaults_SecurityContext(a.SecurityContext) + } } for i := range in.Template.Spec.Template.Spec.Containers { a := &in.Template.Spec.Template.Spec.Containers[i] @@ -319,5 +328,8 @@ func SetObjectDefaults_JobTemplate(in *v1beta1.JobTemplate) { } } } + if a.SecurityContext != nil { + v1.SetDefaults_SecurityContext(a.SecurityContext) + } } } diff --git a/pkg/apis/batch/v2alpha1/zz_generated.defaults.go b/pkg/apis/batch/v2alpha1/zz_generated.defaults.go index 367c56b15ed..8156eaac3f2 100644 --- a/pkg/apis/batch/v2alpha1/zz_generated.defaults.go +++ b/pkg/apis/batch/v2alpha1/zz_generated.defaults.go @@ -131,6 +131,9 @@ func SetObjectDefaults_CronJob(in *v2alpha1.CronJob) { } } } + if a.SecurityContext != nil { + v1.SetDefaults_SecurityContext(a.SecurityContext) + } } for i := range in.Spec.JobTemplate.Spec.Template.Spec.Containers { a := &in.Spec.JobTemplate.Spec.Template.Spec.Containers[i] @@ -173,6 +176,9 @@ func SetObjectDefaults_CronJob(in *v2alpha1.CronJob) { } } } + if a.SecurityContext != nil { + v1.SetDefaults_SecurityContext(a.SecurityContext) + } } } @@ -277,6 +283,9 @@ func SetObjectDefaults_JobTemplate(in *v2alpha1.JobTemplate) { } } } + if a.SecurityContext != nil { + v1.SetDefaults_SecurityContext(a.SecurityContext) + } } for i := range in.Template.Spec.Template.Spec.Containers { a := &in.Template.Spec.Template.Spec.Containers[i] @@ -319,5 +328,8 @@ func SetObjectDefaults_JobTemplate(in *v2alpha1.JobTemplate) { } } } + if a.SecurityContext != nil { + v1.SetDefaults_SecurityContext(a.SecurityContext) + } } } diff --git a/pkg/apis/batch/validation/BUILD b/pkg/apis/batch/validation/BUILD index f9a72f4ed17..0d8df02ba1a 100644 --- a/pkg/apis/batch/validation/BUILD +++ b/pkg/apis/batch/validation/BUILD @@ -14,13 +14,11 @@ go_library( "//pkg/apis/batch:go_default_library", "//pkg/apis/core:go_default_library", "//pkg/apis/core/validation:go_default_library", - "//pkg/features:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/validation:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/labels:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/validation:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/validation/field:go_default_library", - "//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library", "//vendor/github.com/robfig/cron:go_default_library", ], ) diff --git a/pkg/apis/batch/validation/validation.go b/pkg/apis/batch/validation/validation.go index 1e04e9779e5..1907ac9079e 100644 --- a/pkg/apis/batch/validation/validation.go +++ b/pkg/apis/batch/validation/validation.go @@ -24,11 +24,9 @@ import ( "k8s.io/apimachinery/pkg/labels" apimachineryvalidation "k8s.io/apimachinery/pkg/util/validation" "k8s.io/apimachinery/pkg/util/validation/field" - utilfeature "k8s.io/apiserver/pkg/util/feature" "k8s.io/kubernetes/pkg/apis/batch" api "k8s.io/kubernetes/pkg/apis/core" apivalidation "k8s.io/kubernetes/pkg/apis/core/validation" - "k8s.io/kubernetes/pkg/features" ) // TODO: generalize for other controller objects that will follow the same pattern, such as ReplicaSet and DaemonSet, and @@ -119,13 +117,8 @@ func validateJobSpec(spec *batch.JobSpec, fldPath *field.Path) field.ErrorList { if spec.BackoffLimit != nil { allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(*spec.BackoffLimit), fldPath.Child("backoffLimit"))...) } - if utilfeature.DefaultFeatureGate.Enabled(features.TTLAfterFinished) { - // normal validation for TTLSecondsAfterFinished - if spec.TTLSecondsAfterFinished != nil { - allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(*spec.TTLSecondsAfterFinished), fldPath.Child("ttlSecondsAfterFinished"))...) - } - } else if spec.TTLSecondsAfterFinished != nil { - allErrs = append(allErrs, field.Forbidden(fldPath.Child("ttlSecondsAfterFinished"), "disabled by feature-gate")) + if spec.TTLSecondsAfterFinished != nil { + allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(*spec.TTLSecondsAfterFinished), fldPath.Child("ttlSecondsAfterFinished"))...) } allErrs = append(allErrs, apivalidation.ValidatePodTemplateSpec(&spec.Template, fldPath.Child("template"))...) diff --git a/pkg/apis/coordination/BUILD b/pkg/apis/coordination/BUILD index c121148ed13..1057f03da57 100644 --- a/pkg/apis/coordination/BUILD +++ b/pkg/apis/coordination/BUILD @@ -29,6 +29,7 @@ filegroup( srcs = [ ":package-srcs", "//pkg/apis/coordination/install:all-srcs", + "//pkg/apis/coordination/v1:all-srcs", "//pkg/apis/coordination/v1beta1:all-srcs", "//pkg/apis/coordination/validation:all-srcs", ], diff --git a/pkg/apis/coordination/install/BUILD b/pkg/apis/coordination/install/BUILD index 855e7d8ab6b..c33d0b010d0 100644 --- a/pkg/apis/coordination/install/BUILD +++ b/pkg/apis/coordination/install/BUILD @@ -8,6 +8,7 @@ go_library( deps = [ "//pkg/api/legacyscheme:go_default_library", "//pkg/apis/coordination:go_default_library", + "//pkg/apis/coordination/v1:go_default_library", "//pkg/apis/coordination/v1beta1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/runtime:go_default_library", diff --git a/pkg/apis/coordination/install/install.go b/pkg/apis/coordination/install/install.go index ed92e8fdbca..5ef66bddd07 100644 --- a/pkg/apis/coordination/install/install.go +++ b/pkg/apis/coordination/install/install.go @@ -23,6 +23,7 @@ import ( utilruntime "k8s.io/apimachinery/pkg/util/runtime" "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/apis/coordination" + "k8s.io/kubernetes/pkg/apis/coordination/v1" "k8s.io/kubernetes/pkg/apis/coordination/v1beta1" ) @@ -34,5 +35,6 @@ func init() { func Install(scheme *runtime.Scheme) { utilruntime.Must(coordination.AddToScheme(scheme)) utilruntime.Must(v1beta1.AddToScheme(scheme)) - utilruntime.Must(scheme.SetVersionPriority(v1beta1.SchemeGroupVersion)) + utilruntime.Must(v1.AddToScheme(scheme)) + utilruntime.Must(scheme.SetVersionPriority(v1beta1.SchemeGroupVersion, v1.SchemeGroupVersion)) } diff --git a/pkg/apis/coordination/v1/BUILD b/pkg/apis/coordination/v1/BUILD new file mode 100644 index 00000000000..849c112322b --- /dev/null +++ b/pkg/apis/coordination/v1/BUILD @@ -0,0 +1,35 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = [ + "doc.go", + "register.go", + "zz_generated.conversion.go", + "zz_generated.defaults.go", + ], + importpath = "k8s.io/kubernetes/pkg/apis/coordination/v1", + visibility = ["//visibility:public"], + deps = [ + "//pkg/apis/coordination:go_default_library", + "//staging/src/k8s.io/api/coordination/v1:go_default_library", + "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + "//staging/src/k8s.io/apimachinery/pkg/conversion:go_default_library", + "//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library", + "//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/pkg/apis/coordination/v1/doc.go b/pkg/apis/coordination/v1/doc.go new file mode 100644 index 00000000000..afbf128a102 --- /dev/null +++ b/pkg/apis/coordination/v1/doc.go @@ -0,0 +1,24 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// +k8s:conversion-gen=k8s.io/kubernetes/pkg/apis/coordination +// +k8s:conversion-gen-external-types=k8s.io/api/coordination/v1 +// +k8s:defaulter-gen=TypeMeta +// +k8s:defaulter-gen-input=../../../../vendor/k8s.io/api/coordination/v1 + +// +groupName=coordination.k8s.io + +package v1 // import "k8s.io/kubernetes/pkg/apis/coordination/v1" diff --git a/pkg/apis/coordination/v1/register.go b/pkg/apis/coordination/v1/register.go new file mode 100644 index 00000000000..63933c3b14e --- /dev/null +++ b/pkg/apis/coordination/v1/register.go @@ -0,0 +1,45 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1 + +import ( + coordinationv1 "k8s.io/api/coordination/v1" + "k8s.io/apimachinery/pkg/runtime/schema" +) + +// GroupName is the group name use in this package +const GroupName = "coordination.k8s.io" + +// SchemeGroupVersion is group version used to register these objects +var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1"} + +// Resource takes an unqualified resource and returns a Group qualified GroupResource +func Resource(resource string) schema.GroupResource { + return SchemeGroupVersion.WithResource(resource).GroupResource() +} + +var ( + localSchemeBuilder = &coordinationv1.SchemeBuilder + AddToScheme = localSchemeBuilder.AddToScheme +) + +func init() { + // We only register manually written functions here. The registration of the + // generated functions takes place in the generated files. The separation + // makes the code compile even when the generated files are missing. + localSchemeBuilder.Register(RegisterDefaults) +} diff --git a/pkg/apis/coordination/v1/zz_generated.conversion.go b/pkg/apis/coordination/v1/zz_generated.conversion.go new file mode 100644 index 00000000000..c74d3d7f1ce --- /dev/null +++ b/pkg/apis/coordination/v1/zz_generated.conversion.go @@ -0,0 +1,147 @@ +// +build !ignore_autogenerated + +/* +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 conversion-gen. DO NOT EDIT. + +package v1 + +import ( + unsafe "unsafe" + + v1 "k8s.io/api/coordination/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + conversion "k8s.io/apimachinery/pkg/conversion" + runtime "k8s.io/apimachinery/pkg/runtime" + coordination "k8s.io/kubernetes/pkg/apis/coordination" +) + +func init() { + localSchemeBuilder.Register(RegisterConversions) +} + +// RegisterConversions adds conversion functions to the given scheme. +// Public to allow building arbitrary schemes. +func RegisterConversions(s *runtime.Scheme) error { + if err := s.AddGeneratedConversionFunc((*v1.Lease)(nil), (*coordination.Lease)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1_Lease_To_coordination_Lease(a.(*v1.Lease), b.(*coordination.Lease), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*coordination.Lease)(nil), (*v1.Lease)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_coordination_Lease_To_v1_Lease(a.(*coordination.Lease), b.(*v1.Lease), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1.LeaseList)(nil), (*coordination.LeaseList)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1_LeaseList_To_coordination_LeaseList(a.(*v1.LeaseList), b.(*coordination.LeaseList), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*coordination.LeaseList)(nil), (*v1.LeaseList)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_coordination_LeaseList_To_v1_LeaseList(a.(*coordination.LeaseList), b.(*v1.LeaseList), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1.LeaseSpec)(nil), (*coordination.LeaseSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1_LeaseSpec_To_coordination_LeaseSpec(a.(*v1.LeaseSpec), b.(*coordination.LeaseSpec), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*coordination.LeaseSpec)(nil), (*v1.LeaseSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_coordination_LeaseSpec_To_v1_LeaseSpec(a.(*coordination.LeaseSpec), b.(*v1.LeaseSpec), scope) + }); err != nil { + return err + } + return nil +} + +func autoConvert_v1_Lease_To_coordination_Lease(in *v1.Lease, out *coordination.Lease, s conversion.Scope) error { + out.ObjectMeta = in.ObjectMeta + if err := Convert_v1_LeaseSpec_To_coordination_LeaseSpec(&in.Spec, &out.Spec, s); err != nil { + return err + } + return nil +} + +// Convert_v1_Lease_To_coordination_Lease is an autogenerated conversion function. +func Convert_v1_Lease_To_coordination_Lease(in *v1.Lease, out *coordination.Lease, s conversion.Scope) error { + return autoConvert_v1_Lease_To_coordination_Lease(in, out, s) +} + +func autoConvert_coordination_Lease_To_v1_Lease(in *coordination.Lease, out *v1.Lease, s conversion.Scope) error { + out.ObjectMeta = in.ObjectMeta + if err := Convert_coordination_LeaseSpec_To_v1_LeaseSpec(&in.Spec, &out.Spec, s); err != nil { + return err + } + return nil +} + +// Convert_coordination_Lease_To_v1_Lease is an autogenerated conversion function. +func Convert_coordination_Lease_To_v1_Lease(in *coordination.Lease, out *v1.Lease, s conversion.Scope) error { + return autoConvert_coordination_Lease_To_v1_Lease(in, out, s) +} + +func autoConvert_v1_LeaseList_To_coordination_LeaseList(in *v1.LeaseList, out *coordination.LeaseList, s conversion.Scope) error { + out.ListMeta = in.ListMeta + out.Items = *(*[]coordination.Lease)(unsafe.Pointer(&in.Items)) + return nil +} + +// Convert_v1_LeaseList_To_coordination_LeaseList is an autogenerated conversion function. +func Convert_v1_LeaseList_To_coordination_LeaseList(in *v1.LeaseList, out *coordination.LeaseList, s conversion.Scope) error { + return autoConvert_v1_LeaseList_To_coordination_LeaseList(in, out, s) +} + +func autoConvert_coordination_LeaseList_To_v1_LeaseList(in *coordination.LeaseList, out *v1.LeaseList, s conversion.Scope) error { + out.ListMeta = in.ListMeta + out.Items = *(*[]v1.Lease)(unsafe.Pointer(&in.Items)) + return nil +} + +// Convert_coordination_LeaseList_To_v1_LeaseList is an autogenerated conversion function. +func Convert_coordination_LeaseList_To_v1_LeaseList(in *coordination.LeaseList, out *v1.LeaseList, s conversion.Scope) error { + return autoConvert_coordination_LeaseList_To_v1_LeaseList(in, out, s) +} + +func autoConvert_v1_LeaseSpec_To_coordination_LeaseSpec(in *v1.LeaseSpec, out *coordination.LeaseSpec, s conversion.Scope) error { + out.HolderIdentity = (*string)(unsafe.Pointer(in.HolderIdentity)) + out.LeaseDurationSeconds = (*int32)(unsafe.Pointer(in.LeaseDurationSeconds)) + out.AcquireTime = (*metav1.MicroTime)(unsafe.Pointer(in.AcquireTime)) + out.RenewTime = (*metav1.MicroTime)(unsafe.Pointer(in.RenewTime)) + out.LeaseTransitions = (*int32)(unsafe.Pointer(in.LeaseTransitions)) + return nil +} + +// Convert_v1_LeaseSpec_To_coordination_LeaseSpec is an autogenerated conversion function. +func Convert_v1_LeaseSpec_To_coordination_LeaseSpec(in *v1.LeaseSpec, out *coordination.LeaseSpec, s conversion.Scope) error { + return autoConvert_v1_LeaseSpec_To_coordination_LeaseSpec(in, out, s) +} + +func autoConvert_coordination_LeaseSpec_To_v1_LeaseSpec(in *coordination.LeaseSpec, out *v1.LeaseSpec, s conversion.Scope) error { + out.HolderIdentity = (*string)(unsafe.Pointer(in.HolderIdentity)) + out.LeaseDurationSeconds = (*int32)(unsafe.Pointer(in.LeaseDurationSeconds)) + out.AcquireTime = (*metav1.MicroTime)(unsafe.Pointer(in.AcquireTime)) + out.RenewTime = (*metav1.MicroTime)(unsafe.Pointer(in.RenewTime)) + out.LeaseTransitions = (*int32)(unsafe.Pointer(in.LeaseTransitions)) + return nil +} + +// Convert_coordination_LeaseSpec_To_v1_LeaseSpec is an autogenerated conversion function. +func Convert_coordination_LeaseSpec_To_v1_LeaseSpec(in *coordination.LeaseSpec, out *v1.LeaseSpec, s conversion.Scope) error { + return autoConvert_coordination_LeaseSpec_To_v1_LeaseSpec(in, out, s) +} diff --git a/pkg/apis/coordination/v1/zz_generated.defaults.go b/pkg/apis/coordination/v1/zz_generated.defaults.go new file mode 100644 index 00000000000..cce2e603a69 --- /dev/null +++ b/pkg/apis/coordination/v1/zz_generated.defaults.go @@ -0,0 +1,32 @@ +// +build !ignore_autogenerated + +/* +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 defaulter-gen. DO NOT EDIT. + +package v1 + +import ( + runtime "k8s.io/apimachinery/pkg/runtime" +) + +// RegisterDefaults adds defaulters functions to the given scheme. +// Public to allow building arbitrary schemes. +// All generated defaulters are covering - they call all nested defaulters. +func RegisterDefaults(scheme *runtime.Scheme) error { + return nil +} diff --git a/pkg/apis/core/fuzzer/fuzzer.go b/pkg/apis/core/fuzzer/fuzzer.go index 391226ba007..2a6b66e456e 100644 --- a/pkg/apis/core/fuzzer/fuzzer.go +++ b/pkg/apis/core/fuzzer/fuzzer.go @@ -354,6 +354,10 @@ var Funcs = func(codecs runtimeserializer.CodecFactory) []interface{} { c.Fuzz(&sc.Capabilities.Add) c.Fuzz(&sc.Capabilities.Drop) } + if sc.ProcMount == nil { + defProcMount := core.DefaultProcMount + sc.ProcMount = &defProcMount + } }, func(s *core.Secret, c fuzz.Continue) { c.FuzzNoCustom(s) // fuzz self without calling this function again diff --git a/pkg/apis/core/v1/BUILD b/pkg/apis/core/v1/BUILD index e52a3e4f907..7226462bbed 100644 --- a/pkg/apis/core/v1/BUILD +++ b/pkg/apis/core/v1/BUILD @@ -15,7 +15,6 @@ go_library( deps = [ "//pkg/apis/apps:go_default_library", "//pkg/apis/core:go_default_library", - "//pkg/features:go_default_library", "//pkg/util/parsers:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/resource:go_default_library", @@ -26,7 +25,6 @@ go_library( "//staging/src/k8s.io/apimachinery/pkg/types:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/intstr:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/validation/field:go_default_library", - "//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library", "//vendor/k8s.io/utils/pointer:go_default_library", ], ) @@ -44,7 +42,6 @@ go_test( "//pkg/apis/apps:go_default_library", "//pkg/apis/core:go_default_library", "//pkg/apis/core/fuzzer:go_default_library", - "//pkg/features:go_default_library", "//staging/src/k8s.io/api/apps/v1:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/apitesting/fuzzer:go_default_library", @@ -55,8 +52,6 @@ go_test( "//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/diff:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/intstr:go_default_library", - "//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library", - "//staging/src/k8s.io/apiserver/pkg/util/feature/testing:go_default_library", "//vendor/k8s.io/utils/pointer:go_default_library", ], ) diff --git a/pkg/apis/core/v1/defaults.go b/pkg/apis/core/v1/defaults.go index 172d3797bf5..d06356a89dc 100644 --- a/pkg/apis/core/v1/defaults.go +++ b/pkg/apis/core/v1/defaults.go @@ -22,8 +22,6 @@ import ( "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/intstr" - utilfeature "k8s.io/apiserver/pkg/util/feature" - "k8s.io/kubernetes/pkg/features" "k8s.io/kubernetes/pkg/util/parsers" utilpointer "k8s.io/utils/pointer" ) @@ -247,7 +245,7 @@ func SetDefaults_PersistentVolume(obj *v1.PersistentVolume) { if obj.Spec.PersistentVolumeReclaimPolicy == "" { obj.Spec.PersistentVolumeReclaimPolicy = v1.PersistentVolumeReclaimRetain } - if obj.Spec.VolumeMode == nil && utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) { + if obj.Spec.VolumeMode == nil { obj.Spec.VolumeMode = new(v1.PersistentVolumeMode) *obj.Spec.VolumeMode = v1.PersistentVolumeFilesystem } @@ -256,7 +254,7 @@ func SetDefaults_PersistentVolumeClaim(obj *v1.PersistentVolumeClaim) { if obj.Status.Phase == "" { obj.Status.Phase = v1.ClaimPending } - if obj.Spec.VolumeMode == nil && utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) { + if obj.Spec.VolumeMode == nil { obj.Spec.VolumeMode = new(v1.PersistentVolumeMode) *obj.Spec.VolumeMode = v1.PersistentVolumeFilesystem } @@ -423,3 +421,10 @@ func SetDefaults_HostPathVolumeSource(obj *v1.HostPathVolumeSource) { obj.Type = &typeVol } } + +func SetDefaults_SecurityContext(obj *v1.SecurityContext) { + if obj.ProcMount == nil { + defProcMount := v1.DefaultProcMount + obj.ProcMount = &defProcMount + } +} diff --git a/pkg/apis/core/v1/defaults_test.go b/pkg/apis/core/v1/defaults_test.go index b082014864d..b3d9ad4316f 100644 --- a/pkg/apis/core/v1/defaults_test.go +++ b/pkg/apis/core/v1/defaults_test.go @@ -26,11 +26,8 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/intstr" - utilfeature "k8s.io/apiserver/pkg/util/feature" - utilfeaturetesting "k8s.io/apiserver/pkg/util/feature/testing" "k8s.io/kubernetes/pkg/api/legacyscheme" corev1 "k8s.io/kubernetes/pkg/apis/core/v1" - "k8s.io/kubernetes/pkg/features" utilpointer "k8s.io/utils/pointer" // enforce that all types are installed @@ -805,63 +802,91 @@ func TestSetDefaultSecret(t *testing.T) { } func TestSetDefaultPersistentVolume(t *testing.T) { - defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, false)() - pv := &v1.PersistentVolume{} - obj2 := roundTrip(t, runtime.Object(pv)) - pv2 := obj2.(*v1.PersistentVolume) + fsMode := v1.PersistentVolumeFilesystem + blockMode := v1.PersistentVolumeBlock - if pv2.Status.Phase != v1.VolumePending { - t.Errorf("Expected volume phase %v, got %v", v1.VolumePending, pv2.Status.Phase) - } - if pv2.Spec.PersistentVolumeReclaimPolicy != v1.PersistentVolumeReclaimRetain { - t.Errorf("Expected pv reclaim policy %v, got %v", v1.PersistentVolumeReclaimRetain, pv2.Spec.PersistentVolumeReclaimPolicy) + tests := []struct { + name string + volumeMode *v1.PersistentVolumeMode + expectedVolumeMode v1.PersistentVolumeMode + }{ + { + name: "volume mode nil", + volumeMode: nil, + expectedVolumeMode: v1.PersistentVolumeFilesystem, + }, + { + name: "volume mode filesystem", + volumeMode: &fsMode, + expectedVolumeMode: v1.PersistentVolumeFilesystem, + }, + { + name: "volume mode block", + volumeMode: &blockMode, + expectedVolumeMode: v1.PersistentVolumeBlock, + }, } - // When feature gate is disabled, field should not be defaulted - defaultMode := v1.PersistentVolumeFilesystem - outputMode := pv2.Spec.VolumeMode - if outputMode != nil { - t.Errorf("Expected VolumeMode to not be defaulted, got: %+v", outputMode) - } - - // When feature gate is enabled, field should be defaulted - defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, true)() - obj3 := roundTrip(t, runtime.Object(pv)).(*v1.PersistentVolume) - outputMode3 := obj3.Spec.VolumeMode - - if outputMode3 == nil { - t.Errorf("Expected VolumeMode to be defaulted to: %+v, got: nil", defaultMode) - } else if *outputMode3 != defaultMode { - t.Errorf("Expected VolumeMode to be defaulted to: %+v, got: %+v", defaultMode, outputMode3) + for _, test := range tests { + pv := &v1.PersistentVolume{ + Spec: v1.PersistentVolumeSpec{ + VolumeMode: test.volumeMode, + }, + } + obj1 := roundTrip(t, runtime.Object(pv)) + pv1 := obj1.(*v1.PersistentVolume) + if pv1.Status.Phase != v1.VolumePending { + t.Errorf("Expected claim phase %v, got %v", v1.ClaimPending, pv1.Status.Phase) + } + if pv1.Spec.PersistentVolumeReclaimPolicy != v1.PersistentVolumeReclaimRetain { + t.Errorf("Expected pv reclaim policy %v, got %v", v1.PersistentVolumeReclaimRetain, pv1.Spec.PersistentVolumeReclaimPolicy) + } + if *pv1.Spec.VolumeMode != test.expectedVolumeMode { + t.Errorf("Test %s failed, Expected VolumeMode: %v, but got %v", test.name, test.volumeMode, *pv1.Spec.VolumeMode) + } } } func TestSetDefaultPersistentVolumeClaim(t *testing.T) { - defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, false)() - pvc := &v1.PersistentVolumeClaim{} - obj2 := roundTrip(t, runtime.Object(pvc)) - pvc2 := obj2.(*v1.PersistentVolumeClaim) + fsMode := v1.PersistentVolumeFilesystem + blockMode := v1.PersistentVolumeBlock - if pvc2.Status.Phase != v1.ClaimPending { - t.Errorf("Expected claim phase %v, got %v", v1.ClaimPending, pvc2.Status.Phase) + tests := []struct { + name string + volumeMode *v1.PersistentVolumeMode + expectedVolumeMode v1.PersistentVolumeMode + }{ + { + name: "volume mode nil", + volumeMode: nil, + expectedVolumeMode: v1.PersistentVolumeFilesystem, + }, + { + name: "volume mode filesystem", + volumeMode: &fsMode, + expectedVolumeMode: v1.PersistentVolumeFilesystem, + }, + { + name: "volume mode block", + volumeMode: &blockMode, + expectedVolumeMode: v1.PersistentVolumeBlock, + }, } - // When feature gate is disabled, field should not be defaulted - defaultMode := v1.PersistentVolumeFilesystem - outputMode := pvc2.Spec.VolumeMode - if outputMode != nil { - t.Errorf("Expected VolumeMode to not be defaulted, got: %+v", outputMode) - } - - // When feature gate is enabled, field should be defaulted - defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, true)() - obj3 := roundTrip(t, runtime.Object(pvc)).(*v1.PersistentVolumeClaim) - outputMode3 := obj3.Spec.VolumeMode - - if outputMode3 == nil { - t.Errorf("Expected VolumeMode to be defaulted to: %+v, got: nil", defaultMode) - } else if *outputMode3 != defaultMode { - t.Errorf("Expected VolumeMode to be defaulted to: %+v, got: %+v", defaultMode, outputMode3) + for _, test := range tests { + pvc := &v1.PersistentVolumeClaim{ + Spec: v1.PersistentVolumeClaimSpec{ + VolumeMode: test.volumeMode, + }, + } + obj1 := roundTrip(t, runtime.Object(pvc)) + pvc1 := obj1.(*v1.PersistentVolumeClaim) + if pvc1.Status.Phase != v1.ClaimPending { + t.Errorf("Expected claim phase %v, got %v", v1.ClaimPending, pvc1.Status.Phase) + } + if *pvc1.Spec.VolumeMode != test.expectedVolumeMode { + t.Errorf("Test %s failed, Expected VolumeMode: %v, but got %v", test.name, test.volumeMode, *pvc1.Spec.VolumeMode) + } } } diff --git a/pkg/apis/core/v1/zz_generated.defaults.go b/pkg/apis/core/v1/zz_generated.defaults.go index 00e0b384aa8..0ea5e0fae05 100644 --- a/pkg/apis/core/v1/zz_generated.defaults.go +++ b/pkg/apis/core/v1/zz_generated.defaults.go @@ -263,6 +263,9 @@ func SetObjectDefaults_Pod(in *v1.Pod) { } } } + if a.SecurityContext != nil { + SetDefaults_SecurityContext(a.SecurityContext) + } } for i := range in.Spec.Containers { a := &in.Spec.Containers[i] @@ -305,6 +308,9 @@ func SetObjectDefaults_Pod(in *v1.Pod) { } } } + if a.SecurityContext != nil { + SetDefaults_SecurityContext(a.SecurityContext) + } } } @@ -409,6 +415,9 @@ func SetObjectDefaults_PodTemplate(in *v1.PodTemplate) { } } } + if a.SecurityContext != nil { + SetDefaults_SecurityContext(a.SecurityContext) + } } for i := range in.Template.Spec.Containers { a := &in.Template.Spec.Containers[i] @@ -451,6 +460,9 @@ func SetObjectDefaults_PodTemplate(in *v1.PodTemplate) { } } } + if a.SecurityContext != nil { + SetDefaults_SecurityContext(a.SecurityContext) + } } } @@ -557,6 +569,9 @@ func SetObjectDefaults_ReplicationController(in *v1.ReplicationController) { } } } + if a.SecurityContext != nil { + SetDefaults_SecurityContext(a.SecurityContext) + } } for i := range in.Spec.Template.Spec.Containers { a := &in.Spec.Template.Spec.Containers[i] @@ -599,6 +614,9 @@ func SetObjectDefaults_ReplicationController(in *v1.ReplicationController) { } } } + if a.SecurityContext != nil { + SetDefaults_SecurityContext(a.SecurityContext) + } } } } diff --git a/pkg/apis/core/validation/events_test.go b/pkg/apis/core/validation/events_test.go index 1db7463f971..835862ba983 100644 --- a/pkg/apis/core/validation/events_test.go +++ b/pkg/apis/core/validation/events_test.go @@ -84,7 +84,7 @@ func TestValidateEvent(t *testing.T) { Namespace: metav1.NamespaceDefault, }, InvolvedObject: core.ObjectReference{ - APIVersion: "extensions/v1beta1", + APIVersion: "apps/v1", Kind: "NoKind", Namespace: metav1.NamespaceDefault, }, @@ -97,7 +97,7 @@ func TestValidateEvent(t *testing.T) { Namespace: metav1.NamespaceDefault, }, InvolvedObject: core.ObjectReference{ - APIVersion: "extensions/v1beta1", + APIVersion: "batch/v1", Kind: "Job", Namespace: "foo", }, @@ -110,7 +110,7 @@ func TestValidateEvent(t *testing.T) { Namespace: metav1.NamespaceDefault, }, InvolvedObject: core.ObjectReference{ - APIVersion: "extensions/v1beta1", + APIVersion: "batch/v1", Kind: "Job", Namespace: metav1.NamespaceDefault, }, @@ -149,7 +149,7 @@ func TestValidateEvent(t *testing.T) { Namespace: metav1.NamespaceDefault, }, InvolvedObject: core.ObjectReference{ - APIVersion: "extensions", + APIVersion: "batch", Kind: "Job", Namespace: "foo", }, @@ -162,8 +162,7 @@ func TestValidateEvent(t *testing.T) { Namespace: "foo", }, InvolvedObject: core.ObjectReference{ - // must register in v1beta1 to be true - APIVersion: "extensions/v1beta1", + APIVersion: "batch/v1", Kind: "Job", Namespace: "foo", }, diff --git a/pkg/apis/core/validation/validation.go b/pkg/apis/core/validation/validation.go index 4643720eddd..2b56826fbb3 100644 --- a/pkg/apis/core/validation/validation.go +++ b/pkg/apis/core/validation/validation.go @@ -412,14 +412,8 @@ func validateVolumeSource(source *core.VolumeSource, fldPath *field.Path, volNam allErrs := field.ErrorList{} if source.EmptyDir != nil { numVolumes++ - if !utilfeature.DefaultFeatureGate.Enabled(features.LocalStorageCapacityIsolation) { - if source.EmptyDir.SizeLimit != nil && source.EmptyDir.SizeLimit.Cmp(resource.Quantity{}) != 0 { - allErrs = append(allErrs, field.Forbidden(fldPath.Child("emptyDir").Child("sizeLimit"), "SizeLimit field disabled by feature-gate for EmptyDir volumes")) - } - } else { - if source.EmptyDir.SizeLimit != nil && source.EmptyDir.SizeLimit.Cmp(resource.Quantity{}) < 0 { - allErrs = append(allErrs, field.Forbidden(fldPath.Child("emptyDir").Child("sizeLimit"), "SizeLimit field must be a valid resource quantity")) - } + if source.EmptyDir.SizeLimit != nil && source.EmptyDir.SizeLimit.Cmp(resource.Quantity{}) < 0 { + allErrs = append(allErrs, field.Forbidden(fldPath.Child("emptyDir").Child("sizeLimit"), "SizeLimit field must be a valid resource quantity")) } if !utilfeature.DefaultFeatureGate.Enabled(features.HugePages) && source.EmptyDir.Medium == core.StorageMediumHugePages { allErrs = append(allErrs, field.Forbidden(fldPath.Child("emptyDir").Child("medium"), "HugePages medium is disabled by feature-gate for EmptyDir volumes")) @@ -1763,9 +1757,7 @@ func ValidatePersistentVolume(pv *core.PersistentVolume) field.ErrorList { allErrs = append(allErrs, field.Invalid(specPath.Child("storageClassName"), pv.Spec.StorageClassName, msg)) } } - if pv.Spec.VolumeMode != nil && !utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) { - allErrs = append(allErrs, field.Forbidden(specPath.Child("volumeMode"), "PersistentVolume volumeMode is disabled by feature-gate")) - } else if pv.Spec.VolumeMode != nil && !supportedVolumeModes.Has(string(*pv.Spec.VolumeMode)) { + if pv.Spec.VolumeMode != nil && !supportedVolumeModes.Has(string(*pv.Spec.VolumeMode)) { allErrs = append(allErrs, field.NotSupported(specPath.Child("volumeMode"), *pv.Spec.VolumeMode, supportedVolumeModes.List())) } return allErrs @@ -1781,18 +1773,13 @@ func ValidatePersistentVolumeUpdate(newPv, oldPv *core.PersistentVolume) field.E if !apiequality.Semantic.DeepEqual(newPv.Spec.PersistentVolumeSource, oldPv.Spec.PersistentVolumeSource) { allErrs = append(allErrs, field.Forbidden(field.NewPath("spec", "persistentvolumesource"), "is immutable after creation")) } - newPv.Status = oldPv.Status - if utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) { - allErrs = append(allErrs, ValidateImmutableField(newPv.Spec.VolumeMode, oldPv.Spec.VolumeMode, field.NewPath("volumeMode"))...) - } + allErrs = append(allErrs, ValidateImmutableField(newPv.Spec.VolumeMode, oldPv.Spec.VolumeMode, field.NewPath("volumeMode"))...) - if utilfeature.DefaultFeatureGate.Enabled(features.VolumeScheduling) { - // Allow setting NodeAffinity if oldPv NodeAffinity was not set - if oldPv.Spec.NodeAffinity != nil { - allErrs = append(allErrs, ValidateImmutableField(newPv.Spec.NodeAffinity, oldPv.Spec.NodeAffinity, field.NewPath("nodeAffinity"))...) - } + // Allow setting NodeAffinity if oldPv NodeAffinity was not set + if oldPv.Spec.NodeAffinity != nil { + allErrs = append(allErrs, ValidateImmutableField(newPv.Spec.NodeAffinity, oldPv.Spec.NodeAffinity, field.NewPath("nodeAffinity"))...) } return allErrs @@ -1843,9 +1830,7 @@ func ValidatePersistentVolumeClaimSpec(spec *core.PersistentVolumeClaimSpec, fld allErrs = append(allErrs, field.Invalid(fldPath.Child("storageClassName"), *spec.StorageClassName, msg)) } } - if spec.VolumeMode != nil && !utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) { - allErrs = append(allErrs, field.Forbidden(fldPath.Child("volumeMode"), "PersistentVolumeClaim volumeMode is disabled by feature-gate")) - } else if spec.VolumeMode != nil && !supportedVolumeModes.Has(string(*spec.VolumeMode)) { + if spec.VolumeMode != nil && !supportedVolumeModes.Has(string(*spec.VolumeMode)) { allErrs = append(allErrs, field.NotSupported(fldPath.Child("volumeMode"), *spec.VolumeMode, supportedVolumeModes.List())) } @@ -1920,9 +1905,8 @@ func ValidatePersistentVolumeClaimUpdate(newPvc, oldPvc *core.PersistentVolumeCl } } - if utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) { - allErrs = append(allErrs, ValidateImmutableField(newPvc.Spec.VolumeMode, oldPvc.Spec.VolumeMode, field.NewPath("volumeMode"))...) - } + allErrs = append(allErrs, ValidateImmutableField(newPvc.Spec.VolumeMode, oldPvc.Spec.VolumeMode, field.NewPath("volumeMode"))...) + return allErrs } @@ -2127,8 +2111,6 @@ func validateContainerResourceFieldSelector(fs *core.ResourceFieldSelector, expr allErrs = append(allErrs, field.Required(fldPath.Child("resource"), "")) } else if !expressions.Has(fs.Resource) { allErrs = append(allErrs, field.NotSupported(fldPath.Child("resource"), fs.Resource, expressions.List())) - } else if fsResourceIsEphemeralStorage(fs.Resource) && !utilfeature.DefaultFeatureGate.Enabled(features.LocalStorageCapacityIsolation) { - allErrs = append(allErrs, field.Forbidden(fldPath, "Containers' ephemeral storage requests/limits disabled by feature-gate for Downward API")) } allErrs = append(allErrs, validateContainerResourceDivisor(fs.Resource, fs.Divisor, fldPath)...) return allErrs @@ -2299,11 +2281,7 @@ func ValidateVolumeMounts(mounts []core.VolumeMount, voldevices map[string]strin } if len(mnt.SubPath) > 0 { - if !utilfeature.DefaultFeatureGate.Enabled(features.VolumeSubpath) { - allErrs = append(allErrs, field.Forbidden(fldPath.Child("subPath"), "subPath is disabled by feature-gate")) - } else { - allErrs = append(allErrs, validateLocalDescendingPath(mnt.SubPath, fldPath.Child("subPath"))...) - } + allErrs = append(allErrs, validateLocalDescendingPath(mnt.SubPath, fldPath.Child("subPath"))...) } if mnt.MountPropagation != nil { @@ -2318,10 +2296,6 @@ func ValidateVolumeDevices(devices []core.VolumeDevice, volmounts map[string]str devicepath := sets.NewString() devicename := sets.NewString() - if devices != nil && !utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) { - allErrs = append(allErrs, field.Forbidden(fldPath.Child("volumeDevices"), "Container volumeDevices is disabled by feature-gate")) - return allErrs - } if devices != nil { for i, dev := range devices { idxPath := fldPath.Index(i) @@ -3050,14 +3024,12 @@ func ValidatePodSpec(spec *core.PodSpec, fldPath *field.Path) field.ErrorList { } if len(spec.PriorityClassName) > 0 { - if utilfeature.DefaultFeatureGate.Enabled(features.PodPriority) { - for _, msg := range ValidatePriorityClassName(spec.PriorityClassName, false) { - allErrs = append(allErrs, field.Invalid(fldPath.Child("priorityClassName"), spec.PriorityClassName, msg)) - } + for _, msg := range ValidatePriorityClassName(spec.PriorityClassName, false) { + allErrs = append(allErrs, field.Invalid(fldPath.Child("priorityClassName"), spec.PriorityClassName, msg)) } } - if spec.RuntimeClassName != nil && utilfeature.DefaultFeatureGate.Enabled(features.RuntimeClass) { + if spec.RuntimeClassName != nil { allErrs = append(allErrs, ValidateRuntimeClassName(*spec.RuntimeClassName, fldPath.Child("runtimeClassName"))...) } @@ -3182,22 +3154,17 @@ func ValidateTopologySelectorTerm(term core.TopologySelectorTerm, fldPath *field exprMap := make(map[string]sets.String) exprPath := fldPath.Child("matchLabelExpressions") - if utilfeature.DefaultFeatureGate.Enabled(features.VolumeScheduling) { - // Allow empty MatchLabelExpressions, in case this field becomes optional in the future. + // Allow empty MatchLabelExpressions, in case this field becomes optional in the future. + for i, req := range term.MatchLabelExpressions { + idxPath := exprPath.Index(i) + valueSet, exprErrs := validateTopologySelectorLabelRequirement(req, idxPath) + allErrs = append(allErrs, exprErrs...) - for i, req := range term.MatchLabelExpressions { - idxPath := exprPath.Index(i) - valueSet, exprErrs := validateTopologySelectorLabelRequirement(req, idxPath) - allErrs = append(allErrs, exprErrs...) - - // Validate no duplicate keys exist. - if _, exists := exprMap[req.Key]; exists { - allErrs = append(allErrs, field.Duplicate(idxPath.Child("key"), req.Key)) - } - exprMap[req.Key] = valueSet + // Validate no duplicate keys exist. + if _, exists := exprMap[req.Key]; exists { + allErrs = append(allErrs, field.Duplicate(idxPath.Child("key"), req.Key)) } - } else if len(term.MatchLabelExpressions) != 0 { - allErrs = append(allErrs, field.Forbidden(fldPath, "field is disabled by feature-gate VolumeScheduling")) + exprMap[req.Key] = valueSet } return exprMap, allErrs @@ -3472,7 +3439,6 @@ func ValidatePodSecurityContext(securityContext *core.PodSecurityContext, spec * allErrs = append(allErrs, field.Invalid(fldPath.Child("runAsGroup"), *(securityContext.RunAsGroup), msg)) } } - for g, gid := range securityContext.SupplementalGroups { for _, msg := range validation.IsValidGroupID(gid) { allErrs = append(allErrs, field.Invalid(fldPath.Child("supplementalGroups").Index(g), gid, msg)) @@ -4181,16 +4147,6 @@ func ValidateNode(node *core.Node) field.ErrorList { // That said, if specified, we need to ensure they are valid. allErrs = append(allErrs, ValidateNodeResources(node)...) - // Only allow Spec.ConfigSource and Status.Config to be set if the DynamicKubeletConfig feature gate is enabled - if !utilfeature.DefaultFeatureGate.Enabled(features.DynamicKubeletConfig) { - if node.Spec.ConfigSource != nil { - allErrs = append(allErrs, field.Forbidden(field.NewPath("spec", "configSource"), "configSource may only be set if the DynamicKubeletConfig feature gate is enabled)")) - } - if node.Status.Config != nil { - allErrs = append(allErrs, field.Forbidden(field.NewPath("status", "config"), "config may only be set if the DynamicKubeletConfig feature gate is enabled)")) - } - } - if len(node.Spec.PodCIDR) != 0 { _, err := ValidateCIDR(node.Spec.PodCIDR) if err != nil { @@ -4273,17 +4229,14 @@ func ValidateNodeUpdate(node, oldNode *core.Node) field.ErrorList { } } - // Allow and validate updates to Node.Spec.ConfigSource and Node.Status.Config if DynamicKubeletConfig feature gate is enabled - if utilfeature.DefaultFeatureGate.Enabled(features.DynamicKubeletConfig) { - if node.Spec.ConfigSource != nil { - allErrs = append(allErrs, validateNodeConfigSourceSpec(node.Spec.ConfigSource, field.NewPath("spec", "configSource"))...) - } - oldNode.Spec.ConfigSource = node.Spec.ConfigSource - if node.Status.Config != nil { - allErrs = append(allErrs, validateNodeConfigStatus(node.Status.Config, field.NewPath("status", "config"))...) - } - oldNode.Status.Config = node.Status.Config + if node.Spec.ConfigSource != nil { + allErrs = append(allErrs, validateNodeConfigSourceSpec(node.Spec.ConfigSource, field.NewPath("spec", "configSource"))...) } + oldNode.Spec.ConfigSource = node.Spec.ConfigSource + if node.Status.Config != nil { + allErrs = append(allErrs, validateNodeConfigStatus(node.Status.Config, field.NewPath("status", "config"))...) + } + oldNode.Status.Config = node.Status.Config // TODO: move reset function to its own location // Ignore metadata changes now that they have been tested @@ -4466,9 +4419,7 @@ func isLocalStorageResource(name string) bool { // Refer to docs/design/resources.md for more details. func ValidateResourceQuotaResourceName(value string, fldPath *field.Path) field.ErrorList { allErrs := validateResourceName(value, fldPath) - if isLocalStorageResource(value) && !utilfeature.DefaultFeatureGate.Enabled(features.LocalStorageCapacityIsolation) { - return append(allErrs, field.Forbidden(fldPath, "ResourceEphemeralStorage field disabled by feature-gate for ResourceQuota")) - } + if len(strings.Split(value, "/")) == 1 { if !helper.IsStandardQuotaResourceName(value) { return append(allErrs, field.Invalid(fldPath, value, isInvalidQuotaResource)) @@ -4499,10 +4450,6 @@ func validateLimitRangeTypeName(value string, fldPath *field.Path) field.ErrorLi // Validate limit range resource name // limit types (other than Pod/Container) could contain storage not just cpu or memory func validateLimitRangeResourceName(limitType core.LimitType, value string, fldPath *field.Path) field.ErrorList { - allErrs := field.ErrorList{} - if value == string(core.ResourceEphemeralStorage) && !utilfeature.DefaultFeatureGate.Enabled(features.LocalStorageCapacityIsolation) { - return append(allErrs, field.Forbidden(fldPath, "ResourceEphemeralStorage field disabled by feature-gate for Resource LimitRange")) - } switch limitType { case core.LimitTypePod, core.LimitTypeContainer: return validateContainerResourceName(value, fldPath) @@ -4817,9 +4764,6 @@ func ValidateResourceRequirements(requirements *core.ResourceRequirements, fldPa // Validate resource quantity. allErrs = append(allErrs, ValidateResourceQuantityValue(string(resourceName), quantity, fldPath)...) - if resourceName == core.ResourceEphemeralStorage && !utilfeature.DefaultFeatureGate.Enabled(features.LocalStorageCapacityIsolation) { - allErrs = append(allErrs, field.Forbidden(limPath, "ResourceEphemeralStorage field disabled by feature-gate for ResourceRequirements")) - } if helper.IsHugePageResourceName(resourceName) { if !utilfeature.DefaultFeatureGate.Enabled(features.HugePages) { allErrs = append(allErrs, field.Forbidden(limPath, fmt.Sprintf("%s field disabled by feature-gate for ResourceRequirements", resourceName))) @@ -5276,6 +5220,12 @@ func ValidateSecurityContext(sc *core.SecurityContext, fldPath *field.Path) fiel } } + if sc.ProcMount != nil { + if err := ValidateProcMountType(fldPath.Child("procMount"), *sc.ProcMount); err != nil { + allErrs = append(allErrs, err) + } + } + if sc.AllowPrivilegeEscalation != nil && !*sc.AllowPrivilegeEscalation { if sc.Privileged != nil && *sc.Privileged { allErrs = append(allErrs, field.Invalid(fldPath, sc, "cannot set `allowPrivilegeEscalation` to false and `privileged` to true")) @@ -5345,10 +5295,6 @@ func validateVolumeNodeAffinity(nodeAffinity *core.VolumeNodeAffinity, fldPath * return false, allErrs } - if !utilfeature.DefaultFeatureGate.Enabled(features.VolumeScheduling) { - allErrs = append(allErrs, field.Forbidden(fldPath, "Volume node affinity is disabled by feature-gate")) - } - if nodeAffinity.Required != nil { allErrs = append(allErrs, ValidateNodeSelector(nodeAffinity.Required, fldPath.Child("required"))...) } else { @@ -5376,3 +5322,13 @@ func IsDecremented(update, old *int32) bool { } return *update < *old } + +// ValidateProcMountType tests that the argument is a valid ProcMountType. +func ValidateProcMountType(fldPath *field.Path, procMountType core.ProcMountType) *field.Error { + switch procMountType { + case core.DefaultProcMount, core.UnmaskedProcMount: + return nil + default: + return field.NotSupported(fldPath, procMountType, []string{string(core.DefaultProcMount), string(core.UnmaskedProcMount)}) + } +} diff --git a/pkg/apis/core/validation/validation_test.go b/pkg/apis/core/validation/validation_test.go index 1c53800f704..03769ca0d2f 100644 --- a/pkg/apis/core/validation/validation_test.go +++ b/pkg/apis/core/validation/validation_test.go @@ -69,7 +69,6 @@ func TestValidatePersistentVolumes(t *testing.T) { scenarios := map[string]struct { isExpectedFailure bool volume *core.PersistentVolume - disableBlock bool }{ "good-volume": { isExpectedFailure: false, @@ -369,24 +368,6 @@ func TestValidatePersistentVolumes(t *testing.T) { StorageClassName: "-invalid-", }), }, - "feature disabled valid volume mode": { - disableBlock: true, - isExpectedFailure: true, - volume: testVolume("foo", "", core.PersistentVolumeSpec{ - Capacity: core.ResourceList{ - core.ResourceName(core.ResourceStorage): resource.MustParse("10G"), - }, - AccessModes: []core.PersistentVolumeAccessMode{core.ReadWriteOnce}, - PersistentVolumeSource: core.PersistentVolumeSource{ - HostPath: &core.HostPathVolumeSource{ - Path: "/foo", - Type: newHostPathType(string(core.HostPathDirectory)), - }, - }, - StorageClassName: "valid", - VolumeMode: &validMode, - }), - }, "bad-hostpath-volume-backsteps": { isExpectedFailure: true, volume: testVolume("foo", "", core.PersistentVolumeSpec{ @@ -433,7 +414,6 @@ func TestValidatePersistentVolumes(t *testing.T) { for name, scenario := range scenarios { t.Run(name, func(t *testing.T) { - defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, !scenario.disableBlock)() errs := ValidatePersistentVolume(scenario.volume) if len(errs) == 0 && scenario.isExpectedFailure { t.Errorf("Unexpected success for scenario: %s", name) @@ -597,19 +577,6 @@ func TestValidateLocalVolumesDisabled(t *testing.T) { } }) } - - for name, scenario := range scenarios { - t.Run(name+" VolumeScheduling disabled", func(t *testing.T) { - defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.VolumeScheduling, false)() - errs := ValidatePersistentVolume(scenario.volume) - if len(errs) == 0 && scenario.isExpectedFailure { - t.Errorf("Unexpected success for scenario: %s", name) - } - if len(errs) > 0 && !scenario.isExpectedFailure { - t.Errorf("Unexpected failure for scenario: %s - %+v", name, errs) - } - }) - } } func testVolumeWithNodeAffinity(affinity *core.VolumeNodeAffinity) *core.PersistentVolume { @@ -823,7 +790,6 @@ func TestValidatePersistentVolumeClaim(t *testing.T) { scenarios := map[string]struct { isExpectedFailure bool claim *core.PersistentVolumeClaim - disableBlock bool }{ "good-claim": { isExpectedFailure: false, @@ -1018,31 +984,6 @@ func TestValidatePersistentVolumeClaim(t *testing.T) { StorageClassName: &invalidClassName, }), }, - "feature disabled valid volume mode": { - disableBlock: true, - isExpectedFailure: true, - claim: testVolumeClaim("foo", "ns", core.PersistentVolumeClaimSpec{ - Selector: &metav1.LabelSelector{ - MatchExpressions: []metav1.LabelSelectorRequirement{ - { - Key: "key2", - Operator: "Exists", - }, - }, - }, - AccessModes: []core.PersistentVolumeAccessMode{ - core.ReadWriteOnce, - core.ReadOnlyMany, - }, - Resources: core.ResourceRequirements{ - Requests: core.ResourceList{ - core.ResourceName(core.ResourceStorage): resource.MustParse("10G"), - }, - }, - StorageClassName: &validClassName, - VolumeMode: &validMode, - }), - }, "invalid-volume-mode": { isExpectedFailure: true, claim: testVolumeClaim("foo", "ns", core.PersistentVolumeClaimSpec{ @@ -1062,7 +1003,6 @@ func TestValidatePersistentVolumeClaim(t *testing.T) { for name, scenario := range scenarios { t.Run(name, func(t *testing.T) { - defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, !scenario.disableBlock)() errs := ValidatePersistentVolumeClaim(scenario.claim) if len(errs) == 0 && scenario.isExpectedFailure { t.Errorf("Unexpected success for scenario: %s", name) @@ -1082,80 +1022,62 @@ func TestAlphaPVVolumeModeUpdate(t *testing.T) { isExpectedFailure bool oldPV *core.PersistentVolume newPV *core.PersistentVolume - enableBlock bool }{ "valid-update-volume-mode-block-to-block": { isExpectedFailure: false, oldPV: createTestVolModePV(&block), newPV: createTestVolModePV(&block), - enableBlock: true, }, "valid-update-volume-mode-file-to-file": { isExpectedFailure: false, oldPV: createTestVolModePV(&file), newPV: createTestVolModePV(&file), - enableBlock: true, }, "invalid-update-volume-mode-to-block": { isExpectedFailure: true, oldPV: createTestVolModePV(&file), newPV: createTestVolModePV(&block), - enableBlock: true, }, "invalid-update-volume-mode-to-file": { isExpectedFailure: true, oldPV: createTestVolModePV(&block), newPV: createTestVolModePV(&file), - enableBlock: true, - }, - "invalid-update-blocksupport-disabled": { - isExpectedFailure: true, - oldPV: createTestVolModePV(&block), - newPV: createTestVolModePV(&block), - enableBlock: false, }, "invalid-update-volume-mode-nil-to-file": { isExpectedFailure: true, oldPV: createTestVolModePV(nil), newPV: createTestVolModePV(&file), - enableBlock: true, }, "invalid-update-volume-mode-nil-to-block": { isExpectedFailure: true, oldPV: createTestVolModePV(nil), newPV: createTestVolModePV(&block), - enableBlock: true, }, "invalid-update-volume-mode-file-to-nil": { isExpectedFailure: true, oldPV: createTestVolModePV(&file), newPV: createTestVolModePV(nil), - enableBlock: true, }, "invalid-update-volume-mode-block-to-nil": { isExpectedFailure: true, oldPV: createTestVolModePV(&block), newPV: createTestVolModePV(nil), - enableBlock: true, }, "invalid-update-volume-mode-nil-to-nil": { isExpectedFailure: false, oldPV: createTestVolModePV(nil), newPV: createTestVolModePV(nil), - enableBlock: true, }, "invalid-update-volume-mode-empty-to-mode": { isExpectedFailure: true, oldPV: createTestPV(), newPV: createTestVolModePV(&block), - enableBlock: true, }, } for name, scenario := range scenarios { t.Run(name, func(t *testing.T) { // ensure we have a resource version specified for updates - defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, scenario.enableBlock)() errs := ValidatePersistentVolumeUpdate(scenario.newPV, scenario.oldPV) if len(errs) == 0 && scenario.isExpectedFailure { t.Errorf("Unexpected success for scenario: %s", name) @@ -1503,8 +1425,9 @@ func TestValidatePersistentVolumeClaimUpdate(t *testing.T) { enableResize: false, enableBlock: true, }, - "invalid-update-blocksupport-disabled": { - isExpectedFailure: true, + // with the new validation changes this test should not fail + "noop-update-volumemode-allowed": { + isExpectedFailure: false, oldClaim: validClaimVolumeModeFile, newClaim: validClaimVolumeModeFile, enableResize: false, @@ -4055,20 +3978,12 @@ func TestAlphaLocalStorageCapacityIsolation(t *testing.T) { testCases := []core.VolumeSource{ {EmptyDir: &core.EmptyDirVolumeSource{SizeLimit: resource.NewQuantity(int64(5), resource.BinarySI)}}, } - // Enable feature LocalStorageCapacityIsolation - defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.LocalStorageCapacityIsolation, true)() + for _, tc := range testCases { if errs := validateVolumeSource(&tc, field.NewPath("spec"), "tmpvol"); len(errs) != 0 { t.Errorf("expected success: %v", errs) } } - // Disable feature LocalStorageCapacityIsolation - defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.LocalStorageCapacityIsolation, false)() - for _, tc := range testCases { - if errs := validateVolumeSource(&tc, field.NewPath("spec"), "tmpvol"); len(errs) == 0 { - t.Errorf("expected failure: %v", errs) - } - } containerLimitCase := core.ResourceRequirements{ Limits: core.ResourceList{ @@ -4077,17 +3992,9 @@ func TestAlphaLocalStorageCapacityIsolation(t *testing.T) { resource.BinarySI), }, } - // Enable feature LocalStorageCapacityIsolation - defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.LocalStorageCapacityIsolation, true)() if errs := ValidateResourceRequirements(&containerLimitCase, field.NewPath("resources")); len(errs) != 0 { t.Errorf("expected success: %v", errs) } - // Disable feature LocalStorageCapacityIsolation - defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.LocalStorageCapacityIsolation, false)() - if errs := ValidateResourceRequirements(&containerLimitCase, field.NewPath("resources")); len(errs) == 0 { - t.Errorf("expected failure: %v", errs) - } - } func TestValidateResourceQuotaWithAlphaLocalStorageCapacityIsolation(t *testing.T) { @@ -4118,24 +4025,9 @@ func TestValidateResourceQuotaWithAlphaLocalStorageCapacityIsolation(t *testing. Spec: spec, } - // Enable feature LocalStorageCapacityIsolation - defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.LocalStorageCapacityIsolation, true)() if errs := ValidateResourceQuota(resourceQuota); len(errs) != 0 { t.Errorf("expected success: %v", errs) } - - // Disable feature LocalStorageCapacityIsolation - defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.LocalStorageCapacityIsolation, false)() - errs := ValidateResourceQuota(resourceQuota) - if len(errs) == 0 { - t.Errorf("expected failure for %s", resourceQuota.Name) - } - expectedErrMes := "ResourceEphemeralStorage field disabled by feature-gate for ResourceQuota" - for i := range errs { - if !strings.Contains(errs[i].Detail, expectedErrMes) { - t.Errorf("[%s]: expected error detail either empty or %s, got %s", resourceQuota.Name, expectedErrMes, errs[i].Detail) - } - } } func TestValidatePorts(t *testing.T) { @@ -4258,21 +4150,11 @@ func TestLocalStorageEnvWithFeatureGate(t *testing.T) { }, }, } - // Enable feature LocalStorageCapacityIsolation - defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.LocalStorageCapacityIsolation, true)() for _, testCase := range testCases { if errs := validateEnvVarValueFrom(testCase, field.NewPath("field")); len(errs) != 0 { t.Errorf("expected success, got: %v", errs) } } - - // Disable feature LocalStorageCapacityIsolation - defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.LocalStorageCapacityIsolation, false)() - for _, testCase := range testCases { - if errs := validateEnvVarValueFrom(testCase, field.NewPath("field")); len(errs) == 0 { - t.Errorf("expected failure for %v", testCase.Name) - } - } } func TestValidateEnv(t *testing.T) { @@ -4931,7 +4813,7 @@ func TestValidateDisabledSubpath(t *testing.T) { SubPath: "baz", }, }, - true, + false, // validation should not fail, dropping the field is handled in PrepareForCreate/PrepareForUpdate }, } @@ -5079,10 +4961,6 @@ func TestAlphaValidateVolumeDevices(t *testing.T) { return } - disabledAlphaVolDevice := []core.VolumeDevice{ - {Name: "abc", DevicePath: "/foo"}, - } - successCase := []core.VolumeDevice{ {Name: "abc", DevicePath: "/foo"}, {Name: "abc-123", DevicePath: "/usr/share/test"}, @@ -5110,8 +4988,6 @@ func TestAlphaValidateVolumeDevices(t *testing.T) { {Name: "abc-123", MountPath: "/this/path/exists"}, } - // enable BlockVolume - defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, true)() // Success Cases: // Validate normal success cases - only PVC volumeSource if errs := ValidateVolumeDevices(successCase, GetVolumeMountMap(goodVolumeMounts), vols, field.NewPath("field")); len(errs) != 0 { @@ -5125,12 +5001,6 @@ func TestAlphaValidateVolumeDevices(t *testing.T) { t.Errorf("expected failure for %s", k) } } - - // disable BlockVolume - defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, false)() - if errs := ValidateVolumeDevices(disabledAlphaVolDevice, GetVolumeMountMap(goodVolumeMounts), vols, field.NewPath("field")); len(errs) == 0 { - t.Errorf("expected failure: %v", errs) - } } func TestValidateProbe(t *testing.T) { @@ -11120,24 +10990,12 @@ func TestValidateLimitRangeForLocalStorage(t *testing.T) { }, } - // Enable feature LocalStorageCapacityIsolation - defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.LocalStorageCapacityIsolation, true)() for _, testCase := range testCases { limitRange := &core.LimitRange{ObjectMeta: metav1.ObjectMeta{Name: testCase.name, Namespace: "foo"}, Spec: testCase.spec} if errs := ValidateLimitRange(limitRange); len(errs) != 0 { t.Errorf("Case %v, unexpected error: %v", testCase.name, errs) } } - - // Disable feature LocalStorageCapacityIsolation - defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.LocalStorageCapacityIsolation, false)() - for _, testCase := range testCases { - limitRange := &core.LimitRange{ObjectMeta: metav1.ObjectMeta{Name: testCase.name, Namespace: "foo"}, Spec: testCase.spec} - if errs := ValidateLimitRange(limitRange); len(errs) == 0 { - t.Errorf("Case %v, expected feature gate unable error but actually no error", testCase.name) - } - } - } func TestValidateLimitRange(t *testing.T) { diff --git a/pkg/apis/extensions/v1beta1/zz_generated.defaults.go b/pkg/apis/extensions/v1beta1/zz_generated.defaults.go index 0fa4c321c29..ce23c6b801c 100644 --- a/pkg/apis/extensions/v1beta1/zz_generated.defaults.go +++ b/pkg/apis/extensions/v1beta1/zz_generated.defaults.go @@ -138,6 +138,9 @@ func SetObjectDefaults_DaemonSet(in *v1beta1.DaemonSet) { } } } + if a.SecurityContext != nil { + v1.SetDefaults_SecurityContext(a.SecurityContext) + } } for i := range in.Spec.Template.Spec.Containers { a := &in.Spec.Template.Spec.Containers[i] @@ -180,6 +183,9 @@ func SetObjectDefaults_DaemonSet(in *v1beta1.DaemonSet) { } } } + if a.SecurityContext != nil { + v1.SetDefaults_SecurityContext(a.SecurityContext) + } } } @@ -285,6 +291,9 @@ func SetObjectDefaults_Deployment(in *v1beta1.Deployment) { } } } + if a.SecurityContext != nil { + v1.SetDefaults_SecurityContext(a.SecurityContext) + } } for i := range in.Spec.Template.Spec.Containers { a := &in.Spec.Template.Spec.Containers[i] @@ -327,6 +336,9 @@ func SetObjectDefaults_Deployment(in *v1beta1.Deployment) { } } } + if a.SecurityContext != nil { + v1.SetDefaults_SecurityContext(a.SecurityContext) + } } } @@ -454,6 +466,9 @@ func SetObjectDefaults_ReplicaSet(in *v1beta1.ReplicaSet) { } } } + if a.SecurityContext != nil { + v1.SetDefaults_SecurityContext(a.SecurityContext) + } } for i := range in.Spec.Template.Spec.Containers { a := &in.Spec.Template.Spec.Containers[i] @@ -496,6 +511,9 @@ func SetObjectDefaults_ReplicaSet(in *v1beta1.ReplicaSet) { } } } + if a.SecurityContext != nil { + v1.SetDefaults_SecurityContext(a.SecurityContext) + } } } diff --git a/pkg/apis/policy/validation/validation.go b/pkg/apis/policy/validation/validation.go index fa1af17afa7..18108e2e526 100644 --- a/pkg/apis/policy/validation/validation.go +++ b/pkg/apis/policy/validation/validation.go @@ -121,6 +121,7 @@ func ValidatePodSecurityPolicySpec(spec *policy.PodSecurityPolicySpec, fldPath * allErrs = append(allErrs, validatePSPCapsAgainstDrops(spec.RequiredDropCapabilities, spec.DefaultAddCapabilities, field.NewPath("defaultAddCapabilities"))...) allErrs = append(allErrs, validatePSPCapsAgainstDrops(spec.RequiredDropCapabilities, spec.AllowedCapabilities, field.NewPath("allowedCapabilities"))...) allErrs = append(allErrs, validatePSPDefaultAllowPrivilegeEscalation(fldPath.Child("defaultAllowPrivilegeEscalation"), spec.DefaultAllowPrivilegeEscalation, spec.AllowPrivilegeEscalation)...) + allErrs = append(allErrs, validatePSPAllowedProcMountTypes(fldPath.Child("allowedProcMountTypes"), spec.AllowedProcMountTypes)...) allErrs = append(allErrs, validatePSPAllowedHostPaths(fldPath.Child("allowedHostPaths"), spec.AllowedHostPaths)...) allErrs = append(allErrs, validatePSPAllowedFlexVolumes(fldPath.Child("allowedFlexVolumes"), spec.AllowedFlexVolumes)...) allErrs = append(allErrs, validatePodSecurityPolicySysctls(fldPath.Child("allowedUnsafeSysctls"), spec.AllowedUnsafeSysctls)...) @@ -328,6 +329,17 @@ func validatePSPDefaultAllowPrivilegeEscalation(fldPath *field.Path, defaultAllo return allErrs } +// validatePSPAllowedProcMountTypes validates the DefaultAllowPrivilegeEscalation field against the AllowPrivilegeEscalation field of a PodSecurityPolicy. +func validatePSPAllowedProcMountTypes(fldPath *field.Path, allowedProcMountTypes []core.ProcMountType) field.ErrorList { + allErrs := field.ErrorList{} + for i, procMountType := range allowedProcMountTypes { + if err := apivalidation.ValidateProcMountType(fldPath.Index(i), procMountType); err != nil { + allErrs = append(allErrs, err) + } + } + return allErrs +} + const sysctlPatternSegmentFmt string = "([a-z0-9][-_a-z0-9]*)?[a-z0-9*]" const SysctlPatternFmt string = "(" + apivalidation.SysctlSegmentFmt + "\\.)*" + sysctlPatternSegmentFmt diff --git a/pkg/apis/policy/validation/validation_test.go b/pkg/apis/policy/validation/validation_test.go index fea5d01fad9..aecd163afd5 100644 --- a/pkg/apis/policy/validation/validation_test.go +++ b/pkg/apis/policy/validation/validation_test.go @@ -384,6 +384,9 @@ func TestValidatePodSecurityPolicy(t *testing.T) { nonEmptyFlexVolumes := validPSP() nonEmptyFlexVolumes.Spec.AllowedFlexVolumes = []policy.AllowedFlexVolume{{Driver: "example/driver"}} + invalidProcMount := validPSP() + invalidProcMount.Spec.AllowedProcMountTypes = []api.ProcMountType{api.ProcMountType("bogus")} + type testCase struct { psp *policy.PodSecurityPolicy errorType field.ErrorType @@ -550,6 +553,11 @@ func TestValidatePodSecurityPolicy(t *testing.T) { errorType: field.ErrorTypeRequired, errorDetail: "must specify a driver", }, + "invalid allowedProcMountTypes": { + psp: invalidProcMount, + errorType: field.ErrorTypeNotSupported, + errorDetail: `supported values: "Default", "Unmasked"`, + }, } for k, v := range errorCases { @@ -643,6 +651,10 @@ func TestValidatePodSecurityPolicy(t *testing.T) { flexvolumeWhenAllVolumesAllowed.Spec.AllowedFlexVolumes = []policy.AllowedFlexVolume{ {Driver: "example/driver2"}, } + + validProcMount := validPSP() + validProcMount.Spec.AllowedProcMountTypes = []api.ProcMountType{api.DefaultProcMount, api.UnmaskedProcMount} + successCases := map[string]struct { psp *policy.PodSecurityPolicy }{ @@ -682,6 +694,9 @@ func TestValidatePodSecurityPolicy(t *testing.T) { "allow white-listed flexVolume when all volumes are allowed": { psp: flexvolumeWhenAllVolumesAllowed, }, + "valid allowedProcMountTypes": { + psp: validProcMount, + }, } for k, v := range successCases { diff --git a/pkg/apis/storage/util/BUILD b/pkg/apis/storage/util/BUILD index 1b37c7f631d..c8d8964d98a 100644 --- a/pkg/apis/storage/util/BUILD +++ b/pkg/apis/storage/util/BUILD @@ -39,9 +39,9 @@ go_test( srcs = ["util_test.go"], embed = [":go_default_library"], deps = [ - "//pkg/apis/core:go_default_library", "//pkg/apis/storage:go_default_library", "//pkg/features:go_default_library", + "//staging/src/k8s.io/apimachinery/pkg/util/diff:go_default_library", "//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library", "//staging/src/k8s.io/apiserver/pkg/util/feature/testing:go_default_library", ], diff --git a/pkg/apis/storage/util/util.go b/pkg/apis/storage/util/util.go index 382802d9641..135c548125d 100644 --- a/pkg/apis/storage/util/util.go +++ b/pkg/apis/storage/util/util.go @@ -22,10 +22,19 @@ import ( "k8s.io/kubernetes/pkg/features" ) -// DropDisabledAlphaFields removes disabled fields from the StorageClass object. -func DropDisabledAlphaFields(class *storage.StorageClass) { - if !utilfeature.DefaultFeatureGate.Enabled(features.VolumeScheduling) { - class.VolumeBindingMode = nil - class.AllowedTopologies = nil +// DropDisabledFields removes disabled fields from the StorageClass object. +func DropDisabledFields(class, oldClass *storage.StorageClass) { + if !utilfeature.DefaultFeatureGate.Enabled(features.ExpandPersistentVolumes) && !allowVolumeExpansionInUse(oldClass) { + class.AllowVolumeExpansion = nil } } + +func allowVolumeExpansionInUse(oldClass *storage.StorageClass) bool { + if oldClass == nil { + return false + } + if oldClass.AllowVolumeExpansion != nil { + return true + } + return false +} diff --git a/pkg/apis/storage/util/util_test.go b/pkg/apis/storage/util/util_test.go index d2cf1402105..564d7b3a244 100644 --- a/pkg/apis/storage/util/util_test.go +++ b/pkg/apis/storage/util/util_test.go @@ -17,54 +17,92 @@ limitations under the License. package util import ( + "fmt" "reflect" "testing" + "k8s.io/apimachinery/pkg/util/diff" utilfeature "k8s.io/apiserver/pkg/util/feature" utilfeaturetesting "k8s.io/apiserver/pkg/util/feature/testing" - api "k8s.io/kubernetes/pkg/apis/core" "k8s.io/kubernetes/pkg/apis/storage" "k8s.io/kubernetes/pkg/features" ) -func TestDropAlphaFields(t *testing.T) { - bindingMode := storage.VolumeBindingWaitForFirstConsumer - allowedTopologies := []api.TopologySelectorTerm{ +func TestDropAllowVolumeExpansion(t *testing.T) { + allowVolumeExpansion := false + scWithoutAllowVolumeExpansion := func() *storage.StorageClass { + return &storage.StorageClass{} + } + scWithAllowVolumeExpansion := func() *storage.StorageClass { + return &storage.StorageClass{ + AllowVolumeExpansion: &allowVolumeExpansion, + } + } + + scInfo := []struct { + description string + hasAllowVolumeExpansion bool + sc func() *storage.StorageClass + }{ { - MatchLabelExpressions: []api.TopologySelectorLabelRequirement{ - { - Key: "kubernetes.io/hostname", - Values: []string{"node1"}, - }, - }, + description: "StorageClass Without AllowVolumeExpansion", + hasAllowVolumeExpansion: false, + sc: scWithoutAllowVolumeExpansion, + }, + { + description: "StorageClass With AllowVolumeExpansion", + hasAllowVolumeExpansion: true, + sc: scWithAllowVolumeExpansion, + }, + { + description: "is nil", + hasAllowVolumeExpansion: false, + sc: func() *storage.StorageClass { return nil }, }, } - // Test that field gets dropped when feature gate is not set - defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.VolumeScheduling, false)() - class := &storage.StorageClass{ - VolumeBindingMode: &bindingMode, - AllowedTopologies: allowedTopologies, - } - DropDisabledAlphaFields(class) - if class.VolumeBindingMode != nil { - t.Errorf("VolumeBindingMode field didn't get dropped: %+v", class.VolumeBindingMode) - } - if class.AllowedTopologies != nil { - t.Errorf("AllowedTopologies field didn't get dropped: %+v", class.AllowedTopologies) - } + for _, enabled := range []bool{true, false} { + for _, oldStorageClassInfo := range scInfo { + for _, newStorageClassInfo := range scInfo { + oldStorageClassHasAllowVolumeExpansion, oldStorageClass := oldStorageClassInfo.hasAllowVolumeExpansion, oldStorageClassInfo.sc() + newStorageClassHasAllowVolumeExpansion, newStorageClass := newStorageClassInfo.hasAllowVolumeExpansion, newStorageClassInfo.sc() + if newStorageClass == nil { + continue + } - // Test that field does not get dropped when feature gate is set - class = &storage.StorageClass{ - VolumeBindingMode: &bindingMode, - AllowedTopologies: allowedTopologies, - } - defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.VolumeScheduling, true)() - DropDisabledAlphaFields(class) - if class.VolumeBindingMode != &bindingMode { - t.Errorf("VolumeBindingMode field got unexpectantly modified: %+v", class.VolumeBindingMode) - } - if !reflect.DeepEqual(class.AllowedTopologies, allowedTopologies) { - t.Errorf("AllowedTopologies field got unexpectantly modified: %+v", class.AllowedTopologies) + t.Run(fmt.Sprintf("feature enabled=%v, old StorageClass %v, new StorageClass %v", enabled, oldStorageClassInfo.description, newStorageClassInfo.description), func(t *testing.T) { + defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ExpandPersistentVolumes, enabled)() + + DropDisabledFields(newStorageClass, oldStorageClass) + + // old StorageClass should never be changed + if !reflect.DeepEqual(oldStorageClass, oldStorageClassInfo.sc()) { + t.Errorf("old StorageClass changed: %v", diff.ObjectReflectDiff(oldStorageClass, oldStorageClassInfo.sc())) + } + + switch { + case enabled || oldStorageClassHasAllowVolumeExpansion: + // new StorageClass should not be changed if the feature is enabled, or if the old StorageClass had AllowVolumeExpansion + if !reflect.DeepEqual(newStorageClass, newStorageClassInfo.sc()) { + t.Errorf("new StorageClass changed: %v", diff.ObjectReflectDiff(newStorageClass, newStorageClassInfo.sc())) + } + case newStorageClassHasAllowVolumeExpansion: + // new StorageClass should be changed + if reflect.DeepEqual(newStorageClass, newStorageClassInfo.sc()) { + t.Errorf("new StorageClass was not changed") + } + // new StorageClass should not have AllowVolumeExpansion + if !reflect.DeepEqual(newStorageClass, scWithoutAllowVolumeExpansion()) { + t.Errorf("new StorageClass had StorageClassAllowVolumeExpansion: %v", diff.ObjectReflectDiff(newStorageClass, scWithoutAllowVolumeExpansion())) + } + default: + // new StorageClass should not need to be changed + if !reflect.DeepEqual(newStorageClass, newStorageClassInfo.sc()) { + t.Errorf("new StorageClass changed: %v", diff.ObjectReflectDiff(newStorageClass, newStorageClassInfo.sc())) + } + } + }) + } + } } } diff --git a/pkg/apis/storage/v1/BUILD b/pkg/apis/storage/v1/BUILD index 05bd5565a79..622bbecf28d 100644 --- a/pkg/apis/storage/v1/BUILD +++ b/pkg/apis/storage/v1/BUILD @@ -19,13 +19,11 @@ go_library( deps = [ "//pkg/apis/core:go_default_library", "//pkg/apis/storage:go_default_library", - "//pkg/features:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library", "//staging/src/k8s.io/api/storage/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/conversion:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", - "//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library", ], ) @@ -52,10 +50,7 @@ go_test( deps = [ "//pkg/api/legacyscheme:go_default_library", "//pkg/apis/storage/install:go_default_library", - "//pkg/features:go_default_library", "//staging/src/k8s.io/api/storage/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library", - "//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library", - "//staging/src/k8s.io/apiserver/pkg/util/feature/testing:go_default_library", ], ) diff --git a/pkg/apis/storage/v1/defaults.go b/pkg/apis/storage/v1/defaults.go index 6f574f4867c..e50475a8000 100644 --- a/pkg/apis/storage/v1/defaults.go +++ b/pkg/apis/storage/v1/defaults.go @@ -20,8 +20,6 @@ import ( "k8s.io/api/core/v1" storagev1 "k8s.io/api/storage/v1" "k8s.io/apimachinery/pkg/runtime" - utilfeature "k8s.io/apiserver/pkg/util/feature" - "k8s.io/kubernetes/pkg/features" ) func addDefaultingFuncs(scheme *runtime.Scheme) error { @@ -34,7 +32,7 @@ func SetDefaults_StorageClass(obj *storagev1.StorageClass) { *obj.ReclaimPolicy = v1.PersistentVolumeReclaimDelete } - if obj.VolumeBindingMode == nil && utilfeature.DefaultFeatureGate.Enabled(features.VolumeScheduling) { + if obj.VolumeBindingMode == nil { obj.VolumeBindingMode = new(storagev1.VolumeBindingMode) *obj.VolumeBindingMode = storagev1.VolumeBindingImmediate } diff --git a/pkg/apis/storage/v1/defaults_test.go b/pkg/apis/storage/v1/defaults_test.go index 82ea60f0bd1..48a45a27199 100644 --- a/pkg/apis/storage/v1/defaults_test.go +++ b/pkg/apis/storage/v1/defaults_test.go @@ -22,11 +22,8 @@ import ( storagev1 "k8s.io/api/storage/v1" "k8s.io/apimachinery/pkg/runtime" - utilfeature "k8s.io/apiserver/pkg/util/feature" - utilfeaturetesting "k8s.io/apiserver/pkg/util/feature/testing" "k8s.io/kubernetes/pkg/api/legacyscheme" _ "k8s.io/kubernetes/pkg/apis/storage/install" - "k8s.io/kubernetes/pkg/features" ) func roundTrip(t *testing.T, obj runtime.Object) runtime.Object { @@ -53,7 +50,7 @@ func roundTrip(t *testing.T, obj runtime.Object) runtime.Object { func TestSetDefaultVolumeBindingMode(t *testing.T) { class := &storagev1.StorageClass{} - // When feature gate is enabled, field should be defaulted + // field should be defaulted defaultMode := storagev1.VolumeBindingImmediate output := roundTrip(t, runtime.Object(class)).(*storagev1.StorageClass) outMode := output.VolumeBindingMode @@ -62,13 +59,4 @@ func TestSetDefaultVolumeBindingMode(t *testing.T) { } else if *outMode != defaultMode { t.Errorf("Expected VolumeBindingMode to be defaulted to: %+v, got: %+v", defaultMode, outMode) } - - class = &storagev1.StorageClass{} - - // When feature gate is disabled, field should not be defaulted - defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.VolumeScheduling, false)() - output = roundTrip(t, runtime.Object(class)).(*storagev1.StorageClass) - if output.VolumeBindingMode != nil { - t.Errorf("Expected VolumeBindingMode to not be defaulted, got: %+v", output.VolumeBindingMode) - } } diff --git a/pkg/apis/storage/v1beta1/BUILD b/pkg/apis/storage/v1beta1/BUILD index 7be33870151..65c7b40975f 100644 --- a/pkg/apis/storage/v1beta1/BUILD +++ b/pkg/apis/storage/v1beta1/BUILD @@ -19,13 +19,11 @@ go_library( deps = [ "//pkg/apis/core:go_default_library", "//pkg/apis/storage:go_default_library", - "//pkg/features:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library", "//staging/src/k8s.io/api/storage/v1beta1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/conversion:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", - "//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library", ], ) @@ -52,10 +50,7 @@ go_test( deps = [ "//pkg/api/legacyscheme:go_default_library", "//pkg/apis/storage/install:go_default_library", - "//pkg/features:go_default_library", "//staging/src/k8s.io/api/storage/v1beta1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library", - "//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library", - "//staging/src/k8s.io/apiserver/pkg/util/feature/testing:go_default_library", ], ) diff --git a/pkg/apis/storage/v1beta1/defaults.go b/pkg/apis/storage/v1beta1/defaults.go index 97dbff2f378..f2db7d84bfe 100644 --- a/pkg/apis/storage/v1beta1/defaults.go +++ b/pkg/apis/storage/v1beta1/defaults.go @@ -20,8 +20,6 @@ import ( "k8s.io/api/core/v1" storagev1beta1 "k8s.io/api/storage/v1beta1" "k8s.io/apimachinery/pkg/runtime" - utilfeature "k8s.io/apiserver/pkg/util/feature" - "k8s.io/kubernetes/pkg/features" ) func addDefaultingFuncs(scheme *runtime.Scheme) error { @@ -34,7 +32,7 @@ func SetDefaults_StorageClass(obj *storagev1beta1.StorageClass) { *obj.ReclaimPolicy = v1.PersistentVolumeReclaimDelete } - if obj.VolumeBindingMode == nil && utilfeature.DefaultFeatureGate.Enabled(features.VolumeScheduling) { + if obj.VolumeBindingMode == nil { obj.VolumeBindingMode = new(storagev1beta1.VolumeBindingMode) *obj.VolumeBindingMode = storagev1beta1.VolumeBindingImmediate } diff --git a/pkg/apis/storage/v1beta1/defaults_test.go b/pkg/apis/storage/v1beta1/defaults_test.go index 2e1086dad89..d920c5c7f95 100644 --- a/pkg/apis/storage/v1beta1/defaults_test.go +++ b/pkg/apis/storage/v1beta1/defaults_test.go @@ -22,11 +22,8 @@ import ( storagev1beta1 "k8s.io/api/storage/v1beta1" "k8s.io/apimachinery/pkg/runtime" - utilfeature "k8s.io/apiserver/pkg/util/feature" - utilfeaturetesting "k8s.io/apiserver/pkg/util/feature/testing" "k8s.io/kubernetes/pkg/api/legacyscheme" _ "k8s.io/kubernetes/pkg/apis/storage/install" - "k8s.io/kubernetes/pkg/features" ) func roundTrip(t *testing.T, obj runtime.Object) runtime.Object { @@ -53,7 +50,7 @@ func roundTrip(t *testing.T, obj runtime.Object) runtime.Object { func TestSetDefaultVolumeBindingMode(t *testing.T) { class := &storagev1beta1.StorageClass{} - // When feature gate is enabled, field should be defaulted + // field should be defaulted defaultMode := storagev1beta1.VolumeBindingImmediate output := roundTrip(t, runtime.Object(class)).(*storagev1beta1.StorageClass) outMode := output.VolumeBindingMode @@ -62,14 +59,4 @@ func TestSetDefaultVolumeBindingMode(t *testing.T) { } else if *outMode != defaultMode { t.Errorf("Expected VolumeBindingMode to be defaulted to: %+v, got: %+v", defaultMode, outMode) } - - class = &storagev1beta1.StorageClass{} - - // When feature gate is disabled, field should not be defaulted - defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.VolumeScheduling, false)() - output = roundTrip(t, runtime.Object(class)).(*storagev1beta1.StorageClass) - if output.VolumeBindingMode != nil { - t.Errorf("Expected VolumeBindingMode to not be defaulted, got: %+v", output.VolumeBindingMode) - } - } diff --git a/pkg/apis/storage/validation/BUILD b/pkg/apis/storage/validation/BUILD index a91f11d93e1..8051af18fbb 100644 --- a/pkg/apis/storage/validation/BUILD +++ b/pkg/apis/storage/validation/BUILD @@ -15,12 +15,10 @@ go_library( "//pkg/apis/core/helper:go_default_library", "//pkg/apis/core/validation:go_default_library", "//pkg/apis/storage:go_default_library", - "//pkg/features:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/equality:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/validation:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/validation/field:go_default_library", - "//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library", ], ) @@ -31,10 +29,7 @@ go_test( deps = [ "//pkg/apis/core:go_default_library", "//pkg/apis/storage:go_default_library", - "//pkg/features:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library", - "//staging/src/k8s.io/apiserver/pkg/util/feature/testing:go_default_library", ], ) diff --git a/pkg/apis/storage/validation/validation.go b/pkg/apis/storage/validation/validation.go index 48d9ecde476..db974939546 100644 --- a/pkg/apis/storage/validation/validation.go +++ b/pkg/apis/storage/validation/validation.go @@ -24,12 +24,10 @@ import ( "k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/validation" "k8s.io/apimachinery/pkg/util/validation/field" - utilfeature "k8s.io/apiserver/pkg/util/feature" api "k8s.io/kubernetes/pkg/apis/core" "k8s.io/kubernetes/pkg/apis/core/helper" apivalidation "k8s.io/kubernetes/pkg/apis/core/validation" "k8s.io/kubernetes/pkg/apis/storage" - "k8s.io/kubernetes/pkg/features" ) const ( @@ -46,7 +44,6 @@ func ValidateStorageClass(storageClass *storage.StorageClass) field.ErrorList { allErrs = append(allErrs, validateProvisioner(storageClass.Provisioner, field.NewPath("provisioner"))...) allErrs = append(allErrs, validateParameters(storageClass.Parameters, field.NewPath("parameters"))...) allErrs = append(allErrs, validateReclaimPolicy(storageClass.ReclaimPolicy, field.NewPath("reclaimPolicy"))...) - allErrs = append(allErrs, validateAllowVolumeExpansion(storageClass.AllowVolumeExpansion, field.NewPath("allowVolumeExpansion"))...) allErrs = append(allErrs, validateVolumeBindingMode(storageClass.VolumeBindingMode, field.NewPath("volumeBindingMode"))...) allErrs = append(allErrs, validateAllowedTopologies(storageClass.AllowedTopologies, field.NewPath("allowedTopologies"))...) @@ -123,16 +120,6 @@ func validateReclaimPolicy(reclaimPolicy *api.PersistentVolumeReclaimPolicy, fld return allErrs } -// validateAllowVolumeExpansion tests that if ExpandPersistentVolumes feature gate is disabled, whether the AllowVolumeExpansion filed -// of storage class is set -func validateAllowVolumeExpansion(allowExpand *bool, fldPath *field.Path) field.ErrorList { - allErrs := field.ErrorList{} - if allowExpand != nil && !utilfeature.DefaultFeatureGate.Enabled(features.ExpandPersistentVolumes) { - allErrs = append(allErrs, field.Forbidden(fldPath, "field is disabled by feature-gate ExpandPersistentVolumes")) - } - return allErrs -} - // ValidateVolumeAttachment validates a VolumeAttachment. This function is common for v1 and v1beta1 objects, func ValidateVolumeAttachment(volumeAttachment *storage.VolumeAttachment) field.ErrorList { allErrs := apivalidation.ValidateObjectMeta(&volumeAttachment.ObjectMeta, false, apivalidation.ValidateClassName, field.NewPath("metadata")) @@ -244,14 +231,10 @@ var supportedVolumeBindingModes = sets.NewString(string(storage.VolumeBindingImm // validateVolumeBindingMode tests that VolumeBindingMode specifies valid values. func validateVolumeBindingMode(mode *storage.VolumeBindingMode, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} - if utilfeature.DefaultFeatureGate.Enabled(features.VolumeScheduling) { - if mode == nil { - allErrs = append(allErrs, field.Required(fldPath, "")) - } else if !supportedVolumeBindingModes.Has(string(*mode)) { - allErrs = append(allErrs, field.NotSupported(fldPath, mode, supportedVolumeBindingModes.List())) - } - } else if mode != nil { - allErrs = append(allErrs, field.Forbidden(fldPath, "field is disabled by feature-gate VolumeScheduling")) + if mode == nil { + allErrs = append(allErrs, field.Required(fldPath, "")) + } else if !supportedVolumeBindingModes.Has(string(*mode)) { + allErrs = append(allErrs, field.NotSupported(fldPath, mode, supportedVolumeBindingModes.List())) } return allErrs @@ -265,10 +248,6 @@ func validateAllowedTopologies(topologies []api.TopologySelectorTerm, fldPath *f return allErrs } - if !utilfeature.DefaultFeatureGate.Enabled(features.VolumeScheduling) { - allErrs = append(allErrs, field.Forbidden(fldPath, "field is disabled by feature-gate VolumeScheduling")) - } - rawTopologies := make([]map[string]sets.String, len(topologies)) for i, term := range topologies { idxPath := fldPath.Index(i) diff --git a/pkg/apis/storage/validation/validation_test.go b/pkg/apis/storage/validation/validation_test.go index d9940300c98..f5b20041314 100644 --- a/pkg/apis/storage/validation/validation_test.go +++ b/pkg/apis/storage/validation/validation_test.go @@ -22,11 +22,8 @@ import ( "testing" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - utilfeature "k8s.io/apiserver/pkg/util/feature" - utilfeaturetesting "k8s.io/apiserver/pkg/util/feature/testing" api "k8s.io/kubernetes/pkg/apis/core" "k8s.io/kubernetes/pkg/apis/storage" - "k8s.io/kubernetes/pkg/features" ) var ( @@ -140,32 +137,6 @@ func TestValidateStorageClass(t *testing.T) { } } -func TestAlphaExpandPersistentVolumesFeatureValidation(t *testing.T) { - deleteReclaimPolicy := api.PersistentVolumeReclaimPolicy("Delete") - falseVar := false - testSC := &storage.StorageClass{ - // empty parameters - ObjectMeta: metav1.ObjectMeta{Name: "foo"}, - Provisioner: "kubernetes.io/foo-provisioner", - Parameters: map[string]string{}, - ReclaimPolicy: &deleteReclaimPolicy, - AllowVolumeExpansion: &falseVar, - VolumeBindingMode: &immediateMode1, - } - - // Enable feature ExpandPersistentVolumes - defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ExpandPersistentVolumes, true)() - if errs := ValidateStorageClass(testSC); len(errs) != 0 { - t.Errorf("expected success: %v", errs) - } - // Disable feature ExpandPersistentVolumes - defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ExpandPersistentVolumes, false)() - if errs := ValidateStorageClass(testSC); len(errs) == 0 { - t.Errorf("expected failure, but got no error") - } - -} - func TestVolumeAttachmentValidation(t *testing.T) { volumeName := "pv-name" empty := "" @@ -506,22 +477,6 @@ func makeClass(mode *storage.VolumeBindingMode, topologies []api.TopologySelecto } } -// TODO: Remove these tests once feature gate is not required -func TestValidateVolumeBindingModeAlphaDisabled(t *testing.T) { - errorCases := map[string]*storage.StorageClass{ - "immediate mode": makeClass(&immediateMode1, nil), - "waiting mode": makeClass(&waitingMode, nil), - "invalid mode": makeClass(&invalidMode, nil), - } - - defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.VolumeScheduling, false)() - for testName, storageClass := range errorCases { - if errs := ValidateStorageClass(storageClass); len(errs) == 0 { - t.Errorf("Expected failure for test: %v", testName) - } - } -} - type bindingTest struct { class *storage.StorageClass shouldSucceed bool @@ -547,8 +502,6 @@ func TestValidateVolumeBindingMode(t *testing.T) { }, } - // TODO: remove when feature gate not required - defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.VolumeScheduling, true)() for testName, testCase := range cases { errs := ValidateStorageClass(testCase.class) if testCase.shouldSucceed && len(errs) != 0 { @@ -605,8 +558,6 @@ func TestValidateUpdateVolumeBindingMode(t *testing.T) { }, } - // TODO: remove when feature gate not required - defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.VolumeScheduling, true)() for testName, testCase := range cases { errs := ValidateStorageClassUpdate(testCase.newClass, testCase.oldClass) if testCase.shouldSucceed && len(errs) != 0 { @@ -909,7 +860,6 @@ func TestValidateAllowedTopologies(t *testing.T) { }, } - defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.VolumeScheduling, true)() for testName, testCase := range cases { errs := ValidateStorageClass(testCase.class) if testCase.shouldSucceed && len(errs) != 0 { @@ -919,12 +869,4 @@ func TestValidateAllowedTopologies(t *testing.T) { t.Errorf("Expected failure for test %q, got success", testName) } } - - defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.VolumeScheduling, false)() - for testName, testCase := range cases { - errs := ValidateStorageClass(testCase.class) - if len(errs) == 0 && testCase.class.AllowedTopologies != nil { - t.Errorf("Expected failure for test %q, got success", testName) - } - } } diff --git a/pkg/client/clientset_generated/internalclientset/typed/policy/internalversion/fake/fake_eviction_expansion.go b/pkg/client/clientset_generated/internalclientset/typed/policy/internalversion/fake/fake_eviction_expansion.go index fae6df35061..a4d721876d4 100644 --- a/pkg/client/clientset_generated/internalclientset/typed/policy/internalversion/fake/fake_eviction_expansion.go +++ b/pkg/client/clientset_generated/internalclientset/typed/policy/internalversion/fake/fake_eviction_expansion.go @@ -23,11 +23,13 @@ import ( ) func (c *FakeEvictions) Evict(eviction *policy.Eviction) error { - action := core.GetActionImpl{} - action.Verb = "post" + action := core.CreateActionImpl{} + action.Verb = "create" action.Namespace = c.ns action.Resource = schema.GroupVersionResource{Group: "", Version: "", Resource: "pods"} action.Subresource = "eviction" + action.Object = eviction + _, err := c.Fake.Invokes(action, eviction) return err } diff --git a/pkg/cloudprovider/OWNERS b/pkg/cloudprovider/OWNERS index 314eb3d97ae..1603c1de30c 100644 --- a/pkg/cloudprovider/OWNERS +++ b/pkg/cloudprovider/OWNERS @@ -3,6 +3,7 @@ approvers: - dims - wlan0 - andrewsykim +- cheftako reviewers: - thockin - lavalamp diff --git a/pkg/cloudprovider/providers/aws/BUILD b/pkg/cloudprovider/providers/aws/BUILD index 755d731a0fe..35b7d5480bf 100644 --- a/pkg/cloudprovider/providers/aws/BUILD +++ b/pkg/cloudprovider/providers/aws/BUILD @@ -31,6 +31,7 @@ go_library( "//pkg/controller:go_default_library", "//pkg/credentialprovider/aws:go_default_library", "//pkg/kubelet/apis:go_default_library", + "//pkg/version:go_default_library", "//pkg/volume:go_default_library", "//pkg/volume/util:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library", diff --git a/pkg/cloudprovider/providers/aws/aws.go b/pkg/cloudprovider/providers/aws/aws.go index 1ac3334e714..74d1a89202f 100644 --- a/pkg/cloudprovider/providers/aws/aws.go +++ b/pkg/cloudprovider/providers/aws/aws.go @@ -59,6 +59,7 @@ import ( "k8s.io/kubernetes/pkg/api/v1/service" "k8s.io/kubernetes/pkg/controller" kubeletapis "k8s.io/kubernetes/pkg/kubelet/apis" + "k8s.io/kubernetes/pkg/version" "k8s.io/kubernetes/pkg/volume" volumeutil "k8s.io/kubernetes/pkg/volume/util" ) @@ -261,9 +262,6 @@ const DefaultVolumeType = "gp2" // Used to call recognizeWellKnownRegions just once var once sync.Once -// AWS implements PVLabeler. -var _ cloudprovider.PVLabeler = (*Cloud)(nil) - // Services is an abstraction over AWS, to allow mocking/other implementations type Services interface { Compute(region string) (EC2, error) @@ -480,6 +478,13 @@ type InstanceGroupInfo interface { CurrentSize() (int, error) } +var _ cloudprovider.Interface = (*Cloud)(nil) +var _ cloudprovider.Instances = (*Cloud)(nil) +var _ cloudprovider.LoadBalancer = (*Cloud)(nil) +var _ cloudprovider.Routes = (*Cloud)(nil) +var _ cloudprovider.Zones = (*Cloud)(nil) +var _ cloudprovider.PVLabeler = (*Cloud)(nil) + // Cloud is an implementation of Interface, LoadBalancer and Instances for Amazon Web Services. type Cloud struct { ec2 EC2 @@ -588,6 +593,11 @@ func newAWSSDKProvider(creds *credentials.Credentials) *awsSDKProvider { } func (p *awsSDKProvider) addHandlers(regionName string, h *request.Handlers) { + h.Build.PushFrontNamed(request.NamedHandler{ + Name: "k8s/user-agent", + Fn: request.MakeAddToUserAgentHandler("kubernetes", version.Get().String()), + }) + h.Sign.PushFrontNamed(request.NamedHandler{ Name: "k8s/logger", Fn: awsHandlerLogger, diff --git a/pkg/cloudprovider/providers/aws/aws_loadbalancer.go b/pkg/cloudprovider/providers/aws/aws_loadbalancer.go index 3242a057bc3..351088312b8 100644 --- a/pkg/cloudprovider/providers/aws/aws_loadbalancer.go +++ b/pkg/cloudprovider/providers/aws/aws_loadbalancer.go @@ -313,6 +313,64 @@ func (c *Cloud) ensureLoadBalancerv2(namespacedName types.NamespacedName, loadBa } } + desiredLoadBalancerAttributes := map[string]string{} + // Default values to ensured a remove annotation reverts back to the default + desiredLoadBalancerAttributes["load_balancing.cross_zone.enabled"] = "false" + + // Determine if cross zone load balancing enabled/disabled has been specified + crossZoneLoadBalancingEnabledAnnotation := annotations[ServiceAnnotationLoadBalancerCrossZoneLoadBalancingEnabled] + if crossZoneLoadBalancingEnabledAnnotation != "" { + crossZoneEnabled, err := strconv.ParseBool(crossZoneLoadBalancingEnabledAnnotation) + if err != nil { + return nil, fmt.Errorf("error parsing service annotation: %s=%s", + ServiceAnnotationLoadBalancerCrossZoneLoadBalancingEnabled, + crossZoneLoadBalancingEnabledAnnotation, + ) + } + + if crossZoneEnabled { + desiredLoadBalancerAttributes["load_balancing.cross_zone.enabled"] = "true" + } + } + + // Whether the ELB was new or existing, sync attributes regardless. This accounts for things + // that cannot be specified at the time of creation and can only be modified after the fact, + // e.g. idle connection timeout. + describeAttributesRequest := &elbv2.DescribeLoadBalancerAttributesInput{ + LoadBalancerArn: loadBalancer.LoadBalancerArn, + } + describeAttributesOutput, err := c.elbv2.DescribeLoadBalancerAttributes(describeAttributesRequest) + if err != nil { + return nil, fmt.Errorf("Unable to retrieve load balancer attributes during attribute sync: %q", err) + } + + changedAttributes := []*elbv2.LoadBalancerAttribute{} + + // Identify to be changed attributes + for _, foundAttribute := range describeAttributesOutput.Attributes { + if targetValue, ok := desiredLoadBalancerAttributes[*foundAttribute.Key]; ok { + if targetValue != *foundAttribute.Value { + changedAttributes = append(changedAttributes, &elbv2.LoadBalancerAttribute{ + Key: foundAttribute.Key, + Value: aws.String(targetValue), + }) + } + } + } + + // Update attributes requiring changes + if len(changedAttributes) > 0 { + klog.V(2).Infof("Updating load-balancer attributes for %q", loadBalancerName) + + _, err = c.elbv2.ModifyLoadBalancerAttributes(&elbv2.ModifyLoadBalancerAttributesInput{ + LoadBalancerArn: loadBalancer.LoadBalancerArn, + Attributes: changedAttributes, + }) + if err != nil { + return nil, fmt.Errorf("Unable to update load balancer attributes during attribute sync: %q", err) + } + } + // Subnets cannot be modified on NLBs if dirty { loadBalancers, err := c.elbv2.DescribeLoadBalancers( diff --git a/pkg/cloudprovider/providers/azure/azure.go b/pkg/cloudprovider/providers/azure/azure.go index e2205c37fbe..203f7d8534c 100644 --- a/pkg/cloudprovider/providers/azure/azure.go +++ b/pkg/cloudprovider/providers/azure/azure.go @@ -47,18 +47,22 @@ import ( const ( // CloudProviderName is the value used for the --cloud-provider flag - CloudProviderName = "azure" - rateLimitQPSDefault = 1.0 - rateLimitBucketDefault = 5 - backoffRetriesDefault = 6 - backoffExponentDefault = 1.5 - backoffDurationDefault = 5 // in seconds - backoffJitterDefault = 1.0 - maximumLoadBalancerRuleCount = 148 // According to Azure LB rule default limit + CloudProviderName = "azure" + rateLimitQPSDefault = 1.0 + rateLimitBucketDefault = 5 + backoffRetriesDefault = 6 + backoffExponentDefault = 1.5 + backoffDurationDefault = 5 // in seconds + backoffJitterDefault = 1.0 + // According to https://docs.microsoft.com/en-us/azure/azure-subscription-service-limits#load-balancer. + maximumLoadBalancerRuleCount = 250 vmTypeVMSS = "vmss" vmTypeStandard = "standard" + backoffModeDefault = "default" + backoffModeV2 = "v2" + loadBalancerSkuBasic = "basic" loadBalancerSkuStandard = "standard" @@ -71,9 +75,6 @@ var ( defaultExcludeMasterFromStandardLB = true ) -// Azure implements PVLabeler. -var _ cloudprovider.PVLabeler = (*Cloud)(nil) - // Config holds the configuration parsed from the --cloud-config flag // All fields are required unless otherwise specified type Config struct { @@ -118,6 +119,12 @@ type Config struct { CloudProviderBackoffDuration int `json:"cloudProviderBackoffDuration" yaml:"cloudProviderBackoffDuration"` // Backoff jitter CloudProviderBackoffJitter float64 `json:"cloudProviderBackoffJitter" yaml:"cloudProviderBackoffJitter"` + // Backoff mode, options are v2 and default. + // * default means two-layer backoff retrying, one in the cloud provider and the other in the Azure SDK. + // * v2 means only backoff in the Azure SDK is used. In such mode, CloudProviderBackoffDuration and + // CloudProviderBackoffJitter are omitted. + // "default" will be used if not specified. + CloudProviderBackoffMode string `json:"cloudProviderBackoffMode" yaml:"cloudProviderBackoffMode"` // Enable rate limiting CloudProviderRateLimit bool `json:"cloudProviderRateLimit" yaml:"cloudProviderRateLimit"` // Rate limit QPS (Read) @@ -143,6 +150,13 @@ type Config struct { MaximumLoadBalancerRuleCount int `json:"maximumLoadBalancerRuleCount" yaml:"maximumLoadBalancerRuleCount"` } +var _ cloudprovider.Interface = (*Cloud)(nil) +var _ cloudprovider.Instances = (*Cloud)(nil) +var _ cloudprovider.LoadBalancer = (*Cloud)(nil) +var _ cloudprovider.Routes = (*Cloud)(nil) +var _ cloudprovider.Zones = (*Cloud)(nil) +var _ cloudprovider.PVLabeler = (*Cloud)(nil) + // Cloud holds the config and clients type Cloud struct { Config @@ -264,25 +278,71 @@ func NewCloud(configReader io.Reader) (cloudprovider.Interface, error) { config.CloudProviderRateLimitBucketWrite) } + // Conditionally configure resource request backoff + resourceRequestBackoff := wait.Backoff{ + Steps: 1, + } + if config.CloudProviderBackoff { + // Assign backoff defaults if no configuration was passed in + if config.CloudProviderBackoffRetries == 0 { + config.CloudProviderBackoffRetries = backoffRetriesDefault + } + if config.CloudProviderBackoffDuration == 0 { + config.CloudProviderBackoffDuration = backoffDurationDefault + } + if config.CloudProviderBackoffExponent == 0 { + config.CloudProviderBackoffExponent = backoffExponentDefault + } else if config.shouldOmitCloudProviderBackoff() { + klog.Warning("Azure cloud provider config 'cloudProviderBackoffExponent' has been deprecated for 'v2' backoff mode. 2 is always used as the backoff exponent.") + } + if config.CloudProviderBackoffJitter == 0 { + config.CloudProviderBackoffJitter = backoffJitterDefault + } else if config.shouldOmitCloudProviderBackoff() { + klog.Warning("Azure cloud provider config 'cloudProviderBackoffJitter' has been deprecated for 'v2' backoff mode.") + } + + if !config.shouldOmitCloudProviderBackoff() { + resourceRequestBackoff = wait.Backoff{ + Steps: config.CloudProviderBackoffRetries, + Factor: config.CloudProviderBackoffExponent, + Duration: time.Duration(config.CloudProviderBackoffDuration) * time.Second, + Jitter: config.CloudProviderBackoffJitter, + } + } + klog.V(2).Infof("Azure cloudprovider using try backoff: retries=%d, exponent=%f, duration=%d, jitter=%f", + config.CloudProviderBackoffRetries, + config.CloudProviderBackoffExponent, + config.CloudProviderBackoffDuration, + config.CloudProviderBackoffJitter) + } else { + // CloudProviderBackoffRetries will be set to 1 by default as the requirements of Azure SDK. + config.CloudProviderBackoffRetries = 1 + config.CloudProviderBackoffDuration = backoffDurationDefault + } + // Do not add master nodes to standard LB by default. if config.ExcludeMasterFromStandardLB == nil { config.ExcludeMasterFromStandardLB = &defaultExcludeMasterFromStandardLB } azClientConfig := &azClientConfig{ - subscriptionID: config.SubscriptionID, - resourceManagerEndpoint: env.ResourceManagerEndpoint, - servicePrincipalToken: servicePrincipalToken, - rateLimiterReader: operationPollRateLimiter, - rateLimiterWriter: operationPollRateLimiterWrite, + subscriptionID: config.SubscriptionID, + resourceManagerEndpoint: env.ResourceManagerEndpoint, + servicePrincipalToken: servicePrincipalToken, + rateLimiterReader: operationPollRateLimiter, + rateLimiterWriter: operationPollRateLimiterWrite, + CloudProviderBackoffRetries: config.CloudProviderBackoffRetries, + CloudProviderBackoffDuration: config.CloudProviderBackoffDuration, + ShouldOmitCloudProviderBackoff: config.shouldOmitCloudProviderBackoff(), } az := Cloud{ - Config: *config, - Environment: *env, - nodeZones: map[string]sets.String{}, - nodeResourceGroups: map[string]string{}, - unmanagedNodes: sets.NewString(), - routeCIDRs: map[string]string{}, + Config: *config, + Environment: *env, + nodeZones: map[string]sets.String{}, + nodeResourceGroups: map[string]string{}, + unmanagedNodes: sets.NewString(), + routeCIDRs: map[string]string{}, + resourceRequestBackoff: resourceRequestBackoff, DisksClient: newAzDisksClient(azClientConfig), RoutesClient: newAzRoutesClient(azClientConfig), @@ -300,34 +360,6 @@ func NewCloud(configReader io.Reader) (cloudprovider.Interface, error) { FileClient: &azureFileClient{env: *env}, } - // Conditionally configure resource request backoff - if az.CloudProviderBackoff { - // Assign backoff defaults if no configuration was passed in - if az.CloudProviderBackoffRetries == 0 { - az.CloudProviderBackoffRetries = backoffRetriesDefault - } - if az.CloudProviderBackoffExponent == 0 { - az.CloudProviderBackoffExponent = backoffExponentDefault - } - if az.CloudProviderBackoffDuration == 0 { - az.CloudProviderBackoffDuration = backoffDurationDefault - } - if az.CloudProviderBackoffJitter == 0 { - az.CloudProviderBackoffJitter = backoffJitterDefault - } - az.resourceRequestBackoff = wait.Backoff{ - Steps: az.CloudProviderBackoffRetries, - Factor: az.CloudProviderBackoffExponent, - Duration: time.Duration(az.CloudProviderBackoffDuration) * time.Second, - Jitter: az.CloudProviderBackoffJitter, - } - klog.V(2).Infof("Azure cloudprovider using try backoff: retries=%d, exponent=%f, duration=%d, jitter=%f", - az.CloudProviderBackoffRetries, - az.CloudProviderBackoffExponent, - az.CloudProviderBackoffDuration, - az.CloudProviderBackoffJitter) - } - az.metadata, err = NewInstanceMetadataService(metadataURL) if err != nil { return nil, err diff --git a/pkg/cloudprovider/providers/azure/azure_backoff.go b/pkg/cloudprovider/providers/azure/azure_backoff.go index c0a6f4a34ee..2771bef26b1 100644 --- a/pkg/cloudprovider/providers/azure/azure_backoff.go +++ b/pkg/cloudprovider/providers/azure/azure_backoff.go @@ -17,19 +17,18 @@ limitations under the License. package azure import ( - "context" "fmt" "net/http" "github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2018-10-01/compute" "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2017-09-01/network" - "k8s.io/klog" "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/wait" cloudprovider "k8s.io/cloud-provider" + "k8s.io/klog" ) // requestBackoff if backoff is disabled in cloud provider it @@ -43,7 +42,6 @@ func (az *Cloud) requestBackoff() (resourceRequestBackoff wait.Backoff) { resourceRequestBackoff = wait.Backoff{ Steps: 1, } - return resourceRequestBackoff } @@ -73,12 +71,11 @@ func (az *Cloud) GetVirtualMachineWithRetry(name types.NodeName) (compute.Virtua if err == wait.ErrWaitTimeout { err = retryErr } - return machine, err } -// VirtualMachineClientListWithRetry invokes az.VirtualMachinesClient.List with exponential backoff retry -func (az *Cloud) VirtualMachineClientListWithRetry(resourceGroup string) ([]compute.VirtualMachine, error) { +// ListVirtualMachinesWithRetry invokes az.VirtualMachinesClient.List with exponential backoff retry +func (az *Cloud) ListVirtualMachinesWithRetry(resourceGroup string) ([]compute.VirtualMachine, error) { allNodes := []compute.VirtualMachine{} err := wait.ExponentialBackoff(az.requestBackoff(), func() (bool, error) { var retryErr error @@ -101,12 +98,38 @@ func (az *Cloud) VirtualMachineClientListWithRetry(resourceGroup string) ([]comp return allNodes, err } +// ListVirtualMachines invokes az.VirtualMachinesClient.List with exponential backoff retry +func (az *Cloud) ListVirtualMachines(resourceGroup string) ([]compute.VirtualMachine, error) { + if az.Config.shouldOmitCloudProviderBackoff() { + ctx, cancel := getContextWithCancel() + defer cancel() + + allNodes, err := az.VirtualMachinesClient.List(ctx, resourceGroup) + if err != nil { + klog.Errorf("VirtualMachinesClient.List(%v) failure with err=%v", resourceGroup, err) + return nil, err + } + klog.V(2).Infof("VirtualMachinesClient.List(%v) success", resourceGroup) + return allNodes, nil + } + + return az.ListVirtualMachinesWithRetry(resourceGroup) +} + +func (az *Cloud) getIPForMachine(nodeName types.NodeName) (string, string, error) { + if az.Config.shouldOmitCloudProviderBackoff() { + return az.vmSet.GetIPByNodeName(string(nodeName)) + } + + return az.GetIPForMachineWithRetry(nodeName) +} + // GetIPForMachineWithRetry invokes az.getIPForMachine with exponential backoff retry func (az *Cloud) GetIPForMachineWithRetry(name types.NodeName) (string, string, error) { var ip, publicIP string err := wait.ExponentialBackoff(az.requestBackoff(), func() (bool, error) { var retryErr error - ip, publicIP, retryErr = az.getIPForMachine(name) + ip, publicIP, retryErr = az.vmSet.GetIPByNodeName(string(name)) if retryErr != nil { klog.Errorf("GetIPForMachineWithRetry(%s): backoff failure, will retry,err=%v", name, retryErr) return false, nil @@ -117,6 +140,28 @@ func (az *Cloud) GetIPForMachineWithRetry(name types.NodeName) (string, string, return ip, publicIP, err } +// CreateOrUpdateSecurityGroup invokes az.SecurityGroupsClient.CreateOrUpdate with exponential backoff retry +func (az *Cloud) CreateOrUpdateSecurityGroup(service *v1.Service, sg network.SecurityGroup) error { + if az.Config.shouldOmitCloudProviderBackoff() { + ctx, cancel := getContextWithCancel() + defer cancel() + + resp, err := az.SecurityGroupsClient.CreateOrUpdate(ctx, az.ResourceGroup, *sg.Name, sg) + klog.V(10).Infof("SecurityGroupsClient.CreateOrUpdate(%s): end", *sg.Name) + if err == nil { + if isSuccessHTTPResponse(resp) { + // Invalidate the cache right after updating + az.nsgCache.Delete(*sg.Name) + } else if resp != nil { + return fmt.Errorf("HTTP response %q", resp.Status) + } + } + return err + } + + return az.CreateOrUpdateSGWithRetry(service, sg) +} + // CreateOrUpdateSGWithRetry invokes az.SecurityGroupsClient.CreateOrUpdate with exponential backoff retry func (az *Cloud) CreateOrUpdateSGWithRetry(service *v1.Service, sg network.SecurityGroup) error { return wait.ExponentialBackoff(az.requestBackoff(), func() (bool, error) { @@ -134,8 +179,30 @@ func (az *Cloud) CreateOrUpdateSGWithRetry(service *v1.Service, sg network.Secur }) } -// CreateOrUpdateLBWithRetry invokes az.LoadBalancerClient.CreateOrUpdate with exponential backoff retry -func (az *Cloud) CreateOrUpdateLBWithRetry(service *v1.Service, lb network.LoadBalancer) error { +// CreateOrUpdateLB invokes az.LoadBalancerClient.CreateOrUpdate with exponential backoff retry +func (az *Cloud) CreateOrUpdateLB(service *v1.Service, lb network.LoadBalancer) error { + if az.Config.shouldOmitCloudProviderBackoff() { + ctx, cancel := getContextWithCancel() + defer cancel() + + resp, err := az.LoadBalancerClient.CreateOrUpdate(ctx, az.ResourceGroup, *lb.Name, lb) + klog.V(10).Infof("LoadBalancerClient.CreateOrUpdate(%s): end", *lb.Name) + if err == nil { + if isSuccessHTTPResponse(resp) { + // Invalidate the cache right after updating + az.lbCache.Delete(*lb.Name) + } else if resp != nil { + return fmt.Errorf("HTTP response %q", resp.Status) + } + } + return err + } + + return az.createOrUpdateLBWithRetry(service, lb) +} + +// createOrUpdateLBWithRetry invokes az.LoadBalancerClient.CreateOrUpdate with exponential backoff retry +func (az *Cloud) createOrUpdateLBWithRetry(service *v1.Service, lb network.LoadBalancer) error { return wait.ExponentialBackoff(az.requestBackoff(), func() (bool, error) { ctx, cancel := getContextWithCancel() defer cancel() @@ -151,8 +218,27 @@ func (az *Cloud) CreateOrUpdateLBWithRetry(service *v1.Service, lb network.LoadB }) } -// ListLBWithRetry invokes az.LoadBalancerClient.List with exponential backoff retry -func (az *Cloud) ListLBWithRetry(service *v1.Service) ([]network.LoadBalancer, error) { +// ListLB invokes az.LoadBalancerClient.List with exponential backoff retry +func (az *Cloud) ListLB(service *v1.Service) ([]network.LoadBalancer, error) { + if az.Config.shouldOmitCloudProviderBackoff() { + ctx, cancel := getContextWithCancel() + defer cancel() + + allLBs, err := az.LoadBalancerClient.List(ctx, az.ResourceGroup) + if err != nil { + az.Event(service, v1.EventTypeWarning, "ListLoadBalancers", err.Error()) + klog.Errorf("LoadBalancerClient.List(%v) failure with err=%v", az.ResourceGroup, err) + return nil, err + } + klog.V(2).Infof("LoadBalancerClient.List(%v) success", az.ResourceGroup) + return allLBs, nil + } + + return az.listLBWithRetry(service) +} + +// listLBWithRetry invokes az.LoadBalancerClient.List with exponential backoff retry +func (az *Cloud) listLBWithRetry(service *v1.Service) ([]network.LoadBalancer, error) { var allLBs []network.LoadBalancer err := wait.ExponentialBackoff(az.requestBackoff(), func() (bool, error) { @@ -178,8 +264,27 @@ func (az *Cloud) ListLBWithRetry(service *v1.Service) ([]network.LoadBalancer, e return allLBs, nil } -// ListPIPWithRetry list the PIP resources in the given resource group -func (az *Cloud) ListPIPWithRetry(service *v1.Service, pipResourceGroup string) ([]network.PublicIPAddress, error) { +// ListPIP list the PIP resources in the given resource group +func (az *Cloud) ListPIP(service *v1.Service, pipResourceGroup string) ([]network.PublicIPAddress, error) { + if az.Config.shouldOmitCloudProviderBackoff() { + ctx, cancel := getContextWithCancel() + defer cancel() + + allPIPs, err := az.PublicIPAddressesClient.List(ctx, pipResourceGroup) + if err != nil { + az.Event(service, v1.EventTypeWarning, "ListPublicIPs", err.Error()) + klog.Errorf("PublicIPAddressesClient.List(%v) failure with err=%v", pipResourceGroup, err) + return nil, err + } + klog.V(2).Infof("PublicIPAddressesClient.List(%v) success", pipResourceGroup) + return allPIPs, nil + } + + return az.listPIPWithRetry(service, pipResourceGroup) +} + +// listPIPWithRetry list the PIP resources in the given resource group +func (az *Cloud) listPIPWithRetry(service *v1.Service, pipResourceGroup string) ([]network.PublicIPAddress, error) { var allPIPs []network.PublicIPAddress err := wait.ExponentialBackoff(az.requestBackoff(), func() (bool, error) { @@ -205,8 +310,22 @@ func (az *Cloud) ListPIPWithRetry(service *v1.Service, pipResourceGroup string) return allPIPs, nil } -// CreateOrUpdatePIPWithRetry invokes az.PublicIPAddressesClient.CreateOrUpdate with exponential backoff retry -func (az *Cloud) CreateOrUpdatePIPWithRetry(service *v1.Service, pipResourceGroup string, pip network.PublicIPAddress) error { +// CreateOrUpdatePIP invokes az.PublicIPAddressesClient.CreateOrUpdate with exponential backoff retry +func (az *Cloud) CreateOrUpdatePIP(service *v1.Service, pipResourceGroup string, pip network.PublicIPAddress) error { + if az.Config.shouldOmitCloudProviderBackoff() { + ctx, cancel := getContextWithCancel() + defer cancel() + + resp, err := az.PublicIPAddressesClient.CreateOrUpdate(ctx, pipResourceGroup, *pip.Name, pip) + klog.V(10).Infof("PublicIPAddressesClient.CreateOrUpdate(%s, %s): end", pipResourceGroup, *pip.Name) + return az.processHTTPResponse(service, "CreateOrUpdatePublicIPAddress", resp, err) + } + + return az.createOrUpdatePIPWithRetry(service, pipResourceGroup, pip) +} + +// createOrUpdatePIPWithRetry invokes az.PublicIPAddressesClient.CreateOrUpdate with exponential backoff retry +func (az *Cloud) createOrUpdatePIPWithRetry(service *v1.Service, pipResourceGroup string, pip network.PublicIPAddress) error { return wait.ExponentialBackoff(az.requestBackoff(), func() (bool, error) { ctx, cancel := getContextWithCancel() defer cancel() @@ -217,8 +336,22 @@ func (az *Cloud) CreateOrUpdatePIPWithRetry(service *v1.Service, pipResourceGrou }) } -// CreateOrUpdateInterfaceWithRetry invokes az.PublicIPAddressesClient.CreateOrUpdate with exponential backoff retry -func (az *Cloud) CreateOrUpdateInterfaceWithRetry(service *v1.Service, nic network.Interface) error { +// CreateOrUpdateInterface invokes az.PublicIPAddressesClient.CreateOrUpdate with exponential backoff retry +func (az *Cloud) CreateOrUpdateInterface(service *v1.Service, nic network.Interface) error { + if az.Config.shouldOmitCloudProviderBackoff() { + ctx, cancel := getContextWithCancel() + defer cancel() + + resp, err := az.InterfacesClient.CreateOrUpdate(ctx, az.ResourceGroup, *nic.Name, nic) + klog.V(10).Infof("InterfacesClient.CreateOrUpdate(%s): end", *nic.Name) + return az.processHTTPResponse(service, "CreateOrUpdateInterface", resp, err) + } + + return az.createOrUpdateInterfaceWithRetry(service, nic) +} + +// createOrUpdateInterfaceWithRetry invokes az.PublicIPAddressesClient.CreateOrUpdate with exponential backoff retry +func (az *Cloud) createOrUpdateInterfaceWithRetry(service *v1.Service, nic network.Interface) error { return wait.ExponentialBackoff(az.requestBackoff(), func() (bool, error) { ctx, cancel := getContextWithCancel() defer cancel() @@ -229,8 +362,21 @@ func (az *Cloud) CreateOrUpdateInterfaceWithRetry(service *v1.Service, nic netwo }) } -// DeletePublicIPWithRetry invokes az.PublicIPAddressesClient.Delete with exponential backoff retry -func (az *Cloud) DeletePublicIPWithRetry(service *v1.Service, pipResourceGroup string, pipName string) error { +// DeletePublicIP invokes az.PublicIPAddressesClient.Delete with exponential backoff retry +func (az *Cloud) DeletePublicIP(service *v1.Service, pipResourceGroup string, pipName string) error { + if az.Config.shouldOmitCloudProviderBackoff() { + ctx, cancel := getContextWithCancel() + defer cancel() + + resp, err := az.PublicIPAddressesClient.Delete(ctx, pipResourceGroup, pipName) + return az.processHTTPResponse(service, "DeletePublicIPAddress", resp, err) + } + + return az.deletePublicIPWithRetry(service, pipResourceGroup, pipName) +} + +// deletePublicIPWithRetry invokes az.PublicIPAddressesClient.Delete with exponential backoff retry +func (az *Cloud) deletePublicIPWithRetry(service *v1.Service, pipResourceGroup string, pipName string) error { return wait.ExponentialBackoff(az.requestBackoff(), func() (bool, error) { ctx, cancel := getContextWithCancel() defer cancel() @@ -240,8 +386,29 @@ func (az *Cloud) DeletePublicIPWithRetry(service *v1.Service, pipResourceGroup s }) } -// DeleteLBWithRetry invokes az.LoadBalancerClient.Delete with exponential backoff retry -func (az *Cloud) DeleteLBWithRetry(service *v1.Service, lbName string) error { +// DeleteLB invokes az.LoadBalancerClient.Delete with exponential backoff retry +func (az *Cloud) DeleteLB(service *v1.Service, lbName string) error { + if az.Config.shouldOmitCloudProviderBackoff() { + ctx, cancel := getContextWithCancel() + defer cancel() + + resp, err := az.LoadBalancerClient.Delete(ctx, az.ResourceGroup, lbName) + if err == nil { + if isSuccessHTTPResponse(resp) { + // Invalidate the cache right after updating + az.lbCache.Delete(lbName) + } else if resp != nil { + return fmt.Errorf("HTTP response %q", resp.Status) + } + } + return err + } + + return az.deleteLBWithRetry(service, lbName) +} + +// deleteLBWithRetry invokes az.LoadBalancerClient.Delete with exponential backoff retry +func (az *Cloud) deleteLBWithRetry(service *v1.Service, lbName string) error { return wait.ExponentialBackoff(az.requestBackoff(), func() (bool, error) { ctx, cancel := getContextWithCancel() defer cancel() @@ -256,8 +423,21 @@ func (az *Cloud) DeleteLBWithRetry(service *v1.Service, lbName string) error { }) } -// CreateOrUpdateRouteTableWithRetry invokes az.RouteTablesClient.CreateOrUpdate with exponential backoff retry -func (az *Cloud) CreateOrUpdateRouteTableWithRetry(routeTable network.RouteTable) error { +// CreateOrUpdateRouteTable invokes az.RouteTablesClient.CreateOrUpdate with exponential backoff retry +func (az *Cloud) CreateOrUpdateRouteTable(routeTable network.RouteTable) error { + if az.Config.shouldOmitCloudProviderBackoff() { + ctx, cancel := getContextWithCancel() + defer cancel() + + resp, err := az.RouteTablesClient.CreateOrUpdate(ctx, az.ResourceGroup, az.RouteTableName, routeTable) + return az.processHTTPResponse(nil, "", resp, err) + } + + return az.createOrUpdateRouteTableWithRetry(routeTable) +} + +// createOrUpdateRouteTableWithRetry invokes az.RouteTablesClient.CreateOrUpdate with exponential backoff retry +func (az *Cloud) createOrUpdateRouteTableWithRetry(routeTable network.RouteTable) error { return wait.ExponentialBackoff(az.requestBackoff(), func() (bool, error) { ctx, cancel := getContextWithCancel() defer cancel() @@ -267,8 +447,22 @@ func (az *Cloud) CreateOrUpdateRouteTableWithRetry(routeTable network.RouteTable }) } -// CreateOrUpdateRouteWithRetry invokes az.RoutesClient.CreateOrUpdate with exponential backoff retry -func (az *Cloud) CreateOrUpdateRouteWithRetry(route network.Route) error { +// CreateOrUpdateRoute invokes az.RoutesClient.CreateOrUpdate with exponential backoff retry +func (az *Cloud) CreateOrUpdateRoute(route network.Route) error { + if az.Config.shouldOmitCloudProviderBackoff() { + ctx, cancel := getContextWithCancel() + defer cancel() + + resp, err := az.RoutesClient.CreateOrUpdate(ctx, az.ResourceGroup, az.RouteTableName, *route.Name, route) + klog.V(10).Infof("RoutesClient.CreateOrUpdate(%s): end", *route.Name) + return az.processHTTPResponse(nil, "", resp, err) + } + + return az.createOrUpdateRouteWithRetry(route) +} + +// createOrUpdateRouteWithRetry invokes az.RoutesClient.CreateOrUpdate with exponential backoff retry +func (az *Cloud) createOrUpdateRouteWithRetry(route network.Route) error { return wait.ExponentialBackoff(az.requestBackoff(), func() (bool, error) { ctx, cancel := getContextWithCancel() defer cancel() @@ -279,14 +473,28 @@ func (az *Cloud) CreateOrUpdateRouteWithRetry(route network.Route) error { }) } -// DeleteRouteWithRetry invokes az.RoutesClient.Delete with exponential backoff retry -func (az *Cloud) DeleteRouteWithRetry(routeName string) error { +// DeleteRouteWithName invokes az.RoutesClient.CreateOrUpdate with exponential backoff retry +func (az *Cloud) DeleteRouteWithName(routeName string) error { + if az.Config.shouldOmitCloudProviderBackoff() { + ctx, cancel := getContextWithCancel() + defer cancel() + + resp, err := az.RoutesClient.Delete(ctx, az.ResourceGroup, az.RouteTableName, routeName) + klog.V(10).Infof("RoutesClient.Delete(%s,%s): end", az.RouteTableName, routeName) + return az.processHTTPResponse(nil, "", resp, err) + } + + return az.deleteRouteWithRetry(routeName) +} + +// deleteRouteWithRetry invokes az.RoutesClient.Delete with exponential backoff retry +func (az *Cloud) deleteRouteWithRetry(routeName string) error { return wait.ExponentialBackoff(az.requestBackoff(), func() (bool, error) { ctx, cancel := getContextWithCancel() defer cancel() resp, err := az.RoutesClient.Delete(ctx, az.ResourceGroup, az.RouteTableName, routeName) - klog.V(10).Infof("RoutesClient.Delete(%s): end", az.RouteTableName) + klog.V(10).Infof("RoutesClient.Delete(%s,%s): end", az.RouteTableName, routeName) return az.processHTTPRetryResponse(nil, "", resp, err) }) } @@ -303,21 +511,17 @@ func (az *Cloud) CreateOrUpdateVMWithRetry(resourceGroup, vmName string, newVM c }) } -// UpdateVmssVMWithRetry invokes az.VirtualMachineScaleSetVMsClient.Update with exponential backoff retry -func (az *Cloud) UpdateVmssVMWithRetry(ctx context.Context, resourceGroupName string, VMScaleSetName string, instanceID string, parameters compute.VirtualMachineScaleSetVM) error { - return wait.ExponentialBackoff(az.requestBackoff(), func() (bool, error) { - resp, err := az.VirtualMachineScaleSetVMsClient.Update(ctx, resourceGroupName, VMScaleSetName, instanceID, parameters) - klog.V(10).Infof("VirtualMachinesClient.CreateOrUpdate(%s,%s): end", VMScaleSetName, instanceID) - return az.processHTTPRetryResponse(nil, "", resp, err) - }) -} - // isSuccessHTTPResponse determines if the response from an HTTP request suggests success -func isSuccessHTTPResponse(resp http.Response) bool { +func isSuccessHTTPResponse(resp *http.Response) bool { + if resp == nil { + return false + } + // HTTP 2xx suggests a successful response if 199 < resp.StatusCode && resp.StatusCode < 300 { return true } + return false } @@ -337,7 +541,7 @@ func shouldRetryHTTPRequest(resp *http.Response, err error) bool { } func (az *Cloud) processHTTPRetryResponse(service *v1.Service, reason string, resp *http.Response, err error) (bool, error) { - if resp != nil && isSuccessHTTPResponse(*resp) { + if resp != nil && isSuccessHTTPResponse(resp) { // HTTP 2xx suggests a successful response return true, nil } @@ -358,3 +562,24 @@ func (az *Cloud) processHTTPRetryResponse(service *v1.Service, reason string, re // Fall-through: stop periodic backoff return true, nil } + +func (az *Cloud) processHTTPResponse(service *v1.Service, reason string, resp *http.Response, err error) error { + if isSuccessHTTPResponse(resp) { + // HTTP 2xx suggests a successful response + return nil + } + + if err != nil { + az.Event(service, v1.EventTypeWarning, reason, err.Error()) + klog.Errorf("processHTTPRetryResponse failure with err: %v", err) + } else if resp != nil { + az.Event(service, v1.EventTypeWarning, reason, fmt.Sprintf("Azure HTTP response %d", resp.StatusCode)) + klog.Errorf("processHTTPRetryResponse failure with HTTP response %q", resp.Status) + } + + return err +} + +func (cfg *Config) shouldOmitCloudProviderBackoff() bool { + return cfg.CloudProviderBackoffMode == backoffModeV2 +} diff --git a/pkg/cloudprovider/providers/azure/azure_backoff_test.go b/pkg/cloudprovider/providers/azure/azure_backoff_test.go index 767c7cc30e3..d0a1399e27c 100644 --- a/pkg/cloudprovider/providers/azure/azure_backoff_test.go +++ b/pkg/cloudprovider/providers/azure/azure_backoff_test.go @@ -50,7 +50,6 @@ func TestShouldRetryHTTPRequest(t *testing.T) { expected: false, }, } - for _, test := range tests { resp := &http.Response{ StatusCode: test.code, @@ -85,7 +84,7 @@ func TestIsSuccessResponse(t *testing.T) { resp := http.Response{ StatusCode: test.code, } - res := isSuccessHTTPResponse(resp) + res := isSuccessHTTPResponse(&resp) if res != test.expected { t.Errorf("expected: %v, saw: %v", test.expected, res) } diff --git a/pkg/cloudprovider/providers/azure/azure_blobDiskController.go b/pkg/cloudprovider/providers/azure/azure_blobDiskController.go index 9d0be714894..7cb8a756df7 100644 --- a/pkg/cloudprovider/providers/azure/azure_blobDiskController.go +++ b/pkg/cloudprovider/providers/azure/azure_blobDiskController.go @@ -108,7 +108,7 @@ func (c *BlobDiskController) DeleteVolume(diskURI string) error { if err != nil { return fmt.Errorf("failed to parse vhd URI %v", err) } - key, err := c.common.cloud.getStorageAccesskey(accountName, c.common.resourceGroup) + key, err := c.common.cloud.GetStorageAccesskey(accountName, c.common.resourceGroup) if err != nil { return fmt.Errorf("no key for storage account %s, err %v", accountName, err) } diff --git a/pkg/cloudprovider/providers/azure/azure_client.go b/pkg/cloudprovider/providers/azure/azure_client.go index 94a97034275..e7d2a9d6cec 100644 --- a/pkg/cloudprovider/providers/azure/azure_client.go +++ b/pkg/cloudprovider/providers/azure/azure_client.go @@ -145,6 +145,10 @@ type azClientConfig struct { //Details: https://docs.microsoft.com/en-us/azure/azure-resource-manager/resource-manager-request-limits rateLimiterReader flowcontrol.RateLimiter rateLimiterWriter flowcontrol.RateLimiter + + CloudProviderBackoffRetries int + CloudProviderBackoffDuration int + ShouldOmitCloudProviderBackoff bool } // azVirtualMachinesClient implements VirtualMachinesClient. @@ -163,6 +167,10 @@ func newAzVirtualMachinesClient(config *azClientConfig) *azVirtualMachinesClient virtualMachinesClient.BaseURI = config.resourceManagerEndpoint virtualMachinesClient.Authorizer = autorest.NewBearerAuthorizer(config.servicePrincipalToken) virtualMachinesClient.PollingDelay = 5 * time.Second + if config.ShouldOmitCloudProviderBackoff { + virtualMachinesClient.RetryAttempts = config.CloudProviderBackoffRetries + virtualMachinesClient.RetryDuration = time.Duration(config.CloudProviderBackoffDuration) * time.Second + } configureUserAgent(&virtualMachinesClient.Client) return &azVirtualMachinesClient{ @@ -254,6 +262,10 @@ func newAzInterfacesClient(config *azClientConfig) *azInterfacesClient { interfacesClient.BaseURI = config.resourceManagerEndpoint interfacesClient.Authorizer = autorest.NewBearerAuthorizer(config.servicePrincipalToken) interfacesClient.PollingDelay = 5 * time.Second + if config.ShouldOmitCloudProviderBackoff { + interfacesClient.RetryAttempts = config.CloudProviderBackoffRetries + interfacesClient.RetryDuration = time.Duration(config.CloudProviderBackoffDuration) * time.Second + } configureUserAgent(&interfacesClient.Client) return &azInterfacesClient{ @@ -333,6 +345,10 @@ func newAzLoadBalancersClient(config *azClientConfig) *azLoadBalancersClient { loadBalancerClient.BaseURI = config.resourceManagerEndpoint loadBalancerClient.Authorizer = autorest.NewBearerAuthorizer(config.servicePrincipalToken) loadBalancerClient.PollingDelay = 5 * time.Second + if config.ShouldOmitCloudProviderBackoff { + loadBalancerClient.RetryAttempts = config.CloudProviderBackoffRetries + loadBalancerClient.RetryDuration = time.Duration(config.CloudProviderBackoffDuration) * time.Second + } configureUserAgent(&loadBalancerClient.Client) return &azLoadBalancersClient{ @@ -449,6 +465,10 @@ func newAzPublicIPAddressesClient(config *azClientConfig) *azPublicIPAddressesCl publicIPAddressClient.BaseURI = config.resourceManagerEndpoint publicIPAddressClient.Authorizer = autorest.NewBearerAuthorizer(config.servicePrincipalToken) publicIPAddressClient.PollingDelay = 5 * time.Second + if config.ShouldOmitCloudProviderBackoff { + publicIPAddressClient.RetryAttempts = config.CloudProviderBackoffRetries + publicIPAddressClient.RetryDuration = time.Duration(config.CloudProviderBackoffDuration) * time.Second + } configureUserAgent(&publicIPAddressClient.Client) return &azPublicIPAddressesClient{ @@ -564,6 +584,10 @@ func newAzSubnetsClient(config *azClientConfig) *azSubnetsClient { subnetsClient.BaseURI = config.resourceManagerEndpoint subnetsClient.Authorizer = autorest.NewBearerAuthorizer(config.servicePrincipalToken) subnetsClient.PollingDelay = 5 * time.Second + if config.ShouldOmitCloudProviderBackoff { + subnetsClient.RetryAttempts = config.CloudProviderBackoffRetries + subnetsClient.RetryDuration = time.Duration(config.CloudProviderBackoffDuration) * time.Second + } configureUserAgent(&subnetsClient.Client) return &azSubnetsClient{ @@ -679,6 +703,10 @@ func newAzSecurityGroupsClient(config *azClientConfig) *azSecurityGroupsClient { securityGroupsClient.BaseURI = config.resourceManagerEndpoint securityGroupsClient.Authorizer = autorest.NewBearerAuthorizer(config.servicePrincipalToken) securityGroupsClient.PollingDelay = 5 * time.Second + if config.ShouldOmitCloudProviderBackoff { + securityGroupsClient.RetryAttempts = config.CloudProviderBackoffRetries + securityGroupsClient.RetryDuration = time.Duration(config.CloudProviderBackoffDuration) * time.Second + } configureUserAgent(&securityGroupsClient.Client) return &azSecurityGroupsClient{ @@ -794,6 +822,10 @@ func newAzVirtualMachineScaleSetsClient(config *azClientConfig) *azVirtualMachin virtualMachineScaleSetsClient.BaseURI = config.resourceManagerEndpoint virtualMachineScaleSetsClient.Authorizer = autorest.NewBearerAuthorizer(config.servicePrincipalToken) virtualMachineScaleSetsClient.PollingDelay = 5 * time.Second + if config.ShouldOmitCloudProviderBackoff { + virtualMachineScaleSetsClient.RetryAttempts = config.CloudProviderBackoffRetries + virtualMachineScaleSetsClient.RetryDuration = time.Duration(config.CloudProviderBackoffDuration) * time.Second + } configureUserAgent(&virtualMachineScaleSetsClient.Client) return &azVirtualMachineScaleSetsClient{ @@ -910,6 +942,10 @@ func newAzVirtualMachineScaleSetVMsClient(config *azClientConfig) *azVirtualMach virtualMachineScaleSetVMsClient.BaseURI = config.resourceManagerEndpoint virtualMachineScaleSetVMsClient.Authorizer = autorest.NewBearerAuthorizer(config.servicePrincipalToken) virtualMachineScaleSetVMsClient.PollingDelay = 5 * time.Second + if config.ShouldOmitCloudProviderBackoff { + virtualMachineScaleSetVMsClient.RetryAttempts = config.CloudProviderBackoffRetries + virtualMachineScaleSetVMsClient.RetryDuration = time.Duration(config.CloudProviderBackoffDuration) * time.Second + } configureUserAgent(&virtualMachineScaleSetVMsClient.Client) return &azVirtualMachineScaleSetVMsClient{ @@ -1018,6 +1054,10 @@ func newAzRoutesClient(config *azClientConfig) *azRoutesClient { routesClient.BaseURI = config.resourceManagerEndpoint routesClient.Authorizer = autorest.NewBearerAuthorizer(config.servicePrincipalToken) routesClient.PollingDelay = 5 * time.Second + if config.ShouldOmitCloudProviderBackoff { + routesClient.RetryAttempts = config.CloudProviderBackoffRetries + routesClient.RetryDuration = time.Duration(config.CloudProviderBackoffDuration) * time.Second + } configureUserAgent(&routesClient.Client) return &azRoutesClient{ @@ -1087,6 +1127,10 @@ func newAzRouteTablesClient(config *azClientConfig) *azRouteTablesClient { routeTablesClient.BaseURI = config.resourceManagerEndpoint routeTablesClient.Authorizer = autorest.NewBearerAuthorizer(config.servicePrincipalToken) routeTablesClient.PollingDelay = 5 * time.Second + if config.ShouldOmitCloudProviderBackoff { + routeTablesClient.RetryAttempts = config.CloudProviderBackoffRetries + routeTablesClient.RetryDuration = time.Duration(config.CloudProviderBackoffDuration) * time.Second + } configureUserAgent(&routeTablesClient.Client) return &azRouteTablesClient{ @@ -1148,6 +1192,10 @@ func newAzStorageAccountClient(config *azClientConfig) *azStorageAccountClient { storageAccountClient := storage.NewAccountsClientWithBaseURI(config.resourceManagerEndpoint, config.subscriptionID) storageAccountClient.Authorizer = autorest.NewBearerAuthorizer(config.servicePrincipalToken) storageAccountClient.PollingDelay = 5 * time.Second + if config.ShouldOmitCloudProviderBackoff { + storageAccountClient.RetryAttempts = config.CloudProviderBackoffRetries + storageAccountClient.RetryDuration = time.Duration(config.CloudProviderBackoffDuration) * time.Second + } configureUserAgent(&storageAccountClient.Client) return &azStorageAccountClient{ @@ -1259,6 +1307,10 @@ func newAzDisksClient(config *azClientConfig) *azDisksClient { disksClient := compute.NewDisksClientWithBaseURI(config.resourceManagerEndpoint, config.subscriptionID) disksClient.Authorizer = autorest.NewBearerAuthorizer(config.servicePrincipalToken) disksClient.PollingDelay = 5 * time.Second + if config.ShouldOmitCloudProviderBackoff { + disksClient.RetryAttempts = config.CloudProviderBackoffRetries + disksClient.RetryDuration = time.Duration(config.CloudProviderBackoffDuration) * time.Second + } configureUserAgent(&disksClient.Client) return &azDisksClient{ @@ -1345,6 +1397,10 @@ func newAzVirtualMachineSizesClient(config *azClientConfig) *azVirtualMachineSiz VirtualMachineSizesClient.BaseURI = config.resourceManagerEndpoint VirtualMachineSizesClient.Authorizer = autorest.NewBearerAuthorizer(config.servicePrincipalToken) VirtualMachineSizesClient.PollingDelay = 5 * time.Second + if config.ShouldOmitCloudProviderBackoff { + VirtualMachineSizesClient.RetryAttempts = config.CloudProviderBackoffRetries + VirtualMachineSizesClient.RetryDuration = time.Duration(config.CloudProviderBackoffDuration) * time.Second + } configureUserAgent(&VirtualMachineSizesClient.Client) return &azVirtualMachineSizesClient{ diff --git a/pkg/cloudprovider/providers/azure/azure_controller_standard.go b/pkg/cloudprovider/providers/azure/azure_controller_standard.go index 540314ecef7..f600209e284 100644 --- a/pkg/cloudprovider/providers/azure/azure_controller_standard.go +++ b/pkg/cloudprovider/providers/azure/azure_controller_standard.go @@ -68,6 +68,7 @@ func (as *availabilitySet) AttachDisk(isManagedDisk bool, diskName, diskURI stri newVM := compute.VirtualMachine{ Location: vm.Location, VirtualMachineProperties: &compute.VirtualMachineProperties{ + HardwareProfile: vm.HardwareProfile, StorageProfile: &compute.StorageProfile{ DataDisks: &disks, }, @@ -132,6 +133,7 @@ func (as *availabilitySet) DetachDiskByName(diskName, diskURI string, nodeName t newVM := compute.VirtualMachine{ Location: vm.Location, VirtualMachineProperties: &compute.VirtualMachineProperties{ + HardwareProfile: vm.HardwareProfile, StorageProfile: &compute.StorageProfile{ DataDisks: &disks, }, diff --git a/pkg/cloudprovider/providers/azure/azure_controller_vmss.go b/pkg/cloudprovider/providers/azure/azure_controller_vmss.go index b6daa7737eb..80a27bf0385 100644 --- a/pkg/cloudprovider/providers/azure/azure_controller_vmss.go +++ b/pkg/cloudprovider/providers/azure/azure_controller_vmss.go @@ -67,7 +67,17 @@ func (ss *scaleSet) AttachDisk(isManagedDisk bool, diskName, diskURI string, nod CreateOption: "attach", }) } - vm.StorageProfile.DataDisks = &disks + newVM := compute.VirtualMachineScaleSetVM{ + Sku: vm.Sku, + Location: vm.Location, + VirtualMachineScaleSetVMProperties: &compute.VirtualMachineScaleSetVMProperties{ + HardwareProfile: vm.HardwareProfile, + StorageProfile: &compute.StorageProfile{ + OsDisk: vm.StorageProfile.OsDisk, + DataDisks: &disks, + }, + }, + } ctx, cancel := getContextWithCancel() defer cancel() @@ -77,7 +87,7 @@ func (ss *scaleSet) AttachDisk(isManagedDisk bool, diskName, diskURI string, nod defer ss.vmssVMCache.Delete(key) klog.V(2).Infof("azureDisk - update(%s): vm(%s) - attach disk(%s)", nodeResourceGroup, nodeName, diskName) - _, err = ss.VirtualMachineScaleSetVMsClient.Update(ctx, nodeResourceGroup, ssName, instanceID, vm) + _, err = ss.VirtualMachineScaleSetVMsClient.Update(ctx, nodeResourceGroup, ssName, instanceID, newVM) if err != nil { detail := err.Error() if strings.Contains(detail, errLeaseFailed) || strings.Contains(detail, errDiskBlobNotFound) { @@ -126,7 +136,18 @@ func (ss *scaleSet) DetachDiskByName(diskName, diskURI string, nodeName types.No return fmt.Errorf("detach azure disk failure, disk %s not found, diskURI: %s", diskName, diskURI) } - vm.StorageProfile.DataDisks = &disks + newVM := compute.VirtualMachineScaleSetVM{ + Sku: vm.Sku, + Location: vm.Location, + VirtualMachineScaleSetVMProperties: &compute.VirtualMachineScaleSetVMProperties{ + HardwareProfile: vm.HardwareProfile, + StorageProfile: &compute.StorageProfile{ + OsDisk: vm.StorageProfile.OsDisk, + DataDisks: &disks, + }, + }, + } + ctx, cancel := getContextWithCancel() defer cancel() @@ -135,7 +156,7 @@ func (ss *scaleSet) DetachDiskByName(diskName, diskURI string, nodeName types.No defer ss.vmssVMCache.Delete(key) klog.V(2).Infof("azureDisk - update(%s): vm(%s) - detach disk(%s)", nodeResourceGroup, nodeName, diskName) - _, err = ss.VirtualMachineScaleSetVMsClient.Update(ctx, nodeResourceGroup, ssName, instanceID, vm) + _, err = ss.VirtualMachineScaleSetVMsClient.Update(ctx, nodeResourceGroup, ssName, instanceID, newVM) if err != nil { klog.Errorf("azureDisk - detach disk(%s) from %s failed, err: %v", diskName, nodeName, err) } else { diff --git a/pkg/cloudprovider/providers/azure/azure_instances.go b/pkg/cloudprovider/providers/azure/azure_instances.go index 158ffb976ca..87acadfd59f 100644 --- a/pkg/cloudprovider/providers/azure/azure_instances.go +++ b/pkg/cloudprovider/providers/azure/azure_instances.go @@ -23,9 +23,8 @@ import ( "strings" "k8s.io/api/core/v1" - cloudprovider "k8s.io/cloud-provider" - "k8s.io/apimachinery/pkg/types" + cloudprovider "k8s.io/cloud-provider" "k8s.io/klog" ) @@ -48,7 +47,7 @@ func (az *Cloud) NodeAddresses(ctx context.Context, name types.NodeName) ([]v1.N } addressGetter := func(nodeName types.NodeName) ([]v1.NodeAddress, error) { - ip, publicIP, err := az.GetIPForMachineWithRetry(nodeName) + ip, publicIP, err := az.getIPForMachine(nodeName) if err != nil { klog.V(2).Infof("NodeAddresses(%s) abort backoff: %v", nodeName, err) return nil, err @@ -96,7 +95,8 @@ func (az *Cloud) NodeAddresses(ctx context.Context, name types.NodeName) ([]v1.N addresses := []v1.NodeAddress{ {Type: v1.NodeHostName, Address: string(name)}, } - for _, address := range ipAddress.IPV4.IPAddress { + if len(ipAddress.IPV4.IPAddress) > 0 && len(ipAddress.IPV4.IPAddress[0].PrivateIP) > 0 { + address := ipAddress.IPV4.IPAddress[0] addresses = append(addresses, v1.NodeAddress{ Type: v1.NodeInternalIP, Address: address.PrivateIP, @@ -108,7 +108,8 @@ func (az *Cloud) NodeAddresses(ctx context.Context, name types.NodeName) ([]v1.N }) } } - for _, address := range ipAddress.IPV6.IPAddress { + if len(ipAddress.IPV6.IPAddress) > 0 && len(ipAddress.IPV6.IPAddress[0].PrivateIP) > 0 { + address := ipAddress.IPV6.IPAddress[0] addresses = append(addresses, v1.NodeAddress{ Type: v1.NodeInternalIP, Address: address.PrivateIP, @@ -120,6 +121,13 @@ func (az *Cloud) NodeAddresses(ctx context.Context, name types.NodeName) ([]v1.N }) } } + + if len(addresses) == 1 { + // No IP addresses is got from instance metadata service, clean up cache and report errors. + az.metadata.imsCache.Delete(metadataCacheKey) + return nil, fmt.Errorf("get empty IP addresses from instance metadata service") + } + return addresses, nil } @@ -155,6 +163,9 @@ func (az *Cloud) InstanceExistsByProviderID(ctx context.Context, providerID stri name, err := az.vmSet.GetNodeNameByProviderID(providerID) if err != nil { + if err == cloudprovider.InstanceNotFound { + return false, nil + } return false, err } diff --git a/pkg/cloudprovider/providers/azure/azure_instances_test.go b/pkg/cloudprovider/providers/azure/azure_instances_test.go index 3ae39917c72..40c92beb9d9 100644 --- a/pkg/cloudprovider/providers/azure/azure_instances_test.go +++ b/pkg/cloudprovider/providers/azure/azure_instances_test.go @@ -21,10 +21,12 @@ import ( "fmt" "net" "net/http" + "reflect" "testing" "github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2018-10-01/compute" "github.com/Azure/go-autorest/autorest/to" + "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/types" ) @@ -216,3 +218,122 @@ func TestInstanceShutdownByProviderID(t *testing.T) { } } } + +func TestNodeAddresses(t *testing.T) { + cloud := getTestCloud() + cloud.Config.UseInstanceMetadata = true + metadataTemplate := `{"compute":{"name":"%s"},"network":{"interface":[{"ipv4":{"ipAddress":[{"privateIpAddress":"%s","publicIpAddress":"%s"}]},"ipv6":{"ipAddress":[{"privateIpAddress":"%s","publicIpAddress":"%s"}]}}]}}` + + testcases := []struct { + name string + nodeName string + ipV4 string + ipV6 string + ipV4Public string + ipV6Public string + expected []v1.NodeAddress + expectError bool + }{ + { + name: "NodeAddresses should get both ipV4 and ipV6 private addresses", + nodeName: "vm1", + ipV4: "10.240.0.1", + ipV6: "1111:11111:00:00:1111:1111:000:111", + expected: []v1.NodeAddress{ + { + Type: v1.NodeHostName, + Address: "vm1", + }, + { + Type: v1.NodeInternalIP, + Address: "10.240.0.1", + }, + { + Type: v1.NodeInternalIP, + Address: "1111:11111:00:00:1111:1111:000:111", + }, + }, + }, + { + name: "NodeAddresses should report error when IPs are empty", + nodeName: "vm1", + expectError: true, + }, + { + name: "NodeAddresses should get ipV4 private and public addresses", + nodeName: "vm1", + ipV4: "10.240.0.1", + ipV4Public: "9.9.9.9", + expected: []v1.NodeAddress{ + { + Type: v1.NodeHostName, + Address: "vm1", + }, + { + Type: v1.NodeInternalIP, + Address: "10.240.0.1", + }, + { + Type: v1.NodeExternalIP, + Address: "9.9.9.9", + }, + }, + }, + { + name: "NodeAddresses should get ipV6 private and public addresses", + nodeName: "vm1", + ipV6: "1111:11111:00:00:1111:1111:000:111", + ipV6Public: "2222:22221:00:00:2222:2222:000:111", + expected: []v1.NodeAddress{ + { + Type: v1.NodeHostName, + Address: "vm1", + }, + { + Type: v1.NodeInternalIP, + Address: "1111:11111:00:00:1111:1111:000:111", + }, + { + Type: v1.NodeExternalIP, + Address: "2222:22221:00:00:2222:2222:000:111", + }, + }, + }, + } + + for _, test := range testcases { + listener, err := net.Listen("tcp", "127.0.0.1:0") + if err != nil { + t.Errorf("Test [%s] unexpected error: %v", test.name, err) + } + + mux := http.NewServeMux() + mux.Handle("/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + fmt.Fprintf(w, fmt.Sprintf(metadataTemplate, test.nodeName, test.ipV4, test.ipV4Public, test.ipV6, test.ipV6Public)) + })) + go func() { + http.Serve(listener, mux) + }() + defer listener.Close() + + cloud.metadata, err = NewInstanceMetadataService("http://" + listener.Addr().String() + "/") + if err != nil { + t.Errorf("Test [%s] unexpected error: %v", test.name, err) + } + + ipAddresses, err := cloud.NodeAddresses(context.Background(), types.NodeName(test.nodeName)) + if test.expectError { + if err == nil { + t.Errorf("Test [%s] unexpected nil err", test.name) + } + } else { + if err != nil { + t.Errorf("Test [%s] unexpected error: %v", test.name, err) + } + } + + if !reflect.DeepEqual(ipAddresses, test.expected) { + t.Errorf("Test [%s] unexpected ipAddresses: %s, expected %q", test.name, ipAddresses, test.expected) + } + } +} diff --git a/pkg/cloudprovider/providers/azure/azure_loadbalancer.go b/pkg/cloudprovider/providers/azure/azure_loadbalancer.go index 77bfdd20de2..bab5f1daaff 100644 --- a/pkg/cloudprovider/providers/azure/azure_loadbalancer.go +++ b/pkg/cloudprovider/providers/azure/azure_loadbalancer.go @@ -27,11 +27,11 @@ import ( "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/util/sets" cloudprovider "k8s.io/cloud-provider" + "k8s.io/klog" serviceapi "k8s.io/kubernetes/pkg/api/v1/service" "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2017-09-01/network" "github.com/Azure/go-autorest/autorest/to" - "k8s.io/klog" ) const ( @@ -210,7 +210,7 @@ func (az *Cloud) getServiceLoadBalancer(service *v1.Service, clusterName string, primaryVMSetName := az.vmSet.GetPrimaryVMSetName() defaultLBName := az.getAzureLoadBalancerName(clusterName, primaryVMSetName, isInternal) - existingLBs, err := az.ListLBWithRetry(service) + existingLBs, err := az.ListLB(service) if err != nil { return nil, nil, false, err } @@ -387,7 +387,7 @@ func (az *Cloud) determinePublicIPName(clusterName string, service *v1.Service) pipResourceGroup := az.getPublicIPAddressResourceGroup(service) - pips, err := az.ListPIPWithRetry(service, pipResourceGroup) + pips, err := az.ListPIP(service, pipResourceGroup) if err != nil { return "", err } @@ -474,13 +474,13 @@ func (az *Cloud) ensurePublicIPExists(service *v1.Service, pipName string, domai } klog.V(2).Infof("ensurePublicIPExists for service(%s): pip(%s) - creating", serviceName, *pip.Name) - klog.V(10).Infof("CreateOrUpdatePIPWithRetry(%s, %q): start", pipResourceGroup, *pip.Name) - err = az.CreateOrUpdatePIPWithRetry(service, pipResourceGroup, pip) + klog.V(10).Infof("CreateOrUpdatePIP(%s, %q): start", pipResourceGroup, *pip.Name) + err = az.CreateOrUpdatePIP(service, pipResourceGroup, pip) if err != nil { klog.V(2).Infof("ensure(%s) abort backoff: pip(%s) - creating", serviceName, *pip.Name) return nil, err } - klog.V(10).Infof("CreateOrUpdatePIPWithRetry(%s, %q): end", pipResourceGroup, *pip.Name) + klog.V(10).Infof("CreateOrUpdatePIP(%s, %q): end", pipResourceGroup, *pip.Name) ctx, cancel := getContextWithCancel() defer cancel() @@ -818,16 +818,16 @@ func (az *Cloud) reconcileLoadBalancer(clusterName string, service *v1.Service, klog.V(10).Infof("EnsureBackendPoolDeleted(%s, %s): end", lbBackendPoolID, vmSetName) // Remove the LB. - klog.V(10).Infof("reconcileLoadBalancer: az.DeleteLBWithRetry(%q): start", lbName) - err = az.DeleteLBWithRetry(service, lbName) + klog.V(10).Infof("reconcileLoadBalancer: az.DeleteLB(%q): start", lbName) + err = az.DeleteLB(service, lbName) if err != nil { klog.V(2).Infof("reconcileLoadBalancer for service(%s) abort backoff: lb(%s) - deleting; no remaining frontendIPConfigurations", serviceName, lbName) return nil, err } - klog.V(10).Infof("az.DeleteLBWithRetry(%q): end", lbName) + klog.V(10).Infof("az.DeleteLB(%q): end", lbName) } else { klog.V(2).Infof("reconcileLoadBalancer: reconcileLoadBalancer for service(%s): lb(%s) - updating", serviceName, lbName) - err := az.CreateOrUpdateLBWithRetry(service, *lb) + err := az.CreateOrUpdateLB(service, *lb) if err != nil { klog.V(2).Infof("reconcileLoadBalancer for service(%s) abort backoff: lb(%s) - updating", serviceName, lbName) return nil, err @@ -1143,8 +1143,8 @@ func (az *Cloud) reconcileSecurityGroup(clusterName string, service *v1.Service, if dirtySg { sg.SecurityRules = &updatedRules klog.V(2).Infof("reconcileSecurityGroup for service(%s): sg(%s) - updating", serviceName, *sg.Name) - klog.V(10).Infof("CreateOrUpdateSGWithRetry(%q): start", *sg.Name) - err := az.CreateOrUpdateSGWithRetry(service, sg) + klog.V(10).Infof("CreateOrUpdateSecurityGroup(%q): start", *sg.Name) + err := az.CreateOrUpdateSecurityGroup(service, sg) if err != nil { klog.V(2).Infof("ensure(%s) abort backoff: sg(%s) - updating", serviceName, *sg.Name) // TODO (Nov 2017): remove when augmented security rules are out of preview @@ -1157,7 +1157,7 @@ func (az *Cloud) reconcileSecurityGroup(clusterName string, service *v1.Service, // END TODO return nil, err } - klog.V(10).Infof("CreateOrUpdateSGWithRetry(%q): end", *sg.Name) + klog.V(10).Infof("CreateOrUpdateSecurityGroup(%q): end", *sg.Name) } return &sg, nil } @@ -1315,7 +1315,7 @@ func (az *Cloud) reconcilePublicIP(clusterName string, service *v1.Service, lb * pipResourceGroup := az.getPublicIPAddressResourceGroup(service) - pips, err := az.ListPIPWithRetry(service, pipResourceGroup) + pips, err := az.ListPIP(service, pipResourceGroup) if err != nil { return nil, err } @@ -1414,7 +1414,7 @@ func (az *Cloud) safeDeletePublicIP(service *v1.Service, pipResourceGroup string // Update load balancer when frontendIPConfigUpdated or loadBalancerRuleUpdated. if frontendIPConfigUpdated || loadBalancerRuleUpdated { - err := az.CreateOrUpdateLBWithRetry(service, *lb) + err := az.CreateOrUpdateLB(service, *lb) if err != nil { klog.Errorf("safeDeletePublicIP for service(%s) failed with error: %v", getServiceName(service), err) return err @@ -1423,14 +1423,14 @@ func (az *Cloud) safeDeletePublicIP(service *v1.Service, pipResourceGroup string } pipName := to.String(pip.Name) - klog.V(10).Infof("DeletePublicIPWithRetry(%s, %q): start", pipResourceGroup, pipName) - err := az.DeletePublicIPWithRetry(service, pipResourceGroup, pipName) + klog.V(10).Infof("DeletePublicIP(%s, %q): start", pipResourceGroup, pipName) + err := az.DeletePublicIP(service, pipResourceGroup, pipName) if err != nil { if err = ignoreStatusNotFoundFromError(err); err != nil { return err } } - klog.V(10).Infof("DeletePublicIPWithRetry(%s, %q): end", pipResourceGroup, pipName) + klog.V(10).Infof("DeletePublicIP(%s, %q): end", pipResourceGroup, pipName) return nil } diff --git a/pkg/cloudprovider/providers/azure/azure_routes.go b/pkg/cloudprovider/providers/azure/azure_routes.go index 36219b2f917..3a586263148 100644 --- a/pkg/cloudprovider/providers/azure/azure_routes.go +++ b/pkg/cloudprovider/providers/azure/azure_routes.go @@ -20,11 +20,11 @@ import ( "context" "fmt" - cloudprovider "k8s.io/cloud-provider" - "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2017-09-01/network" "github.com/Azure/go-autorest/autorest/to" + "k8s.io/apimachinery/pkg/types" + cloudprovider "k8s.io/cloud-provider" "k8s.io/klog" ) @@ -104,18 +104,7 @@ func (az *Cloud) createRouteTable() error { } klog.V(3).Infof("createRouteTableIfNotExists: creating routetable. routeTableName=%q", az.RouteTableName) - ctx, cancel := getContextWithCancel() - defer cancel() - resp, err := az.RouteTablesClient.CreateOrUpdate(ctx, az.ResourceGroup, az.RouteTableName, routeTable) - klog.V(10).Infof("RouteTablesClient.CreateOrUpdate(%q): end", az.RouteTableName) - if az.CloudProviderBackoff && shouldRetryHTTPRequest(resp, err) { - klog.V(2).Infof("createRouteTableIfNotExists backing off: creating routetable. routeTableName=%q", az.RouteTableName) - retryErr := az.CreateOrUpdateRouteTableWithRetry(routeTable) - if retryErr != nil { - err = retryErr - klog.V(2).Infof("createRouteTableIfNotExists abort backoff: creating routetable. routeTableName=%q", az.RouteTableName) - } - } + err := az.CreateOrUpdateRouteTable(routeTable) if err != nil { return err } @@ -163,18 +152,7 @@ func (az *Cloud) CreateRoute(ctx context.Context, clusterName string, nameHint s } klog.V(3).Infof("CreateRoute: creating route: instance=%q cidr=%q", kubeRoute.TargetNode, kubeRoute.DestinationCIDR) - ctx, cancel := getContextWithCancel() - defer cancel() - resp, err := az.RoutesClient.CreateOrUpdate(ctx, az.ResourceGroup, az.RouteTableName, *route.Name, route) - klog.V(10).Infof("RoutesClient.CreateOrUpdate(%q): end", az.RouteTableName) - if az.CloudProviderBackoff && shouldRetryHTTPRequest(resp, err) { - klog.V(2).Infof("CreateRoute backing off: creating route: instance=%q cidr=%q", kubeRoute.TargetNode, kubeRoute.DestinationCIDR) - retryErr := az.CreateOrUpdateRouteWithRetry(route) - if retryErr != nil { - err = retryErr - klog.V(2).Infof("CreateRoute abort backoff: creating route: instance=%q cidr=%q", kubeRoute.TargetNode, kubeRoute.DestinationCIDR) - } - } + err = az.CreateOrUpdateRoute(route) if err != nil { return err } @@ -202,20 +180,8 @@ func (az *Cloud) DeleteRoute(ctx context.Context, clusterName string, kubeRoute klog.V(2).Infof("DeleteRoute: deleting route. clusterName=%q instance=%q cidr=%q", clusterName, kubeRoute.TargetNode, kubeRoute.DestinationCIDR) - ctx, cancel := getContextWithCancel() - defer cancel() routeName := mapNodeNameToRouteName(kubeRoute.TargetNode) - resp, err := az.RoutesClient.Delete(ctx, az.ResourceGroup, az.RouteTableName, routeName) - klog.V(10).Infof("RoutesClient.Delete(%q): end", az.RouteTableName) - - if az.CloudProviderBackoff && shouldRetryHTTPRequest(resp, err) { - klog.V(2).Infof("DeleteRoute backing off: deleting route. clusterName=%q instance=%q cidr=%q", clusterName, kubeRoute.TargetNode, kubeRoute.DestinationCIDR) - retryErr := az.DeleteRouteWithRetry(routeName) - if retryErr != nil { - err = retryErr - klog.V(2).Infof("DeleteRoute abort backoff: deleting route. clusterName=%q instance=%q cidr=%q", clusterName, kubeRoute.TargetNode, kubeRoute.DestinationCIDR) - } - } + err = az.DeleteRouteWithName(routeName) if err != nil { return err } diff --git a/pkg/cloudprovider/providers/azure/azure_standard.go b/pkg/cloudprovider/providers/azure/azure_standard.go index 95126f58b0f..baad60fd639 100644 --- a/pkg/cloudprovider/providers/azure/azure_standard.go +++ b/pkg/cloudprovider/providers/azure/azure_standard.go @@ -26,16 +26,16 @@ import ( "strconv" "strings" - "k8s.io/api/core/v1" - cloudprovider "k8s.io/cloud-provider" - "github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2018-10-01/compute" "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2017-09-01/network" "github.com/Azure/go-autorest/autorest/to" + + "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/types" utilerrors "k8s.io/apimachinery/pkg/util/errors" "k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/uuid" + cloudprovider "k8s.io/cloud-provider" "k8s.io/klog" ) @@ -84,13 +84,13 @@ func (az *Cloud) getAvailabilitySetID(resourceGroup, availabilitySetName string) } // returns the full identifier of a loadbalancer frontendipconfiguration. -func (az *Cloud) getFrontendIPConfigID(lbName, backendPoolName string) string { +func (az *Cloud) getFrontendIPConfigID(lbName, fipConfigName string) string { return fmt.Sprintf( frontendIPConfigIDTemplate, az.SubscriptionID, az.ResourceGroup, lbName, - backendPoolName) + fipConfigName) } // returns the full identifier of a loadbalancer backendpool. @@ -294,10 +294,6 @@ outer: return -1, fmt.Errorf("securityGroup priorities are exhausted") } -func (az *Cloud) getIPForMachine(nodeName types.NodeName) (string, string, error) { - return az.vmSet.GetIPByNodeName(string(nodeName)) -} - var polyTable = crc32.MakeTable(crc32.Koopman) //MakeCRC32 : convert string to CRC32 format @@ -460,9 +456,9 @@ func (as *availabilitySet) GetIPByNodeName(name string) (string, string, error) // getAgentPoolAvailabiliySets lists the virtual machines for the resource group and then builds // a list of availability sets that match the nodes available to k8s. func (as *availabilitySet) getAgentPoolAvailabiliySets(nodes []*v1.Node) (agentPoolAvailabilitySets *[]string, err error) { - vms, err := as.VirtualMachineClientListWithRetry(as.ResourceGroup) + vms, err := as.ListVirtualMachines(as.ResourceGroup) if err != nil { - klog.Errorf("as.getNodeAvailabilitySet - VirtualMachineClientListWithRetry failed, err=%v", err) + klog.Errorf("as.getNodeAvailabilitySet - ListVirtualMachines failed, err=%v", err) return nil, err } vmNameToAvailabilitySetID := make(map[string]string, len(vms)) @@ -695,18 +691,7 @@ func (as *availabilitySet) ensureHostInPool(service *v1.Service, nodeName types. nicName := *nic.Name klog.V(3).Infof("nicupdate(%s): nic(%s) - updating", serviceName, nicName) - ctx, cancel := getContextWithCancel() - defer cancel() - resp, err := as.InterfacesClient.CreateOrUpdate(ctx, as.ResourceGroup, *nic.Name, nic) - klog.V(10).Infof("InterfacesClient.CreateOrUpdate(%q): end", *nic.Name) - if as.CloudProviderBackoff && shouldRetryHTTPRequest(resp, err) { - klog.V(2).Infof("nicupdate(%s) backing off: nic(%s) - updating, err=%v", serviceName, nicName, err) - retryErr := as.CreateOrUpdateInterfaceWithRetry(service, nic) - if retryErr != nil { - err = retryErr - klog.V(2).Infof("nicupdate(%s) abort backoff: nic(%s) - updating", serviceName, nicName) - } - } + err := as.CreateOrUpdateInterface(service, nic) if err != nil { return err } diff --git a/pkg/cloudprovider/providers/azure/azure_storageaccount.go b/pkg/cloudprovider/providers/azure/azure_storageaccount.go index 34871a11198..8dadcdc2d0f 100644 --- a/pkg/cloudprovider/providers/azure/azure_storageaccount.go +++ b/pkg/cloudprovider/providers/azure/azure_storageaccount.go @@ -64,8 +64,8 @@ func (az *Cloud) getStorageAccounts(matchingAccountType, matchingAccountKind, re return accounts, nil } -// getStorageAccesskey gets the storage account access key -func (az *Cloud) getStorageAccesskey(account, resourceGroup string) (string, error) { +// GetStorageAccesskey gets the storage account access key +func (az *Cloud) GetStorageAccesskey(account, resourceGroup string) (string, error) { ctx, cancel := getContextWithCancel() defer cancel() @@ -137,7 +137,7 @@ func (az *Cloud) ensureStorageAccount(accountName, accountType, accountKind, res } // find the access key with this account - accountKey, err := az.getStorageAccesskey(accountName, resourceGroup) + accountKey, err := az.GetStorageAccesskey(accountName, resourceGroup) if err != nil { return "", "", fmt.Errorf("could not get storage key for storage account %s: %v", accountName, err) } diff --git a/pkg/cloudprovider/providers/azure/azure_storageaccount_test.go b/pkg/cloudprovider/providers/azure/azure_storageaccount_test.go index bba66e0043f..6d6eabd2f14 100644 --- a/pkg/cloudprovider/providers/azure/azure_storageaccount_test.go +++ b/pkg/cloudprovider/providers/azure/azure_storageaccount_test.go @@ -64,7 +64,7 @@ func TestGetStorageAccessKeys(t *testing.T) { expectedKey := test.expectedKey fake.Keys = test.results fake.Err = test.err - key, err := cloud.getStorageAccesskey("acct", "rg") + key, err := cloud.GetStorageAccesskey("acct", "rg") if test.expectErr && err == nil { t.Errorf("Unexpected non-error") continue diff --git a/pkg/cloudprovider/providers/azure/azure_vmss.go b/pkg/cloudprovider/providers/azure/azure_vmss.go index 4d5df404628..26d1bd9d1af 100644 --- a/pkg/cloudprovider/providers/azure/azure_vmss.go +++ b/pkg/cloudprovider/providers/azure/azure_vmss.go @@ -27,13 +27,13 @@ import ( "github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2018-10-01/compute" "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2017-09-01/network" "github.com/Azure/go-autorest/autorest/to" - "k8s.io/klog" "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/wait" cloudprovider "k8s.io/cloud-provider" + "k8s.io/klog" ) var ( @@ -563,6 +563,30 @@ func (ss *scaleSet) GetPrimaryInterface(nodeName string) (network.Interface, err return nic, nil } +// getScaleSet gets scale set with exponential backoff retry +func (ss *scaleSet) getScaleSet(service *v1.Service, name string) (compute.VirtualMachineScaleSet, bool, error) { + if ss.Config.shouldOmitCloudProviderBackoff() { + var result compute.VirtualMachineScaleSet + var exists bool + + cached, err := ss.vmssCache.Get(name) + if err != nil { + ss.Event(service, v1.EventTypeWarning, "GetVirtualMachineScaleSet", err.Error()) + klog.Errorf("backoff: failure for scale set %q, will retry,err=%v", name, err) + return result, false, nil + } + + if cached != nil { + exists = true + result = *(cached.(*compute.VirtualMachineScaleSet)) + } + + return result, exists, err + } + + return ss.getScaleSetWithRetry(service, name) +} + // getScaleSetWithRetry gets scale set with exponential backoff retry func (ss *scaleSet) getScaleSetWithRetry(service *v1.Service, name string) (compute.VirtualMachineScaleSet, bool, error) { var result compute.VirtualMachineScaleSet @@ -621,6 +645,19 @@ func (ss *scaleSet) getPrimaryIPConfigForScaleSet(config *compute.VirtualMachine return nil, fmt.Errorf("failed to find a primary IP configuration for the scale set %q", scaleSetName) } +// createOrUpdateVMSS invokes ss.VirtualMachineScaleSetsClient.CreateOrUpdate with exponential backoff retry. +func (ss *scaleSet) createOrUpdateVMSS(service *v1.Service, virtualMachineScaleSet compute.VirtualMachineScaleSet) error { + if ss.Config.shouldOmitCloudProviderBackoff() { + ctx, cancel := getContextWithCancel() + defer cancel() + resp, err := ss.VirtualMachineScaleSetsClient.CreateOrUpdate(ctx, ss.ResourceGroup, *virtualMachineScaleSet.Name, virtualMachineScaleSet) + klog.V(10).Infof("VirtualMachineScaleSetsClient.CreateOrUpdate(%s): end", *virtualMachineScaleSet.Name) + return ss.processHTTPResponse(service, "CreateOrUpdateVMSS", resp, err) + } + + return ss.createOrUpdateVMSSWithRetry(service, virtualMachineScaleSet) +} + // createOrUpdateVMSSWithRetry invokes ss.VirtualMachineScaleSetsClient.CreateOrUpdate with exponential backoff retry. func (ss *scaleSet) createOrUpdateVMSSWithRetry(service *v1.Service, virtualMachineScaleSet compute.VirtualMachineScaleSet) error { return wait.ExponentialBackoff(ss.requestBackoff(), func() (bool, error) { @@ -632,6 +669,19 @@ func (ss *scaleSet) createOrUpdateVMSSWithRetry(service *v1.Service, virtualMach }) } +// updateVMSSInstances invokes ss.VirtualMachineScaleSetsClient.UpdateInstances with exponential backoff retry. +func (ss *scaleSet) updateVMSSInstances(service *v1.Service, scaleSetName string, vmInstanceIDs compute.VirtualMachineScaleSetVMInstanceRequiredIDs) error { + if ss.Config.shouldOmitCloudProviderBackoff() { + ctx, cancel := getContextWithCancel() + defer cancel() + resp, err := ss.VirtualMachineScaleSetsClient.UpdateInstances(ctx, ss.ResourceGroup, scaleSetName, vmInstanceIDs) + klog.V(10).Infof("VirtualMachineScaleSetsClient.UpdateInstances(%s): end", scaleSetName) + return ss.processHTTPResponse(service, "CreateOrUpdateVMSSInstance", resp, err) + } + + return ss.updateVMSSInstancesWithRetry(service, scaleSetName, vmInstanceIDs) +} + // updateVMSSInstancesWithRetry invokes ss.VirtualMachineScaleSetsClient.UpdateInstances with exponential backoff retry. func (ss *scaleSet) updateVMSSInstancesWithRetry(service *v1.Service, scaleSetName string, vmInstanceIDs compute.VirtualMachineScaleSetVMInstanceRequiredIDs) error { return wait.ExponentialBackoff(ss.requestBackoff(), func() (bool, error) { @@ -687,9 +737,9 @@ func (ss *scaleSet) getNodesScaleSets(nodes []*v1.Node) (map[string]sets.String, func (ss *scaleSet) ensureHostsInVMSetPool(service *v1.Service, backendPoolID string, vmSetName string, instanceIDs []string, isInternal bool) error { klog.V(3).Infof("ensuring hosts %q of scaleset %q in LB backendpool %q", instanceIDs, vmSetName, backendPoolID) serviceName := getServiceName(service) - virtualMachineScaleSet, exists, err := ss.getScaleSetWithRetry(service, vmSetName) + virtualMachineScaleSet, exists, err := ss.getScaleSet(service, vmSetName) if err != nil { - klog.Errorf("ss.getScaleSetWithRetry(%s) for service %q failed: %v", vmSetName, serviceName, err) + klog.Errorf("ss.getScaleSet(%s) for service %q failed: %v", vmSetName, serviceName, err) return err } if !exists { @@ -748,19 +798,7 @@ func (ss *scaleSet) ensureHostsInVMSetPool(service *v1.Service, backendPoolID st }) primaryIPConfiguration.LoadBalancerBackendAddressPools = &newBackendPools - ctx, cancel := getContextWithCancel() - defer cancel() - klog.V(3).Infof("VirtualMachineScaleSetsClient.CreateOrUpdate for service (%s): scale set (%s) - updating", serviceName, vmSetName) - resp, err := ss.VirtualMachineScaleSetsClient.CreateOrUpdate(ctx, ss.ResourceGroup, vmSetName, virtualMachineScaleSet) - klog.V(10).Infof("VirtualMachineScaleSetsClient.CreateOrUpdate(%q): end", vmSetName) - if ss.CloudProviderBackoff && shouldRetryHTTPRequest(resp, err) { - klog.V(2).Infof("VirtualMachineScaleSetsClient.CreateOrUpdate for service (%s): scale set (%s) - updating, err=%v", serviceName, vmSetName, err) - retryErr := ss.createOrUpdateVMSSWithRetry(service, virtualMachineScaleSet) - if retryErr != nil { - err = retryErr - klog.V(2).Infof("VirtualMachineScaleSetsClient.CreateOrUpdate for service (%s) abort backoff: scale set (%s) - updating", serviceName, vmSetName) - } - } + err := ss.createOrUpdateVMSS(service, virtualMachineScaleSet) if err != nil { return err } @@ -770,18 +808,7 @@ func (ss *scaleSet) ensureHostsInVMSetPool(service *v1.Service, backendPoolID st vmInstanceIDs := compute.VirtualMachineScaleSetVMInstanceRequiredIDs{ InstanceIds: &instanceIDs, } - ctx, cancel := getContextWithCancel() - defer cancel() - instanceResp, err := ss.VirtualMachineScaleSetsClient.UpdateInstances(ctx, ss.ResourceGroup, vmSetName, vmInstanceIDs) - klog.V(10).Infof("VirtualMachineScaleSetsClient.CreateOrUpdate(%q): end", vmSetName) - if ss.CloudProviderBackoff && shouldRetryHTTPRequest(instanceResp, err) { - klog.V(2).Infof("VirtualMachineScaleSetsClient.UpdateInstances for service (%s): scale set (%s) - updating, err=%v", serviceName, vmSetName, err) - retryErr := ss.updateVMSSInstancesWithRetry(service, vmSetName, vmInstanceIDs) - if retryErr != nil { - err = retryErr - klog.V(2).Infof("VirtualMachineScaleSetsClient.UpdateInstances for service (%s) abort backoff: scale set (%s) - updating", serviceName, vmSetName) - } - } + err = ss.updateVMSSInstances(service, vmSetName, vmInstanceIDs) if err != nil { return err } @@ -833,9 +860,9 @@ func (ss *scaleSet) EnsureHostsInPool(service *v1.Service, nodes []*v1.Node, bac // ensureScaleSetBackendPoolDeleted ensures the loadBalancer backendAddressPools deleted from the specified scaleset. func (ss *scaleSet) ensureScaleSetBackendPoolDeleted(service *v1.Service, poolID, ssName string) error { klog.V(3).Infof("ensuring backend pool %q deleted from scaleset %q", poolID, ssName) - virtualMachineScaleSet, exists, err := ss.getScaleSetWithRetry(service, ssName) + virtualMachineScaleSet, exists, err := ss.getScaleSet(service, ssName) if err != nil { - klog.Errorf("ss.ensureScaleSetBackendPoolDeleted(%s, %s) getScaleSetWithRetry(%s) failed: %v", poolID, ssName, ssName, err) + klog.Errorf("ss.ensureScaleSetBackendPoolDeleted(%s, %s) getScaleSet(%s) failed: %v", poolID, ssName, ssName, err) return err } if !exists { @@ -879,18 +906,7 @@ func (ss *scaleSet) ensureScaleSetBackendPoolDeleted(service *v1.Service, poolID // Update scale set with backoff. primaryIPConfiguration.LoadBalancerBackendAddressPools = &newBackendPools klog.V(3).Infof("VirtualMachineScaleSetsClient.CreateOrUpdate: scale set (%s) - updating", ssName) - ctx, cancel := getContextWithCancel() - defer cancel() - resp, err := ss.VirtualMachineScaleSetsClient.CreateOrUpdate(ctx, ss.ResourceGroup, ssName, virtualMachineScaleSet) - klog.V(10).Infof("VirtualMachineScaleSetsClient.CreateOrUpdate(%q): end", ssName) - if ss.CloudProviderBackoff && shouldRetryHTTPRequest(resp, err) { - klog.V(2).Infof("VirtualMachineScaleSetsClient.CreateOrUpdate: scale set (%s) - updating, err=%v", ssName, err) - retryErr := ss.createOrUpdateVMSSWithRetry(service, virtualMachineScaleSet) - if retryErr != nil { - err = retryErr - klog.V(2).Infof("VirtualMachineScaleSetsClient.CreateOrUpdate abort backoff: scale set (%s) - updating", ssName) - } - } + err = ss.createOrUpdateVMSS(service, virtualMachineScaleSet) if err != nil { return err } @@ -900,18 +916,7 @@ func (ss *scaleSet) ensureScaleSetBackendPoolDeleted(service *v1.Service, poolID vmInstanceIDs := compute.VirtualMachineScaleSetVMInstanceRequiredIDs{ InstanceIds: &instanceIDs, } - instanceCtx, instanceCancel := getContextWithCancel() - defer instanceCancel() - instanceResp, err := ss.VirtualMachineScaleSetsClient.UpdateInstances(instanceCtx, ss.ResourceGroup, ssName, vmInstanceIDs) - klog.V(10).Infof("VirtualMachineScaleSetsClient.UpdateInstances(%q): end", ssName) - if ss.CloudProviderBackoff && shouldRetryHTTPRequest(instanceResp, err) { - klog.V(2).Infof("VirtualMachineScaleSetsClient.UpdateInstances scale set (%s) - updating, err=%v", ssName, err) - retryErr := ss.updateVMSSInstancesWithRetry(service, ssName, vmInstanceIDs) - if retryErr != nil { - err = retryErr - klog.V(2).Infof("VirtualMachineScaleSetsClient.UpdateInstances abort backoff: scale set (%s) - updating", ssName) - } - } + err = ss.updateVMSSInstances(service, ssName, vmInstanceIDs) if err != nil { return err } @@ -919,17 +924,9 @@ func (ss *scaleSet) ensureScaleSetBackendPoolDeleted(service *v1.Service, poolID // Update virtualMachineScaleSet again. This is a workaround for removing VMSS reference from LB. // TODO: remove this workaround when figuring out the root cause. if len(newBackendPools) == 0 { - updateCtx, updateCancel := getContextWithCancel() - defer updateCancel() - klog.V(3).Infof("VirtualMachineScaleSetsClient.CreateOrUpdate: scale set (%s) - updating second time", ssName) - resp, err = ss.VirtualMachineScaleSetsClient.CreateOrUpdate(updateCtx, ss.ResourceGroup, ssName, virtualMachineScaleSet) - klog.V(10).Infof("VirtualMachineScaleSetsClient.CreateOrUpdate(%q): end", ssName) - if ss.CloudProviderBackoff && shouldRetryHTTPRequest(resp, err) { - klog.V(2).Infof("VirtualMachineScaleSetsClient.CreateOrUpdate: scale set (%s) - updating, err=%v", ssName, err) - retryErr := ss.createOrUpdateVMSSWithRetry(service, virtualMachineScaleSet) - if retryErr != nil { - klog.V(2).Infof("VirtualMachineScaleSetsClient.CreateOrUpdate abort backoff: scale set (%s) - updating", ssName) - } + err = ss.createOrUpdateVMSS(service, virtualMachineScaleSet) + if err != nil { + klog.V(2).Infof("VirtualMachineScaleSetsClient.CreateOrUpdate abort backoff: scale set (%s) - updating", ssName) } } diff --git a/pkg/cloudprovider/providers/azure/azure_vmss_cache.go b/pkg/cloudprovider/providers/azure/azure_vmss_cache.go index a9a46ba703b..534ba9d445b 100644 --- a/pkg/cloudprovider/providers/azure/azure_vmss_cache.go +++ b/pkg/cloudprovider/providers/azure/azure_vmss_cache.go @@ -132,7 +132,7 @@ func (ss *scaleSet) newAvailabilitySetNodesCache() (*timedCache, error) { } for _, resourceGroup := range resourceGroups.List() { - vmList, err := ss.Cloud.VirtualMachineClientListWithRetry(resourceGroup) + vmList, err := ss.Cloud.ListVirtualMachines(resourceGroup) if err != nil { return nil, err } diff --git a/pkg/cloudprovider/providers/cloudstack/cloudstack.go b/pkg/cloudprovider/providers/cloudstack/cloudstack.go index 4769adb647f..222a0356293 100644 --- a/pkg/cloudprovider/providers/cloudstack/cloudstack.go +++ b/pkg/cloudprovider/providers/cloudstack/cloudstack.go @@ -120,6 +120,11 @@ func newCSCloud(cfg *CSConfig) (*CSCloud, error) { return cs, nil } +var _ cloudprovider.Interface = (*CSCloud)(nil) +var _ cloudprovider.Instances = (*CSCloud)(nil) +var _ cloudprovider.LoadBalancer = (*CSCloud)(nil) +var _ cloudprovider.Zones = (*CSCloud)(nil) + // Initialize passes a Kubernetes clientBuilder interface to the cloud provider func (cs *CSCloud) Initialize(clientBuilder cloudprovider.ControllerClientBuilder, stop <-chan struct{}) { } diff --git a/pkg/cloudprovider/providers/cloudstack/metadata.go b/pkg/cloudprovider/providers/cloudstack/metadata.go index f2decccdf86..b666e076dd5 100644 --- a/pkg/cloudprovider/providers/cloudstack/metadata.go +++ b/pkg/cloudprovider/providers/cloudstack/metadata.go @@ -31,6 +31,9 @@ import ( "k8s.io/klog" ) +var _ cloudprovider.Instances = (*metadata)(nil) +var _ cloudprovider.Zones = (*metadata)(nil) + type metadata struct { dhcpServer string zone string diff --git a/pkg/cloudprovider/providers/fake/fake.go b/pkg/cloudprovider/providers/fake/fake.go index 8adf2fed214..01cec8a75a3 100644 --- a/pkg/cloudprovider/providers/fake/fake.go +++ b/pkg/cloudprovider/providers/fake/fake.go @@ -45,6 +45,14 @@ type FakeUpdateBalancerCall struct { Hosts []*v1.Node } +var _ cloudprovider.Interface = (*FakeCloud)(nil) +var _ cloudprovider.Instances = (*FakeCloud)(nil) +var _ cloudprovider.LoadBalancer = (*FakeCloud)(nil) +var _ cloudprovider.Routes = (*FakeCloud)(nil) +var _ cloudprovider.Zones = (*FakeCloud)(nil) +var _ cloudprovider.PVLabeler = (*FakeCloud)(nil) +var _ cloudprovider.Clusters = (*FakeCloud)(nil) + // FakeCloud is a test-double implementation of Interface, LoadBalancer, Instances, and Routes. It is useful for testing. type FakeCloud struct { Exists bool @@ -228,6 +236,8 @@ func (f *FakeCloud) SetNodeAddresses(nodeAddresses []v1.NodeAddress) { // It adds an entry "node-addresses-by-provider-id" into the internal method call record. func (f *FakeCloud) NodeAddressesByProviderID(ctx context.Context, providerID string) ([]v1.NodeAddress, error) { f.addCall("node-addresses-by-provider-id") + f.addressesMux.Lock() + defer f.addressesMux.Unlock() return f.Addresses, f.Err } diff --git a/pkg/cloudprovider/providers/gce/BUILD b/pkg/cloudprovider/providers/gce/BUILD index 0e590564707..92fcfc2cfaa 100644 --- a/pkg/cloudprovider/providers/gce/BUILD +++ b/pkg/cloudprovider/providers/gce/BUILD @@ -47,10 +47,6 @@ go_library( importpath = "k8s.io/kubernetes/pkg/cloudprovider/providers/gce", deps = [ "//pkg/api/v1/service:go_default_library", - "//pkg/cloudprovider/providers/gce/cloud:go_default_library", - "//pkg/cloudprovider/providers/gce/cloud/filter:go_default_library", - "//pkg/cloudprovider/providers/gce/cloud/meta:go_default_library", - "//pkg/cloudprovider/providers/gce/cloud/mock:go_default_library", "//pkg/controller:go_default_library", "//pkg/features:go_default_library", "//pkg/kubelet/apis:go_default_library", @@ -80,6 +76,10 @@ go_library( "//staging/src/k8s.io/client-go/util/flowcontrol:go_default_library", "//staging/src/k8s.io/cloud-provider:go_default_library", "//vendor/cloud.google.com/go/compute/metadata:go_default_library", + "//vendor/github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud:go_default_library", + "//vendor/github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/filter:go_default_library", + "//vendor/github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/meta:go_default_library", + "//vendor/github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/mock:go_default_library", "//vendor/github.com/prometheus/client_golang/prometheus:go_default_library", "//vendor/golang.org/x/oauth2:go_default_library", "//vendor/golang.org/x/oauth2/google:go_default_library", @@ -112,9 +112,6 @@ go_test( embed = [":go_default_library"], deps = [ "//pkg/api/v1/service:go_default_library", - "//pkg/cloudprovider/providers/gce/cloud:go_default_library", - "//pkg/cloudprovider/providers/gce/cloud/meta:go_default_library", - "//pkg/cloudprovider/providers/gce/cloud/mock:go_default_library", "//pkg/kubelet/apis:go_default_library", "//pkg/util/net/sets:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library", @@ -123,6 +120,9 @@ go_test( "//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library", "//staging/src/k8s.io/client-go/tools/record:go_default_library", "//staging/src/k8s.io/cloud-provider:go_default_library", + "//vendor/github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud:go_default_library", + "//vendor/github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/meta:go_default_library", + "//vendor/github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/mock:go_default_library", "//vendor/github.com/stretchr/testify/assert:go_default_library", "//vendor/github.com/stretchr/testify/require:go_default_library", "//vendor/golang.org/x/oauth2/google:go_default_library", @@ -142,9 +142,6 @@ filegroup( filegroup( name = "all-srcs", - srcs = [ - ":package-srcs", - "//pkg/cloudprovider/providers/gce/cloud:all-srcs", - ], + srcs = [":package-srcs"], tags = ["automanaged"], ) diff --git a/pkg/cloudprovider/providers/gce/cloud/BUILD b/pkg/cloudprovider/providers/gce/cloud/BUILD deleted file mode 100644 index e3c289daa6f..00000000000 --- a/pkg/cloudprovider/providers/gce/cloud/BUILD +++ /dev/null @@ -1,67 +0,0 @@ -load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") - -go_library( - name = "go_default_library", - srcs = [ - "constants.go", - "context.go", - "doc.go", - "gce_projects.go", - "gen.go", - "op.go", - "project.go", - "ratelimit.go", - "service.go", - "utils.go", - ], - importpath = "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud", - visibility = ["//visibility:public"], - deps = [ - "//pkg/cloudprovider/providers/gce/cloud/filter:go_default_library", - "//pkg/cloudprovider/providers/gce/cloud/meta:go_default_library", - "//vendor/google.golang.org/api/compute/v0.alpha:go_default_library", - "//vendor/google.golang.org/api/compute/v0.beta:go_default_library", - "//vendor/google.golang.org/api/compute/v1:go_default_library", - "//vendor/google.golang.org/api/googleapi:go_default_library", - "//vendor/k8s.io/klog:go_default_library", - ], -) - -go_test( - name = "go_default_test", - srcs = [ - "gen_test.go", - "mock_test.go", - "ratelimit_test.go", - "service_test.go", - "utils_test.go", - ], - embed = [":go_default_library"], - deps = [ - "//pkg/cloudprovider/providers/gce/cloud/filter:go_default_library", - "//pkg/cloudprovider/providers/gce/cloud/meta:go_default_library", - "//vendor/google.golang.org/api/compute/v0.alpha:go_default_library", - "//vendor/google.golang.org/api/compute/v0.beta:go_default_library", - "//vendor/google.golang.org/api/compute/v1:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [ - ":package-srcs", - "//pkg/cloudprovider/providers/gce/cloud/filter:all-srcs", - "//pkg/cloudprovider/providers/gce/cloud/gen:all-srcs", - "//pkg/cloudprovider/providers/gce/cloud/meta:all-srcs", - "//pkg/cloudprovider/providers/gce/cloud/mock:all-srcs", - ], - tags = ["automanaged"], - visibility = ["//visibility:public"], -) diff --git a/pkg/cloudprovider/providers/gce/cloud/filter/filter_test.go b/pkg/cloudprovider/providers/gce/cloud/filter/filter_test.go deleted file mode 100644 index 46b3c279a47..00000000000 --- a/pkg/cloudprovider/providers/gce/cloud/filter/filter_test.go +++ /dev/null @@ -1,176 +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 filter - -import ( - "reflect" - "testing" -) - -func TestFilterToString(t *testing.T) { - t.Parallel() - - for _, tc := range []struct { - f *F - want string - }{ - {Regexp("field1", "abc"), `field1 eq abc`}, - {NotRegexp("field1", "abc"), `field1 ne abc`}, - {EqualInt("field1", 13), "field1 eq 13"}, - {NotEqualInt("field1", 13), "field1 ne 13"}, - {EqualBool("field1", true), "field1 eq true"}, - {NotEqualBool("field1", true), "field1 ne true"}, - {Regexp("field1", "abc").AndRegexp("field2", "def"), `(field1 eq abc) (field2 eq def)`}, - {Regexp("field1", "abc").AndNotEqualInt("field2", 17), `(field1 eq abc) (field2 ne 17)`}, - {Regexp("field1", "abc").And(EqualInt("field2", 17)), `(field1 eq abc) (field2 eq 17)`}, - } { - if tc.f.String() != tc.want { - t.Errorf("filter %#v String() = %q, want %q", tc.f, tc.f.String(), tc.want) - } - } -} - -func TestFilterMatch(t *testing.T) { - t.Parallel() - - type inner struct { - X string - } - type S struct { - S string - I int - B bool - Unhandled struct{} - NestedField *inner - } - - for _, tc := range []struct { - f *F - o interface{} - want bool - }{ - {f: None, o: &S{}, want: true}, - {f: Regexp("s", "abc"), o: &S{}}, - {f: EqualInt("i", 10), o: &S{}}, - {f: EqualBool("b", true), o: &S{}}, - {f: NotRegexp("s", "abc"), o: &S{}, want: true}, - {f: NotEqualInt("i", 10), o: &S{}, want: true}, - {f: NotEqualBool("b", true), o: &S{}, want: true}, - {f: Regexp("s", "abc").AndEqualBool("b", true), o: &S{}}, - {f: Regexp("s", "abc"), o: &S{S: "abc"}, want: true}, - {f: Regexp("s", "a.*"), o: &S{S: "abc"}, want: true}, - {f: Regexp("s", "a((("), o: &S{S: "abc"}}, - {f: NotRegexp("s", "abc"), o: &S{S: "abc"}}, - {f: EqualInt("i", 10), o: &S{I: 11}}, - {f: EqualInt("i", 10), o: &S{I: 10}, want: true}, - {f: Regexp("s", "abc").AndEqualBool("b", true), o: &S{S: "abc"}}, - {f: Regexp("s", "abcd").AndEqualBool("b", true), o: &S{S: "abc"}}, - {f: Regexp("s", "abc").AndEqualBool("b", true), o: &S{S: "abc", B: true}, want: true}, - {f: Regexp("s", "abc").And(EqualBool("b", true)), o: &S{S: "abc", B: true}, want: true}, - {f: Regexp("unhandled", "xyz"), o: &S{}}, - {f: Regexp("nested_field.x", "xyz"), o: &S{}}, - {f: Regexp("nested_field.x", "xyz"), o: &S{NestedField: &inner{"xyz"}}, want: true}, - {f: NotRegexp("nested_field.x", "xyz"), o: &S{NestedField: &inner{"xyz"}}}, - {f: Regexp("nested_field.y", "xyz"), o: &S{NestedField: &inner{"xyz"}}}, - {f: Regexp("nested_field", "xyz"), o: &S{NestedField: &inner{"xyz"}}}, - } { - got := tc.f.Match(tc.o) - if got != tc.want { - t.Errorf("%v: Match(%+v) = %v, want %v", tc.f, tc.o, got, tc.want) - } - } -} - -func TestFilterSnakeToCamelCase(t *testing.T) { - t.Parallel() - - for _, tc := range []struct { - s string - want string - }{ - {"", ""}, - {"abc", "Abc"}, - {"_foo", "Foo"}, - {"a_b_c", "ABC"}, - {"a_BC_def", "ABCDef"}, - {"a_Bc_def", "ABcDef"}, - } { - got := snakeToCamelCase(tc.s) - if got != tc.want { - t.Errorf("snakeToCamelCase(%q) = %q, want %q", tc.s, got, tc.want) - } - } -} - -func TestFilterExtractValue(t *testing.T) { - t.Parallel() - - type nest2 struct { - Y string - } - type nest struct { - X string - Nest2 nest2 - } - st := &struct { - S string - I int - F bool - Nest nest - NestPtr *nest - - Unhandled float64 - }{ - "abc", - 13, - true, - nest{"xyz", nest2{"zzz"}}, - &nest{"yyy", nest2{}}, - 0.0, - } - - for _, tc := range []struct { - path string - o interface{} - want interface{} - wantErr bool - }{ - {path: "s", o: st, want: "abc"}, - {path: "i", o: st, want: 13}, - {path: "f", o: st, want: true}, - {path: "nest.x", o: st, want: "xyz"}, - {path: "nest_ptr.x", o: st, want: "yyy"}, - // Error cases. - {path: "", o: st, wantErr: true}, - {path: "no_such_field", o: st, wantErr: true}, - {path: "s.invalid_type", o: st, wantErr: true}, - {path: "unhandled", o: st, wantErr: true}, - {path: "nest.x", o: &struct{ Nest *nest }{}, wantErr: true}, - } { - o, err := extractValue(tc.path, tc.o) - gotErr := err != nil - if gotErr != tc.wantErr { - t.Errorf("extractValue(%v, %+v) = %v, %v; gotErr = %v, tc.wantErr = %v", tc.path, tc.o, o, err, gotErr, tc.wantErr) - } - if err != nil { - continue - } - if !reflect.DeepEqual(o, tc.want) { - t.Errorf("extractValue(%v, %+v) = %v, nil; want %v, nil", tc.path, tc.o, o, tc.want) - } - } -} diff --git a/pkg/cloudprovider/providers/gce/cloud/gen/main.go b/pkg/cloudprovider/providers/gce/cloud/gen/main.go deleted file mode 100644 index ff45ccb3e11..00000000000 --- a/pkg/cloudprovider/providers/gce/cloud/gen/main.go +++ /dev/null @@ -1,1376 +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. -*/ - -// Generator for GCE compute wrapper code. You must regenerate the code after -// modifying this file: -// -// $ go run gen/main.go > gen.go -package main - -import ( - "bytes" - "flag" - "fmt" - "io" - "log" - "os" - "os/exec" - "text/template" - "time" - - "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta" -) - -const ( - gofmt = "gofmt" - packageRoot = "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud" - - // readOnly specifies that the given resource is read-only and should not - // have insert() or delete() methods generated for the wrapper. - readOnly = iota -) - -var flags = struct { - gofmt bool - mode string -}{} - -func init() { - flag.BoolVar(&flags.gofmt, "gofmt", true, "run output through gofmt") - flag.StringVar(&flags.mode, "mode", "src", "content to generate: src, test, dummy") -} - -// gofmtContent runs "gofmt" on the given contents. -func gofmtContent(r io.Reader) string { - cmd := exec.Command(gofmt, "-s") - out := &bytes.Buffer{} - cmd.Stdin = r - cmd.Stdout = out - cmdErr := &bytes.Buffer{} - cmd.Stderr = cmdErr - - if err := cmd.Run(); err != nil { - fmt.Fprintf(os.Stderr, cmdErr.String()) - panic(err) - } - return out.String() -} - -// genHeader generate the header for the file. -func genHeader(wr io.Writer) { - const text = `/* -Copyright {{.Year}} 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. -*/ - -// This file was generated by "go run gen/main.go > gen.go". Do not edit -// directly. - -package cloud - -import ( - "context" - "fmt" - "net/http" - "sync" - - "google.golang.org/api/googleapi" - "k8s.io/klog" - - "{{.PackageRoot}}/filter" - "{{.PackageRoot}}/meta" - -` - tmpl := template.Must(template.New("header").Parse(text)) - values := map[string]string{ - "Year": fmt.Sprintf("%v", time.Now().Year()), - "PackageRoot": packageRoot, - } - if err := tmpl.Execute(wr, values); err != nil { - panic(err) - } - - var hasGA, hasAlpha, hasBeta bool - for _, s := range meta.AllServices { - switch s.Version() { - case meta.VersionGA: - hasGA = true - case meta.VersionAlpha: - hasAlpha = true - case meta.VersionBeta: - hasBeta = true - } - } - if hasAlpha { - fmt.Fprintln(wr, ` alpha "google.golang.org/api/compute/v0.alpha"`) - } - if hasBeta { - fmt.Fprintln(wr, ` beta "google.golang.org/api/compute/v0.beta"`) - } - if hasGA { - fmt.Fprintln(wr, ` ga "google.golang.org/api/compute/v1"`) - } - fmt.Fprintf(wr, ")\n\n") -} - -// genStubs generates the interface and wrapper stubs. -func genStubs(wr io.Writer) { - const text = `// Cloud is an interface for the GCE compute API. -type Cloud interface { -{{- range .All}} - {{.WrapType}}() {{.WrapType}} -{{- end}} -} - -// NewGCE returns a GCE. -func NewGCE(s *Service) *GCE { - g := &GCE{ - {{- range .All}} - {{.Field}}: &{{.GCEWrapType}}{s}, - {{- end}} - } - return g -} - -// GCE implements Cloud. -var _ Cloud = (*GCE)(nil) - -// GCE is the golang adapter for the compute APIs. -type GCE struct { -{{- range .All}} - {{.Field}} *{{.GCEWrapType}} -{{- end}} -} - -{{range .All}} -// {{.WrapType}} returns the interface for the {{.Version}} {{.Service}}. -func (gce *GCE) {{.WrapType}}() {{.WrapType}} { - return gce.{{.Field}} -} -{{- end}} - -// NewMockGCE returns a new mock for GCE. -func NewMockGCE(projectRouter ProjectRouter) *MockGCE { - {{- range .Groups}} - mock{{.Service}}Objs := map[meta.Key]*Mock{{.Service}}Obj{} - {{- end}} - - mock := &MockGCE{ - {{- range .All}} - {{.MockField}}: New{{.MockWrapType}}(projectRouter, mock{{.Service}}Objs), - {{- end}} - } - return mock -} - -// MockGCE implements Cloud. -var _ Cloud = (*MockGCE)(nil) - -// MockGCE is the mock for the compute API. -type MockGCE struct { -{{- range .All}} - {{.MockField}} *{{.MockWrapType}} -{{- end}} -} -{{range .All}} -// {{.WrapType}} returns the interface for the {{.Version}} {{.Service}}. -func (mock *MockGCE) {{.WrapType}}() {{.WrapType}} { - return mock.{{.MockField}} -} -{{end}} - -{{range .Groups}} -// Mock{{.Service}}Obj is used to store the various object versions in the shared -// map of mocked objects. This allows for multiple API versions to co-exist and -// share the same "view" of the objects in the backend. -type Mock{{.Service}}Obj struct { - Obj interface{} -} -{{- if .HasAlpha}} -// ToAlpha retrieves the given version of the object. -func (m *Mock{{.Service}}Obj) ToAlpha() *{{.Alpha.FQObjectType}} { - if ret, ok := m.Obj.(*{{.Alpha.FQObjectType}}); ok { - return ret - } - // Convert the object via JSON copying to the type that was requested. - ret := &{{.Alpha.FQObjectType}}{} - if err := copyViaJSON(ret, m.Obj); err != nil { - klog.Errorf("Could not convert %T to *{{.Alpha.FQObjectType}} via JSON: %v", m.Obj, err) - } - return ret -} -{{- end}} -{{- if .HasBeta}} -// ToBeta retrieves the given version of the object. -func (m *Mock{{.Service}}Obj) ToBeta() *{{.Beta.FQObjectType}} { - if ret, ok := m.Obj.(*{{.Beta.FQObjectType}}); ok { - return ret - } - // Convert the object via JSON copying to the type that was requested. - ret := &{{.Beta.FQObjectType}}{} - if err := copyViaJSON(ret, m.Obj); err != nil { - klog.Errorf("Could not convert %T to *{{.Beta.FQObjectType}} via JSON: %v", m.Obj, err) - } - return ret -} -{{- end}} -{{- if .HasGA}} -// ToGA retrieves the given version of the object. -func (m *Mock{{.Service}}Obj) ToGA() *{{.GA.FQObjectType}} { - if ret, ok := m.Obj.(*{{.GA.FQObjectType}}); ok { - return ret - } - // Convert the object via JSON copying to the type that was requested. - ret := &{{.GA.FQObjectType}}{} - if err := copyViaJSON(ret, m.Obj); err != nil { - klog.Errorf("Could not convert %T to *{{.GA.FQObjectType}} via JSON: %v", m.Obj, err) - } - return ret -} -{{- end}} -{{- end}} -` - data := struct { - All []*meta.ServiceInfo - Groups map[string]*meta.ServiceGroup - }{meta.AllServices, meta.AllServicesByGroup} - - tmpl := template.Must(template.New("interface").Parse(text)) - if err := tmpl.Execute(wr, data); err != nil { - panic(err) - } -} - -// genTypes generates the type wrappers. -func genTypes(wr io.Writer) { - const text = `// {{.WrapType}} is an interface that allows for mocking of {{.Service}}. -type {{.WrapType}} interface { -{{- if .GenerateCustomOps}} - // {{.WrapTypeOps}} is an interface with additional non-CRUD type methods. - // This interface is expected to be implemented by hand (non-autogenerated). - {{.WrapTypeOps}} -{{- end}} -{{- if .GenerateGet}} - Get(ctx context.Context, key *meta.Key) (*{{.FQObjectType}}, error) -{{- end -}} -{{- if .GenerateList}} -{{- if .KeyIsGlobal}} - List(ctx context.Context, fl *filter.F) ([]*{{.FQObjectType}}, error) -{{- end -}} -{{- if .KeyIsRegional}} - List(ctx context.Context, region string, fl *filter.F) ([]*{{.FQObjectType}}, error) -{{- end -}} -{{- if .KeyIsZonal}} - List(ctx context.Context, zone string, fl *filter.F) ([]*{{.FQObjectType}}, error) -{{- end -}} -{{- end -}} -{{- if .GenerateInsert}} - Insert(ctx context.Context, key *meta.Key, obj *{{.FQObjectType}}) error -{{- end -}} -{{- if .GenerateDelete}} - Delete(ctx context.Context, key *meta.Key) error -{{- end -}} -{{- if .AggregatedList}} - AggregatedList(ctx context.Context, fl *filter.F) (map[string][]*{{.FQObjectType}}, error) -{{- end}} -{{- with .Methods -}} -{{- range .}} - {{.InterfaceFunc}} -{{- end -}} -{{- end}} -} - -// New{{.MockWrapType}} returns a new mock for {{.Service}}. -func New{{.MockWrapType}}(pr ProjectRouter, objs map[meta.Key]*Mock{{.Service}}Obj) *{{.MockWrapType}} { - mock := &{{.MockWrapType}}{ - ProjectRouter: pr, - - Objects: objs, - {{- if .GenerateGet}} - GetError: map[meta.Key]error{}, - {{- end -}} - {{- if .GenerateInsert}} - InsertError: map[meta.Key]error{}, - {{- end -}} - {{- if .GenerateDelete}} - DeleteError: map[meta.Key]error{}, - {{- end}} - } - return mock -} - -// {{.MockWrapType}} is the mock for {{.Service}}. -type {{.MockWrapType}} struct { - Lock sync.Mutex - - ProjectRouter ProjectRouter - - // Objects maintained by the mock. - Objects map[meta.Key]*Mock{{.Service}}Obj - - // If an entry exists for the given key and operation, then the error - // will be returned instead of the operation. - {{- if .GenerateGet}} - GetError map[meta.Key]error - {{- end -}} - {{- if .GenerateList}} - ListError *error - {{- end -}} - {{- if .GenerateInsert}} - InsertError map[meta.Key]error - {{- end -}} - {{- if .GenerateDelete}} - DeleteError map[meta.Key]error - {{- end -}} - {{- if .AggregatedList}} - AggregatedListError *error - {{- end}} - - // xxxHook allow you to intercept the standard processing of the mock in - // order to add your own logic. Return (true, _, _) to prevent the normal - // execution flow of the mock. Return (false, nil, nil) to continue with - // normal mock behavior/ after the hook function executes. - {{- if .GenerateGet}} - GetHook func(ctx context.Context, key *meta.Key, m *{{.MockWrapType}}) (bool, *{{.FQObjectType}}, error) - {{- end -}} - {{- if .GenerateList}} - {{- if .KeyIsGlobal}} - ListHook func(ctx context.Context, fl *filter.F, m *{{.MockWrapType}}) (bool, []*{{.FQObjectType}}, error) - {{- end -}} - {{- if .KeyIsRegional}} - ListHook func(ctx context.Context, region string, fl *filter.F, m *{{.MockWrapType}}) (bool, []*{{.FQObjectType}}, error) - {{- end -}} - {{- if .KeyIsZonal}} - ListHook func(ctx context.Context, zone string, fl *filter.F, m *{{.MockWrapType}}) (bool, []*{{.FQObjectType}}, error) - {{- end}} - {{- end -}} - {{- if .GenerateInsert}} - InsertHook func(ctx context.Context, key *meta.Key, obj *{{.FQObjectType}}, m *{{.MockWrapType}}) (bool, error) - {{- end -}} - {{- if .GenerateDelete}} - DeleteHook func(ctx context.Context, key *meta.Key, m *{{.MockWrapType}}) (bool, error) - {{- end -}} - {{- if .AggregatedList}} - AggregatedListHook func(ctx context.Context, fl *filter.F, m *{{.MockWrapType}}) (bool, map[string][]*{{.FQObjectType}}, error) - {{- end}} - -{{- with .Methods -}} -{{- range .}} - {{.MockHook}} -{{- end -}} -{{- end}} - - // X is extra state that can be used as part of the mock. Generated code - // will not use this field. - X interface{} -} - -{{- if .GenerateGet}} -// Get returns the object from the mock. -func (m *{{.MockWrapType}}) Get(ctx context.Context, key *meta.Key) (*{{.FQObjectType}}, error) { - if m.GetHook != nil { - if intercept, obj, err := m.GetHook(ctx, key, m); intercept { - klog.V(5).Infof("{{.MockWrapType}}.Get(%v, %s) = %+v, %v", ctx, key, obj ,err) - return obj, err - } - } - if !key.Valid() { - return nil, fmt.Errorf("invalid GCE key (%+v)", key) - } - - m.Lock.Lock() - defer m.Lock.Unlock() - - if err, ok := m.GetError[*key]; ok { - klog.V(5).Infof("{{.MockWrapType}}.Get(%v, %s) = nil, %v", ctx, key, err) - return nil, err - } - if obj, ok := m.Objects[*key]; ok { - typedObj := obj.To{{.VersionTitle}}() - klog.V(5).Infof("{{.MockWrapType}}.Get(%v, %s) = %+v, nil", ctx, key, typedObj) - return typedObj, nil - } - - err := &googleapi.Error{ - Code: http.StatusNotFound, - Message: fmt.Sprintf("{{.MockWrapType}} %v not found", key), - } - klog.V(5).Infof("{{.MockWrapType}}.Get(%v, %s) = nil, %v", ctx, key, err) - return nil, err -} -{{- end}} - -{{- if .GenerateList}} -{{if .KeyIsGlobal -}} -// List all of the objects in the mock. -func (m *{{.MockWrapType}}) List(ctx context.Context, fl *filter.F) ([]*{{.FQObjectType}}, error) { -{{- end -}} -{{- if .KeyIsRegional -}} -// List all of the objects in the mock in the given region. -func (m *{{.MockWrapType}}) List(ctx context.Context, region string, fl *filter.F) ([]*{{.FQObjectType}}, error) { -{{- end -}} -{{- if .KeyIsZonal -}} -// List all of the objects in the mock in the given zone. -func (m *{{.MockWrapType}}) List(ctx context.Context, zone string, fl *filter.F) ([]*{{.FQObjectType}}, error) { -{{- end}} - if m.ListHook != nil { - {{if .KeyIsGlobal -}} - if intercept, objs, err := m.ListHook(ctx, fl, m); intercept { - klog.V(5).Infof("{{.MockWrapType}}.List(%v, %v) = [%v items], %v", ctx, fl, len(objs), err) - {{- end -}} - {{- if .KeyIsRegional -}} - if intercept, objs, err := m.ListHook(ctx, region, fl, m); intercept { - klog.V(5).Infof("{{.MockWrapType}}.List(%v, %q, %v) = [%v items], %v", ctx, region, fl, len(objs), err) - {{- end -}} - {{- if .KeyIsZonal -}} - if intercept, objs, err := m.ListHook(ctx, zone, fl, m); intercept { - klog.V(5).Infof("{{.MockWrapType}}.List(%v, %q, %v) = [%v items], %v", ctx, zone, fl, len(objs), err) - {{- end}} - return objs, err - } - } - - m.Lock.Lock() - defer m.Lock.Unlock() - - if m.ListError != nil { - err := *m.ListError - {{if .KeyIsGlobal -}} - klog.V(5).Infof("{{.MockWrapType}}.List(%v, %v) = nil, %v", ctx, fl, err) - {{- end -}} - {{- if .KeyIsRegional -}} - klog.V(5).Infof("{{.MockWrapType}}.List(%v, %q, %v) = nil, %v", ctx, region, fl, err) - {{- end -}} - {{- if .KeyIsZonal -}} - klog.V(5).Infof("{{.MockWrapType}}.List(%v, %q, %v) = nil, %v", ctx, zone, fl, err) - {{- end}} - - return nil, *m.ListError - } - - var objs []*{{.FQObjectType}} -{{- if .KeyIsGlobal}} - for _, obj := range m.Objects { -{{- else}} - for key, obj := range m.Objects { -{{- end -}} -{{- if .KeyIsRegional}} - if key.Region != region { - continue - } -{{- end -}} -{{- if .KeyIsZonal}} - if key.Zone != zone { - continue - } -{{- end}} - if !fl.Match(obj.To{{.VersionTitle}}()) { - continue - } - objs = append(objs, obj.To{{.VersionTitle}}()) - } - - {{if .KeyIsGlobal -}} - klog.V(5).Infof("{{.MockWrapType}}.List(%v, %v) = [%v items], nil", ctx, fl, len(objs)) - {{- end -}} - {{- if .KeyIsRegional -}} - klog.V(5).Infof("{{.MockWrapType}}.List(%v, %q, %v) = [%v items], nil", ctx, region, fl, len(objs)) - {{- end -}} - {{- if .KeyIsZonal -}} - klog.V(5).Infof("{{.MockWrapType}}.List(%v, %q, %v) = [%v items], nil", ctx, zone, fl, len(objs)) - {{- end}} - return objs, nil -} -{{- end}} - -{{- if .GenerateInsert}} -// Insert is a mock for inserting/creating a new object. -func (m *{{.MockWrapType}}) Insert(ctx context.Context, key *meta.Key, obj *{{.FQObjectType}}) error { - if m.InsertHook != nil { - if intercept, err := m.InsertHook(ctx, key, obj, m); intercept { - klog.V(5).Infof("{{.MockWrapType}}.Insert(%v, %v, %+v) = %v", ctx, key, obj, err) - return err - } - } - if !key.Valid() { - return fmt.Errorf("invalid GCE key (%+v)", key) - } - - m.Lock.Lock() - defer m.Lock.Unlock() - - if err, ok := m.InsertError[*key]; ok { - klog.V(5).Infof("{{.MockWrapType}}.Insert(%v, %v, %+v) = %v", ctx, key, obj, err) - return err - } - if _, ok := m.Objects[*key]; ok { - err := &googleapi.Error{ - Code: http.StatusConflict, - Message: fmt.Sprintf("{{.MockWrapType}} %v exists", key), - } - klog.V(5).Infof("{{.MockWrapType}}.Insert(%v, %v, %+v) = %v", ctx, key, obj, err) - return err - } - - obj.Name = key.Name - projectID := m.ProjectRouter.ProjectID(ctx, "{{.Version}}", "{{.Resource}}") - obj.SelfLink = SelfLink(meta.Version{{.VersionTitle}}, projectID, "{{.Resource}}", key) - - m.Objects[*key] = &Mock{{.Service}}Obj{obj} - klog.V(5).Infof("{{.MockWrapType}}.Insert(%v, %v, %+v) = nil", ctx, key, obj) - return nil -} -{{- end}} - -{{- if .GenerateDelete}} -// Delete is a mock for deleting the object. -func (m *{{.MockWrapType}}) Delete(ctx context.Context, key *meta.Key) error { - if m.DeleteHook != nil { - if intercept, err := m.DeleteHook(ctx, key, m); intercept { - klog.V(5).Infof("{{.MockWrapType}}.Delete(%v, %v) = %v", ctx, key, err) - return err - } - } - if !key.Valid() { - return fmt.Errorf("invalid GCE key (%+v)", key) - } - - m.Lock.Lock() - defer m.Lock.Unlock() - - if err, ok := m.DeleteError[*key]; ok { - klog.V(5).Infof("{{.MockWrapType}}.Delete(%v, %v) = %v", ctx, key, err) - return err - } - if _, ok := m.Objects[*key]; !ok { - err := &googleapi.Error{ - Code: http.StatusNotFound, - Message: fmt.Sprintf("{{.MockWrapType}} %v not found", key), - } - klog.V(5).Infof("{{.MockWrapType}}.Delete(%v, %v) = %v", ctx, key, err) - return err - } - - delete(m.Objects, *key) - klog.V(5).Infof("{{.MockWrapType}}.Delete(%v, %v) = nil", ctx, key) - return nil -} -{{- end}} - -{{- if .AggregatedList}} -// AggregatedList is a mock for AggregatedList. -func (m *{{.MockWrapType}}) AggregatedList(ctx context.Context, fl *filter.F) (map[string][]*{{.FQObjectType}}, error) { - if m.AggregatedListHook != nil { - if intercept, objs, err := m.AggregatedListHook(ctx, fl, m); intercept { - klog.V(5).Infof("{{.MockWrapType}}.AggregatedList(%v, %v) = [%v items], %v", ctx, fl, len(objs), err) - return objs, err - } - } - - m.Lock.Lock() - defer m.Lock.Unlock() - - if m.AggregatedListError != nil { - err := *m.AggregatedListError - klog.V(5).Infof("{{.MockWrapType}}.AggregatedList(%v, %v) = nil, %v", ctx, fl, err) - return nil, err - } - - objs := map[string][]*{{.FQObjectType}}{} - for _, obj := range m.Objects { - res, err := ParseResourceURL(obj.To{{.VersionTitle}}().SelfLink) - {{- if .KeyIsRegional}} - location := res.Key.Region - {{- end -}} - {{- if .KeyIsZonal}} - location := res.Key.Zone - {{- end}} - if err != nil { - klog.V(5).Infof("{{.MockWrapType}}.AggregatedList(%v, %v) = nil, %v", ctx, fl, err) - return nil, err - } - if !fl.Match(obj.To{{.VersionTitle}}()) { - continue - } - objs[location] = append(objs[location], obj.To{{.VersionTitle}}()) - } - klog.V(5).Infof("{{.MockWrapType}}.AggregatedList(%v, %v) = [%v items], nil", ctx, fl, len(objs)) - return objs, nil -} -{{- end}} - -// Obj wraps the object for use in the mock. -func (m *{{.MockWrapType}}) Obj(o *{{.FQObjectType}}) *Mock{{.Service}}Obj { - return &Mock{{.Service}}Obj{o} -} - -{{with .Methods -}} -{{- range .}} -// {{.Name}} is a mock for the corresponding method. -func (m *{{.MockWrapType}}) {{.FcnArgs}} { -{{- if .IsOperation }} - if m.{{.MockHookName}} != nil { - return m.{{.MockHookName}}(ctx, key {{.CallArgs}}, m) - } - return nil -{{- else if .IsGet}} - if m.{{.MockHookName}} != nil { - return m.{{.MockHookName}}(ctx, key {{.CallArgs}}, m) - } - return nil, fmt.Errorf("{{.MockHookName}} must be set") -{{- else if .IsPaged}} - if m.{{.MockHookName}} != nil { - return m.{{.MockHookName}}(ctx, key {{.CallArgs}}, fl, m) - } - return nil, nil -{{- end}} -} -{{end -}} -{{- end}} -// {{.GCEWrapType}} is a simplifying adapter for the GCE {{.Service}}. -type {{.GCEWrapType}} struct { - s *Service -} - -{{- if .GenerateGet}} -// Get the {{.Object}} named by key. -func (g *{{.GCEWrapType}}) Get(ctx context.Context, key *meta.Key) (*{{.FQObjectType}}, error) { - klog.V(5).Infof("{{.GCEWrapType}}.Get(%v, %v): called", ctx, key) - - if !key.Valid() { - klog.V(2).Infof("{{.GCEWrapType}}.Get(%v, %v): key is invalid (%#v)", ctx, key, key) - return nil, fmt.Errorf("invalid GCE key (%#v)", key) - } - projectID := g.s.ProjectRouter.ProjectID(ctx, "{{.Version}}", "{{.Service}}") - rk := &RateLimitKey{ - ProjectID: projectID, - Operation: "Get", - Version: meta.Version("{{.Version}}"), - Service: "{{.Service}}", - } - klog.V(5).Infof("{{.GCEWrapType}}.Get(%v, %v): projectID = %v, rk = %+v", ctx, key, projectID, rk) - if err := g.s.RateLimiter.Accept(ctx, rk); err != nil { - klog.V(4).Infof("{{.GCEWrapType}}.Get(%v, %v): RateLimiter error: %v", ctx, key, err) - return nil, err - } -{{- if .KeyIsGlobal}} - call := g.s.{{.VersionTitle}}.{{.Service}}.Get(projectID, key.Name) -{{- end -}} -{{- if .KeyIsRegional}} - call := g.s.{{.VersionTitle}}.{{.Service}}.Get(projectID, key.Region, key.Name) -{{- end -}} -{{- if .KeyIsZonal}} - call := g.s.{{.VersionTitle}}.{{.Service}}.Get(projectID, key.Zone, key.Name) -{{- end}} - call.Context(ctx) - v, err := call.Do() - klog.V(4).Infof("{{.GCEWrapType}}.Get(%v, %v) = %+v, %v", ctx, key, v, err) - return v, err -} -{{- end}} - -{{- if .GenerateList}} -// List all {{.Object}} objects. -{{- if .KeyIsGlobal}} -func (g *{{.GCEWrapType}}) List(ctx context.Context, fl *filter.F) ([]*{{.FQObjectType}}, error) { - klog.V(5).Infof("{{.GCEWrapType}}.List(%v, %v) called", ctx, fl) -{{- end -}} -{{- if .KeyIsRegional}} -func (g *{{.GCEWrapType}}) List(ctx context.Context, region string, fl *filter.F) ([]*{{.FQObjectType}}, error) { - klog.V(5).Infof("{{.GCEWrapType}}.List(%v, %v, %v) called", ctx, region, fl) -{{- end -}} -{{- if .KeyIsZonal}} -func (g *{{.GCEWrapType}}) List(ctx context.Context, zone string, fl *filter.F) ([]*{{.FQObjectType}}, error) { - klog.V(5).Infof("{{.GCEWrapType}}.List(%v, %v, %v) called", ctx, zone, fl) -{{- end}} - projectID := g.s.ProjectRouter.ProjectID(ctx, "{{.Version}}", "{{.Service}}") - rk := &RateLimitKey{ - ProjectID: projectID, - Operation: "List", - Version: meta.Version("{{.Version}}"), - Service: "{{.Service}}", - } - if err := g.s.RateLimiter.Accept(ctx, rk); err != nil { - return nil, err - } -{{- if .KeyIsGlobal}} - klog.V(5).Infof("{{.GCEWrapType}}.List(%v, %v): projectID = %v, rk = %+v", ctx, fl, projectID, rk) - call := g.s.{{.VersionTitle}}.{{.Service}}.List(projectID) -{{- end -}} -{{- if .KeyIsRegional}} - klog.V(5).Infof("{{.GCEWrapType}}.List(%v, %v, %v): projectID = %v, rk = %+v", ctx, region, fl, projectID, rk) - call := g.s.{{.VersionTitle}}.{{.Service}}.List(projectID, region) -{{- end -}} -{{- if .KeyIsZonal}} - klog.V(5).Infof("{{.GCEWrapType}}.List(%v, %v, %v): projectID = %v, rk = %+v", ctx, zone, fl, projectID, rk) - call := g.s.{{.VersionTitle}}.{{.Service}}.List(projectID, zone) -{{- end}} - if fl != filter.None { - call.Filter(fl.String()) - } - var all []*{{.FQObjectType}} - f := func(l *{{.ObjectListType}}) error { - klog.V(5).Infof("{{.GCEWrapType}}.List(%v, ..., %v): page %+v", ctx, fl, l) - all = append(all, l.Items...) - return nil - } - if err := call.Pages(ctx, f); err != nil { - klog.V(4).Infof("{{.GCEWrapType}}.List(%v, ..., %v) = %v, %v", ctx, fl, nil, err) - return nil, err - } - - if klog.V(4) { - klog.V(4).Infof("{{.GCEWrapType}}.List(%v, ..., %v) = [%v items], %v", ctx, fl, len(all), nil) - } else if klog.V(5) { - var asStr []string - for _, o := range all { - asStr = append(asStr, fmt.Sprintf("%+v", o)) - } - klog.V(5).Infof("{{.GCEWrapType}}.List(%v, ..., %v) = %v, %v", ctx, fl, asStr, nil) - } - - return all, nil -} -{{- end}} - -{{- if .GenerateInsert}} -// Insert {{.Object}} with key of value obj. -func (g *{{.GCEWrapType}}) Insert(ctx context.Context, key *meta.Key, obj *{{.FQObjectType}}) error { - klog.V(5).Infof("{{.GCEWrapType}}.Insert(%v, %v, %+v): called", ctx, key, obj) - if !key.Valid() { - klog.V(2).Infof("{{.GCEWrapType}}.Insert(%v, %v, ...): key is invalid (%#v)", ctx, key, key) - return fmt.Errorf("invalid GCE key (%+v)", key) - } - projectID := g.s.ProjectRouter.ProjectID(ctx, "{{.Version}}", "{{.Service}}") - rk := &RateLimitKey{ - ProjectID: projectID, - Operation: "Insert", - Version: meta.Version("{{.Version}}"), - Service: "{{.Service}}", - } - klog.V(5).Infof("{{.GCEWrapType}}.Insert(%v, %v, ...): projectID = %v, rk = %+v", ctx, key, projectID, rk) - if err := g.s.RateLimiter.Accept(ctx, rk); err != nil { - klog.V(4).Infof("{{.GCEWrapType}}.Insert(%v, %v, ...): RateLimiter error: %v", ctx, key, err) - return err - } - obj.Name = key.Name -{{- if .KeyIsGlobal}} - call := g.s.{{.VersionTitle}}.{{.Service}}.Insert(projectID, obj) -{{- end -}} -{{- if .KeyIsRegional}} - call := g.s.{{.VersionTitle}}.{{.Service}}.Insert(projectID, key.Region, obj) -{{- end -}} -{{- if .KeyIsZonal}} - call := g.s.{{.VersionTitle}}.{{.Service}}.Insert(projectID, key.Zone, obj) -{{- end}} - call.Context(ctx) - - op, err := call.Do() - if err != nil { - klog.V(4).Infof("{{.GCEWrapType}}.Insert(%v, %v, ...) = %+v", ctx, key, err) - return err - } - - err = g.s.WaitForCompletion(ctx, op) - klog.V(4).Infof("{{.GCEWrapType}}.Insert(%v, %v, %+v) = %+v", ctx, key, obj, err) - return err -} -{{- end}} - -{{- if .GenerateDelete}} -// Delete the {{.Object}} referenced by key. -func (g *{{.GCEWrapType}}) Delete(ctx context.Context, key *meta.Key) error { - klog.V(5).Infof("{{.GCEWrapType}}.Delete(%v, %v): called", ctx, key) - if !key.Valid() { - klog.V(2).Infof("{{.GCEWrapType}}.Delete(%v, %v): key is invalid (%#v)", ctx, key, key) - return fmt.Errorf("invalid GCE key (%+v)", key) - } - projectID := g.s.ProjectRouter.ProjectID(ctx, "{{.Version}}", "{{.Service}}") - rk := &RateLimitKey{ - ProjectID: projectID, - Operation: "Delete", - Version: meta.Version("{{.Version}}"), - Service: "{{.Service}}", - } - klog.V(5).Infof("{{.GCEWrapType}}.Delete(%v, %v): projectID = %v, rk = %+v", ctx, key, projectID, rk) - if err := g.s.RateLimiter.Accept(ctx, rk); err != nil { - klog.V(4).Infof("{{.GCEWrapType}}.Delete(%v, %v): RateLimiter error: %v", ctx, key, err) - return err - } -{{- if .KeyIsGlobal}} - call := g.s.{{.VersionTitle}}.{{.Service}}.Delete(projectID, key.Name) -{{end -}} -{{- if .KeyIsRegional}} - call := g.s.{{.VersionTitle}}.{{.Service}}.Delete(projectID, key.Region, key.Name) -{{- end -}} -{{- if .KeyIsZonal}} - call := g.s.{{.VersionTitle}}.{{.Service}}.Delete(projectID, key.Zone, key.Name) -{{- end}} - call.Context(ctx) - - op, err := call.Do() - if err != nil { - klog.V(4).Infof("{{.GCEWrapType}}.Delete(%v, %v) = %v", ctx, key, err) - return err - } - - err = g.s.WaitForCompletion(ctx, op) - klog.V(4).Infof("{{.GCEWrapType}}.Delete(%v, %v) = %v", ctx, key, err) - return err -} -{{end -}} - -{{- if .AggregatedList}} -// AggregatedList lists all resources of the given type across all locations. -func (g *{{.GCEWrapType}}) AggregatedList(ctx context.Context, fl *filter.F) (map[string][]*{{.FQObjectType}}, error) { - klog.V(5).Infof("{{.GCEWrapType}}.AggregatedList(%v, %v) called", ctx, fl) - - projectID := g.s.ProjectRouter.ProjectID(ctx, "{{.Version}}", "{{.Service}}") - rk := &RateLimitKey{ - ProjectID: projectID, - Operation: "AggregatedList", - Version: meta.Version("{{.Version}}"), - Service: "{{.Service}}", - } - - klog.V(5).Infof("{{.GCEWrapType}}.AggregatedList(%v, %v): projectID = %v, rk = %+v", ctx, fl, projectID, rk) - if err := g.s.RateLimiter.Accept(ctx, rk); err != nil { - klog.V(5).Infof("{{.GCEWrapType}}.AggregatedList(%v, %v): RateLimiter error: %v", ctx, fl, err) - return nil, err - } - - call := g.s.{{.VersionTitle}}.{{.Service}}.AggregatedList(projectID) - call.Context(ctx) - if fl != filter.None { - call.Filter(fl.String()) - } - - all := map[string][]*{{.FQObjectType}}{} - f := func(l *{{.ObjectAggregatedListType}}) error { - for k, v := range l.Items { - klog.V(5).Infof("{{.GCEWrapType}}.AggregatedList(%v, %v): page[%v]%+v", ctx, fl, k, v) - all[k] = append(all[k], v.{{.AggregatedListField}}...) - } - return nil - } - if err := call.Pages(ctx, f); err != nil { - klog.V(4).Infof("{{.GCEWrapType}}.AggregatedList(%v, %v) = %v, %v", ctx, fl, nil, err) - return nil, err - } - if klog.V(4) { - klog.V(4).Infof("{{.GCEWrapType}}.AggregatedList(%v, %v) = [%v items], %v", ctx, fl, len(all), nil) - } else if klog.V(5) { - var asStr []string - for _, o := range all { - asStr = append(asStr, fmt.Sprintf("%+v", o)) - } - klog.V(5).Infof("{{.GCEWrapType}}.AggregatedList(%v, %v) = %v, %v", ctx, fl, asStr, nil) - } - return all, nil -} -{{- end}} - -{{- with .Methods -}} -{{- range .}} -// {{.Name}} is a method on {{.GCEWrapType}}. -func (g *{{.GCEWrapType}}) {{.FcnArgs}} { - klog.V(5).Infof("{{.GCEWrapType}}.{{.Name}}(%v, %v, ...): called", ctx, key) - - if !key.Valid() { - klog.V(2).Infof("{{.GCEWrapType}}.{{.Name}}(%v, %v, ...): key is invalid (%#v)", ctx, key, key) -{{- if .IsOperation}} - return fmt.Errorf("invalid GCE key (%+v)", key) -{{- else if .IsGet}} - return nil, fmt.Errorf("invalid GCE key (%+v)", key) -{{- else if .IsPaged}} - return nil, fmt.Errorf("invalid GCE key (%+v)", key) -{{- end}} - } - projectID := g.s.ProjectRouter.ProjectID(ctx, "{{.Version}}", "{{.Service}}") - rk := &RateLimitKey{ - ProjectID: projectID, - Operation: "{{.Name}}", - Version: meta.Version("{{.Version}}"), - Service: "{{.Service}}", - } - klog.V(5).Infof("{{.GCEWrapType}}.{{.Name}}(%v, %v, ...): projectID = %v, rk = %+v", ctx, key, projectID, rk) - - if err := g.s.RateLimiter.Accept(ctx, rk); err != nil { - klog.V(4).Infof("{{.GCEWrapType}}.{{.Name}}(%v, %v, ...): RateLimiter error: %v", ctx, key, err) - {{- if .IsOperation}} - return err - {{- else}} - return nil, err - {{- end}} - } -{{- if .KeyIsGlobal}} - call := g.s.{{.VersionTitle}}.{{.Service}}.{{.Name}}(projectID, key.Name {{.CallArgs}}) -{{- end -}} -{{- if .KeyIsRegional}} - call := g.s.{{.VersionTitle}}.{{.Service}}.{{.Name}}(projectID, key.Region, key.Name {{.CallArgs}}) -{{- end -}} -{{- if .KeyIsZonal}} - call := g.s.{{.VersionTitle}}.{{.Service}}.{{.Name}}(projectID, key.Zone, key.Name {{.CallArgs}}) -{{- end}} -{{- if .IsOperation}} - call.Context(ctx) - op, err := call.Do() - if err != nil { - klog.V(4).Infof("{{.GCEWrapType}}.{{.Name}}(%v, %v, ...) = %+v", ctx, key, err) - return err - } - err = g.s.WaitForCompletion(ctx, op) - klog.V(4).Infof("{{.GCEWrapType}}.{{.Name}}(%v, %v, ...) = %+v", ctx, key, err) - return err -{{- else if .IsGet}} - call.Context(ctx) - v, err := call.Do() - klog.V(4).Infof("{{.GCEWrapType}}.{{.Name}}(%v, %v, ...) = %+v, %v", ctx, key, v, err) - return v, err -{{- else if .IsPaged}} - var all []*{{.Version}}.{{.ItemType}} - f := func(l *{{.Version}}.{{.ReturnType}}) error { - klog.V(5).Infof("{{.GCEWrapType}}.{{.Name}}(%v, %v, ...): page %+v", ctx, key, l) - all = append(all, l.Items...) - return nil - } - if err := call.Pages(ctx, f); err != nil { - klog.V(4).Infof("{{.GCEWrapType}}.{{.Name}}(%v, %v, ...) = %v, %v", ctx, key, nil, err) - return nil, err - } - if klog.V(4) { - klog.V(4).Infof("{{.GCEWrapType}}.{{.Name}}(%v, %v, ...) = [%v items], %v", ctx, key, len(all), nil) - } else if klog.V(5) { - var asStr []string - for _, o := range all { - asStr = append(asStr, fmt.Sprintf("%+v", o)) - } - klog.V(5).Infof("{{.GCEWrapType}}.{{.Name}}(%v, %v, ...) = %v, %v", ctx, key, asStr, nil) - } - return all, nil -{{- end}} -} -{{end -}} -{{- end}} -` - tmpl := template.Must(template.New("interface").Parse(text)) - for _, s := range meta.AllServices { - if err := tmpl.Execute(wr, s); err != nil { - panic(err) - } - } -} - -// genTypes generates the type wrappers. -func genResourceIDs(wr io.Writer) { - const text = ` -// New{{.Service}}ResourceID creates a ResourceID for the {{.Service}} resource. -{{- if .KeyIsProject}} -func New{{.Service}}ResourceID(project string) *ResourceID { - var key *meta.Key -{{- else}} -{{- if .KeyIsGlobal}} -func New{{.Service}}ResourceID(project, name string) *ResourceID { - key := meta.GlobalKey(name) -{{- end}} -{{- if .KeyIsRegional}} -func New{{.Service}}ResourceID(project, region, name string) *ResourceID { - key := meta.RegionalKey(name, region) -{{- end}} -{{- if .KeyIsZonal}} -func New{{.Service}}ResourceID(project, zone, name string) *ResourceID { - key := meta.ZonalKey(name, zone) -{{- end -}} -{{end}} - return &ResourceID{project, "{{.Resource}}", key} -} -` - tmpl := template.Must(template.New("resourceIDs").Parse(text)) - for _, sg := range meta.SortedServicesGroups { - if err := tmpl.Execute(wr, sg.ServiceInfo()); err != nil { - panic(err) - } - } -} - -func genUnitTestHeader(wr io.Writer) { - const text = `/* -Copyright {{.Year}} 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. -*/ - -// This file was generated by "go run gen/main.go -mode test > gen_test.go". Do not edit -// directly. - -package cloud - -import ( - "context" - "reflect" - "testing" - - alpha "google.golang.org/api/compute/v0.alpha" - beta "google.golang.org/api/compute/v0.beta" - ga "google.golang.org/api/compute/v1" - - "{{.PackageRoot}}/filter" - "{{.PackageRoot}}/meta" -) - -const location = "location" -` - tmpl := template.Must(template.New("header").Parse(text)) - values := map[string]string{ - "Year": fmt.Sprintf("%v", time.Now().Year()), - "PackageRoot": packageRoot, - } - if err := tmpl.Execute(wr, values); err != nil { - panic(err) - } -} - -func genUnitTestServices(wr io.Writer) { - const text = ` -func Test{{.Service}}Group(t *testing.T) { - t.Parallel() - - ctx := context.Background() - pr := &SingleProjectRouter{"mock-project"} - mock := NewMockGCE(pr) - - var key *meta.Key -{{- if .HasAlpha}} - keyAlpha := meta.{{.Alpha.MakeKey "key-alpha" "location"}} - key = keyAlpha -{{- end}} -{{- if .HasBeta}} - keyBeta := meta.{{.Beta.MakeKey "key-beta" "location"}} - key = keyBeta -{{- end}} -{{- if .HasGA}} - keyGA := meta.{{.GA.MakeKey "key-ga" "location"}} - key = keyGA -{{- end}} - // Ignore unused variables. - _, _, _ = ctx, mock, key - - // Get not found. -{{- if .HasAlpha}}{{- if .Alpha.GenerateGet}} - if _, err := mock.Alpha{{.Service}}().Get(ctx, key); err == nil { - t.Errorf("Alpha{{.Service}}().Get(%v, %v) = _, nil; want error", ctx, key) - } -{{- end}}{{- end}} -{{- if .HasBeta}}{{- if .Beta.GenerateGet}} - if _, err := mock.Beta{{.Service}}().Get(ctx, key); err == nil { - t.Errorf("Beta{{.Service}}().Get(%v, %v) = _, nil; want error", ctx, key) - } -{{- end}}{{- end}} -{{- if .HasGA}}{{- if .GA.GenerateGet}} - if _, err := mock.{{.Service}}().Get(ctx, key); err == nil { - t.Errorf("{{.Service}}().Get(%v, %v) = _, nil; want error", ctx, key) - } -{{- end}}{{- end}} - - // Insert. -{{- if .HasAlpha}}{{- if .Alpha.GenerateInsert}} - { - obj := &alpha.{{.Alpha.Object}}{} - if err := mock.Alpha{{.Service}}().Insert(ctx, keyAlpha, obj); err != nil { - t.Errorf("Alpha{{.Service}}().Insert(%v, %v, %v) = %v; want nil", ctx, keyAlpha, obj, err) - } - } -{{- end}}{{- end}} -{{- if .HasBeta}}{{- if .Beta.GenerateInsert}} - { - obj := &beta.{{.Beta.Object}}{} - if err := mock.Beta{{.Service}}().Insert(ctx, keyBeta, obj); err != nil { - t.Errorf("Beta{{.Service}}().Insert(%v, %v, %v) = %v; want nil", ctx, keyBeta, obj, err) - } - } -{{- end}}{{- end}} -{{- if .HasGA}}{{- if .GA.GenerateInsert}} - { - obj := &ga.{{.GA.Object}}{} - if err := mock.{{.Service}}().Insert(ctx, keyGA, obj); err != nil { - t.Errorf("{{.Service}}().Insert(%v, %v, %v) = %v; want nil", ctx, keyGA, obj, err) - } - } -{{- end}}{{- end}} - - // Get across versions. -{{- if .HasAlpha}}{{- if .Alpha.GenerateInsert}} - if obj, err := mock.Alpha{{.Service}}().Get(ctx, key); err != nil { - t.Errorf("Alpha{{.Service}}().Get(%v, %v) = %v, %v; want nil", ctx, key, obj, err) - } -{{- end}}{{- end}} -{{- if .HasBeta}}{{- if .Beta.GenerateInsert}} - if obj, err := mock.Beta{{.Service}}().Get(ctx, key); err != nil { - t.Errorf("Beta{{.Service}}().Get(%v, %v) = %v, %v; want nil", ctx, key, obj, err) - } -{{- end}}{{- end}} -{{- if .HasGA}}{{- if .GA.GenerateInsert}} - if obj, err := mock.{{.Service}}().Get(ctx, key); err != nil { - t.Errorf("{{.Service}}().Get(%v, %v) = %v, %v; want nil", ctx, key, obj, err) - } -{{- end}}{{- end}} - - // List. -{{- if .HasAlpha}} - mock.MockAlpha{{.Service}}.Objects[*keyAlpha] = mock.MockAlpha{{.Service}}.Obj(&alpha.{{.Alpha.Object}}{Name: keyAlpha.Name}) -{{- end}} -{{- if .HasBeta}} - mock.MockBeta{{.Service}}.Objects[*keyBeta] = mock.MockBeta{{.Service}}.Obj(&beta.{{.Beta.Object}}{Name: keyBeta.Name}) -{{- end}} -{{- if .HasGA}} - mock.Mock{{.Service}}.Objects[*keyGA] = mock.Mock{{.Service}}.Obj(&ga.{{.GA.Object}}{Name: keyGA.Name}) -{{- end}} - want := map[string]bool{ -{{- if .HasAlpha}} - "key-alpha": true, -{{- end}} -{{- if .HasBeta}} - "key-beta": true, -{{- end}} -{{- if .HasGA}} - "key-ga": true, -{{- end}} - } - _ = want // ignore unused variables. - -{{- if .HasAlpha}}{{- if .Alpha.GenerateList}} - { - {{- if .Alpha.KeyIsGlobal }} - objs, err := mock.Alpha{{.Service}}().List(ctx, filter.None) - {{- else}} - objs, err := mock.Alpha{{.Service}}().List(ctx, location, filter.None) - {{- end}} - if err != nil { - t.Errorf("Alpha{{.Service}}().List(%v, %v, %v) = %v, %v; want _, nil", ctx, location, filter.None, objs, err) - } else { - got := map[string]bool{} - for _, obj := range objs { - got[obj.Name] = true - } - if !reflect.DeepEqual(got, want) { - t.Errorf("Alpha{{.Service}}().List(); got %+v, want %+v", got, want) - } - } - } -{{- end}}{{- end}} -{{- if .HasBeta}}{{- if .Beta.GenerateList}} - { - {{- if .Beta.KeyIsGlobal }} - objs, err := mock.Beta{{.Service}}().List(ctx, filter.None) - {{- else}} - objs, err := mock.Beta{{.Service}}().List(ctx, location, filter.None) - {{- end}} - if err != nil { - t.Errorf("Beta{{.Service}}().List(%v, %v, %v) = %v, %v; want _, nil", ctx, location, filter.None, objs, err) - } else { - got := map[string]bool{} - for _, obj := range objs { - got[obj.Name] = true - } - if !reflect.DeepEqual(got, want) { - t.Errorf("Beta{{.Service}}().List(); got %+v, want %+v", got, want) - } - } - } -{{- end}}{{- end}} -{{- if .HasGA}}{{- if .GA.GenerateList}} - { - {{- if .GA.KeyIsGlobal }} - objs, err := mock.{{.Service}}().List(ctx, filter.None) - {{- else}} - objs, err := mock.{{.Service}}().List(ctx, location, filter.None) - {{- end}} - if err != nil { - t.Errorf("{{.Service}}().List(%v, %v, %v) = %v, %v; want _, nil", ctx, location, filter.None, objs, err) - } else { - got := map[string]bool{} - for _, obj := range objs { - got[obj.Name] = true - } - if !reflect.DeepEqual(got, want) { - t.Errorf("{{.Service}}().List(); got %+v, want %+v", got, want) - } - } - } -{{- end}}{{- end}} - - // Delete across versions. -{{- if .HasAlpha}}{{- if .Alpha.GenerateDelete}} - if err := mock.Alpha{{.Service}}().Delete(ctx, keyAlpha); err != nil { - t.Errorf("Alpha{{.Service}}().Delete(%v, %v) = %v; want nil", ctx, keyAlpha, err) - } -{{- end}}{{- end}} -{{- if .HasBeta}}{{- if .Beta.GenerateDelete}} - if err := mock.Beta{{.Service}}().Delete(ctx, keyBeta); err != nil { - t.Errorf("Beta{{.Service}}().Delete(%v, %v) = %v; want nil", ctx, keyBeta, err) - } -{{- end}}{{- end}} -{{- if .HasGA}}{{- if .GA.GenerateDelete}} - if err := mock.{{.Service}}().Delete(ctx, keyGA); err != nil { - t.Errorf("{{.Service}}().Delete(%v, %v) = %v; want nil", ctx, keyGA, err) - } -{{- end}}{{- end}} - - // Delete not found. -{{- if .HasAlpha}}{{- if .Alpha.GenerateDelete}} - if err := mock.Alpha{{.Service}}().Delete(ctx, keyAlpha); err == nil { - t.Errorf("Alpha{{.Service}}().Delete(%v, %v) = nil; want error", ctx, keyAlpha) - } -{{- end}}{{- end}} -{{- if .HasBeta}}{{- if .Beta.GenerateDelete}} - if err := mock.Beta{{.Service}}().Delete(ctx, keyBeta); err == nil { - t.Errorf("Beta{{.Service}}().Delete(%v, %v) = nil; want error", ctx, keyBeta) - } -{{- end}}{{- end}} -{{- if .HasGA}}{{- if .GA.GenerateDelete}} - if err := mock.{{.Service}}().Delete(ctx, keyGA); err == nil { - t.Errorf("{{.Service}}().Delete(%v, %v) = nil; want error", ctx, keyGA) - } -{{- end}}{{- end}} -} -` - tmpl := template.Must(template.New("unittest").Parse(text)) - for _, sg := range meta.SortedServicesGroups { - if err := tmpl.Execute(wr, sg); err != nil { - panic(err) - } - } -} - -func genUnitTestResourceIDConversion(wr io.Writer) { - const text = ` -func TestResourceIDConversion(t *testing.T) { - t.Parallel() - - for _, id := range []*ResourceID{ - {{- range .Groups}} - {{- with .ServiceInfo}} - {{- if .KeyIsProject}} - New{{.Service}}ResourceID("my-{{.Resource}}-resource"), - {{- else}} - {{- if .KeyIsGlobal}} - New{{.Service}}ResourceID("some-project", "my-{{.Resource}}-resource"), - {{- end}} - {{- if .KeyIsRegional}} - New{{.Service}}ResourceID("some-project", "us-central1", "my-{{.Resource}}-resource"), - {{- end}} - {{- if .KeyIsZonal}} - New{{.Service}}ResourceID("some-project", "us-east1-b", "my-{{.Resource}}-resource"), - {{- end -}} - {{end -}} - {{end -}} - {{end}} - } { - t.Run(id.Resource, func(t *testing.T) { - // Test conversion to and from full URL. - fullURL := id.SelfLink(meta.VersionGA) - parsedID, err := ParseResourceURL(fullURL) - if err != nil { - t.Errorf("ParseResourceURL(%s) = _, %v, want nil", fullURL, err) - } - if !reflect.DeepEqual(id, parsedID) { - t.Errorf("SelfLink(%+v) -> ParseResourceURL(%s) = %+v, want original ID", id, fullURL, parsedID) - } - - // Test conversion to and from relative resource name. - relativeName := id.RelativeResourceName() - parsedID, err = ParseResourceURL(relativeName) - if err != nil { - t.Errorf("ParseResourceURL(%s) = _, %v, want nil", relativeName, err) - } - if !reflect.DeepEqual(id, parsedID) { - t.Errorf("RelativeResourceName(%+v) -> ParseResourceURL(%s) = %+v, want original ID", id, relativeName, parsedID) - } - - // Do not test ResourcePath for projects. - if id.Resource == "projects" { - return - } - - // Test conversion to and from resource path. - resourcePath := id.ResourcePath() - parsedID, err = ParseResourceURL(resourcePath) - if err != nil { - t.Errorf("ParseResourceURL(%s) = _, %v, want nil", resourcePath, err) - } - id.ProjectID = "" - if !reflect.DeepEqual(id, parsedID) { - t.Errorf("ResourcePath(%+v) -> ParseResourceURL(%s) = %+v, want %+v", id, resourcePath, parsedID, id) - } - }) - } -} -` - data := struct { - Groups []*meta.ServiceGroup - }{meta.SortedServicesGroups} - tmpl := template.Must(template.New("unittest-resourceIDs").Parse(text)) - if err := tmpl.Execute(wr, data); err != nil { - panic(err) - } -} - -func main() { - flag.Parse() - - out := &bytes.Buffer{} - - switch flags.mode { - case "src": - genHeader(out) - genStubs(out) - genTypes(out) - genResourceIDs(out) - case "test": - genUnitTestHeader(out) - genUnitTestServices(out) - genUnitTestResourceIDConversion(out) - default: - log.Fatalf("Invalid -mode: %q", flags.mode) - } - - if flags.gofmt { - fmt.Print(gofmtContent(out)) - } else { - fmt.Print(out.String()) - } -} diff --git a/pkg/cloudprovider/providers/gce/cloud/gen_test.go b/pkg/cloudprovider/providers/gce/cloud/gen_test.go deleted file mode 100644 index 902b4ee780d..00000000000 --- a/pkg/cloudprovider/providers/gce/cloud/gen_test.go +++ /dev/null @@ -1,2014 +0,0 @@ -/* -Copyright 2018 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// This file was generated by "go run gen/main.go -mode test > gen_test.go". Do not edit -// directly. - -package cloud - -import ( - "context" - "reflect" - "testing" - - alpha "google.golang.org/api/compute/v0.alpha" - beta "google.golang.org/api/compute/v0.beta" - ga "google.golang.org/api/compute/v1" - - "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/filter" - "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta" -) - -const location = "location" - -func TestAddressesGroup(t *testing.T) { - t.Parallel() - - ctx := context.Background() - pr := &SingleProjectRouter{"mock-project"} - mock := NewMockGCE(pr) - - var key *meta.Key - keyAlpha := meta.RegionalKey("key-alpha", "location") - key = keyAlpha - keyBeta := meta.RegionalKey("key-beta", "location") - key = keyBeta - keyGA := meta.RegionalKey("key-ga", "location") - key = keyGA - // Ignore unused variables. - _, _, _ = ctx, mock, key - - // Get not found. - if _, err := mock.AlphaAddresses().Get(ctx, key); err == nil { - t.Errorf("AlphaAddresses().Get(%v, %v) = _, nil; want error", ctx, key) - } - if _, err := mock.BetaAddresses().Get(ctx, key); err == nil { - t.Errorf("BetaAddresses().Get(%v, %v) = _, nil; want error", ctx, key) - } - if _, err := mock.Addresses().Get(ctx, key); err == nil { - t.Errorf("Addresses().Get(%v, %v) = _, nil; want error", ctx, key) - } - - // Insert. - { - obj := &alpha.Address{} - if err := mock.AlphaAddresses().Insert(ctx, keyAlpha, obj); err != nil { - t.Errorf("AlphaAddresses().Insert(%v, %v, %v) = %v; want nil", ctx, keyAlpha, obj, err) - } - } - { - obj := &beta.Address{} - if err := mock.BetaAddresses().Insert(ctx, keyBeta, obj); err != nil { - t.Errorf("BetaAddresses().Insert(%v, %v, %v) = %v; want nil", ctx, keyBeta, obj, err) - } - } - { - obj := &ga.Address{} - if err := mock.Addresses().Insert(ctx, keyGA, obj); err != nil { - t.Errorf("Addresses().Insert(%v, %v, %v) = %v; want nil", ctx, keyGA, obj, err) - } - } - - // Get across versions. - if obj, err := mock.AlphaAddresses().Get(ctx, key); err != nil { - t.Errorf("AlphaAddresses().Get(%v, %v) = %v, %v; want nil", ctx, key, obj, err) - } - if obj, err := mock.BetaAddresses().Get(ctx, key); err != nil { - t.Errorf("BetaAddresses().Get(%v, %v) = %v, %v; want nil", ctx, key, obj, err) - } - if obj, err := mock.Addresses().Get(ctx, key); err != nil { - t.Errorf("Addresses().Get(%v, %v) = %v, %v; want nil", ctx, key, obj, err) - } - - // List. - mock.MockAlphaAddresses.Objects[*keyAlpha] = mock.MockAlphaAddresses.Obj(&alpha.Address{Name: keyAlpha.Name}) - mock.MockBetaAddresses.Objects[*keyBeta] = mock.MockBetaAddresses.Obj(&beta.Address{Name: keyBeta.Name}) - mock.MockAddresses.Objects[*keyGA] = mock.MockAddresses.Obj(&ga.Address{Name: keyGA.Name}) - want := map[string]bool{ - "key-alpha": true, - "key-beta": true, - "key-ga": true, - } - _ = want // ignore unused variables. - { - objs, err := mock.AlphaAddresses().List(ctx, location, filter.None) - if err != nil { - t.Errorf("AlphaAddresses().List(%v, %v, %v) = %v, %v; want _, nil", ctx, location, filter.None, objs, err) - } else { - got := map[string]bool{} - for _, obj := range objs { - got[obj.Name] = true - } - if !reflect.DeepEqual(got, want) { - t.Errorf("AlphaAddresses().List(); got %+v, want %+v", got, want) - } - } - } - { - objs, err := mock.BetaAddresses().List(ctx, location, filter.None) - if err != nil { - t.Errorf("BetaAddresses().List(%v, %v, %v) = %v, %v; want _, nil", ctx, location, filter.None, objs, err) - } else { - got := map[string]bool{} - for _, obj := range objs { - got[obj.Name] = true - } - if !reflect.DeepEqual(got, want) { - t.Errorf("BetaAddresses().List(); got %+v, want %+v", got, want) - } - } - } - { - objs, err := mock.Addresses().List(ctx, location, filter.None) - if err != nil { - t.Errorf("Addresses().List(%v, %v, %v) = %v, %v; want _, nil", ctx, location, filter.None, objs, err) - } else { - got := map[string]bool{} - for _, obj := range objs { - got[obj.Name] = true - } - if !reflect.DeepEqual(got, want) { - t.Errorf("Addresses().List(); got %+v, want %+v", got, want) - } - } - } - - // Delete across versions. - if err := mock.AlphaAddresses().Delete(ctx, keyAlpha); err != nil { - t.Errorf("AlphaAddresses().Delete(%v, %v) = %v; want nil", ctx, keyAlpha, err) - } - if err := mock.BetaAddresses().Delete(ctx, keyBeta); err != nil { - t.Errorf("BetaAddresses().Delete(%v, %v) = %v; want nil", ctx, keyBeta, err) - } - if err := mock.Addresses().Delete(ctx, keyGA); err != nil { - t.Errorf("Addresses().Delete(%v, %v) = %v; want nil", ctx, keyGA, err) - } - - // Delete not found. - if err := mock.AlphaAddresses().Delete(ctx, keyAlpha); err == nil { - t.Errorf("AlphaAddresses().Delete(%v, %v) = nil; want error", ctx, keyAlpha) - } - if err := mock.BetaAddresses().Delete(ctx, keyBeta); err == nil { - t.Errorf("BetaAddresses().Delete(%v, %v) = nil; want error", ctx, keyBeta) - } - if err := mock.Addresses().Delete(ctx, keyGA); err == nil { - t.Errorf("Addresses().Delete(%v, %v) = nil; want error", ctx, keyGA) - } -} - -func TestBackendServicesGroup(t *testing.T) { - t.Parallel() - - ctx := context.Background() - pr := &SingleProjectRouter{"mock-project"} - mock := NewMockGCE(pr) - - var key *meta.Key - keyAlpha := meta.GlobalKey("key-alpha") - key = keyAlpha - keyBeta := meta.GlobalKey("key-beta") - key = keyBeta - keyGA := meta.GlobalKey("key-ga") - key = keyGA - // Ignore unused variables. - _, _, _ = ctx, mock, key - - // Get not found. - if _, err := mock.AlphaBackendServices().Get(ctx, key); err == nil { - t.Errorf("AlphaBackendServices().Get(%v, %v) = _, nil; want error", ctx, key) - } - if _, err := mock.BetaBackendServices().Get(ctx, key); err == nil { - t.Errorf("BetaBackendServices().Get(%v, %v) = _, nil; want error", ctx, key) - } - if _, err := mock.BackendServices().Get(ctx, key); err == nil { - t.Errorf("BackendServices().Get(%v, %v) = _, nil; want error", ctx, key) - } - - // Insert. - { - obj := &alpha.BackendService{} - if err := mock.AlphaBackendServices().Insert(ctx, keyAlpha, obj); err != nil { - t.Errorf("AlphaBackendServices().Insert(%v, %v, %v) = %v; want nil", ctx, keyAlpha, obj, err) - } - } - { - obj := &beta.BackendService{} - if err := mock.BetaBackendServices().Insert(ctx, keyBeta, obj); err != nil { - t.Errorf("BetaBackendServices().Insert(%v, %v, %v) = %v; want nil", ctx, keyBeta, obj, err) - } - } - { - obj := &ga.BackendService{} - if err := mock.BackendServices().Insert(ctx, keyGA, obj); err != nil { - t.Errorf("BackendServices().Insert(%v, %v, %v) = %v; want nil", ctx, keyGA, obj, err) - } - } - - // Get across versions. - if obj, err := mock.AlphaBackendServices().Get(ctx, key); err != nil { - t.Errorf("AlphaBackendServices().Get(%v, %v) = %v, %v; want nil", ctx, key, obj, err) - } - if obj, err := mock.BetaBackendServices().Get(ctx, key); err != nil { - t.Errorf("BetaBackendServices().Get(%v, %v) = %v, %v; want nil", ctx, key, obj, err) - } - if obj, err := mock.BackendServices().Get(ctx, key); err != nil { - t.Errorf("BackendServices().Get(%v, %v) = %v, %v; want nil", ctx, key, obj, err) - } - - // List. - mock.MockAlphaBackendServices.Objects[*keyAlpha] = mock.MockAlphaBackendServices.Obj(&alpha.BackendService{Name: keyAlpha.Name}) - mock.MockBetaBackendServices.Objects[*keyBeta] = mock.MockBetaBackendServices.Obj(&beta.BackendService{Name: keyBeta.Name}) - mock.MockBackendServices.Objects[*keyGA] = mock.MockBackendServices.Obj(&ga.BackendService{Name: keyGA.Name}) - want := map[string]bool{ - "key-alpha": true, - "key-beta": true, - "key-ga": true, - } - _ = want // ignore unused variables. - { - objs, err := mock.AlphaBackendServices().List(ctx, filter.None) - if err != nil { - t.Errorf("AlphaBackendServices().List(%v, %v, %v) = %v, %v; want _, nil", ctx, location, filter.None, objs, err) - } else { - got := map[string]bool{} - for _, obj := range objs { - got[obj.Name] = true - } - if !reflect.DeepEqual(got, want) { - t.Errorf("AlphaBackendServices().List(); got %+v, want %+v", got, want) - } - } - } - { - objs, err := mock.BetaBackendServices().List(ctx, filter.None) - if err != nil { - t.Errorf("BetaBackendServices().List(%v, %v, %v) = %v, %v; want _, nil", ctx, location, filter.None, objs, err) - } else { - got := map[string]bool{} - for _, obj := range objs { - got[obj.Name] = true - } - if !reflect.DeepEqual(got, want) { - t.Errorf("BetaBackendServices().List(); got %+v, want %+v", got, want) - } - } - } - { - objs, err := mock.BackendServices().List(ctx, filter.None) - if err != nil { - t.Errorf("BackendServices().List(%v, %v, %v) = %v, %v; want _, nil", ctx, location, filter.None, objs, err) - } else { - got := map[string]bool{} - for _, obj := range objs { - got[obj.Name] = true - } - if !reflect.DeepEqual(got, want) { - t.Errorf("BackendServices().List(); got %+v, want %+v", got, want) - } - } - } - - // Delete across versions. - if err := mock.AlphaBackendServices().Delete(ctx, keyAlpha); err != nil { - t.Errorf("AlphaBackendServices().Delete(%v, %v) = %v; want nil", ctx, keyAlpha, err) - } - if err := mock.BetaBackendServices().Delete(ctx, keyBeta); err != nil { - t.Errorf("BetaBackendServices().Delete(%v, %v) = %v; want nil", ctx, keyBeta, err) - } - if err := mock.BackendServices().Delete(ctx, keyGA); err != nil { - t.Errorf("BackendServices().Delete(%v, %v) = %v; want nil", ctx, keyGA, err) - } - - // Delete not found. - if err := mock.AlphaBackendServices().Delete(ctx, keyAlpha); err == nil { - t.Errorf("AlphaBackendServices().Delete(%v, %v) = nil; want error", ctx, keyAlpha) - } - if err := mock.BetaBackendServices().Delete(ctx, keyBeta); err == nil { - t.Errorf("BetaBackendServices().Delete(%v, %v) = nil; want error", ctx, keyBeta) - } - if err := mock.BackendServices().Delete(ctx, keyGA); err == nil { - t.Errorf("BackendServices().Delete(%v, %v) = nil; want error", ctx, keyGA) - } -} - -func TestDisksGroup(t *testing.T) { - t.Parallel() - - ctx := context.Background() - pr := &SingleProjectRouter{"mock-project"} - mock := NewMockGCE(pr) - - var key *meta.Key - keyGA := meta.ZonalKey("key-ga", "location") - key = keyGA - // Ignore unused variables. - _, _, _ = ctx, mock, key - - // Get not found. - if _, err := mock.Disks().Get(ctx, key); err == nil { - t.Errorf("Disks().Get(%v, %v) = _, nil; want error", ctx, key) - } - - // Insert. - { - obj := &ga.Disk{} - if err := mock.Disks().Insert(ctx, keyGA, obj); err != nil { - t.Errorf("Disks().Insert(%v, %v, %v) = %v; want nil", ctx, keyGA, obj, err) - } - } - - // Get across versions. - if obj, err := mock.Disks().Get(ctx, key); err != nil { - t.Errorf("Disks().Get(%v, %v) = %v, %v; want nil", ctx, key, obj, err) - } - - // List. - mock.MockDisks.Objects[*keyGA] = mock.MockDisks.Obj(&ga.Disk{Name: keyGA.Name}) - want := map[string]bool{ - "key-ga": true, - } - _ = want // ignore unused variables. - { - objs, err := mock.Disks().List(ctx, location, filter.None) - if err != nil { - t.Errorf("Disks().List(%v, %v, %v) = %v, %v; want _, nil", ctx, location, filter.None, objs, err) - } else { - got := map[string]bool{} - for _, obj := range objs { - got[obj.Name] = true - } - if !reflect.DeepEqual(got, want) { - t.Errorf("Disks().List(); got %+v, want %+v", got, want) - } - } - } - - // Delete across versions. - if err := mock.Disks().Delete(ctx, keyGA); err != nil { - t.Errorf("Disks().Delete(%v, %v) = %v; want nil", ctx, keyGA, err) - } - - // Delete not found. - if err := mock.Disks().Delete(ctx, keyGA); err == nil { - t.Errorf("Disks().Delete(%v, %v) = nil; want error", ctx, keyGA) - } -} - -func TestFirewallsGroup(t *testing.T) { - t.Parallel() - - ctx := context.Background() - pr := &SingleProjectRouter{"mock-project"} - mock := NewMockGCE(pr) - - var key *meta.Key - keyGA := meta.GlobalKey("key-ga") - key = keyGA - // Ignore unused variables. - _, _, _ = ctx, mock, key - - // Get not found. - if _, err := mock.Firewalls().Get(ctx, key); err == nil { - t.Errorf("Firewalls().Get(%v, %v) = _, nil; want error", ctx, key) - } - - // Insert. - { - obj := &ga.Firewall{} - if err := mock.Firewalls().Insert(ctx, keyGA, obj); err != nil { - t.Errorf("Firewalls().Insert(%v, %v, %v) = %v; want nil", ctx, keyGA, obj, err) - } - } - - // Get across versions. - if obj, err := mock.Firewalls().Get(ctx, key); err != nil { - t.Errorf("Firewalls().Get(%v, %v) = %v, %v; want nil", ctx, key, obj, err) - } - - // List. - mock.MockFirewalls.Objects[*keyGA] = mock.MockFirewalls.Obj(&ga.Firewall{Name: keyGA.Name}) - want := map[string]bool{ - "key-ga": true, - } - _ = want // ignore unused variables. - { - objs, err := mock.Firewalls().List(ctx, filter.None) - if err != nil { - t.Errorf("Firewalls().List(%v, %v, %v) = %v, %v; want _, nil", ctx, location, filter.None, objs, err) - } else { - got := map[string]bool{} - for _, obj := range objs { - got[obj.Name] = true - } - if !reflect.DeepEqual(got, want) { - t.Errorf("Firewalls().List(); got %+v, want %+v", got, want) - } - } - } - - // Delete across versions. - if err := mock.Firewalls().Delete(ctx, keyGA); err != nil { - t.Errorf("Firewalls().Delete(%v, %v) = %v; want nil", ctx, keyGA, err) - } - - // Delete not found. - if err := mock.Firewalls().Delete(ctx, keyGA); err == nil { - t.Errorf("Firewalls().Delete(%v, %v) = nil; want error", ctx, keyGA) - } -} - -func TestForwardingRulesGroup(t *testing.T) { - t.Parallel() - - ctx := context.Background() - pr := &SingleProjectRouter{"mock-project"} - mock := NewMockGCE(pr) - - var key *meta.Key - keyAlpha := meta.RegionalKey("key-alpha", "location") - key = keyAlpha - keyGA := meta.RegionalKey("key-ga", "location") - key = keyGA - // Ignore unused variables. - _, _, _ = ctx, mock, key - - // Get not found. - if _, err := mock.AlphaForwardingRules().Get(ctx, key); err == nil { - t.Errorf("AlphaForwardingRules().Get(%v, %v) = _, nil; want error", ctx, key) - } - if _, err := mock.ForwardingRules().Get(ctx, key); err == nil { - t.Errorf("ForwardingRules().Get(%v, %v) = _, nil; want error", ctx, key) - } - - // Insert. - { - obj := &alpha.ForwardingRule{} - if err := mock.AlphaForwardingRules().Insert(ctx, keyAlpha, obj); err != nil { - t.Errorf("AlphaForwardingRules().Insert(%v, %v, %v) = %v; want nil", ctx, keyAlpha, obj, err) - } - } - { - obj := &ga.ForwardingRule{} - if err := mock.ForwardingRules().Insert(ctx, keyGA, obj); err != nil { - t.Errorf("ForwardingRules().Insert(%v, %v, %v) = %v; want nil", ctx, keyGA, obj, err) - } - } - - // Get across versions. - if obj, err := mock.AlphaForwardingRules().Get(ctx, key); err != nil { - t.Errorf("AlphaForwardingRules().Get(%v, %v) = %v, %v; want nil", ctx, key, obj, err) - } - if obj, err := mock.ForwardingRules().Get(ctx, key); err != nil { - t.Errorf("ForwardingRules().Get(%v, %v) = %v, %v; want nil", ctx, key, obj, err) - } - - // List. - mock.MockAlphaForwardingRules.Objects[*keyAlpha] = mock.MockAlphaForwardingRules.Obj(&alpha.ForwardingRule{Name: keyAlpha.Name}) - mock.MockForwardingRules.Objects[*keyGA] = mock.MockForwardingRules.Obj(&ga.ForwardingRule{Name: keyGA.Name}) - want := map[string]bool{ - "key-alpha": true, - "key-ga": true, - } - _ = want // ignore unused variables. - { - objs, err := mock.AlphaForwardingRules().List(ctx, location, filter.None) - if err != nil { - t.Errorf("AlphaForwardingRules().List(%v, %v, %v) = %v, %v; want _, nil", ctx, location, filter.None, objs, err) - } else { - got := map[string]bool{} - for _, obj := range objs { - got[obj.Name] = true - } - if !reflect.DeepEqual(got, want) { - t.Errorf("AlphaForwardingRules().List(); got %+v, want %+v", got, want) - } - } - } - { - objs, err := mock.ForwardingRules().List(ctx, location, filter.None) - if err != nil { - t.Errorf("ForwardingRules().List(%v, %v, %v) = %v, %v; want _, nil", ctx, location, filter.None, objs, err) - } else { - got := map[string]bool{} - for _, obj := range objs { - got[obj.Name] = true - } - if !reflect.DeepEqual(got, want) { - t.Errorf("ForwardingRules().List(); got %+v, want %+v", got, want) - } - } - } - - // Delete across versions. - if err := mock.AlphaForwardingRules().Delete(ctx, keyAlpha); err != nil { - t.Errorf("AlphaForwardingRules().Delete(%v, %v) = %v; want nil", ctx, keyAlpha, err) - } - if err := mock.ForwardingRules().Delete(ctx, keyGA); err != nil { - t.Errorf("ForwardingRules().Delete(%v, %v) = %v; want nil", ctx, keyGA, err) - } - - // Delete not found. - if err := mock.AlphaForwardingRules().Delete(ctx, keyAlpha); err == nil { - t.Errorf("AlphaForwardingRules().Delete(%v, %v) = nil; want error", ctx, keyAlpha) - } - if err := mock.ForwardingRules().Delete(ctx, keyGA); err == nil { - t.Errorf("ForwardingRules().Delete(%v, %v) = nil; want error", ctx, keyGA) - } -} - -func TestGlobalAddressesGroup(t *testing.T) { - t.Parallel() - - ctx := context.Background() - pr := &SingleProjectRouter{"mock-project"} - mock := NewMockGCE(pr) - - var key *meta.Key - keyGA := meta.GlobalKey("key-ga") - key = keyGA - // Ignore unused variables. - _, _, _ = ctx, mock, key - - // Get not found. - if _, err := mock.GlobalAddresses().Get(ctx, key); err == nil { - t.Errorf("GlobalAddresses().Get(%v, %v) = _, nil; want error", ctx, key) - } - - // Insert. - { - obj := &ga.Address{} - if err := mock.GlobalAddresses().Insert(ctx, keyGA, obj); err != nil { - t.Errorf("GlobalAddresses().Insert(%v, %v, %v) = %v; want nil", ctx, keyGA, obj, err) - } - } - - // Get across versions. - if obj, err := mock.GlobalAddresses().Get(ctx, key); err != nil { - t.Errorf("GlobalAddresses().Get(%v, %v) = %v, %v; want nil", ctx, key, obj, err) - } - - // List. - mock.MockGlobalAddresses.Objects[*keyGA] = mock.MockGlobalAddresses.Obj(&ga.Address{Name: keyGA.Name}) - want := map[string]bool{ - "key-ga": true, - } - _ = want // ignore unused variables. - { - objs, err := mock.GlobalAddresses().List(ctx, filter.None) - if err != nil { - t.Errorf("GlobalAddresses().List(%v, %v, %v) = %v, %v; want _, nil", ctx, location, filter.None, objs, err) - } else { - got := map[string]bool{} - for _, obj := range objs { - got[obj.Name] = true - } - if !reflect.DeepEqual(got, want) { - t.Errorf("GlobalAddresses().List(); got %+v, want %+v", got, want) - } - } - } - - // Delete across versions. - if err := mock.GlobalAddresses().Delete(ctx, keyGA); err != nil { - t.Errorf("GlobalAddresses().Delete(%v, %v) = %v; want nil", ctx, keyGA, err) - } - - // Delete not found. - if err := mock.GlobalAddresses().Delete(ctx, keyGA); err == nil { - t.Errorf("GlobalAddresses().Delete(%v, %v) = nil; want error", ctx, keyGA) - } -} - -func TestGlobalForwardingRulesGroup(t *testing.T) { - t.Parallel() - - ctx := context.Background() - pr := &SingleProjectRouter{"mock-project"} - mock := NewMockGCE(pr) - - var key *meta.Key - keyGA := meta.GlobalKey("key-ga") - key = keyGA - // Ignore unused variables. - _, _, _ = ctx, mock, key - - // Get not found. - if _, err := mock.GlobalForwardingRules().Get(ctx, key); err == nil { - t.Errorf("GlobalForwardingRules().Get(%v, %v) = _, nil; want error", ctx, key) - } - - // Insert. - { - obj := &ga.ForwardingRule{} - if err := mock.GlobalForwardingRules().Insert(ctx, keyGA, obj); err != nil { - t.Errorf("GlobalForwardingRules().Insert(%v, %v, %v) = %v; want nil", ctx, keyGA, obj, err) - } - } - - // Get across versions. - if obj, err := mock.GlobalForwardingRules().Get(ctx, key); err != nil { - t.Errorf("GlobalForwardingRules().Get(%v, %v) = %v, %v; want nil", ctx, key, obj, err) - } - - // List. - mock.MockGlobalForwardingRules.Objects[*keyGA] = mock.MockGlobalForwardingRules.Obj(&ga.ForwardingRule{Name: keyGA.Name}) - want := map[string]bool{ - "key-ga": true, - } - _ = want // ignore unused variables. - { - objs, err := mock.GlobalForwardingRules().List(ctx, filter.None) - if err != nil { - t.Errorf("GlobalForwardingRules().List(%v, %v, %v) = %v, %v; want _, nil", ctx, location, filter.None, objs, err) - } else { - got := map[string]bool{} - for _, obj := range objs { - got[obj.Name] = true - } - if !reflect.DeepEqual(got, want) { - t.Errorf("GlobalForwardingRules().List(); got %+v, want %+v", got, want) - } - } - } - - // Delete across versions. - if err := mock.GlobalForwardingRules().Delete(ctx, keyGA); err != nil { - t.Errorf("GlobalForwardingRules().Delete(%v, %v) = %v; want nil", ctx, keyGA, err) - } - - // Delete not found. - if err := mock.GlobalForwardingRules().Delete(ctx, keyGA); err == nil { - t.Errorf("GlobalForwardingRules().Delete(%v, %v) = nil; want error", ctx, keyGA) - } -} - -func TestHealthChecksGroup(t *testing.T) { - t.Parallel() - - ctx := context.Background() - pr := &SingleProjectRouter{"mock-project"} - mock := NewMockGCE(pr) - - var key *meta.Key - keyAlpha := meta.GlobalKey("key-alpha") - key = keyAlpha - keyBeta := meta.GlobalKey("key-beta") - key = keyBeta - keyGA := meta.GlobalKey("key-ga") - key = keyGA - // Ignore unused variables. - _, _, _ = ctx, mock, key - - // Get not found. - if _, err := mock.AlphaHealthChecks().Get(ctx, key); err == nil { - t.Errorf("AlphaHealthChecks().Get(%v, %v) = _, nil; want error", ctx, key) - } - if _, err := mock.BetaHealthChecks().Get(ctx, key); err == nil { - t.Errorf("BetaHealthChecks().Get(%v, %v) = _, nil; want error", ctx, key) - } - if _, err := mock.HealthChecks().Get(ctx, key); err == nil { - t.Errorf("HealthChecks().Get(%v, %v) = _, nil; want error", ctx, key) - } - - // Insert. - { - obj := &alpha.HealthCheck{} - if err := mock.AlphaHealthChecks().Insert(ctx, keyAlpha, obj); err != nil { - t.Errorf("AlphaHealthChecks().Insert(%v, %v, %v) = %v; want nil", ctx, keyAlpha, obj, err) - } - } - { - obj := &beta.HealthCheck{} - if err := mock.BetaHealthChecks().Insert(ctx, keyBeta, obj); err != nil { - t.Errorf("BetaHealthChecks().Insert(%v, %v, %v) = %v; want nil", ctx, keyBeta, obj, err) - } - } - { - obj := &ga.HealthCheck{} - if err := mock.HealthChecks().Insert(ctx, keyGA, obj); err != nil { - t.Errorf("HealthChecks().Insert(%v, %v, %v) = %v; want nil", ctx, keyGA, obj, err) - } - } - - // Get across versions. - if obj, err := mock.AlphaHealthChecks().Get(ctx, key); err != nil { - t.Errorf("AlphaHealthChecks().Get(%v, %v) = %v, %v; want nil", ctx, key, obj, err) - } - if obj, err := mock.BetaHealthChecks().Get(ctx, key); err != nil { - t.Errorf("BetaHealthChecks().Get(%v, %v) = %v, %v; want nil", ctx, key, obj, err) - } - if obj, err := mock.HealthChecks().Get(ctx, key); err != nil { - t.Errorf("HealthChecks().Get(%v, %v) = %v, %v; want nil", ctx, key, obj, err) - } - - // List. - mock.MockAlphaHealthChecks.Objects[*keyAlpha] = mock.MockAlphaHealthChecks.Obj(&alpha.HealthCheck{Name: keyAlpha.Name}) - mock.MockBetaHealthChecks.Objects[*keyBeta] = mock.MockBetaHealthChecks.Obj(&beta.HealthCheck{Name: keyBeta.Name}) - mock.MockHealthChecks.Objects[*keyGA] = mock.MockHealthChecks.Obj(&ga.HealthCheck{Name: keyGA.Name}) - want := map[string]bool{ - "key-alpha": true, - "key-beta": true, - "key-ga": true, - } - _ = want // ignore unused variables. - { - objs, err := mock.AlphaHealthChecks().List(ctx, filter.None) - if err != nil { - t.Errorf("AlphaHealthChecks().List(%v, %v, %v) = %v, %v; want _, nil", ctx, location, filter.None, objs, err) - } else { - got := map[string]bool{} - for _, obj := range objs { - got[obj.Name] = true - } - if !reflect.DeepEqual(got, want) { - t.Errorf("AlphaHealthChecks().List(); got %+v, want %+v", got, want) - } - } - } - { - objs, err := mock.BetaHealthChecks().List(ctx, filter.None) - if err != nil { - t.Errorf("BetaHealthChecks().List(%v, %v, %v) = %v, %v; want _, nil", ctx, location, filter.None, objs, err) - } else { - got := map[string]bool{} - for _, obj := range objs { - got[obj.Name] = true - } - if !reflect.DeepEqual(got, want) { - t.Errorf("BetaHealthChecks().List(); got %+v, want %+v", got, want) - } - } - } - { - objs, err := mock.HealthChecks().List(ctx, filter.None) - if err != nil { - t.Errorf("HealthChecks().List(%v, %v, %v) = %v, %v; want _, nil", ctx, location, filter.None, objs, err) - } else { - got := map[string]bool{} - for _, obj := range objs { - got[obj.Name] = true - } - if !reflect.DeepEqual(got, want) { - t.Errorf("HealthChecks().List(); got %+v, want %+v", got, want) - } - } - } - - // Delete across versions. - if err := mock.AlphaHealthChecks().Delete(ctx, keyAlpha); err != nil { - t.Errorf("AlphaHealthChecks().Delete(%v, %v) = %v; want nil", ctx, keyAlpha, err) - } - if err := mock.BetaHealthChecks().Delete(ctx, keyBeta); err != nil { - t.Errorf("BetaHealthChecks().Delete(%v, %v) = %v; want nil", ctx, keyBeta, err) - } - if err := mock.HealthChecks().Delete(ctx, keyGA); err != nil { - t.Errorf("HealthChecks().Delete(%v, %v) = %v; want nil", ctx, keyGA, err) - } - - // Delete not found. - if err := mock.AlphaHealthChecks().Delete(ctx, keyAlpha); err == nil { - t.Errorf("AlphaHealthChecks().Delete(%v, %v) = nil; want error", ctx, keyAlpha) - } - if err := mock.BetaHealthChecks().Delete(ctx, keyBeta); err == nil { - t.Errorf("BetaHealthChecks().Delete(%v, %v) = nil; want error", ctx, keyBeta) - } - if err := mock.HealthChecks().Delete(ctx, keyGA); err == nil { - t.Errorf("HealthChecks().Delete(%v, %v) = nil; want error", ctx, keyGA) - } -} - -func TestHttpHealthChecksGroup(t *testing.T) { - t.Parallel() - - ctx := context.Background() - pr := &SingleProjectRouter{"mock-project"} - mock := NewMockGCE(pr) - - var key *meta.Key - keyGA := meta.GlobalKey("key-ga") - key = keyGA - // Ignore unused variables. - _, _, _ = ctx, mock, key - - // Get not found. - if _, err := mock.HttpHealthChecks().Get(ctx, key); err == nil { - t.Errorf("HttpHealthChecks().Get(%v, %v) = _, nil; want error", ctx, key) - } - - // Insert. - { - obj := &ga.HttpHealthCheck{} - if err := mock.HttpHealthChecks().Insert(ctx, keyGA, obj); err != nil { - t.Errorf("HttpHealthChecks().Insert(%v, %v, %v) = %v; want nil", ctx, keyGA, obj, err) - } - } - - // Get across versions. - if obj, err := mock.HttpHealthChecks().Get(ctx, key); err != nil { - t.Errorf("HttpHealthChecks().Get(%v, %v) = %v, %v; want nil", ctx, key, obj, err) - } - - // List. - mock.MockHttpHealthChecks.Objects[*keyGA] = mock.MockHttpHealthChecks.Obj(&ga.HttpHealthCheck{Name: keyGA.Name}) - want := map[string]bool{ - "key-ga": true, - } - _ = want // ignore unused variables. - { - objs, err := mock.HttpHealthChecks().List(ctx, filter.None) - if err != nil { - t.Errorf("HttpHealthChecks().List(%v, %v, %v) = %v, %v; want _, nil", ctx, location, filter.None, objs, err) - } else { - got := map[string]bool{} - for _, obj := range objs { - got[obj.Name] = true - } - if !reflect.DeepEqual(got, want) { - t.Errorf("HttpHealthChecks().List(); got %+v, want %+v", got, want) - } - } - } - - // Delete across versions. - if err := mock.HttpHealthChecks().Delete(ctx, keyGA); err != nil { - t.Errorf("HttpHealthChecks().Delete(%v, %v) = %v; want nil", ctx, keyGA, err) - } - - // Delete not found. - if err := mock.HttpHealthChecks().Delete(ctx, keyGA); err == nil { - t.Errorf("HttpHealthChecks().Delete(%v, %v) = nil; want error", ctx, keyGA) - } -} - -func TestHttpsHealthChecksGroup(t *testing.T) { - t.Parallel() - - ctx := context.Background() - pr := &SingleProjectRouter{"mock-project"} - mock := NewMockGCE(pr) - - var key *meta.Key - keyGA := meta.GlobalKey("key-ga") - key = keyGA - // Ignore unused variables. - _, _, _ = ctx, mock, key - - // Get not found. - if _, err := mock.HttpsHealthChecks().Get(ctx, key); err == nil { - t.Errorf("HttpsHealthChecks().Get(%v, %v) = _, nil; want error", ctx, key) - } - - // Insert. - { - obj := &ga.HttpsHealthCheck{} - if err := mock.HttpsHealthChecks().Insert(ctx, keyGA, obj); err != nil { - t.Errorf("HttpsHealthChecks().Insert(%v, %v, %v) = %v; want nil", ctx, keyGA, obj, err) - } - } - - // Get across versions. - if obj, err := mock.HttpsHealthChecks().Get(ctx, key); err != nil { - t.Errorf("HttpsHealthChecks().Get(%v, %v) = %v, %v; want nil", ctx, key, obj, err) - } - - // List. - mock.MockHttpsHealthChecks.Objects[*keyGA] = mock.MockHttpsHealthChecks.Obj(&ga.HttpsHealthCheck{Name: keyGA.Name}) - want := map[string]bool{ - "key-ga": true, - } - _ = want // ignore unused variables. - { - objs, err := mock.HttpsHealthChecks().List(ctx, filter.None) - if err != nil { - t.Errorf("HttpsHealthChecks().List(%v, %v, %v) = %v, %v; want _, nil", ctx, location, filter.None, objs, err) - } else { - got := map[string]bool{} - for _, obj := range objs { - got[obj.Name] = true - } - if !reflect.DeepEqual(got, want) { - t.Errorf("HttpsHealthChecks().List(); got %+v, want %+v", got, want) - } - } - } - - // Delete across versions. - if err := mock.HttpsHealthChecks().Delete(ctx, keyGA); err != nil { - t.Errorf("HttpsHealthChecks().Delete(%v, %v) = %v; want nil", ctx, keyGA, err) - } - - // Delete not found. - if err := mock.HttpsHealthChecks().Delete(ctx, keyGA); err == nil { - t.Errorf("HttpsHealthChecks().Delete(%v, %v) = nil; want error", ctx, keyGA) - } -} - -func TestInstanceGroupsGroup(t *testing.T) { - t.Parallel() - - ctx := context.Background() - pr := &SingleProjectRouter{"mock-project"} - mock := NewMockGCE(pr) - - var key *meta.Key - keyGA := meta.ZonalKey("key-ga", "location") - key = keyGA - // Ignore unused variables. - _, _, _ = ctx, mock, key - - // Get not found. - if _, err := mock.InstanceGroups().Get(ctx, key); err == nil { - t.Errorf("InstanceGroups().Get(%v, %v) = _, nil; want error", ctx, key) - } - - // Insert. - { - obj := &ga.InstanceGroup{} - if err := mock.InstanceGroups().Insert(ctx, keyGA, obj); err != nil { - t.Errorf("InstanceGroups().Insert(%v, %v, %v) = %v; want nil", ctx, keyGA, obj, err) - } - } - - // Get across versions. - if obj, err := mock.InstanceGroups().Get(ctx, key); err != nil { - t.Errorf("InstanceGroups().Get(%v, %v) = %v, %v; want nil", ctx, key, obj, err) - } - - // List. - mock.MockInstanceGroups.Objects[*keyGA] = mock.MockInstanceGroups.Obj(&ga.InstanceGroup{Name: keyGA.Name}) - want := map[string]bool{ - "key-ga": true, - } - _ = want // ignore unused variables. - { - objs, err := mock.InstanceGroups().List(ctx, location, filter.None) - if err != nil { - t.Errorf("InstanceGroups().List(%v, %v, %v) = %v, %v; want _, nil", ctx, location, filter.None, objs, err) - } else { - got := map[string]bool{} - for _, obj := range objs { - got[obj.Name] = true - } - if !reflect.DeepEqual(got, want) { - t.Errorf("InstanceGroups().List(); got %+v, want %+v", got, want) - } - } - } - - // Delete across versions. - if err := mock.InstanceGroups().Delete(ctx, keyGA); err != nil { - t.Errorf("InstanceGroups().Delete(%v, %v) = %v; want nil", ctx, keyGA, err) - } - - // Delete not found. - if err := mock.InstanceGroups().Delete(ctx, keyGA); err == nil { - t.Errorf("InstanceGroups().Delete(%v, %v) = nil; want error", ctx, keyGA) - } -} - -func TestInstancesGroup(t *testing.T) { - t.Parallel() - - ctx := context.Background() - pr := &SingleProjectRouter{"mock-project"} - mock := NewMockGCE(pr) - - var key *meta.Key - keyAlpha := meta.ZonalKey("key-alpha", "location") - key = keyAlpha - keyBeta := meta.ZonalKey("key-beta", "location") - key = keyBeta - keyGA := meta.ZonalKey("key-ga", "location") - key = keyGA - // Ignore unused variables. - _, _, _ = ctx, mock, key - - // Get not found. - if _, err := mock.AlphaInstances().Get(ctx, key); err == nil { - t.Errorf("AlphaInstances().Get(%v, %v) = _, nil; want error", ctx, key) - } - if _, err := mock.BetaInstances().Get(ctx, key); err == nil { - t.Errorf("BetaInstances().Get(%v, %v) = _, nil; want error", ctx, key) - } - if _, err := mock.Instances().Get(ctx, key); err == nil { - t.Errorf("Instances().Get(%v, %v) = _, nil; want error", ctx, key) - } - - // Insert. - { - obj := &alpha.Instance{} - if err := mock.AlphaInstances().Insert(ctx, keyAlpha, obj); err != nil { - t.Errorf("AlphaInstances().Insert(%v, %v, %v) = %v; want nil", ctx, keyAlpha, obj, err) - } - } - { - obj := &beta.Instance{} - if err := mock.BetaInstances().Insert(ctx, keyBeta, obj); err != nil { - t.Errorf("BetaInstances().Insert(%v, %v, %v) = %v; want nil", ctx, keyBeta, obj, err) - } - } - { - obj := &ga.Instance{} - if err := mock.Instances().Insert(ctx, keyGA, obj); err != nil { - t.Errorf("Instances().Insert(%v, %v, %v) = %v; want nil", ctx, keyGA, obj, err) - } - } - - // Get across versions. - if obj, err := mock.AlphaInstances().Get(ctx, key); err != nil { - t.Errorf("AlphaInstances().Get(%v, %v) = %v, %v; want nil", ctx, key, obj, err) - } - if obj, err := mock.BetaInstances().Get(ctx, key); err != nil { - t.Errorf("BetaInstances().Get(%v, %v) = %v, %v; want nil", ctx, key, obj, err) - } - if obj, err := mock.Instances().Get(ctx, key); err != nil { - t.Errorf("Instances().Get(%v, %v) = %v, %v; want nil", ctx, key, obj, err) - } - - // List. - mock.MockAlphaInstances.Objects[*keyAlpha] = mock.MockAlphaInstances.Obj(&alpha.Instance{Name: keyAlpha.Name}) - mock.MockBetaInstances.Objects[*keyBeta] = mock.MockBetaInstances.Obj(&beta.Instance{Name: keyBeta.Name}) - mock.MockInstances.Objects[*keyGA] = mock.MockInstances.Obj(&ga.Instance{Name: keyGA.Name}) - want := map[string]bool{ - "key-alpha": true, - "key-beta": true, - "key-ga": true, - } - _ = want // ignore unused variables. - { - objs, err := mock.AlphaInstances().List(ctx, location, filter.None) - if err != nil { - t.Errorf("AlphaInstances().List(%v, %v, %v) = %v, %v; want _, nil", ctx, location, filter.None, objs, err) - } else { - got := map[string]bool{} - for _, obj := range objs { - got[obj.Name] = true - } - if !reflect.DeepEqual(got, want) { - t.Errorf("AlphaInstances().List(); got %+v, want %+v", got, want) - } - } - } - { - objs, err := mock.BetaInstances().List(ctx, location, filter.None) - if err != nil { - t.Errorf("BetaInstances().List(%v, %v, %v) = %v, %v; want _, nil", ctx, location, filter.None, objs, err) - } else { - got := map[string]bool{} - for _, obj := range objs { - got[obj.Name] = true - } - if !reflect.DeepEqual(got, want) { - t.Errorf("BetaInstances().List(); got %+v, want %+v", got, want) - } - } - } - { - objs, err := mock.Instances().List(ctx, location, filter.None) - if err != nil { - t.Errorf("Instances().List(%v, %v, %v) = %v, %v; want _, nil", ctx, location, filter.None, objs, err) - } else { - got := map[string]bool{} - for _, obj := range objs { - got[obj.Name] = true - } - if !reflect.DeepEqual(got, want) { - t.Errorf("Instances().List(); got %+v, want %+v", got, want) - } - } - } - - // Delete across versions. - if err := mock.AlphaInstances().Delete(ctx, keyAlpha); err != nil { - t.Errorf("AlphaInstances().Delete(%v, %v) = %v; want nil", ctx, keyAlpha, err) - } - if err := mock.BetaInstances().Delete(ctx, keyBeta); err != nil { - t.Errorf("BetaInstances().Delete(%v, %v) = %v; want nil", ctx, keyBeta, err) - } - if err := mock.Instances().Delete(ctx, keyGA); err != nil { - t.Errorf("Instances().Delete(%v, %v) = %v; want nil", ctx, keyGA, err) - } - - // Delete not found. - if err := mock.AlphaInstances().Delete(ctx, keyAlpha); err == nil { - t.Errorf("AlphaInstances().Delete(%v, %v) = nil; want error", ctx, keyAlpha) - } - if err := mock.BetaInstances().Delete(ctx, keyBeta); err == nil { - t.Errorf("BetaInstances().Delete(%v, %v) = nil; want error", ctx, keyBeta) - } - if err := mock.Instances().Delete(ctx, keyGA); err == nil { - t.Errorf("Instances().Delete(%v, %v) = nil; want error", ctx, keyGA) - } -} - -func TestNetworkEndpointGroupsGroup(t *testing.T) { - t.Parallel() - - ctx := context.Background() - pr := &SingleProjectRouter{"mock-project"} - mock := NewMockGCE(pr) - - var key *meta.Key - keyAlpha := meta.ZonalKey("key-alpha", "location") - key = keyAlpha - keyBeta := meta.ZonalKey("key-beta", "location") - key = keyBeta - // Ignore unused variables. - _, _, _ = ctx, mock, key - - // Get not found. - if _, err := mock.AlphaNetworkEndpointGroups().Get(ctx, key); err == nil { - t.Errorf("AlphaNetworkEndpointGroups().Get(%v, %v) = _, nil; want error", ctx, key) - } - if _, err := mock.BetaNetworkEndpointGroups().Get(ctx, key); err == nil { - t.Errorf("BetaNetworkEndpointGroups().Get(%v, %v) = _, nil; want error", ctx, key) - } - - // Insert. - { - obj := &alpha.NetworkEndpointGroup{} - if err := mock.AlphaNetworkEndpointGroups().Insert(ctx, keyAlpha, obj); err != nil { - t.Errorf("AlphaNetworkEndpointGroups().Insert(%v, %v, %v) = %v; want nil", ctx, keyAlpha, obj, err) - } - } - { - obj := &beta.NetworkEndpointGroup{} - if err := mock.BetaNetworkEndpointGroups().Insert(ctx, keyBeta, obj); err != nil { - t.Errorf("BetaNetworkEndpointGroups().Insert(%v, %v, %v) = %v; want nil", ctx, keyBeta, obj, err) - } - } - - // Get across versions. - if obj, err := mock.AlphaNetworkEndpointGroups().Get(ctx, key); err != nil { - t.Errorf("AlphaNetworkEndpointGroups().Get(%v, %v) = %v, %v; want nil", ctx, key, obj, err) - } - if obj, err := mock.BetaNetworkEndpointGroups().Get(ctx, key); err != nil { - t.Errorf("BetaNetworkEndpointGroups().Get(%v, %v) = %v, %v; want nil", ctx, key, obj, err) - } - - // List. - mock.MockAlphaNetworkEndpointGroups.Objects[*keyAlpha] = mock.MockAlphaNetworkEndpointGroups.Obj(&alpha.NetworkEndpointGroup{Name: keyAlpha.Name}) - mock.MockBetaNetworkEndpointGroups.Objects[*keyBeta] = mock.MockBetaNetworkEndpointGroups.Obj(&beta.NetworkEndpointGroup{Name: keyBeta.Name}) - want := map[string]bool{ - "key-alpha": true, - "key-beta": true, - } - _ = want // ignore unused variables. - { - objs, err := mock.AlphaNetworkEndpointGroups().List(ctx, location, filter.None) - if err != nil { - t.Errorf("AlphaNetworkEndpointGroups().List(%v, %v, %v) = %v, %v; want _, nil", ctx, location, filter.None, objs, err) - } else { - got := map[string]bool{} - for _, obj := range objs { - got[obj.Name] = true - } - if !reflect.DeepEqual(got, want) { - t.Errorf("AlphaNetworkEndpointGroups().List(); got %+v, want %+v", got, want) - } - } - } - { - objs, err := mock.BetaNetworkEndpointGroups().List(ctx, location, filter.None) - if err != nil { - t.Errorf("BetaNetworkEndpointGroups().List(%v, %v, %v) = %v, %v; want _, nil", ctx, location, filter.None, objs, err) - } else { - got := map[string]bool{} - for _, obj := range objs { - got[obj.Name] = true - } - if !reflect.DeepEqual(got, want) { - t.Errorf("BetaNetworkEndpointGroups().List(); got %+v, want %+v", got, want) - } - } - } - - // Delete across versions. - if err := mock.AlphaNetworkEndpointGroups().Delete(ctx, keyAlpha); err != nil { - t.Errorf("AlphaNetworkEndpointGroups().Delete(%v, %v) = %v; want nil", ctx, keyAlpha, err) - } - if err := mock.BetaNetworkEndpointGroups().Delete(ctx, keyBeta); err != nil { - t.Errorf("BetaNetworkEndpointGroups().Delete(%v, %v) = %v; want nil", ctx, keyBeta, err) - } - - // Delete not found. - if err := mock.AlphaNetworkEndpointGroups().Delete(ctx, keyAlpha); err == nil { - t.Errorf("AlphaNetworkEndpointGroups().Delete(%v, %v) = nil; want error", ctx, keyAlpha) - } - if err := mock.BetaNetworkEndpointGroups().Delete(ctx, keyBeta); err == nil { - t.Errorf("BetaNetworkEndpointGroups().Delete(%v, %v) = nil; want error", ctx, keyBeta) - } -} - -func TestProjectsGroup(t *testing.T) { - t.Parallel() - - ctx := context.Background() - pr := &SingleProjectRouter{"mock-project"} - mock := NewMockGCE(pr) - - var key *meta.Key - keyGA := meta.GlobalKey("key-ga") - key = keyGA - // Ignore unused variables. - _, _, _ = ctx, mock, key - - // Get not found. - - // Insert. - - // Get across versions. - - // List. - mock.MockProjects.Objects[*keyGA] = mock.MockProjects.Obj(&ga.Project{Name: keyGA.Name}) - want := map[string]bool{ - "key-ga": true, - } - _ = want // ignore unused variables. - - // Delete across versions. - - // Delete not found. -} - -func TestRegionBackendServicesGroup(t *testing.T) { - t.Parallel() - - ctx := context.Background() - pr := &SingleProjectRouter{"mock-project"} - mock := NewMockGCE(pr) - - var key *meta.Key - keyAlpha := meta.RegionalKey("key-alpha", "location") - key = keyAlpha - keyGA := meta.RegionalKey("key-ga", "location") - key = keyGA - // Ignore unused variables. - _, _, _ = ctx, mock, key - - // Get not found. - if _, err := mock.AlphaRegionBackendServices().Get(ctx, key); err == nil { - t.Errorf("AlphaRegionBackendServices().Get(%v, %v) = _, nil; want error", ctx, key) - } - if _, err := mock.RegionBackendServices().Get(ctx, key); err == nil { - t.Errorf("RegionBackendServices().Get(%v, %v) = _, nil; want error", ctx, key) - } - - // Insert. - { - obj := &alpha.BackendService{} - if err := mock.AlphaRegionBackendServices().Insert(ctx, keyAlpha, obj); err != nil { - t.Errorf("AlphaRegionBackendServices().Insert(%v, %v, %v) = %v; want nil", ctx, keyAlpha, obj, err) - } - } - { - obj := &ga.BackendService{} - if err := mock.RegionBackendServices().Insert(ctx, keyGA, obj); err != nil { - t.Errorf("RegionBackendServices().Insert(%v, %v, %v) = %v; want nil", ctx, keyGA, obj, err) - } - } - - // Get across versions. - if obj, err := mock.AlphaRegionBackendServices().Get(ctx, key); err != nil { - t.Errorf("AlphaRegionBackendServices().Get(%v, %v) = %v, %v; want nil", ctx, key, obj, err) - } - if obj, err := mock.RegionBackendServices().Get(ctx, key); err != nil { - t.Errorf("RegionBackendServices().Get(%v, %v) = %v, %v; want nil", ctx, key, obj, err) - } - - // List. - mock.MockAlphaRegionBackendServices.Objects[*keyAlpha] = mock.MockAlphaRegionBackendServices.Obj(&alpha.BackendService{Name: keyAlpha.Name}) - mock.MockRegionBackendServices.Objects[*keyGA] = mock.MockRegionBackendServices.Obj(&ga.BackendService{Name: keyGA.Name}) - want := map[string]bool{ - "key-alpha": true, - "key-ga": true, - } - _ = want // ignore unused variables. - { - objs, err := mock.AlphaRegionBackendServices().List(ctx, location, filter.None) - if err != nil { - t.Errorf("AlphaRegionBackendServices().List(%v, %v, %v) = %v, %v; want _, nil", ctx, location, filter.None, objs, err) - } else { - got := map[string]bool{} - for _, obj := range objs { - got[obj.Name] = true - } - if !reflect.DeepEqual(got, want) { - t.Errorf("AlphaRegionBackendServices().List(); got %+v, want %+v", got, want) - } - } - } - { - objs, err := mock.RegionBackendServices().List(ctx, location, filter.None) - if err != nil { - t.Errorf("RegionBackendServices().List(%v, %v, %v) = %v, %v; want _, nil", ctx, location, filter.None, objs, err) - } else { - got := map[string]bool{} - for _, obj := range objs { - got[obj.Name] = true - } - if !reflect.DeepEqual(got, want) { - t.Errorf("RegionBackendServices().List(); got %+v, want %+v", got, want) - } - } - } - - // Delete across versions. - if err := mock.AlphaRegionBackendServices().Delete(ctx, keyAlpha); err != nil { - t.Errorf("AlphaRegionBackendServices().Delete(%v, %v) = %v; want nil", ctx, keyAlpha, err) - } - if err := mock.RegionBackendServices().Delete(ctx, keyGA); err != nil { - t.Errorf("RegionBackendServices().Delete(%v, %v) = %v; want nil", ctx, keyGA, err) - } - - // Delete not found. - if err := mock.AlphaRegionBackendServices().Delete(ctx, keyAlpha); err == nil { - t.Errorf("AlphaRegionBackendServices().Delete(%v, %v) = nil; want error", ctx, keyAlpha) - } - if err := mock.RegionBackendServices().Delete(ctx, keyGA); err == nil { - t.Errorf("RegionBackendServices().Delete(%v, %v) = nil; want error", ctx, keyGA) - } -} - -func TestRegionDisksGroup(t *testing.T) { - t.Parallel() - - ctx := context.Background() - pr := &SingleProjectRouter{"mock-project"} - mock := NewMockGCE(pr) - - var key *meta.Key - keyGA := meta.RegionalKey("key-ga", "location") - key = keyGA - // Ignore unused variables. - _, _, _ = ctx, mock, key - - // Get not found. - if _, err := mock.RegionDisks().Get(ctx, key); err == nil { - t.Errorf("RegionDisks().Get(%v, %v) = _, nil; want error", ctx, key) - } - - // Insert. - { - obj := &ga.Disk{} - if err := mock.RegionDisks().Insert(ctx, keyGA, obj); err != nil { - t.Errorf("RegionDisks().Insert(%v, %v, %v) = %v; want nil", ctx, keyGA, obj, err) - } - } - - // Get across versions. - if obj, err := mock.RegionDisks().Get(ctx, key); err != nil { - t.Errorf("RegionDisks().Get(%v, %v) = %v, %v; want nil", ctx, key, obj, err) - } - - // List. - mock.MockRegionDisks.Objects[*keyGA] = mock.MockRegionDisks.Obj(&ga.Disk{Name: keyGA.Name}) - want := map[string]bool{ - "key-ga": true, - } - _ = want // ignore unused variables. - { - objs, err := mock.RegionDisks().List(ctx, location, filter.None) - if err != nil { - t.Errorf("RegionDisks().List(%v, %v, %v) = %v, %v; want _, nil", ctx, location, filter.None, objs, err) - } else { - got := map[string]bool{} - for _, obj := range objs { - got[obj.Name] = true - } - if !reflect.DeepEqual(got, want) { - t.Errorf("RegionDisks().List(); got %+v, want %+v", got, want) - } - } - } - - // Delete across versions. - if err := mock.RegionDisks().Delete(ctx, keyGA); err != nil { - t.Errorf("RegionDisks().Delete(%v, %v) = %v; want nil", ctx, keyGA, err) - } - - // Delete not found. - if err := mock.RegionDisks().Delete(ctx, keyGA); err == nil { - t.Errorf("RegionDisks().Delete(%v, %v) = nil; want error", ctx, keyGA) - } -} - -func TestRegionsGroup(t *testing.T) { - t.Parallel() - - ctx := context.Background() - pr := &SingleProjectRouter{"mock-project"} - mock := NewMockGCE(pr) - - var key *meta.Key - keyGA := meta.GlobalKey("key-ga") - key = keyGA - // Ignore unused variables. - _, _, _ = ctx, mock, key - - // Get not found. - if _, err := mock.Regions().Get(ctx, key); err == nil { - t.Errorf("Regions().Get(%v, %v) = _, nil; want error", ctx, key) - } - - // Insert. - - // Get across versions. - - // List. - mock.MockRegions.Objects[*keyGA] = mock.MockRegions.Obj(&ga.Region{Name: keyGA.Name}) - want := map[string]bool{ - "key-ga": true, - } - _ = want // ignore unused variables. - { - objs, err := mock.Regions().List(ctx, filter.None) - if err != nil { - t.Errorf("Regions().List(%v, %v, %v) = %v, %v; want _, nil", ctx, location, filter.None, objs, err) - } else { - got := map[string]bool{} - for _, obj := range objs { - got[obj.Name] = true - } - if !reflect.DeepEqual(got, want) { - t.Errorf("Regions().List(); got %+v, want %+v", got, want) - } - } - } - - // Delete across versions. - - // Delete not found. -} - -func TestRoutesGroup(t *testing.T) { - t.Parallel() - - ctx := context.Background() - pr := &SingleProjectRouter{"mock-project"} - mock := NewMockGCE(pr) - - var key *meta.Key - keyGA := meta.GlobalKey("key-ga") - key = keyGA - // Ignore unused variables. - _, _, _ = ctx, mock, key - - // Get not found. - if _, err := mock.Routes().Get(ctx, key); err == nil { - t.Errorf("Routes().Get(%v, %v) = _, nil; want error", ctx, key) - } - - // Insert. - { - obj := &ga.Route{} - if err := mock.Routes().Insert(ctx, keyGA, obj); err != nil { - t.Errorf("Routes().Insert(%v, %v, %v) = %v; want nil", ctx, keyGA, obj, err) - } - } - - // Get across versions. - if obj, err := mock.Routes().Get(ctx, key); err != nil { - t.Errorf("Routes().Get(%v, %v) = %v, %v; want nil", ctx, key, obj, err) - } - - // List. - mock.MockRoutes.Objects[*keyGA] = mock.MockRoutes.Obj(&ga.Route{Name: keyGA.Name}) - want := map[string]bool{ - "key-ga": true, - } - _ = want // ignore unused variables. - { - objs, err := mock.Routes().List(ctx, filter.None) - if err != nil { - t.Errorf("Routes().List(%v, %v, %v) = %v, %v; want _, nil", ctx, location, filter.None, objs, err) - } else { - got := map[string]bool{} - for _, obj := range objs { - got[obj.Name] = true - } - if !reflect.DeepEqual(got, want) { - t.Errorf("Routes().List(); got %+v, want %+v", got, want) - } - } - } - - // Delete across versions. - if err := mock.Routes().Delete(ctx, keyGA); err != nil { - t.Errorf("Routes().Delete(%v, %v) = %v; want nil", ctx, keyGA, err) - } - - // Delete not found. - if err := mock.Routes().Delete(ctx, keyGA); err == nil { - t.Errorf("Routes().Delete(%v, %v) = nil; want error", ctx, keyGA) - } -} - -func TestSecurityPoliciesGroup(t *testing.T) { - t.Parallel() - - ctx := context.Background() - pr := &SingleProjectRouter{"mock-project"} - mock := NewMockGCE(pr) - - var key *meta.Key - keyBeta := meta.GlobalKey("key-beta") - key = keyBeta - // Ignore unused variables. - _, _, _ = ctx, mock, key - - // Get not found. - if _, err := mock.BetaSecurityPolicies().Get(ctx, key); err == nil { - t.Errorf("BetaSecurityPolicies().Get(%v, %v) = _, nil; want error", ctx, key) - } - - // Insert. - { - obj := &beta.SecurityPolicy{} - if err := mock.BetaSecurityPolicies().Insert(ctx, keyBeta, obj); err != nil { - t.Errorf("BetaSecurityPolicies().Insert(%v, %v, %v) = %v; want nil", ctx, keyBeta, obj, err) - } - } - - // Get across versions. - if obj, err := mock.BetaSecurityPolicies().Get(ctx, key); err != nil { - t.Errorf("BetaSecurityPolicies().Get(%v, %v) = %v, %v; want nil", ctx, key, obj, err) - } - - // List. - mock.MockBetaSecurityPolicies.Objects[*keyBeta] = mock.MockBetaSecurityPolicies.Obj(&beta.SecurityPolicy{Name: keyBeta.Name}) - want := map[string]bool{ - "key-beta": true, - } - _ = want // ignore unused variables. - { - objs, err := mock.BetaSecurityPolicies().List(ctx, filter.None) - if err != nil { - t.Errorf("BetaSecurityPolicies().List(%v, %v, %v) = %v, %v; want _, nil", ctx, location, filter.None, objs, err) - } else { - got := map[string]bool{} - for _, obj := range objs { - got[obj.Name] = true - } - if !reflect.DeepEqual(got, want) { - t.Errorf("BetaSecurityPolicies().List(); got %+v, want %+v", got, want) - } - } - } - - // Delete across versions. - if err := mock.BetaSecurityPolicies().Delete(ctx, keyBeta); err != nil { - t.Errorf("BetaSecurityPolicies().Delete(%v, %v) = %v; want nil", ctx, keyBeta, err) - } - - // Delete not found. - if err := mock.BetaSecurityPolicies().Delete(ctx, keyBeta); err == nil { - t.Errorf("BetaSecurityPolicies().Delete(%v, %v) = nil; want error", ctx, keyBeta) - } -} - -func TestSslCertificatesGroup(t *testing.T) { - t.Parallel() - - ctx := context.Background() - pr := &SingleProjectRouter{"mock-project"} - mock := NewMockGCE(pr) - - var key *meta.Key - keyGA := meta.GlobalKey("key-ga") - key = keyGA - // Ignore unused variables. - _, _, _ = ctx, mock, key - - // Get not found. - if _, err := mock.SslCertificates().Get(ctx, key); err == nil { - t.Errorf("SslCertificates().Get(%v, %v) = _, nil; want error", ctx, key) - } - - // Insert. - { - obj := &ga.SslCertificate{} - if err := mock.SslCertificates().Insert(ctx, keyGA, obj); err != nil { - t.Errorf("SslCertificates().Insert(%v, %v, %v) = %v; want nil", ctx, keyGA, obj, err) - } - } - - // Get across versions. - if obj, err := mock.SslCertificates().Get(ctx, key); err != nil { - t.Errorf("SslCertificates().Get(%v, %v) = %v, %v; want nil", ctx, key, obj, err) - } - - // List. - mock.MockSslCertificates.Objects[*keyGA] = mock.MockSslCertificates.Obj(&ga.SslCertificate{Name: keyGA.Name}) - want := map[string]bool{ - "key-ga": true, - } - _ = want // ignore unused variables. - { - objs, err := mock.SslCertificates().List(ctx, filter.None) - if err != nil { - t.Errorf("SslCertificates().List(%v, %v, %v) = %v, %v; want _, nil", ctx, location, filter.None, objs, err) - } else { - got := map[string]bool{} - for _, obj := range objs { - got[obj.Name] = true - } - if !reflect.DeepEqual(got, want) { - t.Errorf("SslCertificates().List(); got %+v, want %+v", got, want) - } - } - } - - // Delete across versions. - if err := mock.SslCertificates().Delete(ctx, keyGA); err != nil { - t.Errorf("SslCertificates().Delete(%v, %v) = %v; want nil", ctx, keyGA, err) - } - - // Delete not found. - if err := mock.SslCertificates().Delete(ctx, keyGA); err == nil { - t.Errorf("SslCertificates().Delete(%v, %v) = nil; want error", ctx, keyGA) - } -} - -func TestTargetHttpProxiesGroup(t *testing.T) { - t.Parallel() - - ctx := context.Background() - pr := &SingleProjectRouter{"mock-project"} - mock := NewMockGCE(pr) - - var key *meta.Key - keyGA := meta.GlobalKey("key-ga") - key = keyGA - // Ignore unused variables. - _, _, _ = ctx, mock, key - - // Get not found. - if _, err := mock.TargetHttpProxies().Get(ctx, key); err == nil { - t.Errorf("TargetHttpProxies().Get(%v, %v) = _, nil; want error", ctx, key) - } - - // Insert. - { - obj := &ga.TargetHttpProxy{} - if err := mock.TargetHttpProxies().Insert(ctx, keyGA, obj); err != nil { - t.Errorf("TargetHttpProxies().Insert(%v, %v, %v) = %v; want nil", ctx, keyGA, obj, err) - } - } - - // Get across versions. - if obj, err := mock.TargetHttpProxies().Get(ctx, key); err != nil { - t.Errorf("TargetHttpProxies().Get(%v, %v) = %v, %v; want nil", ctx, key, obj, err) - } - - // List. - mock.MockTargetHttpProxies.Objects[*keyGA] = mock.MockTargetHttpProxies.Obj(&ga.TargetHttpProxy{Name: keyGA.Name}) - want := map[string]bool{ - "key-ga": true, - } - _ = want // ignore unused variables. - { - objs, err := mock.TargetHttpProxies().List(ctx, filter.None) - if err != nil { - t.Errorf("TargetHttpProxies().List(%v, %v, %v) = %v, %v; want _, nil", ctx, location, filter.None, objs, err) - } else { - got := map[string]bool{} - for _, obj := range objs { - got[obj.Name] = true - } - if !reflect.DeepEqual(got, want) { - t.Errorf("TargetHttpProxies().List(); got %+v, want %+v", got, want) - } - } - } - - // Delete across versions. - if err := mock.TargetHttpProxies().Delete(ctx, keyGA); err != nil { - t.Errorf("TargetHttpProxies().Delete(%v, %v) = %v; want nil", ctx, keyGA, err) - } - - // Delete not found. - if err := mock.TargetHttpProxies().Delete(ctx, keyGA); err == nil { - t.Errorf("TargetHttpProxies().Delete(%v, %v) = nil; want error", ctx, keyGA) - } -} - -func TestTargetHttpsProxiesGroup(t *testing.T) { - t.Parallel() - - ctx := context.Background() - pr := &SingleProjectRouter{"mock-project"} - mock := NewMockGCE(pr) - - var key *meta.Key - keyGA := meta.GlobalKey("key-ga") - key = keyGA - // Ignore unused variables. - _, _, _ = ctx, mock, key - - // Get not found. - if _, err := mock.TargetHttpsProxies().Get(ctx, key); err == nil { - t.Errorf("TargetHttpsProxies().Get(%v, %v) = _, nil; want error", ctx, key) - } - - // Insert. - { - obj := &ga.TargetHttpsProxy{} - if err := mock.TargetHttpsProxies().Insert(ctx, keyGA, obj); err != nil { - t.Errorf("TargetHttpsProxies().Insert(%v, %v, %v) = %v; want nil", ctx, keyGA, obj, err) - } - } - - // Get across versions. - if obj, err := mock.TargetHttpsProxies().Get(ctx, key); err != nil { - t.Errorf("TargetHttpsProxies().Get(%v, %v) = %v, %v; want nil", ctx, key, obj, err) - } - - // List. - mock.MockTargetHttpsProxies.Objects[*keyGA] = mock.MockTargetHttpsProxies.Obj(&ga.TargetHttpsProxy{Name: keyGA.Name}) - want := map[string]bool{ - "key-ga": true, - } - _ = want // ignore unused variables. - { - objs, err := mock.TargetHttpsProxies().List(ctx, filter.None) - if err != nil { - t.Errorf("TargetHttpsProxies().List(%v, %v, %v) = %v, %v; want _, nil", ctx, location, filter.None, objs, err) - } else { - got := map[string]bool{} - for _, obj := range objs { - got[obj.Name] = true - } - if !reflect.DeepEqual(got, want) { - t.Errorf("TargetHttpsProxies().List(); got %+v, want %+v", got, want) - } - } - } - - // Delete across versions. - if err := mock.TargetHttpsProxies().Delete(ctx, keyGA); err != nil { - t.Errorf("TargetHttpsProxies().Delete(%v, %v) = %v; want nil", ctx, keyGA, err) - } - - // Delete not found. - if err := mock.TargetHttpsProxies().Delete(ctx, keyGA); err == nil { - t.Errorf("TargetHttpsProxies().Delete(%v, %v) = nil; want error", ctx, keyGA) - } -} - -func TestTargetPoolsGroup(t *testing.T) { - t.Parallel() - - ctx := context.Background() - pr := &SingleProjectRouter{"mock-project"} - mock := NewMockGCE(pr) - - var key *meta.Key - keyGA := meta.RegionalKey("key-ga", "location") - key = keyGA - // Ignore unused variables. - _, _, _ = ctx, mock, key - - // Get not found. - if _, err := mock.TargetPools().Get(ctx, key); err == nil { - t.Errorf("TargetPools().Get(%v, %v) = _, nil; want error", ctx, key) - } - - // Insert. - { - obj := &ga.TargetPool{} - if err := mock.TargetPools().Insert(ctx, keyGA, obj); err != nil { - t.Errorf("TargetPools().Insert(%v, %v, %v) = %v; want nil", ctx, keyGA, obj, err) - } - } - - // Get across versions. - if obj, err := mock.TargetPools().Get(ctx, key); err != nil { - t.Errorf("TargetPools().Get(%v, %v) = %v, %v; want nil", ctx, key, obj, err) - } - - // List. - mock.MockTargetPools.Objects[*keyGA] = mock.MockTargetPools.Obj(&ga.TargetPool{Name: keyGA.Name}) - want := map[string]bool{ - "key-ga": true, - } - _ = want // ignore unused variables. - { - objs, err := mock.TargetPools().List(ctx, location, filter.None) - if err != nil { - t.Errorf("TargetPools().List(%v, %v, %v) = %v, %v; want _, nil", ctx, location, filter.None, objs, err) - } else { - got := map[string]bool{} - for _, obj := range objs { - got[obj.Name] = true - } - if !reflect.DeepEqual(got, want) { - t.Errorf("TargetPools().List(); got %+v, want %+v", got, want) - } - } - } - - // Delete across versions. - if err := mock.TargetPools().Delete(ctx, keyGA); err != nil { - t.Errorf("TargetPools().Delete(%v, %v) = %v; want nil", ctx, keyGA, err) - } - - // Delete not found. - if err := mock.TargetPools().Delete(ctx, keyGA); err == nil { - t.Errorf("TargetPools().Delete(%v, %v) = nil; want error", ctx, keyGA) - } -} - -func TestUrlMapsGroup(t *testing.T) { - t.Parallel() - - ctx := context.Background() - pr := &SingleProjectRouter{"mock-project"} - mock := NewMockGCE(pr) - - var key *meta.Key - keyGA := meta.GlobalKey("key-ga") - key = keyGA - // Ignore unused variables. - _, _, _ = ctx, mock, key - - // Get not found. - if _, err := mock.UrlMaps().Get(ctx, key); err == nil { - t.Errorf("UrlMaps().Get(%v, %v) = _, nil; want error", ctx, key) - } - - // Insert. - { - obj := &ga.UrlMap{} - if err := mock.UrlMaps().Insert(ctx, keyGA, obj); err != nil { - t.Errorf("UrlMaps().Insert(%v, %v, %v) = %v; want nil", ctx, keyGA, obj, err) - } - } - - // Get across versions. - if obj, err := mock.UrlMaps().Get(ctx, key); err != nil { - t.Errorf("UrlMaps().Get(%v, %v) = %v, %v; want nil", ctx, key, obj, err) - } - - // List. - mock.MockUrlMaps.Objects[*keyGA] = mock.MockUrlMaps.Obj(&ga.UrlMap{Name: keyGA.Name}) - want := map[string]bool{ - "key-ga": true, - } - _ = want // ignore unused variables. - { - objs, err := mock.UrlMaps().List(ctx, filter.None) - if err != nil { - t.Errorf("UrlMaps().List(%v, %v, %v) = %v, %v; want _, nil", ctx, location, filter.None, objs, err) - } else { - got := map[string]bool{} - for _, obj := range objs { - got[obj.Name] = true - } - if !reflect.DeepEqual(got, want) { - t.Errorf("UrlMaps().List(); got %+v, want %+v", got, want) - } - } - } - - // Delete across versions. - if err := mock.UrlMaps().Delete(ctx, keyGA); err != nil { - t.Errorf("UrlMaps().Delete(%v, %v) = %v; want nil", ctx, keyGA, err) - } - - // Delete not found. - if err := mock.UrlMaps().Delete(ctx, keyGA); err == nil { - t.Errorf("UrlMaps().Delete(%v, %v) = nil; want error", ctx, keyGA) - } -} - -func TestZonesGroup(t *testing.T) { - t.Parallel() - - ctx := context.Background() - pr := &SingleProjectRouter{"mock-project"} - mock := NewMockGCE(pr) - - var key *meta.Key - keyGA := meta.GlobalKey("key-ga") - key = keyGA - // Ignore unused variables. - _, _, _ = ctx, mock, key - - // Get not found. - if _, err := mock.Zones().Get(ctx, key); err == nil { - t.Errorf("Zones().Get(%v, %v) = _, nil; want error", ctx, key) - } - - // Insert. - - // Get across versions. - - // List. - mock.MockZones.Objects[*keyGA] = mock.MockZones.Obj(&ga.Zone{Name: keyGA.Name}) - want := map[string]bool{ - "key-ga": true, - } - _ = want // ignore unused variables. - { - objs, err := mock.Zones().List(ctx, filter.None) - if err != nil { - t.Errorf("Zones().List(%v, %v, %v) = %v, %v; want _, nil", ctx, location, filter.None, objs, err) - } else { - got := map[string]bool{} - for _, obj := range objs { - got[obj.Name] = true - } - if !reflect.DeepEqual(got, want) { - t.Errorf("Zones().List(); got %+v, want %+v", got, want) - } - } - } - - // Delete across versions. - - // Delete not found. -} - -func TestResourceIDConversion(t *testing.T) { - t.Parallel() - - for _, id := range []*ResourceID{ - NewAddressesResourceID("some-project", "us-central1", "my-addresses-resource"), - NewBackendServicesResourceID("some-project", "my-backendServices-resource"), - NewDisksResourceID("some-project", "us-east1-b", "my-disks-resource"), - NewFirewallsResourceID("some-project", "my-firewalls-resource"), - NewForwardingRulesResourceID("some-project", "us-central1", "my-forwardingRules-resource"), - NewGlobalAddressesResourceID("some-project", "my-addresses-resource"), - NewGlobalForwardingRulesResourceID("some-project", "my-forwardingRules-resource"), - NewHealthChecksResourceID("some-project", "my-healthChecks-resource"), - NewHttpHealthChecksResourceID("some-project", "my-httpHealthChecks-resource"), - NewHttpsHealthChecksResourceID("some-project", "my-httpsHealthChecks-resource"), - NewInstanceGroupsResourceID("some-project", "us-east1-b", "my-instanceGroups-resource"), - NewInstancesResourceID("some-project", "us-east1-b", "my-instances-resource"), - NewNetworkEndpointGroupsResourceID("some-project", "us-east1-b", "my-networkEndpointGroups-resource"), - NewProjectsResourceID("my-projects-resource"), - NewRegionBackendServicesResourceID("some-project", "us-central1", "my-backendServices-resource"), - NewRegionDisksResourceID("some-project", "us-central1", "my-disks-resource"), - NewRegionsResourceID("some-project", "my-regions-resource"), - NewRoutesResourceID("some-project", "my-routes-resource"), - NewSecurityPoliciesResourceID("some-project", "my-securityPolicies-resource"), - NewSslCertificatesResourceID("some-project", "my-sslCertificates-resource"), - NewTargetHttpProxiesResourceID("some-project", "my-targetHttpProxies-resource"), - NewTargetHttpsProxiesResourceID("some-project", "my-targetHttpsProxies-resource"), - NewTargetPoolsResourceID("some-project", "us-central1", "my-targetPools-resource"), - NewUrlMapsResourceID("some-project", "my-urlMaps-resource"), - NewZonesResourceID("some-project", "my-zones-resource"), - } { - t.Run(id.Resource, func(t *testing.T) { - // Test conversion to and from full URL. - fullURL := id.SelfLink(meta.VersionGA) - parsedID, err := ParseResourceURL(fullURL) - if err != nil { - t.Errorf("ParseResourceURL(%s) = _, %v, want nil", fullURL, err) - } - if !reflect.DeepEqual(id, parsedID) { - t.Errorf("SelfLink(%+v) -> ParseResourceURL(%s) = %+v, want original ID", id, fullURL, parsedID) - } - - // Test conversion to and from relative resource name. - relativeName := id.RelativeResourceName() - parsedID, err = ParseResourceURL(relativeName) - if err != nil { - t.Errorf("ParseResourceURL(%s) = _, %v, want nil", relativeName, err) - } - if !reflect.DeepEqual(id, parsedID) { - t.Errorf("RelativeResourceName(%+v) -> ParseResourceURL(%s) = %+v, want original ID", id, relativeName, parsedID) - } - - // Do not test ResourcePath for projects. - if id.Resource == "projects" { - return - } - - // Test conversion to and from resource path. - resourcePath := id.ResourcePath() - parsedID, err = ParseResourceURL(resourcePath) - if err != nil { - t.Errorf("ParseResourceURL(%s) = _, %v, want nil", resourcePath, err) - } - id.ProjectID = "" - if !reflect.DeepEqual(id, parsedID) { - t.Errorf("ResourcePath(%+v) -> ParseResourceURL(%s) = %+v, want %+v", id, resourcePath, parsedID, id) - } - }) - } -} diff --git a/pkg/cloudprovider/providers/gce/cloud/meta/key_test.go b/pkg/cloudprovider/providers/gce/cloud/meta/key_test.go deleted file mode 100644 index e661bb8f76b..00000000000 --- a/pkg/cloudprovider/providers/gce/cloud/meta/key_test.go +++ /dev/null @@ -1,76 +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 meta - -import ( - "testing" -) - -func TestKeyType(t *testing.T) { - t.Parallel() - - for _, tc := range []struct { - key *Key - want KeyType - }{ - {GlobalKey("abc"), Global}, - {ZonalKey("abc", "us-central1-b"), Zonal}, - {RegionalKey("abc", "us-central1"), Regional}, - } { - if tc.key.Type() != tc.want { - t.Errorf("key.Type() == %v, want %v", tc.key.Type(), tc.want) - } - } -} - -func TestKeyString(t *testing.T) { - t.Parallel() - - for _, k := range []*Key{ - GlobalKey("abc"), - RegionalKey("abc", "us-central1"), - ZonalKey("abc", "us-central1-b"), - } { - if k.String() == "" { - t.Errorf(`k.String() = "", want non-empty`) - } - } -} - -func TestKeyValid(t *testing.T) { - t.Parallel() - - region := "us-central1" - zone := "us-central1-b" - - for _, tc := range []struct { - key *Key - want bool - }{ - {GlobalKey("abc"), true}, - {RegionalKey("abc", region), true}, - {ZonalKey("abc", zone), true}, - {RegionalKey("abc", "/invalid/"), false}, - {ZonalKey("abc", "/invalid/"), false}, - {&Key{"abc", zone, region}, false}, - } { - got := tc.key.Valid() - if got != tc.want { - t.Errorf("key %+v; key.Valid() = %v, want %v", tc.key, got, tc.want) - } - } -} diff --git a/pkg/cloudprovider/providers/gce/cloud/mock_test.go b/pkg/cloudprovider/providers/gce/cloud/mock_test.go deleted file mode 100644 index 4736f3a31cb..00000000000 --- a/pkg/cloudprovider/providers/gce/cloud/mock_test.go +++ /dev/null @@ -1,151 +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 cloud - -import ( - "context" - "reflect" - "testing" - - alpha "google.golang.org/api/compute/v0.alpha" - beta "google.golang.org/api/compute/v0.beta" - ga "google.golang.org/api/compute/v1" - - "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/filter" - "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta" -) - -func TestMocks(t *testing.T) { - t.Parallel() - - // This test uses Addresses, but the logic that is generated is the same for - // other basic objects. - const region = "us-central1" - - ctx := context.Background() - pr := &SingleProjectRouter{"mock-project"} - mock := NewMockGCE(pr) - - keyAlpha := meta.RegionalKey("key-alpha", region) - keyBeta := meta.RegionalKey("key-beta", region) - keyGA := meta.RegionalKey("key-ga", region) - key := keyAlpha - - // Get not found. - if _, err := mock.AlphaAddresses().Get(ctx, key); err == nil { - t.Errorf("AlphaAddresses().Get(%v, %v) = _, nil; want error", ctx, key) - } - if _, err := mock.BetaAddresses().Get(ctx, key); err == nil { - t.Errorf("BetaAddresses().Get(%v, %v) = _, nil; want error", ctx, key) - } - if _, err := mock.Addresses().Get(ctx, key); err == nil { - t.Errorf("Addresses().Get(%v, %v) = _, nil; want error", ctx, key) - } - // Insert. - { - obj := &alpha.Address{} - if err := mock.AlphaAddresses().Insert(ctx, keyAlpha, obj); err != nil { - t.Errorf("AlphaAddresses().Insert(%v, %v, %v) = %v; want nil", ctx, key, obj, err) - } - } - { - obj := &beta.Address{} - if err := mock.BetaAddresses().Insert(ctx, keyBeta, obj); err != nil { - t.Errorf("BetaAddresses().Insert(%v, %v, %v) = %v; want nil", ctx, key, obj, err) - } - } - { - obj := &ga.Address{} - if err := mock.Addresses().Insert(ctx, keyGA, &ga.Address{Name: "ga"}); err != nil { - t.Errorf("Addresses().Insert(%v, %v, %v) = %v; want nil", ctx, key, obj, err) - } - } - // Get across versions. - if obj, err := mock.AlphaAddresses().Get(ctx, key); err != nil { - t.Errorf("AlphaAddresses().Get(%v, %v) = %v, %v; want nil", ctx, key, obj, err) - } - if obj, err := mock.BetaAddresses().Get(ctx, key); err != nil { - t.Errorf("BetaAddresses().Get(%v, %v) = %v, %v; want nil", ctx, key, obj, err) - } - if obj, err := mock.Addresses().Get(ctx, key); err != nil { - t.Errorf("Addresses().Get(%v, %v) = %v, %v; want nil", ctx, key, obj, err) - } - // List across versions. - want := map[string]bool{"key-alpha": true, "key-beta": true, "key-ga": true} - { - objs, err := mock.AlphaAddresses().List(ctx, region, filter.None) - if err != nil { - t.Errorf("AlphaAddresses().List(%v, %v, %v) = %v, %v; want _, nil", ctx, region, filter.None, objs, err) - } else { - got := map[string]bool{} - for _, obj := range objs { - got[obj.Name] = true - } - if !reflect.DeepEqual(got, want) { - t.Errorf("AlphaAddresses().List(); got %+v, want %+v", got, want) - } - } - } - { - objs, err := mock.BetaAddresses().List(ctx, region, filter.None) - if err != nil { - t.Errorf("BetaAddresses().List(%v, %v, %v) = %v, %v; want _, nil", ctx, region, filter.None, objs, err) - } else { - got := map[string]bool{} - for _, obj := range objs { - got[obj.Name] = true - } - if !reflect.DeepEqual(got, want) { - t.Errorf("AlphaAddresses().List(); got %+v, want %+v", got, want) - } - } - } - { - objs, err := mock.Addresses().List(ctx, region, filter.None) - if err != nil { - t.Errorf("Addresses().List(%v, %v, %v) = %v, %v; want _, nil", ctx, region, filter.None, objs, err) - } else { - got := map[string]bool{} - for _, obj := range objs { - got[obj.Name] = true - } - if !reflect.DeepEqual(got, want) { - t.Errorf("AlphaAddresses().List(); got %+v, want %+v", got, want) - } - } - } - // Delete across versions. - if err := mock.AlphaAddresses().Delete(ctx, keyAlpha); err != nil { - t.Errorf("AlphaAddresses().Delete(%v, %v) = %v; want nil", ctx, key, err) - } - if err := mock.BetaAddresses().Delete(ctx, keyBeta); err != nil { - t.Errorf("BetaAddresses().Delete(%v, %v) = %v; want nil", ctx, key, err) - } - if err := mock.Addresses().Delete(ctx, keyGA); err != nil { - t.Errorf("Addresses().Delete(%v, %v) = %v; want nil", ctx, key, err) - } - // Delete not found. - if err := mock.AlphaAddresses().Delete(ctx, keyAlpha); err == nil { - t.Errorf("AlphaAddresses().Delete(%v, %v) = nil; want error", ctx, key) - } - if err := mock.BetaAddresses().Delete(ctx, keyBeta); err == nil { - t.Errorf("BetaAddresses().Delete(%v, %v) = nil; want error", ctx, key) - } - if err := mock.Addresses().Delete(ctx, keyGA); err == nil { - t.Errorf("Addresses().Delete(%v, %v) = nil; want error", ctx, key) - } -} diff --git a/pkg/cloudprovider/providers/gce/cloud/ratelimit_test.go b/pkg/cloudprovider/providers/gce/cloud/ratelimit_test.go deleted file mode 100644 index 4bb4512e133..00000000000 --- a/pkg/cloudprovider/providers/gce/cloud/ratelimit_test.go +++ /dev/null @@ -1,80 +0,0 @@ -/* -Copyright 2018 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package cloud - -import ( - "context" - "testing" - "time" -) - -type FakeAcceptor struct{ accept func() } - -func (f *FakeAcceptor) Accept() { - f.accept() -} - -func TestAcceptRateLimiter(t *testing.T) { - fa := &FakeAcceptor{accept: func() {}} - arl := &AcceptRateLimiter{fa} - err := arl.Accept(context.Background(), nil) - if err != nil { - t.Errorf("AcceptRateLimiter.Accept() = %v, want nil", err) - } - - // Use context that has been cancelled and expect a context error returned. - ctxCancelled, cancelled := context.WithCancel(context.Background()) - cancelled() - // Verify context is cancelled by now. - <-ctxCancelled.Done() - - fa.accept = func() { time.Sleep(1 * time.Second) } - err = arl.Accept(ctxCancelled, nil) - if err != ctxCancelled.Err() { - t.Errorf("AcceptRateLimiter.Accept() = %v, want %v", err, ctxCancelled.Err()) - } -} - -func TestMinimumRateLimiter(t *testing.T) { - fa := &FakeAcceptor{accept: func() {}} - arl := &AcceptRateLimiter{fa} - var called bool - fa.accept = func() { called = true } - m := &MinimumRateLimiter{RateLimiter: arl, Minimum: 10 * time.Millisecond} - - err := m.Accept(context.Background(), nil) - if err != nil { - t.Errorf("MinimumRateLimiter.Accept = %v, want nil", err) - } - if !called { - t.Errorf("`called` = false, want true") - } - - // Use context that has been cancelled and expect a context error returned. - ctxCancelled, cancelled := context.WithCancel(context.Background()) - cancelled() - // Verify context is cancelled by now. - <-ctxCancelled.Done() - called = false - err = m.Accept(ctxCancelled, nil) - if err != ctxCancelled.Err() { - t.Errorf("AcceptRateLimiter.Accept() = %v, want %v", err, ctxCancelled.Err()) - } - if called { - t.Errorf("`called` = true, want false") - } -} diff --git a/pkg/cloudprovider/providers/gce/cloud/service_test.go b/pkg/cloudprovider/providers/gce/cloud/service_test.go deleted file mode 100644 index fc6fbb51d89..00000000000 --- a/pkg/cloudprovider/providers/gce/cloud/service_test.go +++ /dev/null @@ -1,84 +0,0 @@ -/* -Copyright 2018 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package cloud - -import ( - "context" - "fmt" - "testing" -) - -func TestPollOperation(t *testing.T) { - const totalAttempts = 10 - var attempts int - fo := &fakeOperation{isDoneFunc: func(ctx context.Context) (bool, error) { - attempts++ - if attempts < totalAttempts { - return false, nil - } - return true, nil - }} - s := Service{RateLimiter: &NopRateLimiter{}} - // Check that pollOperation will retry the operation multiple times. - err := s.pollOperation(context.Background(), fo) - if err != nil { - t.Errorf("pollOperation() = %v, want nil", err) - } - if attempts != totalAttempts { - t.Errorf("`attempts` = %d, want %d", attempts, totalAttempts) - } - - // Check that the operation's error is returned. - fo.err = fmt.Errorf("test operation failed") - err = s.pollOperation(context.Background(), fo) - if err != fo.err { - t.Errorf("pollOperation() = %v, want %v", err, fo.err) - } - fo.err = nil - - fo.isDoneFunc = func(ctx context.Context) (bool, error) { - return false, nil - } - // Use context that has been cancelled and expect a context error returned. - ctxCancelled, cancelled := context.WithCancel(context.Background()) - cancelled() - // Verify context is cancelled by now. - <-ctxCancelled.Done() - // Check that pollOperation returns because the context is cancelled. - err = s.pollOperation(ctxCancelled, fo) - if err == nil { - t.Errorf("pollOperation() = nil, want: %v", ctxCancelled.Err()) - } -} - -type fakeOperation struct { - isDoneFunc func(ctx context.Context) (bool, error) - err error - rateKey *RateLimitKey -} - -func (f *fakeOperation) isDone(ctx context.Context) (bool, error) { - return f.isDoneFunc(ctx) -} - -func (f *fakeOperation) error() error { - return f.err -} - -func (f *fakeOperation) rateLimitKey() *RateLimitKey { - return f.rateKey -} diff --git a/pkg/cloudprovider/providers/gce/cloud/utils_test.go b/pkg/cloudprovider/providers/gce/cloud/utils_test.go deleted file mode 100644 index 0565638ccee..00000000000 --- a/pkg/cloudprovider/providers/gce/cloud/utils_test.go +++ /dev/null @@ -1,291 +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 cloud - -import ( - "errors" - "testing" - - "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta" -) - -func TestEqualResourceID(t *testing.T) { - t.Parallel() - - for _, tc := range []struct { - a *ResourceID - b *ResourceID - }{ - { - a: &ResourceID{"some-gce-project", "projects", nil}, - b: &ResourceID{"some-gce-project", "projects", nil}, - }, - { - a: &ResourceID{"", "networks", meta.GlobalKey("my-net")}, - b: &ResourceID{"", "networks", meta.GlobalKey("my-net")}, - }, - { - a: &ResourceID{"some-gce-project", "projects", meta.GlobalKey("us-central1")}, - b: &ResourceID{"some-gce-project", "projects", meta.GlobalKey("us-central1")}, - }, - } { - if !tc.a.Equal(tc.b) { - t.Errorf("%v.Equal(%v) = false, want true", tc.a, tc.b) - } - } - - for _, tc := range []struct { - a *ResourceID - b *ResourceID - }{ - { - a: &ResourceID{"some-gce-project", "projects", nil}, - b: &ResourceID{"some-other-project", "projects", nil}, - }, - { - a: &ResourceID{"some-gce-project", "projects", nil}, - b: &ResourceID{"some-gce-project", "projects", meta.GlobalKey("us-central1")}, - }, - { - a: &ResourceID{"some-gce-project", "networks", meta.GlobalKey("us-central1")}, - b: &ResourceID{"some-gce-project", "projects", meta.GlobalKey("us-central1")}, - }, - } { - if tc.a.Equal(tc.b) { - t.Errorf("%v.Equal(%v) = true, want false", tc.a, tc.b) - } - } -} - -func TestParseResourceURL(t *testing.T) { - t.Parallel() - - for _, tc := range []struct { - in string - r *ResourceID - }{ - { - "https://www.googleapis.com/compute/v1/projects/some-gce-project", - &ResourceID{"some-gce-project", "projects", nil}, - }, - { - "https://www.googleapis.com/compute/v1/projects/some-gce-project/regions/us-central1", - &ResourceID{"some-gce-project", "regions", meta.GlobalKey("us-central1")}, - }, - { - "https://www.googleapis.com/compute/v1/projects/some-gce-project/zones/us-central1-b", - &ResourceID{"some-gce-project", "zones", meta.GlobalKey("us-central1-b")}, - }, - { - "https://www.googleapis.com/compute/v1/projects/some-gce-project/global/operations/operation-1513289952196-56054460af5a0-b1dae0c3-9bbf9dbf", - &ResourceID{"some-gce-project", "operations", meta.GlobalKey("operation-1513289952196-56054460af5a0-b1dae0c3-9bbf9dbf")}, - }, - { - "https://www.googleapis.com/compute/alpha/projects/some-gce-project/regions/us-central1/addresses/my-address", - &ResourceID{"some-gce-project", "addresses", meta.RegionalKey("my-address", "us-central1")}, - }, - { - "https://www.googleapis.com/compute/v1/projects/some-gce-project/zones/us-central1-c/instances/instance-1", - &ResourceID{"some-gce-project", "instances", meta.ZonalKey("instance-1", "us-central1-c")}, - }, - { - "http://localhost:3990/compute/beta/projects/some-gce-project/global/operations/operation-1513289952196-56054460af5a0-b1dae0c3-9bbf9dbf", - &ResourceID{"some-gce-project", "operations", meta.GlobalKey("operation-1513289952196-56054460af5a0-b1dae0c3-9bbf9dbf")}, - }, - { - "http://localhost:3990/compute/alpha/projects/some-gce-project/regions/dev-central1/addresses/my-address", - &ResourceID{"some-gce-project", "addresses", meta.RegionalKey("my-address", "dev-central1")}, - }, - { - "http://localhost:3990/compute/v1/projects/some-gce-project/zones/dev-central1-std/instances/instance-1", - &ResourceID{"some-gce-project", "instances", meta.ZonalKey("instance-1", "dev-central1-std")}, - }, - { - "projects/some-gce-project", - &ResourceID{"some-gce-project", "projects", nil}, - }, - { - "projects/some-gce-project/regions/us-central1", - &ResourceID{"some-gce-project", "regions", meta.GlobalKey("us-central1")}, - }, - { - "projects/some-gce-project/zones/us-central1-b", - &ResourceID{"some-gce-project", "zones", meta.GlobalKey("us-central1-b")}, - }, - { - "projects/some-gce-project/global/operations/operation-1513289952196-56054460af5a0-b1dae0c3-9bbf9dbf", - &ResourceID{"some-gce-project", "operations", meta.GlobalKey("operation-1513289952196-56054460af5a0-b1dae0c3-9bbf9dbf")}, - }, - { - "projects/some-gce-project/regions/us-central1/addresses/my-address", - &ResourceID{"some-gce-project", "addresses", meta.RegionalKey("my-address", "us-central1")}, - }, - { - "projects/some-gce-project/zones/us-central1-c/instances/instance-1", - &ResourceID{"some-gce-project", "instances", meta.ZonalKey("instance-1", "us-central1-c")}, - }, - { - "global/networks/my-network", - &ResourceID{"", "networks", meta.GlobalKey("my-network")}, - }, - { - "regions/us-central1/subnetworks/my-subnet", - &ResourceID{"", "subnetworks", meta.RegionalKey("my-subnet", "us-central1")}, - }, - { - "zones/us-central1-c/instances/instance-1", - &ResourceID{"", "instances", meta.ZonalKey("instance-1", "us-central1-c")}, - }, - } { - r, err := ParseResourceURL(tc.in) - if err != nil { - t.Errorf("ParseResourceURL(%q) = %+v, %v; want _, nil", tc.in, r, err) - continue - } - if !r.Equal(tc.r) { - t.Errorf("ParseResourceURL(%q) = %+v, nil; want %+v, nil", tc.in, r, tc.r) - } - } - // Malformed URLs. - for _, tc := range []string{ - "", - "/", - "/a", - "/a/b", - "/a/b/c", - "/a/b/c/d", - "/a/b/c/d/e", - "/a/b/c/d/e/f", - "https://www.googleapis.com/compute/v1/projects/some-gce-project/global", - "projects/some-gce-project/global", - "projects/some-gce-project/global/foo", - "projects/some-gce-project/global/foo/bar/baz", - "projects/some-gce-project/regions/us-central1/res", - "projects/some-gce-project/zones/us-central1-c/res", - "projects/some-gce-project/zones/us-central1-c/res/name/extra", - } { - r, err := ParseResourceURL(tc) - if err == nil { - t.Errorf("ParseResourceURL(%q) = %+v, %v, want _, error", tc, r, err) - } - } -} - -type A struct { - A, B, C string -} - -type B struct { - A, B, D string -} - -type E struct{} - -func (*E) MarshalJSON() ([]byte, error) { - return nil, errors.New("injected error") -} - -func TestCopyVisJSON(t *testing.T) { - t.Parallel() - - var b B - srcA := &A{"aa", "bb", "cc"} - err := copyViaJSON(&b, srcA) - if err != nil { - t.Errorf(`copyViaJSON(&b, %+v) = %v, want nil`, srcA, err) - } else { - expectedB := B{"aa", "bb", ""} - if b != expectedB { - t.Errorf("b == %+v, want %+v", b, expectedB) - } - } - - var a A - srcB := &B{"aaa", "bbb", "ccc"} - err = copyViaJSON(&a, srcB) - if err != nil { - t.Errorf(`copyViaJSON(&a, %+v) = %v, want nil`, srcB, err) - } else { - expectedA := A{"aaa", "bbb", ""} - if a != expectedA { - t.Errorf("a == %+v, want %+v", a, expectedA) - } - } - - if err := copyViaJSON(&a, &E{}); err == nil { - t.Errorf("copyViaJSON(&a, &E{}) = nil, want error") - } -} - -func TestSelfLink(t *testing.T) { - t.Parallel() - - for _, tc := range []struct { - ver meta.Version - project string - resource string - key *meta.Key - want string - }{ - { - meta.VersionAlpha, - "proj1", - "addresses", - meta.RegionalKey("key1", "us-central1"), - "https://www.googleapis.com/compute/alpha/projects/proj1/regions/us-central1/addresses/key1", - }, - { - meta.VersionBeta, - "proj3", - "disks", - meta.ZonalKey("key2", "us-central1-b"), - "https://www.googleapis.com/compute/beta/projects/proj3/zones/us-central1-b/disks/key2", - }, - { - meta.VersionGA, - "proj4", - "urlMaps", - meta.GlobalKey("key3"), - "https://www.googleapis.com/compute/v1/projects/proj4/global/urlMaps/key3", - }, - { - meta.VersionGA, - "proj4", - "projects", - nil, - "https://www.googleapis.com/compute/v1/projects/proj4", - }, - { - meta.VersionGA, - "proj4", - "regions", - meta.GlobalKey("us-central1"), - "https://www.googleapis.com/compute/v1/projects/proj4/regions/us-central1", - }, - { - meta.VersionGA, - "proj4", - "zones", - meta.GlobalKey("us-central1-a"), - "https://www.googleapis.com/compute/v1/projects/proj4/zones/us-central1-a", - }, - } { - if link := SelfLink(tc.ver, tc.project, tc.resource, tc.key); link != tc.want { - t.Errorf("SelfLink(%v, %q, %q, %v) = %v, want %q", tc.ver, tc.project, tc.resource, tc.key, link, tc.want) - } - } -} diff --git a/pkg/cloudprovider/providers/gce/gce.go b/pkg/cloudprovider/providers/gce/gce.go index 616fe5f5477..239e515efdf 100644 --- a/pkg/cloudprovider/providers/gce/gce.go +++ b/pkg/cloudprovider/providers/gce/gce.go @@ -49,8 +49,8 @@ import ( "k8s.io/client-go/tools/record" "k8s.io/client-go/util/flowcontrol" + "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud" cloudprovider "k8s.io/cloud-provider" - "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud" "k8s.io/kubernetes/pkg/controller" kubeletapis "k8s.io/kubernetes/pkg/kubelet/apis" "k8s.io/kubernetes/pkg/version" @@ -98,6 +98,14 @@ type gceObject interface { MarshalJSON() ([]byte, error) } +var _ cloudprovider.Interface = (*Cloud)(nil) +var _ cloudprovider.Instances = (*Cloud)(nil) +var _ cloudprovider.LoadBalancer = (*Cloud)(nil) +var _ cloudprovider.Routes = (*Cloud)(nil) +var _ cloudprovider.Zones = (*Cloud)(nil) +var _ cloudprovider.PVLabeler = (*Cloud)(nil) +var _ cloudprovider.Clusters = (*Cloud)(nil) + // Cloud is an implementation of Interface, LoadBalancer and Instances for Google Compute Engine. type Cloud struct { // ClusterID contains functionality for getting (and initializing) the ingress-uid. Call Cloud.Initialize() @@ -765,9 +773,6 @@ func isProjectNumber(idOrNumber string) bool { return err == nil } -// Cloud implements cloudprovider.Interface. -var _ cloudprovider.Interface = (*Cloud)(nil) - func gceNetworkURL(apiEndpoint, project, network string) string { if apiEndpoint == "" { apiEndpoint = gceComputeAPIEndpoint diff --git a/pkg/cloudprovider/providers/gce/gce_address_manager.go b/pkg/cloudprovider/providers/gce/gce_address_manager.go index 51b9bc5e718..7674e36df60 100644 --- a/pkg/cloudprovider/providers/gce/gce_address_manager.go +++ b/pkg/cloudprovider/providers/gce/gce_address_manager.go @@ -22,8 +22,8 @@ import ( compute "google.golang.org/api/compute/v1" + "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud" "k8s.io/klog" - "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud" ) type addressManager struct { diff --git a/pkg/cloudprovider/providers/gce/gce_address_manager_test.go b/pkg/cloudprovider/providers/gce/gce_address_manager_test.go index 3b7409c6c19..48a5fcedd96 100644 --- a/pkg/cloudprovider/providers/gce/gce_address_manager_test.go +++ b/pkg/cloudprovider/providers/gce/gce_address_manager_test.go @@ -19,10 +19,10 @@ package gce import ( "testing" + "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" compute "google.golang.org/api/compute/v1" - "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud" ) const testSvcName = "my-service" diff --git a/pkg/cloudprovider/providers/gce/gce_addresses.go b/pkg/cloudprovider/providers/gce/gce_addresses.go index 044258f1b4e..08ef981157e 100644 --- a/pkg/cloudprovider/providers/gce/gce_addresses.go +++ b/pkg/cloudprovider/providers/gce/gce_addresses.go @@ -25,9 +25,9 @@ import ( computebeta "google.golang.org/api/compute/v0.beta" compute "google.golang.org/api/compute/v1" - "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud" - "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/filter" - "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta" + "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud" + "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/filter" + "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/meta" ) func newAddressMetricContext(request, region string) *metricContext { diff --git a/pkg/cloudprovider/providers/gce/gce_annotations.go b/pkg/cloudprovider/providers/gce/gce_annotations.go index 39e632e0795..a9cab8f366f 100644 --- a/pkg/cloudprovider/providers/gce/gce_annotations.go +++ b/pkg/cloudprovider/providers/gce/gce_annotations.go @@ -21,8 +21,8 @@ import ( "k8s.io/klog" + "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud" "k8s.io/api/core/v1" - "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud" ) // LoadBalancerType defines a specific type for holding load balancer types (eg. Internal) diff --git a/pkg/cloudprovider/providers/gce/gce_annotations_test.go b/pkg/cloudprovider/providers/gce/gce_annotations_test.go index a3b2dfb86bf..049b2bd545d 100644 --- a/pkg/cloudprovider/providers/gce/gce_annotations_test.go +++ b/pkg/cloudprovider/providers/gce/gce_annotations_test.go @@ -19,9 +19,9 @@ package gce import ( "testing" + "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud" "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud" "github.com/stretchr/testify/assert" ) diff --git a/pkg/cloudprovider/providers/gce/gce_backendservice.go b/pkg/cloudprovider/providers/gce/gce_backendservice.go index 6560c912606..aa0f52d212b 100644 --- a/pkg/cloudprovider/providers/gce/gce_backendservice.go +++ b/pkg/cloudprovider/providers/gce/gce_backendservice.go @@ -21,9 +21,9 @@ import ( computebeta "google.golang.org/api/compute/v0.beta" compute "google.golang.org/api/compute/v1" - "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud" - "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/filter" - "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta" + "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud" + "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/filter" + "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/meta" ) func newBackendServiceMetricContext(request, region string) *metricContext { diff --git a/pkg/cloudprovider/providers/gce/gce_cert.go b/pkg/cloudprovider/providers/gce/gce_cert.go index 5153f067e8a..8d9481945c0 100644 --- a/pkg/cloudprovider/providers/gce/gce_cert.go +++ b/pkg/cloudprovider/providers/gce/gce_cert.go @@ -19,9 +19,9 @@ package gce import ( compute "google.golang.org/api/compute/v1" - "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud" - "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/filter" - "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta" + "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud" + "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/filter" + "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/meta" ) func newCertMetricContext(request string) *metricContext { diff --git a/pkg/cloudprovider/providers/gce/gce_disks.go b/pkg/cloudprovider/providers/gce/gce_disks.go index 7e10e50c32b..1c3bda8dd87 100644 --- a/pkg/cloudprovider/providers/gce/gce_disks.go +++ b/pkg/cloudprovider/providers/gce/gce_disks.go @@ -33,12 +33,12 @@ import ( "k8s.io/kubernetes/pkg/volume" volumeutil "k8s.io/kubernetes/pkg/volume/util" + "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud" + "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/meta" compute "google.golang.org/api/compute/v1" "google.golang.org/api/googleapi" utilfeature "k8s.io/apiserver/pkg/util/feature" "k8s.io/klog" - "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud" - "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta" "k8s.io/kubernetes/pkg/features" ) diff --git a/pkg/cloudprovider/providers/gce/gce_fake.go b/pkg/cloudprovider/providers/gce/gce_fake.go index 73a724d74ae..2394cb47333 100644 --- a/pkg/cloudprovider/providers/gce/gce_fake.go +++ b/pkg/cloudprovider/providers/gce/gce_fake.go @@ -20,9 +20,9 @@ import ( "fmt" "net/http" + "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud" compute "google.golang.org/api/compute/v1" "k8s.io/client-go/tools/cache" - "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud" ) // TestClusterValues holds the config values for the fake/test gce cloud object. diff --git a/pkg/cloudprovider/providers/gce/gce_firewall.go b/pkg/cloudprovider/providers/gce/gce_firewall.go index 4aea4970956..d8b2ae749f3 100644 --- a/pkg/cloudprovider/providers/gce/gce_firewall.go +++ b/pkg/cloudprovider/providers/gce/gce_firewall.go @@ -19,8 +19,8 @@ package gce import ( compute "google.golang.org/api/compute/v1" - "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud" - "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta" + "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud" + "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/meta" ) func newFirewallMetricContext(request string) *metricContext { diff --git a/pkg/cloudprovider/providers/gce/gce_forwardingrule.go b/pkg/cloudprovider/providers/gce/gce_forwardingrule.go index 5689cfd32ea..af12aa47c2b 100644 --- a/pkg/cloudprovider/providers/gce/gce_forwardingrule.go +++ b/pkg/cloudprovider/providers/gce/gce_forwardingrule.go @@ -17,11 +17,11 @@ limitations under the License. package gce import ( + "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud" + "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/filter" + "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/meta" computealpha "google.golang.org/api/compute/v0.alpha" compute "google.golang.org/api/compute/v1" - "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud" - "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/filter" - "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta" ) func newForwardingRuleMetricContext(request, region string) *metricContext { diff --git a/pkg/cloudprovider/providers/gce/gce_healthchecks.go b/pkg/cloudprovider/providers/gce/gce_healthchecks.go index d314376db12..a545b49f9e5 100644 --- a/pkg/cloudprovider/providers/gce/gce_healthchecks.go +++ b/pkg/cloudprovider/providers/gce/gce_healthchecks.go @@ -23,11 +23,11 @@ import ( computebeta "google.golang.org/api/compute/v0.beta" compute "google.golang.org/api/compute/v1" + "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud" + "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/filter" + "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/meta" "k8s.io/api/core/v1" utilversion "k8s.io/apimachinery/pkg/util/version" - "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud" - "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/filter" - "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta" "k8s.io/kubernetes/pkg/master/ports" ) diff --git a/pkg/cloudprovider/providers/gce/gce_instancegroup.go b/pkg/cloudprovider/providers/gce/gce_instancegroup.go index edc5f093339..8fbdf8ae55d 100644 --- a/pkg/cloudprovider/providers/gce/gce_instancegroup.go +++ b/pkg/cloudprovider/providers/gce/gce_instancegroup.go @@ -19,9 +19,9 @@ package gce import ( compute "google.golang.org/api/compute/v1" - "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud" - "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/filter" - "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta" + "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud" + "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/filter" + "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/meta" ) func newInstanceGroupMetricContext(request string, zone string) *metricContext { diff --git a/pkg/cloudprovider/providers/gce/gce_instances.go b/pkg/cloudprovider/providers/gce/gce_instances.go index e8345abfae5..f93e0fff006 100644 --- a/pkg/cloudprovider/providers/gce/gce_instances.go +++ b/pkg/cloudprovider/providers/gce/gce_instances.go @@ -29,14 +29,14 @@ import ( compute "google.golang.org/api/compute/v1" "k8s.io/klog" + "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud" + "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/filter" + "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/meta" "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/wait" cloudprovider "k8s.io/cloud-provider" - "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud" - "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/filter" - "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta" kubeletapis "k8s.io/kubernetes/pkg/kubelet/apis" ) diff --git a/pkg/cloudprovider/providers/gce/gce_loadbalancer.go b/pkg/cloudprovider/providers/gce/gce_loadbalancer.go index 35a2c6952f4..5c9dbb027ed 100644 --- a/pkg/cloudprovider/providers/gce/gce_loadbalancer.go +++ b/pkg/cloudprovider/providers/gce/gce_loadbalancer.go @@ -26,9 +26,9 @@ import ( "k8s.io/klog" + "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud" "k8s.io/api/core/v1" cloudprovider "k8s.io/cloud-provider" - "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud" netsets "k8s.io/kubernetes/pkg/util/net/sets" ) diff --git a/pkg/cloudprovider/providers/gce/gce_loadbalancer_external.go b/pkg/cloudprovider/providers/gce/gce_loadbalancer_external.go index 6b92e71ef77..5606467586d 100644 --- a/pkg/cloudprovider/providers/gce/gce_loadbalancer_external.go +++ b/pkg/cloudprovider/providers/gce/gce_loadbalancer_external.go @@ -23,12 +23,12 @@ import ( "strconv" "strings" + "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud" "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/types" utilerrors "k8s.io/apimachinery/pkg/util/errors" "k8s.io/apimachinery/pkg/util/sets" apiservice "k8s.io/kubernetes/pkg/api/v1/service" - "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud" netsets "k8s.io/kubernetes/pkg/util/net/sets" computealpha "google.golang.org/api/compute/v0.alpha" diff --git a/pkg/cloudprovider/providers/gce/gce_loadbalancer_external_test.go b/pkg/cloudprovider/providers/gce/gce_loadbalancer_external_test.go index a238d888db8..cc5c90cae62 100644 --- a/pkg/cloudprovider/providers/gce/gce_loadbalancer_external_test.go +++ b/pkg/cloudprovider/providers/gce/gce_loadbalancer_external_test.go @@ -27,13 +27,13 @@ import ( computealpha "google.golang.org/api/compute/v0.alpha" compute "google.golang.org/api/compute/v1" + "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud" + "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/meta" + "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/mock" ga "google.golang.org/api/compute/v1" "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/types" "k8s.io/client-go/tools/record" - "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud" - "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta" - "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/mock" netsets "k8s.io/kubernetes/pkg/util/net/sets" ) diff --git a/pkg/cloudprovider/providers/gce/gce_loadbalancer_internal.go b/pkg/cloudprovider/providers/gce/gce_loadbalancer_internal.go index 87d1be64b49..69bbd853063 100644 --- a/pkg/cloudprovider/providers/gce/gce_loadbalancer_internal.go +++ b/pkg/cloudprovider/providers/gce/gce_loadbalancer_internal.go @@ -22,13 +22,13 @@ import ( "strconv" "strings" + "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud" compute "google.golang.org/api/compute/v1" "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/sets" "k8s.io/klog" v1_service "k8s.io/kubernetes/pkg/api/v1/service" - "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud" ) const ( diff --git a/pkg/cloudprovider/providers/gce/gce_loadbalancer_internal_test.go b/pkg/cloudprovider/providers/gce/gce_loadbalancer_internal_test.go index 8b08ce378e8..6480b8b11ca 100644 --- a/pkg/cloudprovider/providers/gce/gce_loadbalancer_internal_test.go +++ b/pkg/cloudprovider/providers/gce/gce_loadbalancer_internal_test.go @@ -25,13 +25,13 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud" + "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/mock" compute "google.golang.org/api/compute/v1" "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/types" "k8s.io/client-go/tools/record" v1_service "k8s.io/kubernetes/pkg/api/v1/service" - "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud" - "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/mock" ) func createInternalLoadBalancer(gce *Cloud, svc *v1.Service, existingFwdRule *compute.ForwardingRule, nodeNames []string, clusterName, clusterID, zoneName string) (*v1.LoadBalancerStatus, error) { diff --git a/pkg/cloudprovider/providers/gce/gce_loadbalancer_naming.go b/pkg/cloudprovider/providers/gce/gce_loadbalancer_naming.go index 63b11eb1141..f7c2e0ce289 100644 --- a/pkg/cloudprovider/providers/gce/gce_loadbalancer_naming.go +++ b/pkg/cloudprovider/providers/gce/gce_loadbalancer_naming.go @@ -22,9 +22,9 @@ import ( "fmt" "strings" + "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud" "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/types" - "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud" ) // Internal Load Balancer diff --git a/pkg/cloudprovider/providers/gce/gce_loadbalancer_utils_test.go b/pkg/cloudprovider/providers/gce/gce_loadbalancer_utils_test.go index 7c133c7c9a2..7c460809ea8 100644 --- a/pkg/cloudprovider/providers/gce/gce_loadbalancer_utils_test.go +++ b/pkg/cloudprovider/providers/gce/gce_loadbalancer_utils_test.go @@ -31,11 +31,11 @@ import ( "github.com/stretchr/testify/require" compute "google.golang.org/api/compute/v1" + "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud" "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/tools/record" v1_service "k8s.io/kubernetes/pkg/api/v1/service" - "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud" kubeletapis "k8s.io/kubernetes/pkg/kubelet/apis" ) diff --git a/pkg/cloudprovider/providers/gce/gce_networkendpointgroup.go b/pkg/cloudprovider/providers/gce/gce_networkendpointgroup.go index b7aa998cc34..23503d2e007 100644 --- a/pkg/cloudprovider/providers/gce/gce_networkendpointgroup.go +++ b/pkg/cloudprovider/providers/gce/gce_networkendpointgroup.go @@ -22,9 +22,9 @@ import ( computebeta "google.golang.org/api/compute/v0.beta" - "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud" - "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/filter" - "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta" + "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud" + "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/filter" + "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/meta" ) func newNetworkEndpointGroupMetricContext(request string, zone string) *metricContext { diff --git a/pkg/cloudprovider/providers/gce/gce_routes.go b/pkg/cloudprovider/providers/gce/gce_routes.go index cc3cbfc53a0..62d9b0995f7 100644 --- a/pkg/cloudprovider/providers/gce/gce_routes.go +++ b/pkg/cloudprovider/providers/gce/gce_routes.go @@ -26,10 +26,10 @@ import ( "k8s.io/apimachinery/pkg/types" "k8s.io/klog" + "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud" + "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/filter" + "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/meta" cloudprovider "k8s.io/cloud-provider" - "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud" - "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/filter" - "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta" ) func newRoutesMetricContext(request string) *metricContext { diff --git a/pkg/cloudprovider/providers/gce/gce_securitypolicy.go b/pkg/cloudprovider/providers/gce/gce_securitypolicy.go index 3ce2f71fa54..bfb2cb96ebe 100644 --- a/pkg/cloudprovider/providers/gce/gce_securitypolicy.go +++ b/pkg/cloudprovider/providers/gce/gce_securitypolicy.go @@ -19,9 +19,9 @@ package gce import ( computebeta "google.golang.org/api/compute/v0.beta" - "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud" - "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/filter" - "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta" + "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud" + "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/filter" + "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/meta" ) func newSecurityPolicyMetricContextWithVersion(request, version string) *metricContext { diff --git a/pkg/cloudprovider/providers/gce/gce_targetpool.go b/pkg/cloudprovider/providers/gce/gce_targetpool.go index 65388b44980..8f2f2cdff1b 100644 --- a/pkg/cloudprovider/providers/gce/gce_targetpool.go +++ b/pkg/cloudprovider/providers/gce/gce_targetpool.go @@ -19,8 +19,8 @@ package gce import ( compute "google.golang.org/api/compute/v1" - "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud" - "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta" + "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud" + "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/meta" ) func newTargetPoolMetricContext(request, region string) *metricContext { diff --git a/pkg/cloudprovider/providers/gce/gce_targetproxy.go b/pkg/cloudprovider/providers/gce/gce_targetproxy.go index 64a4190628e..1744e88e86a 100644 --- a/pkg/cloudprovider/providers/gce/gce_targetproxy.go +++ b/pkg/cloudprovider/providers/gce/gce_targetproxy.go @@ -19,9 +19,9 @@ package gce import ( compute "google.golang.org/api/compute/v1" - "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud" - "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/filter" - "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta" + "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud" + "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/filter" + "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/meta" ) func newTargetProxyMetricContext(request string) *metricContext { diff --git a/pkg/cloudprovider/providers/gce/gce_urlmap.go b/pkg/cloudprovider/providers/gce/gce_urlmap.go index 7ee8b821327..2ea04e4a2c4 100644 --- a/pkg/cloudprovider/providers/gce/gce_urlmap.go +++ b/pkg/cloudprovider/providers/gce/gce_urlmap.go @@ -19,9 +19,9 @@ package gce import ( compute "google.golang.org/api/compute/v1" - "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud" - "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/filter" - "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta" + "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud" + "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/filter" + "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/meta" ) func newURLMapMetricContext(request string) *metricContext { diff --git a/pkg/cloudprovider/providers/gce/gce_util.go b/pkg/cloudprovider/providers/gce/gce_util.go index d66029a1df6..328b9204f56 100644 --- a/pkg/cloudprovider/providers/gce/gce_util.go +++ b/pkg/cloudprovider/providers/gce/gce_util.go @@ -26,12 +26,12 @@ import ( "strings" "sync" + "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud" + "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/meta" + "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/mock" "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/sets" - "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud" - "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta" - "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/mock" "cloud.google.com/go/compute/metadata" compute "google.golang.org/api/compute/v1" diff --git a/pkg/cloudprovider/providers/gce/gce_zones.go b/pkg/cloudprovider/providers/gce/gce_zones.go index 3e4bb059bd6..0862d6dea9f 100644 --- a/pkg/cloudprovider/providers/gce/gce_zones.go +++ b/pkg/cloudprovider/providers/gce/gce_zones.go @@ -22,10 +22,10 @@ import ( compute "google.golang.org/api/compute/v1" + "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud" + "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/filter" "k8s.io/apimachinery/pkg/types" cloudprovider "k8s.io/cloud-provider" - "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud" - "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/filter" ) func newZonesMetricContext(request, region string) *metricContext { diff --git a/pkg/cloudprovider/providers/gce/support.go b/pkg/cloudprovider/providers/gce/support.go index e6c471855fe..9ad04439780 100644 --- a/pkg/cloudprovider/providers/gce/support.go +++ b/pkg/cloudprovider/providers/gce/support.go @@ -19,8 +19,8 @@ package gce import ( "context" - "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud" - "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta" + "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud" + "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/meta" ) // gceProjectRouter sends requests to the appropriate project ID. diff --git a/pkg/cloudprovider/providers/openstack/openstack.go b/pkg/cloudprovider/providers/openstack/openstack.go index 9f13db944e1..9af4e4f7bd0 100644 --- a/pkg/cloudprovider/providers/openstack/openstack.go +++ b/pkg/cloudprovider/providers/openstack/openstack.go @@ -126,6 +126,9 @@ type MetadataOpts struct { RequestTimeout MyDuration `gcfg:"request-timeout"` } +var _ cloudprovider.Interface = (*OpenStack)(nil) +var _ cloudprovider.Zones = (*OpenStack)(nil) + // OpenStack is an implementation of cloud provider Interface for OpenStack. type OpenStack struct { provider *gophercloud.ProviderClient diff --git a/pkg/cloudprovider/providers/openstack/openstack_instances.go b/pkg/cloudprovider/providers/openstack/openstack_instances.go index c52ce21998e..4ca4198f419 100644 --- a/pkg/cloudprovider/providers/openstack/openstack_instances.go +++ b/pkg/cloudprovider/providers/openstack/openstack_instances.go @@ -30,6 +30,8 @@ import ( cloudprovider "k8s.io/cloud-provider" ) +var _ cloudprovider.Instances = (*Instances)(nil) + // Instances encapsulates an implementation of Instances for OpenStack. type Instances struct { compute *gophercloud.ServiceClient diff --git a/pkg/cloudprovider/providers/openstack/openstack_loadbalancer.go b/pkg/cloudprovider/providers/openstack/openstack_loadbalancer.go index 26e6b095a2c..5f793924a35 100644 --- a/pkg/cloudprovider/providers/openstack/openstack_loadbalancer.go +++ b/pkg/cloudprovider/providers/openstack/openstack_loadbalancer.go @@ -78,6 +78,8 @@ const ( ServiceAnnotationLoadBalancerInternal = "service.beta.kubernetes.io/openstack-internal-load-balancer" ) +var _ cloudprovider.LoadBalancer = (*LbaasV2)(nil) + // LbaasV2 is a LoadBalancer implementation for Neutron LBaaS v2 API type LbaasV2 struct { LoadBalancer diff --git a/pkg/cloudprovider/providers/openstack/openstack_routes.go b/pkg/cloudprovider/providers/openstack/openstack_routes.go index 0cb31a435a7..a1b447e37cf 100644 --- a/pkg/cloudprovider/providers/openstack/openstack_routes.go +++ b/pkg/cloudprovider/providers/openstack/openstack_routes.go @@ -33,6 +33,8 @@ import ( var errNoRouterID = errors.New("router-id not set in cloud provider config") +var _ cloudprovider.Routes = (*Routes)(nil) + // Routes implements the cloudprovider.Routes for OpenStack clouds type Routes struct { compute *gophercloud.ServiceClient diff --git a/pkg/cloudprovider/providers/ovirt/ovirt.go b/pkg/cloudprovider/providers/ovirt/ovirt.go index 472c8c3ecdd..c9364a2585b 100644 --- a/pkg/cloudprovider/providers/ovirt/ovirt.go +++ b/pkg/cloudprovider/providers/ovirt/ovirt.go @@ -49,6 +49,9 @@ type Instance struct { // InstanceMap provides the map of Ovirt instances. type InstanceMap map[string]Instance +var _ cloudprovider.Interface = (*Cloud)(nil) +var _ cloudprovider.Instances = (*Cloud)(nil) + // Cloud is an implementation of the cloud provider interface for Ovirt. type Cloud struct { VmsRequest *url.URL diff --git a/pkg/cloudprovider/providers/photon/photon.go b/pkg/cloudprovider/providers/photon/photon.go index 24f8d2b8dd8..8bcca5a093d 100644 --- a/pkg/cloudprovider/providers/photon/photon.go +++ b/pkg/cloudprovider/providers/photon/photon.go @@ -55,6 +55,10 @@ const ( // overrideIP = true in cloud config file. Default value is false. var overrideIP bool = false +var _ cloudprovider.Interface = (*PCCloud)(nil) +var _ cloudprovider.Instances = (*PCCloud)(nil) +var _ cloudprovider.Zones = (*PCCloud)(nil) + // Photon is an implementation of the cloud provider interface for Photon Controller. type PCCloud struct { cfg *PCConfig diff --git a/pkg/cloudprovider/providers/vsphere/vclib/constants.go b/pkg/cloudprovider/providers/vsphere/vclib/constants.go index 522f308b8b3..74386bae240 100644 --- a/pkg/cloudprovider/providers/vsphere/vclib/constants.go +++ b/pkg/cloudprovider/providers/vsphere/vclib/constants.go @@ -16,7 +16,7 @@ limitations under the License. package vclib -// Volume Constnts +// Volume Constants const ( ThinDiskType = "thin" PreallocatedDiskType = "preallocated" diff --git a/pkg/cloudprovider/providers/vsphere/vsphere.go b/pkg/cloudprovider/providers/vsphere/vsphere.go index 26180e6aff9..2e562b036ed 100644 --- a/pkg/cloudprovider/providers/vsphere/vsphere.go +++ b/pkg/cloudprovider/providers/vsphere/vsphere.go @@ -76,6 +76,10 @@ var ( ErrPasswordMissing = errors.New(MissingPasswordErrMsg) ) +var _ cloudprovider.Interface = (*VSphere)(nil) +var _ cloudprovider.Instances = (*VSphere)(nil) +var _ cloudprovider.Zones = (*VSphere)(nil) + // VSphere is an implementation of cloud provider Interface for VSphere. type VSphere struct { cfg *VSphereConfig diff --git a/pkg/controller/.import-restrictions b/pkg/controller/.import-restrictions index 31aa4d0b504..c96ccd7dce0 100644 --- a/pkg/controller/.import-restrictions +++ b/pkg/controller/.import-restrictions @@ -103,15 +103,16 @@ "github.com/cloudflare/cfssl/signer", "github.com/cloudflare/cfssl/signer/local", "github.com/davecgh/go-spew/spew", + "github.com/docker/distribution/reference", "github.com/evanphx/json-patch", "github.com/golang/groupcache/lru", + "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud", + "github.com/google/gofuzz", "github.com/prometheus/client_golang/prometheus", "github.com/robfig/cron", "github.com/spf13/pflag", "github.com/stretchr/testify/assert", - "github.com/stretchr/testify/require", - "github.com/docker/distribution/reference", - "github.com/google/gofuzz" + "github.com/stretchr/testify/require" ] }, { @@ -278,7 +279,7 @@ "k8s.io/kubernetes/pkg/registry/core/secret", "k8s.io/kubernetes/pkg/scheduler/algorithm", "k8s.io/kubernetes/pkg/scheduler/algorithm/predicates", - "k8s.io/kubernetes/pkg/scheduler/cache", + "k8s.io/kubernetes/pkg/scheduler/nodeinfo", "k8s.io/kubernetes/pkg/securitycontext", "k8s.io/kubernetes/pkg/serviceaccount", "k8s.io/kubernetes/pkg/util/goroutinemap", diff --git a/pkg/controller/BUILD b/pkg/controller/BUILD index b4915ac5365..57f6c8f70ab 100644 --- a/pkg/controller/BUILD +++ b/pkg/controller/BUILD @@ -55,7 +55,6 @@ go_library( "//pkg/apis/core:go_default_library", "//pkg/apis/core/install:go_default_library", "//pkg/apis/core/validation:go_default_library", - "//pkg/scheduler/api:go_default_library", "//pkg/serviceaccount:go_default_library", "//pkg/util/hash:go_default_library", "//pkg/util/taints:go_default_library", diff --git a/pkg/controller/OWNERS b/pkg/controller/OWNERS index b5bd7631ef8..591fa3b2286 100644 --- a/pkg/controller/OWNERS +++ b/pkg/controller/OWNERS @@ -5,5 +5,6 @@ approvers: - janetkuo reviewers: - deads2k +- cheftako labels: - sig/apps diff --git a/pkg/controller/client_builder.go b/pkg/controller/client_builder.go index caac5649d2f..18418dcaa19 100644 --- a/pkg/controller/client_builder.go +++ b/pkg/controller/client_builder.go @@ -146,15 +146,15 @@ func (b SAControllerClientBuilder) Config(name string) (*restclient.Config, erro } validConfig, valid, err := b.getAuthenticatedConfig(sa, string(secret.Data[v1.ServiceAccountTokenKey])) if err != nil { - klog.Warningf("error validating API token for %s/%s in secret %s: %v", sa.Name, sa.Namespace, secret.Name, err) + klog.Warningf("error validating API token for %s/%s in secret %s: %v", sa.Namespace, sa.Name, secret.Name, err) // continue watching for good tokens return false, nil } if !valid { - klog.Warningf("secret %s contained an invalid API token for %s/%s", secret.Name, sa.Name, sa.Namespace) + klog.Warningf("secret %s contained an invalid API token for %s/%s", secret.Name, sa.Namespace, sa.Name) // try to delete the secret containing the invalid token if err := b.CoreClient.Secrets(secret.Namespace).Delete(secret.Name, &metav1.DeleteOptions{}); err != nil && !apierrors.IsNotFound(err) { - klog.Warningf("error deleting secret %s containing invalid API token for %s/%s: %v", secret.Name, sa.Name, sa.Namespace, err) + klog.Warningf("error deleting secret %s containing invalid API token for %s/%s: %v", secret.Name, sa.Namespace, sa.Name, err) } // continue watching for good tokens return false, nil @@ -208,14 +208,14 @@ func (b SAControllerClientBuilder) getAuthenticatedConfig(sa *v1.ServiceAccount, tokenReview := &v1authenticationapi.TokenReview{Spec: v1authenticationapi.TokenReviewSpec{Token: token}} if tokenResult, err := b.AuthenticationClient.TokenReviews().Create(tokenReview); err == nil { if !tokenResult.Status.Authenticated { - klog.Warningf("Token for %s/%s did not authenticate correctly", sa.Name, sa.Namespace) + klog.Warningf("Token for %s/%s did not authenticate correctly", sa.Namespace, sa.Name) return nil, false, nil } if tokenResult.Status.User.Username != username { - klog.Warningf("Token for %s/%s authenticated as unexpected username: %s", sa.Name, sa.Namespace, tokenResult.Status.User.Username) + klog.Warningf("Token for %s/%s authenticated as unexpected username: %s", sa.Namespace, sa.Name, tokenResult.Status.User.Username) return nil, false, nil } - klog.V(4).Infof("Verified credential for %s/%s", sa.Name, sa.Namespace) + klog.V(4).Infof("Verified credential for %s/%s", sa.Namespace, sa.Name) return clientConfig, true, nil } @@ -229,7 +229,7 @@ func (b SAControllerClientBuilder) getAuthenticatedConfig(sa *v1.ServiceAccount, } err = client.Get().AbsPath("/apis").Do().Error() if apierrors.IsUnauthorized(err) { - klog.Warningf("Token for %s/%s did not authenticate correctly: %v", sa.Name, sa.Namespace, err) + klog.Warningf("Token for %s/%s did not authenticate correctly: %v", sa.Namespace, sa.Name, err) return nil, false, nil } diff --git a/pkg/controller/cloud/BUILD b/pkg/controller/cloud/BUILD index 65171eaf32e..1348d836c50 100644 --- a/pkg/controller/cloud/BUILD +++ b/pkg/controller/cloud/BUILD @@ -10,6 +10,7 @@ go_library( name = "go_default_library", srcs = [ "node_controller.go", + "node_lifecycle_controller.go", "pvlcontroller.go", ], importpath = "k8s.io/kubernetes/pkg/controller/cloud", @@ -17,8 +18,6 @@ go_library( "//pkg/api/v1/node:go_default_library", "//pkg/apis/core/v1/helper:go_default_library", "//pkg/controller:go_default_library", - "//pkg/controller/util/node:go_default_library", - "//pkg/features:go_default_library", "//pkg/kubelet/apis:go_default_library", "//pkg/scheduler/api:go_default_library", "//pkg/util/node:go_default_library", @@ -26,13 +25,13 @@ go_library( "//staging/src/k8s.io/api/core/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + "//staging/src/k8s.io/apimachinery/pkg/labels:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/types:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/runtime:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/strategicpatch:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/watch:go_default_library", - "//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library", "//staging/src/k8s.io/client-go/informers/core/v1:go_default_library", "//staging/src/k8s.io/client-go/kubernetes:go_default_library", "//staging/src/k8s.io/client-go/kubernetes/scheme:go_default_library", @@ -51,6 +50,7 @@ go_test( name = "go_default_test", srcs = [ "node_controller_test.go", + "node_lifecycle_controller_test.go", "pvlcontroller_test.go", ], embed = [":go_default_library"], @@ -58,7 +58,6 @@ go_test( "//pkg/cloudprovider/providers/fake:go_default_library", "//pkg/controller:go_default_library", "//pkg/controller/testutil:go_default_library", - "//pkg/features:go_default_library", "//pkg/kubelet/apis:go_default_library", "//pkg/scheduler/api:go_default_library", "//pkg/volume/util:go_default_library", @@ -67,10 +66,8 @@ go_test( "//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/types:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library", - "//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library", - "//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library", - "//staging/src/k8s.io/apiserver/pkg/util/feature/testing:go_default_library", "//staging/src/k8s.io/client-go/informers:go_default_library", + "//staging/src/k8s.io/client-go/informers/core/v1:go_default_library", "//staging/src/k8s.io/client-go/kubernetes/fake:go_default_library", "//staging/src/k8s.io/client-go/kubernetes/scheme:go_default_library", "//staging/src/k8s.io/client-go/testing:go_default_library", diff --git a/pkg/controller/cloud/node_controller.go b/pkg/controller/cloud/node_controller.go index bfce4e59d4b..7c1575b1b0a 100644 --- a/pkg/controller/cloud/node_controller.go +++ b/pkg/controller/cloud/node_controller.go @@ -37,9 +37,6 @@ import ( "k8s.io/client-go/tools/record" clientretry "k8s.io/client-go/util/retry" cloudprovider "k8s.io/cloud-provider" - nodeutilv1 "k8s.io/kubernetes/pkg/api/v1/node" - "k8s.io/kubernetes/pkg/controller" - nodectrlutil "k8s.io/kubernetes/pkg/controller/util/node" kubeletapis "k8s.io/kubernetes/pkg/kubelet/apis" schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" nodeutil "k8s.io/kubernetes/pkg/util/node" @@ -58,11 +55,6 @@ type CloudNodeController struct { cloud cloudprovider.Interface - // Value controlling NodeController monitoring period, i.e. how often does NodeController - // check node status posted from kubelet. This value should be lower than nodeMonitorGracePeriod - // set in controller-manager - nodeMonitorPeriod time.Duration - nodeStatusUpdateFrequency time.Duration } @@ -79,7 +71,6 @@ func NewCloudNodeController( nodeInformer coreinformers.NodeInformer, kubeClient clientset.Interface, cloud cloudprovider.Interface, - nodeMonitorPeriod time.Duration, nodeStatusUpdateFrequency time.Duration) *CloudNodeController { eventBroadcaster := record.NewBroadcaster() @@ -97,7 +88,6 @@ func NewCloudNodeController( kubeClient: kubeClient, recorder: recorder, cloud: cloud, - nodeMonitorPeriod: nodeMonitorPeriod, nodeStatusUpdateFrequency: nodeStatusUpdateFrequency, } @@ -111,8 +101,9 @@ func NewCloudNodeController( return cnc } -// This controller deletes a node if kubelet is not reporting -// and the node is gone from the cloud provider. +// This controller updates newly registered nodes with information +// from the cloud provider. This call is blocking so should be called +// via a goroutine func (cnc *CloudNodeController) Run(stopCh <-chan struct{}) { defer utilruntime.HandleCrash() @@ -121,10 +112,7 @@ func (cnc *CloudNodeController) Run(stopCh <-chan struct{}) { // very infrequently. DO NOT MODIFY this to perform frequent operations. // Start a loop to periodically update the node addresses obtained from the cloud - go wait.Until(cnc.UpdateNodeStatus, cnc.nodeStatusUpdateFrequency, stopCh) - - // Start a loop to periodically check if any nodes have been deleted from cloudprovider - go wait.Until(cnc.MonitorNode, cnc.nodeMonitorPeriod, stopCh) + wait.Until(cnc.UpdateNodeStatus, cnc.nodeStatusUpdateFrequency, stopCh) } // UpdateNodeStatus updates the node status, such as node addresses @@ -210,108 +198,6 @@ func (cnc *CloudNodeController) updateNodeAddress(node *v1.Node, instances cloud } } -// Monitor node queries the cloudprovider for non-ready nodes and deletes them -// if they cannot be found in the cloud provider -func (cnc *CloudNodeController) MonitorNode() { - instances, ok := cnc.cloud.Instances() - if !ok { - utilruntime.HandleError(fmt.Errorf("failed to get instances from cloud provider")) - return - } - - nodes, err := cnc.kubeClient.CoreV1().Nodes().List(metav1.ListOptions{ResourceVersion: "0"}) - if err != nil { - klog.Errorf("Error monitoring node status: %v", err) - return - } - - for i := range nodes.Items { - var currentReadyCondition *v1.NodeCondition - node := &nodes.Items[i] - // Try to get the current node status - // If node status is empty, then kubelet has not posted ready status yet. In this case, process next node - for rep := 0; rep < nodeStatusUpdateRetry; rep++ { - _, currentReadyCondition = nodeutilv1.GetNodeCondition(&node.Status, v1.NodeReady) - if currentReadyCondition != nil { - break - } - name := node.Name - node, err = cnc.kubeClient.CoreV1().Nodes().Get(name, metav1.GetOptions{}) - if err != nil { - klog.Errorf("Failed while getting a Node to retry updating NodeStatus. Probably Node %s was deleted.", name) - break - } - time.Sleep(retrySleepTime) - } - if currentReadyCondition == nil { - klog.Errorf("Update status of Node %v from CloudNodeController exceeds retry count or the Node was deleted.", node.Name) - continue - } - // If the known node status says that Node is NotReady, then check if the node has been removed - // from the cloud provider. If node cannot be found in cloudprovider, then delete the node immediately - if currentReadyCondition != nil { - if currentReadyCondition.Status != v1.ConditionTrue { - // we need to check this first to get taint working in similar in all cloudproviders - // current problem is that shutdown nodes are not working in similar way ie. all cloudproviders - // does not delete node from kubernetes cluster when instance it is shutdown see issue #46442 - shutdown, err := nodectrlutil.ShutdownInCloudProvider(context.TODO(), cnc.cloud, node) - if err != nil { - klog.Errorf("Error checking if node %s is shutdown: %v", node.Name, err) - } - - if shutdown && err == nil { - // if node is shutdown add shutdown taint - err = controller.AddOrUpdateTaintOnNode(cnc.kubeClient, node.Name, controller.ShutdownTaint) - if err != nil { - klog.Errorf("Error patching node taints: %v", err) - } - // Continue checking the remaining nodes since the current one is shutdown. - continue - } - - // Check with the cloud provider to see if the node still exists. If it - // doesn't, delete the node immediately. - exists, err := ensureNodeExistsByProviderID(instances, node) - if err != nil { - klog.Errorf("Error checking if node %s exists: %v", node.Name, err) - continue - } - - if exists { - // Continue checking the remaining nodes since the current one is fine. - continue - } - - klog.V(2).Infof("Deleting node since it is no longer present in cloud provider: %s", node.Name) - - ref := &v1.ObjectReference{ - Kind: "Node", - Name: node.Name, - UID: types.UID(node.UID), - Namespace: "", - } - klog.V(2).Infof("Recording %s event message for node %s", "DeletingNode", node.Name) - - cnc.recorder.Eventf(ref, v1.EventTypeNormal, fmt.Sprintf("Deleting Node %v because it's not present according to cloud provider", node.Name), "Node %s event: %s", node.Name, "DeletingNode") - - go func(nodeName string) { - defer utilruntime.HandleCrash() - if err := cnc.kubeClient.CoreV1().Nodes().Delete(nodeName, nil); err != nil { - klog.Errorf("unable to delete node %q: %v", nodeName, err) - } - }(node.Name) - - } else { - // if taint exist remove taint - err = controller.RemoveTaintOffNode(cnc.kubeClient, node.Name, node, controller.ShutdownTaint) - if err != nil { - klog.Errorf("Error patching node taints: %v", err) - } - } - } - } -} - func (cnc *CloudNodeController) UpdateCloudNode(_, newObj interface{}) { if _, ok := newObj.(*v1.Node); !ok { utilruntime.HandleError(fmt.Errorf("unexpected object type: %v", newObj)) diff --git a/pkg/controller/cloud/node_controller_test.go b/pkg/controller/cloud/node_controller_test.go index 855594dcc8e..e5ccc73642d 100644 --- a/pkg/controller/cloud/node_controller_test.go +++ b/pkg/controller/cloud/node_controller_test.go @@ -27,7 +27,6 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" - "k8s.io/apimachinery/pkg/util/wait" "k8s.io/client-go/informers" "k8s.io/client-go/tools/record" cloudprovider "k8s.io/cloud-provider" @@ -164,205 +163,6 @@ func TestEnsureNodeExistsByProviderID(t *testing.T) { } -func TestNodeShutdown(t *testing.T) { - - testCases := []struct { - testName string - node *v1.Node - existsByProviderID bool - shutdown bool - }{ - { - testName: "node shutdowned add taint", - existsByProviderID: true, - shutdown: true, - node: &v1.Node{ - ObjectMeta: metav1.ObjectMeta{ - Name: "node0", - CreationTimestamp: metav1.Date(2012, 1, 1, 0, 0, 0, 0, time.UTC), - }, - Spec: v1.NodeSpec{ - ProviderID: "node0", - }, - Status: v1.NodeStatus{ - Conditions: []v1.NodeCondition{ - { - Type: v1.NodeReady, - Status: v1.ConditionUnknown, - LastHeartbeatTime: metav1.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC), - LastTransitionTime: metav1.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC), - }, - }, - }, - }, - }, - { - testName: "node started after shutdown remove taint", - existsByProviderID: true, - shutdown: false, - node: &v1.Node{ - ObjectMeta: metav1.ObjectMeta{ - Name: "node0", - CreationTimestamp: metav1.Date(2012, 1, 1, 0, 0, 0, 0, time.UTC), - }, - Spec: v1.NodeSpec{ - ProviderID: "node0", - Taints: []v1.Taint{ - { - Key: schedulerapi.TaintNodeShutdown, - Effect: v1.TaintEffectNoSchedule, - }, - }, - }, - Status: v1.NodeStatus{ - Conditions: []v1.NodeCondition{ - { - Type: v1.NodeReady, - Status: v1.ConditionTrue, - LastHeartbeatTime: metav1.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC), - LastTransitionTime: metav1.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC), - }, - }, - }, - }, - }, - } - for _, tc := range testCases { - t.Run(tc.testName, func(t *testing.T) { - fc := &fakecloud.FakeCloud{ - ExistsByProviderID: tc.existsByProviderID, - NodeShutdown: tc.shutdown, - } - fnh := &testutil.FakeNodeHandler{ - Existing: []*v1.Node{tc.node}, - Clientset: fake.NewSimpleClientset(), - PatchWaitChan: make(chan struct{}), - } - - factory := informers.NewSharedInformerFactory(fnh, controller.NoResyncPeriodFunc()) - - eventBroadcaster := record.NewBroadcaster() - cloudNodeController := &CloudNodeController{ - kubeClient: fnh, - nodeInformer: factory.Core().V1().Nodes(), - cloud: fc, - nodeMonitorPeriod: 1 * time.Second, - recorder: eventBroadcaster.NewRecorder(scheme.Scheme, v1.EventSource{Component: "cloud-node-controller"}), - nodeStatusUpdateFrequency: 1 * time.Second, - } - eventBroadcaster.StartLogging(klog.Infof) - - cloudNodeController.Run(wait.NeverStop) - - select { - case <-fnh.PatchWaitChan: - case <-time.After(1 * time.Second): - t.Errorf("Timed out waiting %v for node to be updated", wait.ForeverTestTimeout) - } - - assert.Equal(t, 1, len(fnh.UpdatedNodes), "Node was not updated") - if tc.shutdown { - assert.Equal(t, 1, len(fnh.UpdatedNodes[0].Spec.Taints), "Node Taint was not added") - assert.Equal(t, "node.cloudprovider.kubernetes.io/shutdown", fnh.UpdatedNodes[0].Spec.Taints[0].Key, "Node Taint key is not correct") - } else { - assert.Equal(t, 0, len(fnh.UpdatedNodes[0].Spec.Taints), "Node Taint was not removed after node is back in ready state") - } - - }) - } - -} - -// This test checks that the node is deleted when kubelet stops reporting -// and cloud provider says node is gone -func TestNodeDeleted(t *testing.T) { - pod0 := &v1.Pod{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: "default", - Name: "pod0", - }, - Spec: v1.PodSpec{ - NodeName: "node0", - }, - Status: v1.PodStatus{ - Conditions: []v1.PodCondition{ - { - Type: v1.PodReady, - Status: v1.ConditionTrue, - }, - }, - }, - } - - pod1 := &v1.Pod{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: "default", - Name: "pod1", - }, - Spec: v1.PodSpec{ - NodeName: "node0", - }, - Status: v1.PodStatus{ - Conditions: []v1.PodCondition{ - { - Type: v1.PodReady, - Status: v1.ConditionTrue, - }, - }, - }, - } - - fnh := &testutil.FakeNodeHandler{ - Existing: []*v1.Node{ - { - ObjectMeta: metav1.ObjectMeta{ - Name: "node0", - CreationTimestamp: metav1.Date(2012, 1, 1, 0, 0, 0, 0, time.UTC), - }, - Status: v1.NodeStatus{ - Conditions: []v1.NodeCondition{ - { - Type: v1.NodeReady, - Status: v1.ConditionUnknown, - LastHeartbeatTime: metav1.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC), - LastTransitionTime: metav1.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC), - }, - }, - }, - }, - }, - Clientset: fake.NewSimpleClientset(&v1.PodList{Items: []v1.Pod{*pod0, *pod1}}), - DeleteWaitChan: make(chan struct{}), - } - - factory := informers.NewSharedInformerFactory(fnh, controller.NoResyncPeriodFunc()) - - eventBroadcaster := record.NewBroadcaster() - cloudNodeController := &CloudNodeController{ - kubeClient: fnh, - nodeInformer: factory.Core().V1().Nodes(), - cloud: &fakecloud.FakeCloud{ - ExistsByProviderID: false, - Err: nil, - }, - nodeMonitorPeriod: 1 * time.Second, - recorder: eventBroadcaster.NewRecorder(scheme.Scheme, v1.EventSource{Component: "cloud-node-controller"}), - nodeStatusUpdateFrequency: 1 * time.Second, - } - eventBroadcaster.StartLogging(klog.Infof) - - cloudNodeController.Run(wait.NeverStop) - - select { - case <-fnh.DeleteWaitChan: - case <-time.After(wait.ForeverTestTimeout): - t.Errorf("Timed out waiting %v for node to be deleted", wait.ForeverTestTimeout) - } - - assert.Equal(t, 1, len(fnh.DeletedNodes), "Node was not deleted") - assert.Equal(t, "node0", fnh.DeletedNodes[0].Name, "Node was not deleted") -} - // This test checks that a node with the external cloud provider taint is cloudprovider initialized func TestNodeInitialized(t *testing.T) { fnh := &testutil.FakeNodeHandler{ @@ -425,7 +225,6 @@ func TestNodeInitialized(t *testing.T) { kubeClient: fnh, nodeInformer: factory.Core().V1().Nodes(), cloud: fakeCloud, - nodeMonitorPeriod: 1 * time.Second, recorder: eventBroadcaster.NewRecorder(scheme.Scheme, v1.EventSource{Component: "cloud-node-controller"}), nodeStatusUpdateFrequency: 1 * time.Second, } @@ -488,11 +287,10 @@ func TestNodeIgnored(t *testing.T) { eventBroadcaster := record.NewBroadcaster() cloudNodeController := &CloudNodeController{ - kubeClient: fnh, - nodeInformer: factory.Core().V1().Nodes(), - cloud: fakeCloud, - nodeMonitorPeriod: 5 * time.Second, - recorder: eventBroadcaster.NewRecorder(scheme.Scheme, v1.EventSource{Component: "cloud-node-controller"}), + kubeClient: fnh, + nodeInformer: factory.Core().V1().Nodes(), + cloud: fakeCloud, + recorder: eventBroadcaster.NewRecorder(scheme.Scheme, v1.EventSource{Component: "cloud-node-controller"}), } eventBroadcaster.StartLogging(klog.Infof) @@ -562,11 +360,10 @@ func TestGCECondition(t *testing.T) { eventBroadcaster := record.NewBroadcaster() cloudNodeController := &CloudNodeController{ - kubeClient: fnh, - nodeInformer: factory.Core().V1().Nodes(), - cloud: fakeCloud, - nodeMonitorPeriod: 1 * time.Second, - recorder: eventBroadcaster.NewRecorder(scheme.Scheme, v1.EventSource{Component: "cloud-node-controller"}), + kubeClient: fnh, + nodeInformer: factory.Core().V1().Nodes(), + cloud: fakeCloud, + recorder: eventBroadcaster.NewRecorder(scheme.Scheme, v1.EventSource{Component: "cloud-node-controller"}), } eventBroadcaster.StartLogging(klog.Infof) @@ -652,11 +449,10 @@ func TestZoneInitialized(t *testing.T) { eventBroadcaster := record.NewBroadcaster() cloudNodeController := &CloudNodeController{ - kubeClient: fnh, - nodeInformer: factory.Core().V1().Nodes(), - cloud: fakeCloud, - nodeMonitorPeriod: 5 * time.Second, - recorder: eventBroadcaster.NewRecorder(scheme.Scheme, v1.EventSource{Component: "cloud-node-controller"}), + kubeClient: fnh, + nodeInformer: factory.Core().V1().Nodes(), + cloud: fakeCloud, + recorder: eventBroadcaster.NewRecorder(scheme.Scheme, v1.EventSource{Component: "cloud-node-controller"}), } eventBroadcaster.StartLogging(klog.Infof) @@ -745,7 +541,6 @@ func TestNodeAddresses(t *testing.T) { kubeClient: fnh, nodeInformer: factory.Core().V1().Nodes(), cloud: fakeCloud, - nodeMonitorPeriod: 5 * time.Second, nodeStatusUpdateFrequency: 1 * time.Second, recorder: eventBroadcaster.NewRecorder(scheme.Scheme, v1.EventSource{Component: "cloud-node-controller"}), } @@ -768,9 +563,7 @@ func TestNodeAddresses(t *testing.T) { }, } - cloudNodeController.Run(wait.NeverStop) - - <-time.After(2 * time.Second) + cloudNodeController.UpdateNodeStatus() updatedNodes := fnh.GetUpdatedNodesCopy() @@ -860,7 +653,6 @@ func TestNodeProvidedIPAddresses(t *testing.T) { kubeClient: fnh, nodeInformer: factory.Core().V1().Nodes(), cloud: fakeCloud, - nodeMonitorPeriod: 5 * time.Second, nodeStatusUpdateFrequency: 1 * time.Second, recorder: eventBroadcaster.NewRecorder(scheme.Scheme, v1.EventSource{Component: "cloud-node-controller"}), } @@ -872,9 +664,7 @@ func TestNodeProvidedIPAddresses(t *testing.T) { assert.Equal(t, "node0", fnh.UpdatedNodes[0].Name, "Node was not updated") assert.Equal(t, 3, len(fnh.UpdatedNodes[0].Status.Addresses), "Node status unexpectedly updated") - cloudNodeController.Run(wait.NeverStop) - - <-time.After(2 * time.Second) + cloudNodeController.UpdateNodeStatus() updatedNodes := fnh.GetUpdatedNodesCopy() @@ -1152,7 +942,6 @@ func TestNodeProviderID(t *testing.T) { kubeClient: fnh, nodeInformer: factory.Core().V1().Nodes(), cloud: fakeCloud, - nodeMonitorPeriod: 5 * time.Second, nodeStatusUpdateFrequency: 1 * time.Second, recorder: eventBroadcaster.NewRecorder(scheme.Scheme, v1.EventSource{Component: "cloud-node-controller"}), } @@ -1236,7 +1025,6 @@ func TestNodeProviderIDAlreadySet(t *testing.T) { kubeClient: fnh, nodeInformer: factory.Core().V1().Nodes(), cloud: fakeCloud, - nodeMonitorPeriod: 5 * time.Second, nodeStatusUpdateFrequency: 1 * time.Second, recorder: eventBroadcaster.NewRecorder(scheme.Scheme, v1.EventSource{Component: "cloud-node-controller"}), } diff --git a/pkg/controller/cloud/node_lifecycle_controller.go b/pkg/controller/cloud/node_lifecycle_controller.go new file mode 100644 index 00000000000..809e85c55d9 --- /dev/null +++ b/pkg/controller/cloud/node_lifecycle_controller.go @@ -0,0 +1,212 @@ +/* +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 cloud + +import ( + "context" + "errors" + "fmt" + "time" + + "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/types" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" + "k8s.io/apimachinery/pkg/util/wait" + coreinformers "k8s.io/client-go/informers/core/v1" + clientset "k8s.io/client-go/kubernetes" + "k8s.io/client-go/kubernetes/scheme" + v1core "k8s.io/client-go/kubernetes/typed/core/v1" + v1lister "k8s.io/client-go/listers/core/v1" + "k8s.io/client-go/tools/record" + cloudprovider "k8s.io/cloud-provider" + "k8s.io/klog" + nodeutilv1 "k8s.io/kubernetes/pkg/api/v1/node" + "k8s.io/kubernetes/pkg/controller" + schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" +) + +const ( + deleteNodeEvent = "DeletingNode" +) + +var ShutdownTaint = &v1.Taint{ + Key: schedulerapi.TaintNodeShutdown, + Effect: v1.TaintEffectNoSchedule, +} + +// CloudNodeLifecycleController is responsible for deleting/updating kubernetes +// nodes that have been deleted/shutdown on the cloud provider +type CloudNodeLifecycleController struct { + kubeClient clientset.Interface + nodeLister v1lister.NodeLister + recorder record.EventRecorder + + cloud cloudprovider.Interface + + // Value controlling NodeController monitoring period, i.e. how often does NodeController + // check node status posted from kubelet. This value should be lower than nodeMonitorGracePeriod + // set in controller-manager + nodeMonitorPeriod time.Duration +} + +func NewCloudNodeLifecycleController( + nodeInformer coreinformers.NodeInformer, + kubeClient clientset.Interface, + cloud cloudprovider.Interface, + nodeMonitorPeriod time.Duration) (*CloudNodeLifecycleController, error) { + + eventBroadcaster := record.NewBroadcaster() + recorder := eventBroadcaster.NewRecorder(scheme.Scheme, v1.EventSource{Component: "cloud-node-lifecycle-controller"}) + eventBroadcaster.StartLogging(klog.Infof) + + klog.Info("Sending events to api server") + eventBroadcaster.StartRecordingToSink(&v1core.EventSinkImpl{Interface: kubeClient.CoreV1().Events("")}) + + if kubeClient == nil { + return nil, errors.New("kubernetes client is nil") + } + + if cloud == nil { + return nil, errors.New("no cloud provider provided") + } + + if _, ok := cloud.Instances(); !ok { + return nil, errors.New("cloud provider does not support instances") + } + + c := &CloudNodeLifecycleController{ + kubeClient: kubeClient, + nodeLister: nodeInformer.Lister(), + recorder: recorder, + cloud: cloud, + nodeMonitorPeriod: nodeMonitorPeriod, + } + + return c, nil +} + +// Run starts the main loop for this controller. Run is blocking so should +// be called via a goroutine +func (c *CloudNodeLifecycleController) Run(stopCh <-chan struct{}) { + defer utilruntime.HandleCrash() + + // The following loops run communicate with the APIServer with a worst case complexity + // of O(num_nodes) per cycle. These functions are justified here because these events fire + // very infrequently. DO NOT MODIFY this to perform frequent operations. + + // Start a loop to periodically check if any nodes have been + // deleted or shutdown from the cloudprovider + wait.Until(c.MonitorNodes, c.nodeMonitorPeriod, stopCh) +} + +// MonitorNodes checks to see if nodes in the cluster have been deleted +// or shutdown. If deleeted, it deletes the node resource. If shutdown it +// applies a shutdown taint to the node +func (c *CloudNodeLifecycleController) MonitorNodes() { + instances, ok := c.cloud.Instances() + if !ok { + utilruntime.HandleError(fmt.Errorf("failed to get instances from cloud provider")) + return + } + + nodes, err := c.nodeLister.List(labels.Everything()) + if err != nil { + klog.Errorf("error listing nodes from cache: %s", err) + return + } + + for _, node := range nodes { + // Default NodeReady status to v1.ConditionUnknown + status := v1.ConditionUnknown + if _, c := nodeutilv1.GetNodeCondition(&node.Status, v1.NodeReady); c != nil { + status = c.Status + } + + if status == v1.ConditionTrue { + // if taint exist remove taint + err = controller.RemoveTaintOffNode(c.kubeClient, node.Name, node, ShutdownTaint) + if err != nil { + klog.Errorf("error patching node taints: %v", err) + } + continue + } + + // we need to check this first to get taint working in similar in all cloudproviders + // current problem is that shutdown nodes are not working in similar way ie. all cloudproviders + // does not delete node from kubernetes cluster when instance it is shutdown see issue #46442 + shutdown, err := shutdownInCloudProvider(context.TODO(), c.cloud, node) + if err != nil { + klog.Errorf("error checking if node %s is shutdown: %v", node.Name, err) + } + + if shutdown && err == nil { + // if node is shutdown add shutdown taint + err = controller.AddOrUpdateTaintOnNode(c.kubeClient, node.Name, ShutdownTaint) + if err != nil { + klog.Errorf("failed to apply shutdown taint to node %s, it may have been deleted.", node.Name) + } + // Continue checking the remaining nodes since the current one is shutdown. + continue + } + + // At this point the node has NotReady status, we need to check if the node has been removed + // from the cloud provider. If node cannot be found in cloudprovider, then delete the node + exists, err := ensureNodeExistsByProviderID(instances, node) + if err != nil { + klog.Errorf("error checking if node %s exists: %v", node.Name, err) + continue + } + + if exists { + // Continue checking the remaining nodes since the current one is fine. + continue + } + + klog.V(2).Infof("deleting node since it is no longer present in cloud provider: %s", node.Name) + + ref := &v1.ObjectReference{ + Kind: "Node", + Name: node.Name, + UID: types.UID(node.UID), + Namespace: "", + } + + c.recorder.Eventf(ref, v1.EventTypeNormal, + fmt.Sprintf("Deleting node %v because it does not exist in the cloud provider", node.Name), + "Node %s event: %s", node.Name, deleteNodeEvent) + + if err := c.kubeClient.CoreV1().Nodes().Delete(node.Name, nil); err != nil { + klog.Errorf("unable to delete node %q: %v", node.Name, err) + } + } +} + +// shutdownInCloudProvider returns true if the node is shutdown on the cloud provider +func shutdownInCloudProvider(ctx context.Context, cloud cloudprovider.Interface, node *v1.Node) (bool, error) { + instances, ok := cloud.Instances() + if !ok { + return false, errors.New("cloud provider does not support instances") + } + + shutdown, err := instances.InstanceShutdownByProviderID(ctx, node.Spec.ProviderID) + if err == cloudprovider.NotImplemented { + return false, nil + } + + return shutdown, err +} diff --git a/pkg/controller/cloud/node_lifecycle_controller_test.go b/pkg/controller/cloud/node_lifecycle_controller_test.go new file mode 100644 index 00000000000..c6e395274c5 --- /dev/null +++ b/pkg/controller/cloud/node_lifecycle_controller_test.go @@ -0,0 +1,460 @@ +/* +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 cloud + +import ( + "errors" + "reflect" + "testing" + "time" + + "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + "k8s.io/client-go/informers" + coreinformers "k8s.io/client-go/informers/core/v1" + "k8s.io/client-go/kubernetes/fake" + "k8s.io/client-go/kubernetes/scheme" + "k8s.io/client-go/tools/record" + "k8s.io/klog" + fakecloud "k8s.io/kubernetes/pkg/cloudprovider/providers/fake" + "k8s.io/kubernetes/pkg/controller/testutil" +) + +func Test_NodesDeleted(t *testing.T) { + testcases := []struct { + name string + fnh *testutil.FakeNodeHandler + fakeCloud *fakecloud.FakeCloud + deleteNodes []*v1.Node + }{ + { + name: "node is not ready and does not exist", + fnh: &testutil.FakeNodeHandler{ + Existing: []*v1.Node{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "node0", + CreationTimestamp: metav1.Date(2012, 1, 1, 0, 0, 0, 0, time.UTC), + }, + Status: v1.NodeStatus{ + Conditions: []v1.NodeCondition{ + { + Type: v1.NodeReady, + Status: v1.ConditionFalse, + LastHeartbeatTime: metav1.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC), + LastTransitionTime: metav1.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC), + }, + }, + }, + }, + }, + DeletedNodes: []*v1.Node{}, + Clientset: fake.NewSimpleClientset(), + }, + fakeCloud: &fakecloud.FakeCloud{ + ExistsByProviderID: false, + }, + deleteNodes: []*v1.Node{ + testutil.NewNode("node0"), + }, + }, + { + name: "node is not ready and provider returns err", + fnh: &testutil.FakeNodeHandler{ + Existing: []*v1.Node{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "node0", + CreationTimestamp: metav1.Date(2012, 1, 1, 0, 0, 0, 0, time.UTC), + }, + Spec: v1.NodeSpec{ + ProviderID: "node0", + }, + Status: v1.NodeStatus{ + Conditions: []v1.NodeCondition{ + { + Type: v1.NodeReady, + Status: v1.ConditionFalse, + LastHeartbeatTime: metav1.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC), + LastTransitionTime: metav1.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC), + }, + }, + }, + }, + }, + DeletedNodes: []*v1.Node{}, + Clientset: fake.NewSimpleClientset(), + }, + fakeCloud: &fakecloud.FakeCloud{ + ExistsByProviderID: false, + ErrByProviderID: errors.New("err!"), + }, + deleteNodes: []*v1.Node{}, + }, + { + name: "node is not ready but still exists", + fnh: &testutil.FakeNodeHandler{ + Existing: []*v1.Node{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "node0", + CreationTimestamp: metav1.Date(2012, 1, 1, 0, 0, 0, 0, time.UTC), + }, + Spec: v1.NodeSpec{ + ProviderID: "node0", + }, + Status: v1.NodeStatus{ + Conditions: []v1.NodeCondition{ + { + Type: v1.NodeReady, + Status: v1.ConditionFalse, + LastHeartbeatTime: metav1.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC), + LastTransitionTime: metav1.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC), + }, + }, + }, + }, + }, + DeletedNodes: []*v1.Node{}, + Clientset: fake.NewSimpleClientset(), + }, + fakeCloud: &fakecloud.FakeCloud{ + ExistsByProviderID: true, + }, + deleteNodes: []*v1.Node{}, + }, + { + name: "node ready condition is unknown, node doesn't exist", + fnh: &testutil.FakeNodeHandler{ + Existing: []*v1.Node{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "node0", + CreationTimestamp: metav1.Date(2012, 1, 1, 0, 0, 0, 0, time.UTC), + }, + Status: v1.NodeStatus{ + Conditions: []v1.NodeCondition{ + { + Type: v1.NodeReady, + Status: v1.ConditionUnknown, + LastHeartbeatTime: metav1.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC), + LastTransitionTime: metav1.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC), + }, + }, + }, + }, + }, + DeletedNodes: []*v1.Node{}, + Clientset: fake.NewSimpleClientset(), + }, + fakeCloud: &fakecloud.FakeCloud{ + ExistsByProviderID: false, + }, + deleteNodes: []*v1.Node{ + testutil.NewNode("node0"), + }, + }, + { + name: "node ready condition is unknown, node exists", + fnh: &testutil.FakeNodeHandler{ + Existing: []*v1.Node{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "node0", + CreationTimestamp: metav1.Date(2012, 1, 1, 0, 0, 0, 0, time.UTC), + }, + Status: v1.NodeStatus{ + Conditions: []v1.NodeCondition{ + { + Type: v1.NodeReady, + Status: v1.ConditionUnknown, + LastHeartbeatTime: metav1.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC), + LastTransitionTime: metav1.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC), + }, + }, + }, + }, + }, + DeletedNodes: []*v1.Node{}, + Clientset: fake.NewSimpleClientset(), + }, + fakeCloud: &fakecloud.FakeCloud{ + NodeShutdown: false, + ExistsByProviderID: true, + ExtID: map[types.NodeName]string{ + types.NodeName("node0"): "foo://12345", + }, + }, + deleteNodes: []*v1.Node{}, + }, + { + name: "node is ready, but provider said it is deleted (maybe a bug in provider)", + fnh: &testutil.FakeNodeHandler{ + Existing: []*v1.Node{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "node0", + CreationTimestamp: metav1.Date(2012, 1, 1, 0, 0, 0, 0, time.UTC), + }, + Spec: v1.NodeSpec{ + ProviderID: "node0", + }, + Status: v1.NodeStatus{ + Conditions: []v1.NodeCondition{ + { + Type: v1.NodeReady, + Status: v1.ConditionTrue, + LastHeartbeatTime: metav1.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC), + LastTransitionTime: metav1.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC), + }, + }, + }, + }, + }, + DeletedNodes: []*v1.Node{}, + Clientset: fake.NewSimpleClientset(), + }, + fakeCloud: &fakecloud.FakeCloud{ + ExistsByProviderID: false, + }, + deleteNodes: []*v1.Node{}, + }, + } + + for _, testcase := range testcases { + t.Run(testcase.name, func(t *testing.T) { + informer := informers.NewSharedInformerFactory(testcase.fnh.Clientset, time.Second) + nodeInformer := informer.Core().V1().Nodes() + + if err := syncNodeStore(nodeInformer, testcase.fnh); err != nil { + t.Errorf("unexpected error: %v", err) + } + + eventBroadcaster := record.NewBroadcaster() + cloudNodeLifecycleController := &CloudNodeLifecycleController{ + nodeLister: nodeInformer.Lister(), + kubeClient: testcase.fnh, + cloud: testcase.fakeCloud, + recorder: eventBroadcaster.NewRecorder(scheme.Scheme, v1.EventSource{Component: "cloud-node-lifecycle-controller"}), + nodeMonitorPeriod: 1 * time.Second, + } + + eventBroadcaster.StartLogging(klog.Infof) + cloudNodeLifecycleController.MonitorNodes() + + if !reflect.DeepEqual(testcase.fnh.DeletedNodes, testcase.deleteNodes) { + t.Logf("actual nodes: %v", testcase.fnh.DeletedNodes) + t.Logf("expected nodes: %v", testcase.deleteNodes) + t.Error("unexpected deleted nodes") + } + }) + } +} + +func Test_NodesShutdown(t *testing.T) { + testcases := []struct { + name string + fnh *testutil.FakeNodeHandler + fakeCloud *fakecloud.FakeCloud + updatedNodes []*v1.Node + }{ + { + name: "node is not ready and was shutdown", + fnh: &testutil.FakeNodeHandler{ + Existing: []*v1.Node{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "node0", + CreationTimestamp: metav1.Date(2012, 1, 1, 0, 0, 0, 0, time.Local), + }, + Status: v1.NodeStatus{ + Conditions: []v1.NodeCondition{ + { + Type: v1.NodeReady, + Status: v1.ConditionFalse, + LastHeartbeatTime: metav1.Date(2015, 1, 1, 12, 0, 0, 0, time.Local), + LastTransitionTime: metav1.Date(2015, 1, 1, 12, 0, 0, 0, time.Local), + }, + }, + }, + }, + }, + UpdatedNodes: []*v1.Node{}, + Clientset: fake.NewSimpleClientset(), + }, + fakeCloud: &fakecloud.FakeCloud{ + NodeShutdown: true, + ErrShutdownByProviderID: nil, + }, + updatedNodes: []*v1.Node{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "node0", + CreationTimestamp: metav1.Date(2012, 1, 1, 0, 0, 0, 0, time.Local), + }, + Spec: v1.NodeSpec{ + Taints: []v1.Taint{ + *ShutdownTaint, + }, + }, + Status: v1.NodeStatus{ + Conditions: []v1.NodeCondition{ + { + Type: v1.NodeReady, + Status: v1.ConditionFalse, + LastHeartbeatTime: metav1.Date(2015, 1, 1, 12, 0, 0, 0, time.Local), + LastTransitionTime: metav1.Date(2015, 1, 1, 12, 0, 0, 0, time.Local), + }, + }, + }, + }, + }, + }, + { + name: "node is not ready, but there is error checking if node is shutdown", + fnh: &testutil.FakeNodeHandler{ + Existing: []*v1.Node{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "node0", + CreationTimestamp: metav1.Date(2012, 1, 1, 0, 0, 0, 0, time.Local), + }, + Status: v1.NodeStatus{ + Conditions: []v1.NodeCondition{ + { + Type: v1.NodeReady, + Status: v1.ConditionFalse, + LastHeartbeatTime: metav1.Date(2015, 1, 1, 12, 0, 0, 0, time.Local), + LastTransitionTime: metav1.Date(2015, 1, 1, 12, 0, 0, 0, time.Local), + }, + }, + }, + }, + }, + UpdatedNodes: []*v1.Node{}, + Clientset: fake.NewSimpleClientset(), + }, + fakeCloud: &fakecloud.FakeCloud{ + NodeShutdown: false, + ErrShutdownByProviderID: errors.New("err!"), + }, + updatedNodes: []*v1.Node{}, + }, + { + name: "node is not ready and is not shutdown", + fnh: &testutil.FakeNodeHandler{ + Existing: []*v1.Node{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "node0", + CreationTimestamp: metav1.Date(2012, 1, 1, 0, 0, 0, 0, time.Local), + }, + Status: v1.NodeStatus{ + Conditions: []v1.NodeCondition{ + { + Type: v1.NodeReady, + Status: v1.ConditionFalse, + LastHeartbeatTime: metav1.Date(2015, 1, 1, 12, 0, 0, 0, time.Local), + LastTransitionTime: metav1.Date(2015, 1, 1, 12, 0, 0, 0, time.Local), + }, + }, + }, + }, + }, + UpdatedNodes: []*v1.Node{}, + Clientset: fake.NewSimpleClientset(), + }, + fakeCloud: &fakecloud.FakeCloud{ + NodeShutdown: false, + ErrShutdownByProviderID: nil, + }, + updatedNodes: []*v1.Node{}, + }, + { + name: "node is ready but provider says it's shutdown (maybe a bug by provider)", + fnh: &testutil.FakeNodeHandler{ + Existing: []*v1.Node{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "node0", + CreationTimestamp: metav1.Date(2012, 1, 1, 0, 0, 0, 0, time.Local), + }, + Status: v1.NodeStatus{ + Conditions: []v1.NodeCondition{ + { + Type: v1.NodeReady, + Status: v1.ConditionTrue, + LastHeartbeatTime: metav1.Date(2015, 1, 1, 12, 0, 0, 0, time.Local), + LastTransitionTime: metav1.Date(2015, 1, 1, 12, 0, 0, 0, time.Local), + }, + }, + }, + }, + }, + UpdatedNodes: []*v1.Node{}, + Clientset: fake.NewSimpleClientset(), + }, + fakeCloud: &fakecloud.FakeCloud{ + NodeShutdown: true, + ErrShutdownByProviderID: nil, + }, + updatedNodes: []*v1.Node{}, + }, + } + + for _, testcase := range testcases { + t.Run(testcase.name, func(t *testing.T) { + informer := informers.NewSharedInformerFactory(testcase.fnh.Clientset, time.Second) + nodeInformer := informer.Core().V1().Nodes() + + if err := syncNodeStore(nodeInformer, testcase.fnh); err != nil { + t.Errorf("unexpected error: %v", err) + } + + eventBroadcaster := record.NewBroadcaster() + cloudNodeLifecycleController := &CloudNodeLifecycleController{ + nodeLister: nodeInformer.Lister(), + kubeClient: testcase.fnh, + cloud: testcase.fakeCloud, + recorder: eventBroadcaster.NewRecorder(scheme.Scheme, v1.EventSource{Component: "cloud-node-lifecycle-controller"}), + nodeMonitorPeriod: 1 * time.Second, + } + + eventBroadcaster.StartLogging(klog.Infof) + cloudNodeLifecycleController.MonitorNodes() + + if !reflect.DeepEqual(testcase.fnh.UpdatedNodes, testcase.updatedNodes) { + t.Logf("actual nodes: %v", testcase.fnh.UpdatedNodes) + t.Logf("expected nodes: %v", testcase.updatedNodes) + t.Error("unexpected updated nodes") + } + }) + } +} + +func syncNodeStore(nodeinformer coreinformers.NodeInformer, f *testutil.FakeNodeHandler) error { + nodes, err := f.List(metav1.ListOptions{}) + if err != nil { + return err + } + newElems := make([]interface{}, 0, len(nodes.Items)) + for i := range nodes.Items { + newElems = append(newElems, &nodes.Items[i]) + } + return nodeinformer.Informer().GetStore().Replace(newElems, "newRV") +} diff --git a/pkg/controller/cloud/pvlcontroller.go b/pkg/controller/cloud/pvlcontroller.go index 5cce125a6ae..d33d98f3a7e 100644 --- a/pkg/controller/cloud/pvlcontroller.go +++ b/pkg/controller/cloud/pvlcontroller.go @@ -25,7 +25,6 @@ import ( "k8s.io/klog" "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -34,19 +33,15 @@ import ( "k8s.io/apimachinery/pkg/util/strategicpatch" "k8s.io/apimachinery/pkg/util/wait" "k8s.io/apimachinery/pkg/watch" - utilfeature "k8s.io/apiserver/pkg/util/feature" - v1helper "k8s.io/kubernetes/pkg/apis/core/v1/helper" - "k8s.io/kubernetes/pkg/features" - kubeletapis "k8s.io/kubernetes/pkg/kubelet/apis" - volumeutil "k8s.io/kubernetes/pkg/volume/util" - "k8s.io/client-go/kubernetes" corelisters "k8s.io/client-go/listers/core/v1" "k8s.io/client-go/tools/cache" "k8s.io/client-go/util/workqueue" - cloudprovider "k8s.io/cloud-provider" + v1helper "k8s.io/kubernetes/pkg/apis/core/v1/helper" "k8s.io/kubernetes/pkg/controller" + kubeletapis "k8s.io/kubernetes/pkg/kubelet/apis" + volumeutil "k8s.io/kubernetes/pkg/volume/util" ) const initializerName = "pvlabel.kubernetes.io" @@ -207,7 +202,7 @@ func (pvlc *PersistentVolumeLabelController) addLabelsAndAffinityToVolume(vol *v func (pvlc *PersistentVolumeLabelController) createPatch(vol *v1.PersistentVolume, volLabels map[string]string) ([]byte, error) { volName := vol.Name newVolume := vol.DeepCopyObject().(*v1.PersistentVolume) - populateAffinity := utilfeature.DefaultFeatureGate.Enabled(features.VolumeScheduling) && len(volLabels) != 0 + populateAffinity := len(volLabels) != 0 if newVolume.Labels == nil { newVolume.Labels = make(map[string]string) diff --git a/pkg/controller/cloud/pvlcontroller_test.go b/pkg/controller/cloud/pvlcontroller_test.go index 1931540d1ef..96d12421c47 100644 --- a/pkg/controller/cloud/pvlcontroller_test.go +++ b/pkg/controller/cloud/pvlcontroller_test.go @@ -27,11 +27,8 @@ import ( "k8s.io/apimachinery/pkg/runtime" sets "k8s.io/apimachinery/pkg/util/sets" - utilfeature "k8s.io/apiserver/pkg/util/feature" - utilfeaturetesting "k8s.io/apiserver/pkg/util/feature/testing" "k8s.io/client-go/kubernetes/fake" core "k8s.io/client-go/testing" - "k8s.io/kubernetes/pkg/features" kubeletapis "k8s.io/kubernetes/pkg/kubelet/apis" volumeutil "k8s.io/kubernetes/pkg/volume/util" @@ -451,7 +448,6 @@ func TestCreatePatch(t *testing.T) { }, } - defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.VolumeScheduling, true)() for d, tc := range testCases { cloud := &fakecloud.FakeCloud{} client := fake.NewSimpleClientset() @@ -520,8 +516,6 @@ func TestAddLabelsToVolume(t *testing.T) { }, } - defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.VolumeScheduling, true)() - for d, tc := range testCases { labeledCh := make(chan bool, 1) client := fake.NewSimpleClientset() diff --git a/pkg/controller/controller_utils.go b/pkg/controller/controller_utils.go index 6ccc32aed0f..dbcafd4fc02 100644 --- a/pkg/controller/controller_utils.go +++ b/pkg/controller/controller_utils.go @@ -47,7 +47,6 @@ import ( podutil "k8s.io/kubernetes/pkg/api/v1/pod" _ "k8s.io/kubernetes/pkg/apis/core/install" "k8s.io/kubernetes/pkg/apis/core/validation" - schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" hashutil "k8s.io/kubernetes/pkg/util/hash" taintutils "k8s.io/kubernetes/pkg/util/taints" @@ -89,11 +88,6 @@ var UpdateTaintBackoff = wait.Backoff{ Jitter: 1.0, } -var ShutdownTaint = &v1.Taint{ - Key: schedulerapi.TaintNodeShutdown, - Effect: v1.TaintEffectNoSchedule, -} - var ( KeyFunc = cache.DeletionHandlingMetaNamespaceKeyFunc ) @@ -418,7 +412,7 @@ type RealRSControl struct { var _ RSControlInterface = &RealRSControl{} func (r RealRSControl) PatchReplicaSet(namespace, name string, data []byte) error { - _, err := r.KubeClient.ExtensionsV1beta1().ReplicaSets(namespace).Patch(name, types.StrategicMergePatchType, data) + _, err := r.KubeClient.AppsV1().ReplicaSets(namespace).Patch(name, types.StrategicMergePatchType, data) return err } diff --git a/pkg/controller/cronjob/injection.go b/pkg/controller/cronjob/injection.go index 7108879a8f9..14831fe1f6e 100644 --- a/pkg/controller/cronjob/injection.go +++ b/pkg/controller/cronjob/injection.go @@ -118,7 +118,8 @@ func (r realJobControl) CreateJob(namespace string, job *batchv1.Job) (*batchv1. } func (r realJobControl) DeleteJob(namespace string, name string) error { - return r.KubeClient.BatchV1().Jobs(namespace).Delete(name, nil) + background := metav1.DeletePropagationBackground + return r.KubeClient.BatchV1().Jobs(namespace).Delete(name, &metav1.DeleteOptions{PropagationPolicy: &background}) } type fakeJobControl struct { diff --git a/pkg/controller/daemon/BUILD b/pkg/controller/daemon/BUILD index cdb3a6ed75e..f98dafce883 100644 --- a/pkg/controller/daemon/BUILD +++ b/pkg/controller/daemon/BUILD @@ -20,9 +20,8 @@ go_library( "//pkg/controller/daemon/util:go_default_library", "//pkg/features:go_default_library", "//pkg/kubelet/types:go_default_library", - "//pkg/scheduler/algorithm:go_default_library", "//pkg/scheduler/algorithm/predicates:go_default_library", - "//pkg/scheduler/cache:go_default_library", + "//pkg/scheduler/nodeinfo:go_default_library", "//pkg/util/labels:go_default_library", "//pkg/util/metrics:go_default_library", "//staging/src/k8s.io/api/apps/v1:go_default_library", diff --git a/pkg/controller/daemon/daemon_controller.go b/pkg/controller/daemon/daemon_controller.go index f05c4827afc..d98ea75166d 100644 --- a/pkg/controller/daemon/daemon_controller.go +++ b/pkg/controller/daemon/daemon_controller.go @@ -54,9 +54,8 @@ import ( "k8s.io/kubernetes/pkg/controller/daemon/util" "k8s.io/kubernetes/pkg/features" kubelettypes "k8s.io/kubernetes/pkg/kubelet/types" - "k8s.io/kubernetes/pkg/scheduler/algorithm" "k8s.io/kubernetes/pkg/scheduler/algorithm/predicates" - schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" + schedulernodeinfo "k8s.io/kubernetes/pkg/scheduler/nodeinfo" "k8s.io/kubernetes/pkg/util/metrics" ) @@ -1028,10 +1027,8 @@ func (dsc *DaemonSetsController) syncNodes(ds *apps.DaemonSet, podsToDelete, nod defer createWait.Done() var err error - podTemplate := &template - + podTemplate := template.DeepCopy() if utilfeature.DefaultFeatureGate.Enabled(features.ScheduleDaemonSetPods) { - podTemplate = template.DeepCopy() // The pod's NodeAffinity will be updated to make sure the Pod is bound // to the target node by default scheduler. It is safe to do so because there // should be no conflicting node affinity with the target node. @@ -1041,6 +1038,9 @@ func (dsc *DaemonSetsController) syncNodes(ds *apps.DaemonSet, podsToDelete, nod err = dsc.podControl.CreatePodsWithControllerRef(ds.Namespace, podTemplate, ds, metav1.NewControllerRef(ds, controllerKind)) } else { + // If pod is scheduled by DaemonSetController, set its '.spec.scheduleName'. + podTemplate.Spec.SchedulerName = "kubernetes.io/daemonset-controller" + err = dsc.podControl.CreatePodsOnNode(nodesNeedingDaemonPods[ix], ds.Namespace, podTemplate, ds, metav1.NewControllerRef(ds, controllerKind)) } @@ -1287,13 +1287,13 @@ func (dsc *DaemonSetsController) syncDaemonSet(key string) error { return dsc.updateDaemonSetStatus(ds, hash, true) } -func (dsc *DaemonSetsController) simulate(newPod *v1.Pod, node *v1.Node, ds *apps.DaemonSet) ([]algorithm.PredicateFailureReason, *schedulercache.NodeInfo, error) { +func (dsc *DaemonSetsController) simulate(newPod *v1.Pod, node *v1.Node, ds *apps.DaemonSet) ([]predicates.PredicateFailureReason, *schedulernodeinfo.NodeInfo, error) { objects, err := dsc.podNodeIndex.ByIndex("nodeName", node.Name) if err != nil { return nil, nil, err } - nodeInfo := schedulercache.NewNodeInfo() + nodeInfo := schedulernodeinfo.NewNodeInfo() nodeInfo.SetNode(node) for _, obj := range objects { @@ -1428,8 +1428,8 @@ func NewPod(ds *apps.DaemonSet, nodeName string) *v1.Pod { // - PodFitsHost: checks pod's NodeName against node // - PodMatchNodeSelector: checks pod's NodeSelector and NodeAffinity against node // - PodToleratesNodeTaints: exclude tainted node unless pod has specific toleration -func checkNodeFitness(pod *v1.Pod, meta algorithm.PredicateMetadata, nodeInfo *schedulercache.NodeInfo) (bool, []algorithm.PredicateFailureReason, error) { - var predicateFails []algorithm.PredicateFailureReason +func checkNodeFitness(pod *v1.Pod, meta predicates.PredicateMetadata, nodeInfo *schedulernodeinfo.NodeInfo) (bool, []predicates.PredicateFailureReason, error) { + var predicateFails []predicates.PredicateFailureReason fit, reasons, err := predicates.PodFitsHost(pod, meta, nodeInfo) if err != nil { return false, predicateFails, err @@ -1458,8 +1458,8 @@ func checkNodeFitness(pod *v1.Pod, meta algorithm.PredicateMetadata, nodeInfo *s // Predicates checks if a DaemonSet's pod can be scheduled on a node using GeneralPredicates // and PodToleratesNodeTaints predicate -func Predicates(pod *v1.Pod, nodeInfo *schedulercache.NodeInfo) (bool, []algorithm.PredicateFailureReason, error) { - var predicateFails []algorithm.PredicateFailureReason +func Predicates(pod *v1.Pod, nodeInfo *schedulernodeinfo.NodeInfo) (bool, []predicates.PredicateFailureReason, error) { + var predicateFails []predicates.PredicateFailureReason // If ScheduleDaemonSetPods is enabled, only check nodeSelector, nodeAffinity and toleration/taint match. if utilfeature.DefaultFeatureGate.Enabled(features.ScheduleDaemonSetPods) { diff --git a/pkg/controller/daemon/daemon_controller_test.go b/pkg/controller/daemon/daemon_controller_test.go index 9dd5c01f500..59fe7c026b3 100644 --- a/pkg/controller/daemon/daemon_controller_test.go +++ b/pkg/controller/daemon/daemon_controller_test.go @@ -149,7 +149,7 @@ func newNode(name string, label map[string]string) *v1.Node { ObjectMeta: metav1.ObjectMeta{ Name: name, Labels: label, - Namespace: metav1.NamespaceDefault, + Namespace: metav1.NamespaceNone, }, Status: v1.NodeStatus{ Conditions: []v1.NodeCondition{ diff --git a/pkg/controller/daemon/update.go b/pkg/controller/daemon/update.go index ac13b32fb27..600e430ceb5 100644 --- a/pkg/controller/daemon/update.go +++ b/pkg/controller/daemon/update.go @@ -261,7 +261,7 @@ func (dsc *DaemonSetsController) controlledHistories(ds *apps.DaemonSet) ([]*app // If any adoptions are attempted, we should first recheck for deletion with // an uncached quorum read sometime after listing Pods (see #42639). canAdoptFunc := controller.RecheckDeletionTimestamp(func() (metav1.Object, error) { - fresh, err := dsc.kubeClient.ExtensionsV1beta1().DaemonSets(ds.Namespace).Get(ds.Name, metav1.GetOptions{}) + fresh, err := dsc.kubeClient.AppsV1().DaemonSets(ds.Namespace).Get(ds.Name, metav1.GetOptions{}) if err != nil { return nil, err } @@ -348,7 +348,7 @@ func (dsc *DaemonSetsController) snapshot(ds *apps.DaemonSet, revision int64) (* // Handle name collisions between different history // Get the latest DaemonSet from the API server to make sure collision count is only increased when necessary - currDS, getErr := dsc.kubeClient.ExtensionsV1beta1().DaemonSets(ds.Namespace).Get(ds.Name, metav1.GetOptions{}) + currDS, getErr := dsc.kubeClient.AppsV1().DaemonSets(ds.Namespace).Get(ds.Name, metav1.GetOptions{}) if getErr != nil { return nil, getErr } @@ -360,7 +360,7 @@ func (dsc *DaemonSetsController) snapshot(ds *apps.DaemonSet, revision int64) (* currDS.Status.CollisionCount = new(int32) } *currDS.Status.CollisionCount++ - _, updateErr := dsc.kubeClient.ExtensionsV1beta1().DaemonSets(ds.Namespace).UpdateStatus(currDS) + _, updateErr := dsc.kubeClient.AppsV1().DaemonSets(ds.Namespace).UpdateStatus(currDS) if updateErr != nil { return nil, updateErr } diff --git a/pkg/controller/disruption/BUILD b/pkg/controller/disruption/BUILD index 440966beca9..1e837373291 100644 --- a/pkg/controller/disruption/BUILD +++ b/pkg/controller/disruption/BUILD @@ -23,17 +23,15 @@ go_library( "//staging/src/k8s.io/apimachinery/pkg/util/intstr:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/runtime:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library", - "//staging/src/k8s.io/client-go/informers/apps/v1beta1:go_default_library", + "//staging/src/k8s.io/client-go/informers/apps/v1:go_default_library", "//staging/src/k8s.io/client-go/informers/core/v1:go_default_library", - "//staging/src/k8s.io/client-go/informers/extensions/v1beta1:go_default_library", "//staging/src/k8s.io/client-go/informers/policy/v1beta1:go_default_library", "//staging/src/k8s.io/client-go/kubernetes:go_default_library", "//staging/src/k8s.io/client-go/kubernetes/scheme:go_default_library", "//staging/src/k8s.io/client-go/kubernetes/typed/core/v1:go_default_library", "//staging/src/k8s.io/client-go/kubernetes/typed/policy/v1beta1:go_default_library", - "//staging/src/k8s.io/client-go/listers/apps/v1beta1:go_default_library", + "//staging/src/k8s.io/client-go/listers/apps/v1:go_default_library", "//staging/src/k8s.io/client-go/listers/core/v1:go_default_library", - "//staging/src/k8s.io/client-go/listers/extensions/v1beta1:go_default_library", "//staging/src/k8s.io/client-go/listers/policy/v1beta1:go_default_library", "//staging/src/k8s.io/client-go/tools/cache:go_default_library", "//staging/src/k8s.io/client-go/tools/record:go_default_library", @@ -49,9 +47,8 @@ go_test( deps = [ "//pkg/apis/core/install:go_default_library", "//pkg/controller:go_default_library", - "//staging/src/k8s.io/api/apps/v1beta1:go_default_library", + "//staging/src/k8s.io/api/apps/v1:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library", - "//staging/src/k8s.io/api/extensions/v1beta1:go_default_library", "//staging/src/k8s.io/api/policy/v1beta1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/intstr:go_default_library", diff --git a/pkg/controller/disruption/disruption.go b/pkg/controller/disruption/disruption.go index 8c45cc06011..2333df77030 100644 --- a/pkg/controller/disruption/disruption.go +++ b/pkg/controller/disruption/disruption.go @@ -31,17 +31,15 @@ import ( "k8s.io/apimachinery/pkg/util/intstr" utilruntime "k8s.io/apimachinery/pkg/util/runtime" "k8s.io/apimachinery/pkg/util/wait" - appsinformers "k8s.io/client-go/informers/apps/v1beta1" + appsv1informers "k8s.io/client-go/informers/apps/v1" coreinformers "k8s.io/client-go/informers/core/v1" - extensionsinformers "k8s.io/client-go/informers/extensions/v1beta1" policyinformers "k8s.io/client-go/informers/policy/v1beta1" clientset "k8s.io/client-go/kubernetes" "k8s.io/client-go/kubernetes/scheme" v1core "k8s.io/client-go/kubernetes/typed/core/v1" policyclientset "k8s.io/client-go/kubernetes/typed/policy/v1beta1" - appslisters "k8s.io/client-go/listers/apps/v1beta1" + appsv1listers "k8s.io/client-go/listers/apps/v1" corelisters "k8s.io/client-go/listers/core/v1" - extensionslisters "k8s.io/client-go/listers/extensions/v1beta1" policylisters "k8s.io/client-go/listers/policy/v1beta1" "k8s.io/client-go/tools/cache" "k8s.io/client-go/tools/record" @@ -79,13 +77,13 @@ type DisruptionController struct { rcLister corelisters.ReplicationControllerLister rcListerSynced cache.InformerSynced - rsLister extensionslisters.ReplicaSetLister + rsLister appsv1listers.ReplicaSetLister rsListerSynced cache.InformerSynced - dLister extensionslisters.DeploymentLister + dLister appsv1listers.DeploymentLister dListerSynced cache.InformerSynced - ssLister appslisters.StatefulSetLister + ssLister appsv1listers.StatefulSetLister ssListerSynced cache.InformerSynced // PodDisruptionBudget keys that need to be synced. @@ -113,9 +111,9 @@ func NewDisruptionController( podInformer coreinformers.PodInformer, pdbInformer policyinformers.PodDisruptionBudgetInformer, rcInformer coreinformers.ReplicationControllerInformer, - rsInformer extensionsinformers.ReplicaSetInformer, - dInformer extensionsinformers.DeploymentInformer, - ssInformer appsinformers.StatefulSetInformer, + rsInformer appsv1informers.ReplicaSetInformer, + dInformer appsv1informers.DeploymentInformer, + ssInformer appsv1informers.StatefulSetInformer, kubeClient clientset.Interface, ) *DisruptionController { dc := &DisruptionController{ diff --git a/pkg/controller/disruption/disruption_test.go b/pkg/controller/disruption/disruption_test.go index b0dc45c2d9f..add31408691 100644 --- a/pkg/controller/disruption/disruption_test.go +++ b/pkg/controller/disruption/disruption_test.go @@ -23,9 +23,8 @@ import ( "testing" "time" - apps "k8s.io/api/apps/v1beta1" + apps "k8s.io/api/apps/v1" "k8s.io/api/core/v1" - extensions "k8s.io/api/extensions/v1beta1" policy "k8s.io/api/policy/v1beta1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/intstr" @@ -102,9 +101,9 @@ func newFakeDisruptionController() (*disruptionController, *pdbStates) { informerFactory.Core().V1().Pods(), informerFactory.Policy().V1beta1().PodDisruptionBudgets(), informerFactory.Core().V1().ReplicationControllers(), - informerFactory.Extensions().V1beta1().ReplicaSets(), - informerFactory.Extensions().V1beta1().Deployments(), - informerFactory.Apps().V1beta1().StatefulSets(), + informerFactory.Apps().V1().ReplicaSets(), + informerFactory.Apps().V1().Deployments(), + informerFactory.Apps().V1().StatefulSets(), nil, ) dc.getUpdater = func() updater { return ps.Set } @@ -120,9 +119,9 @@ func newFakeDisruptionController() (*disruptionController, *pdbStates) { informerFactory.Core().V1().Pods().Informer().GetStore(), informerFactory.Policy().V1beta1().PodDisruptionBudgets().Informer().GetStore(), informerFactory.Core().V1().ReplicationControllers().Informer().GetStore(), - informerFactory.Extensions().V1beta1().ReplicaSets().Informer().GetStore(), - informerFactory.Extensions().V1beta1().Deployments().Informer().GetStore(), - informerFactory.Apps().V1beta1().StatefulSets().Informer().GetStore(), + informerFactory.Apps().V1().ReplicaSets().Informer().GetStore(), + informerFactory.Apps().V1().Deployments().Informer().GetStore(), + informerFactory.Apps().V1().StatefulSets().Informer().GetStore(), }, ps } @@ -192,7 +191,7 @@ func updatePodOwnerToRc(t *testing.T, pod *v1.Pod, rc *v1.ReplicationController) pod.OwnerReferences = append(pod.OwnerReferences, controllerReference) } -func updatePodOwnerToRs(t *testing.T, pod *v1.Pod, rs *extensions.ReplicaSet) { +func updatePodOwnerToRs(t *testing.T, pod *v1.Pod, rs *apps.ReplicaSet) { var controllerReference metav1.OwnerReference var trueVar = true controllerReference = metav1.OwnerReference{UID: rs.UID, APIVersion: controllerKindRS.GroupVersion().String(), Kind: controllerKindRS.Kind, Name: rs.Name, Controller: &trueVar} @@ -258,8 +257,8 @@ func newReplicationController(t *testing.T, size int32) (*v1.ReplicationControll return rc, rcName } -func newDeployment(t *testing.T, size int32) (*extensions.Deployment, string) { - d := &extensions.Deployment{ +func newDeployment(t *testing.T, size int32) (*apps.Deployment, string) { + d := &apps.Deployment{ TypeMeta: metav1.TypeMeta{APIVersion: "v1"}, ObjectMeta: metav1.ObjectMeta{ UID: uuid.NewUUID(), @@ -268,7 +267,7 @@ func newDeployment(t *testing.T, size int32) (*extensions.Deployment, string) { ResourceVersion: "18", Labels: fooBar(), }, - Spec: extensions.DeploymentSpec{ + Spec: apps.DeploymentSpec{ Replicas: &size, Selector: newSelFooBar(), }, @@ -282,8 +281,8 @@ func newDeployment(t *testing.T, size int32) (*extensions.Deployment, string) { return d, dName } -func newReplicaSet(t *testing.T, size int32) (*extensions.ReplicaSet, string) { - rs := &extensions.ReplicaSet{ +func newReplicaSet(t *testing.T, size int32) (*apps.ReplicaSet, string) { + rs := &apps.ReplicaSet{ TypeMeta: metav1.TypeMeta{APIVersion: "v1"}, ObjectMeta: metav1.ObjectMeta{ UID: uuid.NewUUID(), @@ -292,7 +291,7 @@ func newReplicaSet(t *testing.T, size int32) (*extensions.ReplicaSet, string) { ResourceVersion: "18", Labels: fooBar(), }, - Spec: extensions.ReplicaSetSpec{ + Spec: apps.ReplicaSetSpec{ Replicas: &size, Selector: newSelFooBar(), }, diff --git a/pkg/controller/history/controller_history.go b/pkg/controller/history/controller_history.go index cc7fc433ce7..85a65eaad02 100644 --- a/pkg/controller/history/controller_history.go +++ b/pkg/controller/history/controller_history.go @@ -113,7 +113,7 @@ func HashControllerRevision(revision *apps.ControllerRevision, probe *int32) str // SortControllerRevisions sorts revisions by their Revision. func SortControllerRevisions(revisions []*apps.ControllerRevision) { - sort.Sort(byRevision(revisions)) + sort.Stable(byRevision(revisions)) } // EqualRevision returns true if lhs and rhs are either both nil, or both point to non-nil ControllerRevisions that @@ -162,7 +162,14 @@ func (br byRevision) Len() int { return len(br) } +// Less breaks ties first by creation timestamp, then by name func (br byRevision) Less(i, j int) bool { + if br[i].Revision == br[j].Revision { + if br[j].CreationTimestamp.Equal(&br[i].CreationTimestamp) { + return br[i].Name < br[j].Name + } + return br[j].CreationTimestamp.After(br[i].CreationTimestamp.Time) + } return br[i].Revision < br[j].Revision } diff --git a/pkg/controller/history/controller_history_test.go b/pkg/controller/history/controller_history_test.go index 13aaaf5d092..dcf6bb609eb 100644 --- a/pkg/controller/history/controller_history_test.go +++ b/pkg/controller/history/controller_history_test.go @@ -40,6 +40,7 @@ import ( "k8s.io/apimachinery/pkg/util/strategicpatch" core "k8s.io/client-go/testing" + "time" ) func TestRealHistory_ListControllerRevisions(t *testing.T) { @@ -1545,12 +1546,14 @@ func TestSortControllerRevisions(t *testing.T) { want []string } testFn := func(test *testcase, t *testing.T) { - SortControllerRevisions(test.revisions) - for i := range test.revisions { - if test.revisions[i].Name != test.want[i] { - t.Errorf("%s: want %s at %d got %s", test.name, test.want[i], i, test.revisions[i].Name) + t.Run(test.name, func(t *testing.T) { + SortControllerRevisions(test.revisions) + for i := range test.revisions { + if test.revisions[i].Name != test.want[i] { + t.Errorf("%s: want %s at %d got %s", test.name, test.want[i], i, test.revisions[i].Name) + } } - } + }) } ss1 := newStatefulSet(3, "ss1", types.UID("ss1"), map[string]string{"foo": "bar"}) ss1.Status.CollisionCount = new(int32) @@ -1559,17 +1562,32 @@ func TestSortControllerRevisions(t *testing.T) { if err != nil { t.Fatal(err) } + ss1Rev1.Namespace = ss1.Namespace ss1Rev2, err := NewControllerRevision(ss1, parentKind, ss1.Spec.Template.Labels, rawTemplate(&ss1.Spec.Template), 2, ss1.Status.CollisionCount) if err != nil { t.Fatal(err) } + ss1Rev2.Namespace = ss1.Namespace ss1Rev3, err := NewControllerRevision(ss1, parentKind, ss1.Spec.Template.Labels, rawTemplate(&ss1.Spec.Template), 3, ss1.Status.CollisionCount) if err != nil { t.Fatal(err) } - ss1Rev3.Namespace = ss1.Namespace + + ss1Rev3Time2, err := NewControllerRevision(ss1, parentKind, ss1.Spec.Template.Labels, rawTemplate(&ss1.Spec.Template), 3, ss1.Status.CollisionCount) + if err != nil { + t.Fatal(err) + } + ss1Rev3Time2.Namespace = ss1.Namespace + ss1Rev3Time2.CreationTimestamp = metav1.Time{Time: ss1Rev3.CreationTimestamp.Add(time.Second)} + + ss1Rev3Time2Name2, err := NewControllerRevision(ss1, parentKind, ss1.Spec.Template.Labels, rawTemplate(&ss1.Spec.Template), 3, ss1.Status.CollisionCount) + if err != nil { + t.Fatal(err) + } + ss1Rev3Time2Name2.Namespace = ss1.Namespace + ss1Rev3Time2Name2.CreationTimestamp = metav1.Time{Time: ss1Rev3.CreationTimestamp.Add(time.Second)} tests := []testcase{ { @@ -1587,6 +1605,11 @@ func TestSortControllerRevisions(t *testing.T) { revisions: []*apps.ControllerRevision{ss1Rev3, ss1Rev2, ss1Rev1}, want: []string{ss1Rev1.Name, ss1Rev2.Name, ss1Rev3.Name}, }, + { + name: "with ties", + revisions: []*apps.ControllerRevision{ss1Rev3, ss1Rev3Time2, ss1Rev2, ss1Rev1}, + want: []string{ss1Rev1.Name, ss1Rev2.Name, ss1Rev3.Name, ss1Rev3Time2.Name, ss1Rev3Time2Name2.Name}, + }, { name: "empty", revisions: nil, diff --git a/pkg/controller/namespace/deletion/namespaced_resources_deleter_test.go b/pkg/controller/namespace/deletion/namespaced_resources_deleter_test.go index 5a35633753c..ae9770cad07 100644 --- a/pkg/controller/namespace/deletion/namespaced_resources_deleter_test.go +++ b/pkg/controller/namespace/deletion/namespaced_resources_deleter_test.go @@ -234,8 +234,8 @@ func TestSyncNamespaceThatIsTerminatingNonExperimental(t *testing.T) { testSyncNamespaceThatIsTerminating(t, &metav1.APIVersions{}) } -func TestSyncNamespaceThatIsTerminatingV1Beta1(t *testing.T) { - testSyncNamespaceThatIsTerminating(t, &metav1.APIVersions{Versions: []string{"extensions/v1beta1"}}) +func TestSyncNamespaceThatIsTerminatingV1(t *testing.T) { + testSyncNamespaceThatIsTerminating(t, &metav1.APIVersions{Versions: []string{"apps/v1"}}) } func TestSyncNamespaceThatIsActive(t *testing.T) { @@ -331,7 +331,7 @@ func testResources() []*metav1.APIResourceList { }, }, { - GroupVersion: "extensions/v1beta1", + GroupVersion: "apps/v1", APIResources: []metav1.APIResource{ { Name: "deployments", diff --git a/pkg/controller/nodelifecycle/BUILD b/pkg/controller/nodelifecycle/BUILD index 74eb860fa2a..015b150ea8b 100644 --- a/pkg/controller/nodelifecycle/BUILD +++ b/pkg/controller/nodelifecycle/BUILD @@ -25,24 +25,22 @@ go_library( "//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/labels:go_default_library", - "//staging/src/k8s.io/apimachinery/pkg/types:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/runtime:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library", "//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library", + "//staging/src/k8s.io/client-go/informers/apps/v1:go_default_library", "//staging/src/k8s.io/client-go/informers/coordination/v1beta1:go_default_library", "//staging/src/k8s.io/client-go/informers/core/v1:go_default_library", - "//staging/src/k8s.io/client-go/informers/extensions/v1beta1:go_default_library", "//staging/src/k8s.io/client-go/kubernetes:go_default_library", "//staging/src/k8s.io/client-go/kubernetes/scheme:go_default_library", "//staging/src/k8s.io/client-go/kubernetes/typed/core/v1:go_default_library", + "//staging/src/k8s.io/client-go/listers/apps/v1:go_default_library", "//staging/src/k8s.io/client-go/listers/coordination/v1beta1:go_default_library", "//staging/src/k8s.io/client-go/listers/core/v1:go_default_library", - "//staging/src/k8s.io/client-go/listers/extensions/v1beta1:go_default_library", "//staging/src/k8s.io/client-go/tools/cache:go_default_library", "//staging/src/k8s.io/client-go/tools/record:go_default_library", "//staging/src/k8s.io/client-go/util/flowcontrol:go_default_library", "//staging/src/k8s.io/client-go/util/workqueue:go_default_library", - "//staging/src/k8s.io/cloud-provider:go_default_library", "//vendor/github.com/prometheus/client_golang/prometheus:go_default_library", "//vendor/k8s.io/klog:go_default_library", ], @@ -70,7 +68,6 @@ go_test( srcs = ["node_lifecycle_controller_test.go"], embed = [":go_default_library"], deps = [ - "//pkg/cloudprovider/providers/fake:go_default_library", "//pkg/controller:go_default_library", "//pkg/controller/nodelifecycle/scheduler:go_default_library", "//pkg/controller/testutil:go_default_library", @@ -80,25 +77,22 @@ go_test( "//pkg/scheduler/api:go_default_library", "//pkg/util/node:go_default_library", "//pkg/util/taints:go_default_library", + "//staging/src/k8s.io/api/apps/v1:go_default_library", "//staging/src/k8s.io/api/coordination/v1beta1:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library", - "//staging/src/k8s.io/api/extensions/v1beta1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/equality:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/resource:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//staging/src/k8s.io/apimachinery/pkg/types:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/diff:go_default_library", - "//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library", "//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library", "//staging/src/k8s.io/apiserver/pkg/util/feature/testing:go_default_library", "//staging/src/k8s.io/client-go/informers:go_default_library", + "//staging/src/k8s.io/client-go/informers/apps/v1:go_default_library", "//staging/src/k8s.io/client-go/informers/coordination/v1beta1:go_default_library", "//staging/src/k8s.io/client-go/informers/core/v1:go_default_library", - "//staging/src/k8s.io/client-go/informers/extensions/v1beta1:go_default_library", "//staging/src/k8s.io/client-go/kubernetes:go_default_library", "//staging/src/k8s.io/client-go/kubernetes/fake:go_default_library", "//staging/src/k8s.io/client-go/testing:go_default_library", - "//staging/src/k8s.io/cloud-provider:go_default_library", "//vendor/k8s.io/utils/pointer:go_default_library", ], ) diff --git a/pkg/controller/nodelifecycle/node_lifecycle_controller.go b/pkg/controller/nodelifecycle/node_lifecycle_controller.go index f474b55df9e..d5154f003e7 100644 --- a/pkg/controller/nodelifecycle/node_lifecycle_controller.go +++ b/pkg/controller/nodelifecycle/node_lifecycle_controller.go @@ -22,7 +22,6 @@ limitations under the License. package nodelifecycle import ( - "context" "fmt" "hash/fnv" "io" @@ -37,24 +36,22 @@ import ( apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" - "k8s.io/apimachinery/pkg/types" utilruntime "k8s.io/apimachinery/pkg/util/runtime" "k8s.io/apimachinery/pkg/util/wait" utilfeature "k8s.io/apiserver/pkg/util/feature" + appsv1informers "k8s.io/client-go/informers/apps/v1" coordinformers "k8s.io/client-go/informers/coordination/v1beta1" coreinformers "k8s.io/client-go/informers/core/v1" - extensionsinformers "k8s.io/client-go/informers/extensions/v1beta1" clientset "k8s.io/client-go/kubernetes" "k8s.io/client-go/kubernetes/scheme" v1core "k8s.io/client-go/kubernetes/typed/core/v1" + appsv1listers "k8s.io/client-go/listers/apps/v1" coordlisters "k8s.io/client-go/listers/coordination/v1beta1" corelisters "k8s.io/client-go/listers/core/v1" - extensionslisters "k8s.io/client-go/listers/extensions/v1beta1" "k8s.io/client-go/tools/cache" "k8s.io/client-go/tools/record" "k8s.io/client-go/util/flowcontrol" "k8s.io/client-go/util/workqueue" - cloudprovider "k8s.io/cloud-provider" v1node "k8s.io/kubernetes/pkg/api/v1/node" "k8s.io/kubernetes/pkg/controller" "k8s.io/kubernetes/pkg/controller/nodelifecycle/scheduler" @@ -98,9 +95,6 @@ var ( v1.NodeMemoryPressure: { v1.ConditionTrue: schedulerapi.TaintNodeMemoryPressure, }, - v1.NodeOutOfDisk: { - v1.ConditionTrue: schedulerapi.TaintNodeOutOfDisk, - }, v1.NodeDiskPressure: { v1.ConditionTrue: schedulerapi.TaintNodeDiskPressure, }, @@ -117,7 +111,6 @@ var ( schedulerapi.TaintNodeUnreachable: v1.NodeReady, schedulerapi.TaintNodeNetworkUnavailable: v1.NodeNetworkUnavailable, schedulerapi.TaintNodeMemoryPressure: v1.NodeMemoryPressure, - schedulerapi.TaintNodeOutOfDisk: v1.NodeOutOfDisk, schedulerapi.TaintNodeDiskPressure: v1.NodeDiskPressure, schedulerapi.TaintNodePIDPressure: v1.NodePIDPressure, } @@ -150,7 +143,6 @@ type Controller struct { taintManager *scheduler.NoExecuteTaintManager podInformerSynced cache.InformerSynced - cloud cloudprovider.Interface kubeClient clientset.Interface // This timestamp is to be used instead of LastProbeTime stored in Condition. We do this @@ -176,15 +168,13 @@ type Controller struct { zoneStates map[string]ZoneState - daemonSetStore extensionslisters.DaemonSetLister + daemonSetStore appsv1listers.DaemonSetLister daemonSetInformerSynced cache.InformerSynced - leaseLister coordlisters.LeaseLister - leaseInformerSynced cache.InformerSynced - nodeLister corelisters.NodeLister - nodeInformerSynced cache.InformerSynced - nodeExistsInCloudProvider func(types.NodeName) (bool, error) - nodeShutdownInCloudProvider func(context.Context, *v1.Node) (bool, error) + leaseLister coordlisters.LeaseLister + leaseInformerSynced cache.InformerSynced + nodeLister corelisters.NodeLister + nodeInformerSynced cache.InformerSynced recorder record.EventRecorder @@ -235,7 +225,7 @@ type Controller struct { useTaintBasedEvictions bool // if set to true, NodeController will taint Nodes based on its condition for 'NetworkUnavailable', - // 'MemoryPressure', 'OutOfDisk' and 'DiskPressure'. + // 'MemoryPressure', 'PIDPressure' and 'DiskPressure'. taintNodeByCondition bool nodeUpdateQueue workqueue.Interface @@ -246,8 +236,7 @@ func NewNodeLifecycleController( leaseInformer coordinformers.LeaseInformer, podInformer coreinformers.PodInformer, nodeInformer coreinformers.NodeInformer, - daemonSetInformer extensionsinformers.DaemonSetInformer, - cloud cloudprovider.Interface, + daemonSetInformer appsv1informers.DaemonSetInformer, kubeClient clientset.Interface, nodeMonitorPeriod time.Duration, nodeStartupGracePeriod time.Duration, @@ -280,17 +269,10 @@ func NewNodeLifecycleController( } nc := &Controller{ - cloud: cloud, - kubeClient: kubeClient, - now: metav1.Now, - knownNodeSet: make(map[string]*v1.Node), - nodeHealthMap: make(map[string]*nodeHealthData), - nodeExistsInCloudProvider: func(nodeName types.NodeName) (bool, error) { - return nodeutil.ExistsInCloudProvider(cloud, nodeName) - }, - nodeShutdownInCloudProvider: func(ctx context.Context, node *v1.Node) (bool, error) { - return nodeutil.ShutdownInCloudProvider(ctx, cloud, node) - }, + kubeClient: kubeClient, + now: metav1.Now, + knownNodeSet: make(map[string]*v1.Node), + nodeHealthMap: make(map[string]*nodeHealthData), recorder: recorder, nodeMonitorPeriod: nodeMonitorPeriod, nodeStartupGracePeriod: nodeStartupGracePeriod, @@ -779,11 +761,6 @@ func (nc *Controller) monitorNodeHealth() error { klog.V(2).Infof("Node %s is ready again, cancelled pod eviction", node.Name) } } - // remove shutdown taint this is needed always depending do we use taintbased or not - err := nc.markNodeAsNotShutdown(node) - if err != nil { - klog.Errorf("Failed to remove taints from node %v. Will retry in next iteration.", node.Name) - } } // Report node event. @@ -793,42 +770,6 @@ func (nc *Controller) monitorNodeHealth() error { utilruntime.HandleError(fmt.Errorf("Unable to mark all pods NotReady on node %v: %v", node.Name, err)) } } - - // Check with the cloud provider to see if the node still exists. If it - // doesn't, delete the node immediately. - if currentReadyCondition.Status != v1.ConditionTrue && nc.cloud != nil { - // check is node shutdowned, if yes do not deleted it. Instead add taint - shutdown, err := nc.nodeShutdownInCloudProvider(context.TODO(), node) - if err != nil { - klog.Errorf("Error determining if node %v shutdown in cloud: %v", node.Name, err) - } - // node shutdown - if shutdown && err == nil { - err = controller.AddOrUpdateTaintOnNode(nc.kubeClient, node.Name, controller.ShutdownTaint) - if err != nil { - klog.Errorf("Error patching node taints: %v", err) - } - continue - } - exists, err := nc.nodeExistsInCloudProvider(types.NodeName(node.Name)) - if err != nil { - klog.Errorf("Error determining if node %v exists in cloud: %v", node.Name, err) - continue - } - if !exists { - klog.V(2).Infof("Deleting node (no longer present in cloud provider): %s", node.Name) - nodeutil.RecordNodeEvent(nc.recorder, node.Name, string(node.UID), v1.EventTypeNormal, "DeletingNode", fmt.Sprintf("Deleting Node %v because it's not present according to cloud provider", node.Name)) - go func(nodeName string) { - defer utilruntime.HandleCrash() - // Kubelet is not reporting and Cloud Provider says node - // is gone. Delete it without worrying about grace - // periods. - if err := nodeutil.ForcefullyDeleteNode(nc.kubeClient, nodeName); err != nil { - klog.Errorf("Unable to forcefully delete node %q: %v", nodeName, err) - } - }(node.Name) - } - } } } nc.handleDisruption(zoneToNodeConditions, nodes) @@ -976,7 +917,6 @@ func (nc *Controller) tryUpdateNodeHealth(node *v1.Node) (time.Duration, v1.Node // remaining node conditions should also be set to Unknown remainingNodeConditionTypes := []v1.NodeConditionType{ - v1.NodeOutOfDisk, v1.NodeMemoryPressure, v1.NodeDiskPressure, v1.NodePIDPressure, @@ -1268,17 +1208,6 @@ func (nc *Controller) markNodeAsReachable(node *v1.Node) (bool, error) { return nc.zoneNoExecuteTainter[utilnode.GetZoneKey(node)].Remove(node.Name), nil } -func (nc *Controller) markNodeAsNotShutdown(node *v1.Node) error { - nc.evictorLock.Lock() - defer nc.evictorLock.Unlock() - err := controller.RemoveTaintOffNode(nc.kubeClient, node.Name, node, controller.ShutdownTaint) - if err != nil { - klog.Errorf("Failed to remove taint from node %v: %v", node.Name, err) - return err - } - return nil -} - // ComputeZoneState returns a slice of NodeReadyConditions for all Nodes in a given zone. // The zone is considered: // - fullyDisrupted if there're no Ready Nodes, diff --git a/pkg/controller/nodelifecycle/node_lifecycle_controller_test.go b/pkg/controller/nodelifecycle/node_lifecycle_controller_test.go index 3b17a9f86fd..268f1c62e16 100644 --- a/pkg/controller/nodelifecycle/node_lifecycle_controller_test.go +++ b/pkg/controller/nodelifecycle/node_lifecycle_controller_test.go @@ -17,31 +17,26 @@ limitations under the License. package nodelifecycle import ( - "context" "strings" "testing" "time" + apps "k8s.io/api/apps/v1" coordv1beta1 "k8s.io/api/coordination/v1beta1" "k8s.io/api/core/v1" - extensions "k8s.io/api/extensions/v1beta1" apiequality "k8s.io/apimachinery/pkg/api/equality" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/diff" - "k8s.io/apimachinery/pkg/util/wait" utilfeature "k8s.io/apiserver/pkg/util/feature" utilfeaturetesting "k8s.io/apiserver/pkg/util/feature/testing" "k8s.io/client-go/informers" + appsinformers "k8s.io/client-go/informers/apps/v1" coordinformers "k8s.io/client-go/informers/coordination/v1beta1" coreinformers "k8s.io/client-go/informers/core/v1" - extensionsinformers "k8s.io/client-go/informers/extensions/v1beta1" clientset "k8s.io/client-go/kubernetes" "k8s.io/client-go/kubernetes/fake" testcore "k8s.io/client-go/testing" - cloudprovider "k8s.io/cloud-provider" - fakecloud "k8s.io/kubernetes/pkg/cloudprovider/providers/fake" "k8s.io/kubernetes/pkg/controller" "k8s.io/kubernetes/pkg/controller/nodelifecycle/scheduler" "k8s.io/kubernetes/pkg/controller/testutil" @@ -69,7 +64,7 @@ type nodeLifecycleController struct { *Controller leaseInformer coordinformers.LeaseInformer nodeInformer coreinformers.NodeInformer - daemonSetInformer extensionsinformers.DaemonSetInformer + daemonSetInformer appsinformers.DaemonSetInformer } // doEviction does the fake eviction and returns the status of eviction operation. @@ -128,7 +123,6 @@ func (nc *nodeLifecycleController) syncNodeStore(fakeNodeHandler *testutil.FakeN } func newNodeLifecycleControllerFromClient( - cloud cloudprovider.Interface, kubeClient clientset.Interface, podEvictionTimeout time.Duration, evictionLimiterQPS float32, @@ -145,14 +139,13 @@ func newNodeLifecycleControllerFromClient( leaseInformer := factory.Coordination().V1beta1().Leases() nodeInformer := factory.Core().V1().Nodes() - daemonSetInformer := factory.Extensions().V1beta1().DaemonSets() + daemonSetInformer := factory.Apps().V1().DaemonSets() nc, err := NewNodeLifecycleController( leaseInformer, factory.Core().V1().Pods(), nodeInformer, daemonSetInformer, - cloud, kubeClient, nodeMonitorPeriod, nodeStartupGracePeriod, @@ -203,7 +196,7 @@ func TestMonitorNodeHealthEvictPods(t *testing.T) { table := []struct { fakeNodeHandler *testutil.FakeNodeHandler - daemonSets []extensions.DaemonSet + daemonSets []apps.DaemonSet timeToPass time.Duration newNodeStatus v1.NodeStatus secondNodeNewStatus v1.NodeStatus @@ -416,13 +409,13 @@ func TestMonitorNodeHealthEvictPods(t *testing.T) { }, ), }, - daemonSets: []extensions.DaemonSet{ + daemonSets: []apps.DaemonSet{ { ObjectMeta: metav1.ObjectMeta{ Name: "ds0", Namespace: "default", }, - Spec: extensions.DaemonSetSpec{ + Spec: apps.DaemonSetSpec{ Selector: &metav1.LabelSelector{ MatchLabels: map[string]string{"daemon": "yes"}, }, @@ -641,7 +634,6 @@ func TestMonitorNodeHealthEvictPods(t *testing.T) { for _, item := range table { nodeController, _ := newNodeLifecycleControllerFromClient( - nil, item.fakeNodeHandler, evictionTimeout, testRateLimiterQPS, @@ -802,7 +794,6 @@ func TestPodStatusChange(t *testing.T) { for _, item := range table { nodeController, _ := newNodeLifecycleControllerFromClient( - nil, item.fakeNodeHandler, evictionTimeout, testRateLimiterQPS, @@ -1327,7 +1318,6 @@ func TestMonitorNodeHealthEvictPodsWithDisruption(t *testing.T) { Clientset: fake.NewSimpleClientset(&v1.PodList{Items: item.podList}), } nodeController, _ := newNodeLifecycleControllerFromClient( - nil, fakeNodeHandler, evictionTimeout, testRateLimiterQPS, @@ -1392,185 +1382,6 @@ func TestMonitorNodeHealthEvictPodsWithDisruption(t *testing.T) { } } -func TestCloudProviderNodeShutdown(t *testing.T) { - - testCases := []struct { - testName string - node *v1.Node - shutdown bool - }{ - { - testName: "node shutdowned add taint", - shutdown: true, - node: &v1.Node{ - ObjectMeta: metav1.ObjectMeta{ - Name: "node0", - CreationTimestamp: metav1.Date(2012, 1, 1, 0, 0, 0, 0, time.UTC), - }, - Spec: v1.NodeSpec{ - ProviderID: "node0", - }, - Status: v1.NodeStatus{ - Conditions: []v1.NodeCondition{ - { - Type: v1.NodeReady, - Status: v1.ConditionUnknown, - LastHeartbeatTime: metav1.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC), - LastTransitionTime: metav1.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC), - }, - }, - }, - }, - }, - { - testName: "node started after shutdown remove taint", - shutdown: false, - node: &v1.Node{ - ObjectMeta: metav1.ObjectMeta{ - Name: "node0", - CreationTimestamp: metav1.Date(2012, 1, 1, 0, 0, 0, 0, time.UTC), - }, - Spec: v1.NodeSpec{ - ProviderID: "node0", - Taints: []v1.Taint{ - { - Key: schedulerapi.TaintNodeShutdown, - Effect: v1.TaintEffectNoSchedule, - }, - }, - }, - Status: v1.NodeStatus{ - Conditions: []v1.NodeCondition{ - { - Type: v1.NodeReady, - Status: v1.ConditionTrue, - LastHeartbeatTime: metav1.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC), - LastTransitionTime: metav1.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC), - }, - }, - }, - }, - }, - } - for _, tc := range testCases { - t.Run(tc.testName, func(t *testing.T) { - fnh := &testutil.FakeNodeHandler{ - Existing: []*v1.Node{tc.node}, - Clientset: fake.NewSimpleClientset(), - } - nodeController, _ := newNodeLifecycleControllerFromClient( - nil, - fnh, - 10*time.Minute, - testRateLimiterQPS, - testRateLimiterQPS, - testLargeClusterThreshold, - testUnhealthyThreshold, - testNodeMonitorGracePeriod, - testNodeStartupGracePeriod, - testNodeMonitorPeriod, - false) - nodeController.cloud = &fakecloud.FakeCloud{} - nodeController.now = func() metav1.Time { return metav1.Date(2016, 1, 1, 12, 0, 0, 0, time.UTC) } - nodeController.recorder = testutil.NewFakeRecorder() - nodeController.nodeShutdownInCloudProvider = func(ctx context.Context, node *v1.Node) (bool, error) { - return tc.shutdown, nil - } - - if err := nodeController.syncNodeStore(fnh); err != nil { - t.Errorf("unexpected error: %v", err) - } - if err := nodeController.monitorNodeHealth(); err != nil { - t.Errorf("unexpected error: %v", err) - } - - if len(fnh.UpdatedNodes) != 1 { - t.Errorf("Node was not updated") - } - if tc.shutdown { - if len(fnh.UpdatedNodes[0].Spec.Taints) != 1 { - t.Errorf("Node Taint was not added") - } - if fnh.UpdatedNodes[0].Spec.Taints[0].Key != "node.cloudprovider.kubernetes.io/shutdown" { - t.Errorf("Node Taint key is not correct") - } - } else { - if len(fnh.UpdatedNodes[0].Spec.Taints) != 0 { - t.Errorf("Node Taint was not removed after node is back in ready state") - } - } - }) - } - -} - -// TestCloudProviderNoRateLimit tests that monitorNodes() immediately deletes -// pods and the node when kubelet has not reported, and the cloudprovider says -// the node is gone. -func TestCloudProviderNoRateLimit(t *testing.T) { - fnh := &testutil.FakeNodeHandler{ - Existing: []*v1.Node{ - { - ObjectMeta: metav1.ObjectMeta{ - Name: "node0", - CreationTimestamp: metav1.Date(2012, 1, 1, 0, 0, 0, 0, time.UTC), - }, - Status: v1.NodeStatus{ - Conditions: []v1.NodeCondition{ - { - Type: v1.NodeReady, - Status: v1.ConditionUnknown, - LastHeartbeatTime: metav1.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC), - LastTransitionTime: metav1.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC), - }, - }, - }, - }, - }, - Clientset: fake.NewSimpleClientset(&v1.PodList{Items: []v1.Pod{*testutil.NewPod("pod0", "node0"), *testutil.NewPod("pod1", "node0")}}), - DeleteWaitChan: make(chan struct{}), - } - nodeController, _ := newNodeLifecycleControllerFromClient( - nil, - fnh, - 10*time.Minute, - testRateLimiterQPS, - testRateLimiterQPS, - testLargeClusterThreshold, - testUnhealthyThreshold, - testNodeMonitorGracePeriod, - testNodeStartupGracePeriod, - testNodeMonitorPeriod, - false) - nodeController.cloud = &fakecloud.FakeCloud{} - nodeController.now = func() metav1.Time { return metav1.Date(2016, 1, 1, 12, 0, 0, 0, time.UTC) } - nodeController.recorder = testutil.NewFakeRecorder() - nodeController.nodeExistsInCloudProvider = func(nodeName types.NodeName) (bool, error) { - return false, nil - } - nodeController.nodeShutdownInCloudProvider = func(ctx context.Context, node *v1.Node) (bool, error) { - return false, nil - } - // monitorNodeHealth should allow this node to be immediately deleted - if err := nodeController.syncNodeStore(fnh); err != nil { - t.Errorf("unexpected error: %v", err) - } - if err := nodeController.monitorNodeHealth(); err != nil { - t.Errorf("unexpected error: %v", err) - } - select { - case <-fnh.DeleteWaitChan: - case <-time.After(wait.ForeverTestTimeout): - t.Errorf("Timed out waiting %v for node to be deleted", wait.ForeverTestTimeout) - } - if len(fnh.DeletedNodes) != 1 || fnh.DeletedNodes[0].Name != "node0" { - t.Errorf("Node was not deleted") - } - if nodeOnQueue := nodeController.zonePodEvictor[""].Remove("node0"); nodeOnQueue { - t.Errorf("Node was queued for eviction. Should have been immediately deleted.") - } -} - func TestMonitorNodeHealthUpdateStatus(t *testing.T) { fakeNow := metav1.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC) table := []struct { @@ -1612,14 +1423,6 @@ func TestMonitorNodeHealthUpdateStatus(t *testing.T) { LastHeartbeatTime: metav1.Date(2012, 1, 1, 0, 0, 0, 0, time.UTC), LastTransitionTime: fakeNow, }, - { - Type: v1.NodeOutOfDisk, - Status: v1.ConditionUnknown, - Reason: "NodeStatusNeverUpdated", - Message: "Kubelet never posted node status.", - LastHeartbeatTime: metav1.Date(2012, 1, 1, 0, 0, 0, 0, time.UTC), - LastTransitionTime: fakeNow, - }, { Type: v1.NodeMemoryPressure, Status: v1.ConditionUnknown, @@ -1687,13 +1490,6 @@ func TestMonitorNodeHealthUpdateStatus(t *testing.T) { LastHeartbeatTime: metav1.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC), LastTransitionTime: metav1.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC), }, - { - Type: v1.NodeOutOfDisk, - Status: v1.ConditionFalse, - // Node status hasn't been updated for 1hr. - LastHeartbeatTime: metav1.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC), - LastTransitionTime: metav1.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC), - }, }, Capacity: v1.ResourceList{ v1.ResourceName(v1.ResourceCPU): resource.MustParse("10"), @@ -1715,13 +1511,6 @@ func TestMonitorNodeHealthUpdateStatus(t *testing.T) { LastHeartbeatTime: metav1.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC), LastTransitionTime: metav1.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC), }, - { - Type: v1.NodeOutOfDisk, - Status: v1.ConditionFalse, - // Node status hasn't been updated for 1hr. - LastHeartbeatTime: metav1.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC), - LastTransitionTime: metav1.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC), - }, }, Capacity: v1.ResourceList{ v1.ResourceName(v1.ResourceCPU): resource.MustParse("10"), @@ -1744,14 +1533,6 @@ func TestMonitorNodeHealthUpdateStatus(t *testing.T) { LastHeartbeatTime: metav1.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC), LastTransitionTime: metav1.Time{Time: metav1.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC).Add(time.Hour)}, }, - { - Type: v1.NodeOutOfDisk, - Status: v1.ConditionUnknown, - Reason: "NodeStatusUnknown", - Message: "Kubelet stopped posting node status.", - LastHeartbeatTime: metav1.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC), - LastTransitionTime: metav1.Time{Time: metav1.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC).Add(time.Hour)}, - }, { Type: v1.NodeMemoryPressure, Status: v1.ConditionUnknown, @@ -1822,7 +1603,6 @@ func TestMonitorNodeHealthUpdateStatus(t *testing.T) { } for i, item := range table { nodeController, _ := newNodeLifecycleControllerFromClient( - nil, item.fakeNodeHandler, 5*time.Minute, testRateLimiterQPS, @@ -1960,14 +1740,6 @@ func TestMonitorNodeHealthUpdateNodeAndPodStatusWithLease(t *testing.T) { LastHeartbeatTime: nodeCreationTime, LastTransitionTime: fakeNow, }, - { - Type: v1.NodeOutOfDisk, - Status: v1.ConditionUnknown, - Reason: "NodeStatusNeverUpdated", - Message: "Kubelet never posted node status.", - LastHeartbeatTime: nodeCreationTime, - LastTransitionTime: fakeNow, - }, { Type: v1.NodeMemoryPressure, Status: v1.ConditionUnknown, @@ -2062,14 +1834,6 @@ func TestMonitorNodeHealthUpdateNodeAndPodStatusWithLease(t *testing.T) { LastHeartbeatTime: nodeCreationTime, LastTransitionTime: metav1.Time{Time: fakeNow.Add(time.Hour)}, }, - { - Type: v1.NodeOutOfDisk, - Status: v1.ConditionUnknown, - Reason: "NodeStatusNeverUpdated", - Message: "Kubelet never posted node status.", - LastHeartbeatTime: nodeCreationTime, - LastTransitionTime: metav1.Time{Time: fakeNow.Add(time.Hour)}, - }, { Type: v1.NodeMemoryPressure, Status: v1.ConditionUnknown, @@ -2120,7 +1884,7 @@ func TestMonitorNodeHealthUpdateNodeAndPodStatusWithLease(t *testing.T) { LastTransitionTime: fakeNow, }, { - Type: v1.NodeOutOfDisk, + Type: v1.NodeDiskPressure, Status: v1.ConditionFalse, LastHeartbeatTime: fakeNow, LastTransitionTime: fakeNow, @@ -2148,7 +1912,7 @@ func TestMonitorNodeHealthUpdateNodeAndPodStatusWithLease(t *testing.T) { LastTransitionTime: fakeNow, }, { - Type: v1.NodeOutOfDisk, + Type: v1.NodeDiskPressure, Status: v1.ConditionFalse, LastHeartbeatTime: fakeNow, LastTransitionTime: fakeNow, @@ -2175,7 +1939,7 @@ func TestMonitorNodeHealthUpdateNodeAndPodStatusWithLease(t *testing.T) { LastTransitionTime: fakeNow, }, { - Type: v1.NodeOutOfDisk, + Type: v1.NodeDiskPressure, Status: v1.ConditionFalse, LastHeartbeatTime: fakeNow, LastTransitionTime: fakeNow, @@ -2210,7 +1974,7 @@ func TestMonitorNodeHealthUpdateNodeAndPodStatusWithLease(t *testing.T) { LastTransitionTime: fakeNow, }, { - Type: v1.NodeOutOfDisk, + Type: v1.NodeDiskPressure, Status: v1.ConditionFalse, LastHeartbeatTime: fakeNow, LastTransitionTime: fakeNow, @@ -2238,7 +2002,7 @@ func TestMonitorNodeHealthUpdateNodeAndPodStatusWithLease(t *testing.T) { LastTransitionTime: fakeNow, }, { - Type: v1.NodeOutOfDisk, + Type: v1.NodeDiskPressure, Status: v1.ConditionFalse, LastHeartbeatTime: metav1.Time{Time: fakeNow.Add(time.Hour)}, LastTransitionTime: fakeNow, @@ -2265,7 +2029,7 @@ func TestMonitorNodeHealthUpdateNodeAndPodStatusWithLease(t *testing.T) { LastTransitionTime: fakeNow, }, { - Type: v1.NodeOutOfDisk, + Type: v1.NodeDiskPressure, Status: v1.ConditionFalse, LastHeartbeatTime: metav1.Time{Time: fakeNow.Add(time.Hour)}, LastTransitionTime: fakeNow, @@ -2299,12 +2063,6 @@ func TestMonitorNodeHealthUpdateNodeAndPodStatusWithLease(t *testing.T) { LastHeartbeatTime: fakeNow, LastTransitionTime: fakeNow, }, - { - Type: v1.NodeOutOfDisk, - Status: v1.ConditionFalse, - LastHeartbeatTime: fakeNow, - LastTransitionTime: fakeNow, - }, }, Capacity: v1.ResourceList{ v1.ResourceName(v1.ResourceCPU): resource.MustParse("10"), @@ -2327,12 +2085,6 @@ func TestMonitorNodeHealthUpdateNodeAndPodStatusWithLease(t *testing.T) { LastHeartbeatTime: fakeNow, LastTransitionTime: fakeNow, }, - { - Type: v1.NodeOutOfDisk, - Status: v1.ConditionFalse, - LastHeartbeatTime: fakeNow, - LastTransitionTime: fakeNow, - }, }, Capacity: v1.ResourceList{ v1.ResourceName(v1.ResourceCPU): resource.MustParse("10"), @@ -2356,14 +2108,6 @@ func TestMonitorNodeHealthUpdateNodeAndPodStatusWithLease(t *testing.T) { LastHeartbeatTime: fakeNow, LastTransitionTime: metav1.Time{Time: fakeNow.Add(time.Hour)}, }, - { - Type: v1.NodeOutOfDisk, - Status: v1.ConditionUnknown, - Reason: "NodeStatusUnknown", - Message: "Kubelet stopped posting node status.", - LastHeartbeatTime: fakeNow, - LastTransitionTime: metav1.Time{Time: fakeNow.Add(time.Hour)}, - }, { Type: v1.NodeMemoryPressure, Status: v1.ConditionUnknown, @@ -2403,7 +2147,6 @@ func TestMonitorNodeHealthUpdateNodeAndPodStatusWithLease(t *testing.T) { for _, item := range testcases { t.Run(item.description, func(t *testing.T) { nodeController, _ := newNodeLifecycleControllerFromClient( - nil, item.fakeNodeHandler, 5*time.Minute, testRateLimiterQPS, @@ -2567,7 +2310,6 @@ func TestMonitorNodeHealthMarkPodsNotReady(t *testing.T) { for i, item := range table { nodeController, _ := newNodeLifecycleControllerFromClient( - nil, item.fakeNodeHandler, 5*time.Minute, testRateLimiterQPS, @@ -2697,7 +2439,6 @@ func TestApplyNoExecuteTaints(t *testing.T) { } originalTaint := UnreachableTaintTemplate nodeController, _ := newNodeLifecycleControllerFromClient( - nil, fakeNodeHandler, evictionTimeout, testRateLimiterQPS, @@ -2838,7 +2579,6 @@ func TestSwapUnreachableNotReadyTaints(t *testing.T) { updatedTaint := NotReadyTaintTemplate nodeController, _ := newNodeLifecycleControllerFromClient( - nil, fakeNodeHandler, evictionTimeout, testRateLimiterQPS, @@ -2940,7 +2680,6 @@ func TestTaintsNodeByCondition(t *testing.T) { } nodeController, _ := newNodeLifecycleControllerFromClient( - nil, fakeNodeHandler, evictionTimeout, testRateLimiterQPS, @@ -2954,10 +2693,6 @@ func TestTaintsNodeByCondition(t *testing.T) { nodeController.now = func() metav1.Time { return fakeNow } nodeController.recorder = testutil.NewFakeRecorder() - outOfDiskTaint := &v1.Taint{ - Key: schedulerapi.TaintNodeOutOfDisk, - Effect: v1.TaintEffectNoSchedule, - } networkUnavailableTaint := &v1.Taint{ Key: schedulerapi.TaintNodeNetworkUnavailable, Effect: v1.TaintEffectNoSchedule, @@ -3007,7 +2742,7 @@ func TestTaintsNodeByCondition(t *testing.T) { ExpectedTaints: []*v1.Taint{networkUnavailableTaint}, }, { - Name: "NetworkUnavailable and OutOfDisk are true", + Name: "NetworkUnavailable is true", Node: &v1.Node{ ObjectMeta: metav1.ObjectMeta{ Name: "node0", @@ -3031,48 +2766,6 @@ func TestTaintsNodeByCondition(t *testing.T) { LastHeartbeatTime: metav1.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC), LastTransitionTime: metav1.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC), }, - { - Type: v1.NodeOutOfDisk, - Status: v1.ConditionTrue, - LastHeartbeatTime: metav1.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC), - LastTransitionTime: metav1.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC), - }, - }, - }, - }, - ExpectedTaints: []*v1.Taint{networkUnavailableTaint, outOfDiskTaint}, - }, - { - Name: "NetworkUnavailable is true, OutOfDisk is unknown", - Node: &v1.Node{ - ObjectMeta: metav1.ObjectMeta{ - Name: "node0", - CreationTimestamp: metav1.Date(2012, 1, 1, 0, 0, 0, 0, time.UTC), - Labels: map[string]string{ - kubeletapis.LabelZoneRegion: "region1", - kubeletapis.LabelZoneFailureDomain: "zone1", - }, - }, - Status: v1.NodeStatus{ - Conditions: []v1.NodeCondition{ - { - Type: v1.NodeReady, - Status: v1.ConditionTrue, - LastHeartbeatTime: metav1.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC), - LastTransitionTime: metav1.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC), - }, - { - Type: v1.NodeNetworkUnavailable, - Status: v1.ConditionTrue, - LastHeartbeatTime: metav1.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC), - LastTransitionTime: metav1.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC), - }, - { - Type: v1.NodeOutOfDisk, - Status: v1.ConditionUnknown, - LastHeartbeatTime: metav1.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC), - LastTransitionTime: metav1.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC), - }, }, }, }, @@ -3180,7 +2873,6 @@ func TestNodeEventGeneration(t *testing.T) { } nodeController, _ := newNodeLifecycleControllerFromClient( - nil, fakeNodeHandler, 5*time.Minute, testRateLimiterQPS, @@ -3191,26 +2883,20 @@ func TestNodeEventGeneration(t *testing.T) { testNodeStartupGracePeriod, testNodeMonitorPeriod, false) - nodeController.cloud = &fakecloud.FakeCloud{} - nodeController.nodeExistsInCloudProvider = func(nodeName types.NodeName) (bool, error) { - return false, nil - } - nodeController.nodeShutdownInCloudProvider = func(ctx context.Context, node *v1.Node) (bool, error) { - return false, nil - } nodeController.now = func() metav1.Time { return fakeNow } fakeRecorder := testutil.NewFakeRecorder() nodeController.recorder = fakeRecorder + if err := nodeController.syncNodeStore(fakeNodeHandler); err != nil { t.Errorf("unexpected error: %v", err) } if err := nodeController.monitorNodeHealth(); err != nil { t.Errorf("unexpected error: %v", err) } - if len(fakeRecorder.Events) != 2 { - t.Fatalf("unexpected events, got %v, expected %v: %+v", len(fakeRecorder.Events), 2, fakeRecorder.Events) + if len(fakeRecorder.Events) != 1 { + t.Fatalf("unexpected events, got %v, expected %v: %+v", len(fakeRecorder.Events), 1, fakeRecorder.Events) } - if fakeRecorder.Events[0].Reason != "RegisteredNode" || fakeRecorder.Events[1].Reason != "DeletingNode" { + if fakeRecorder.Events[0].Reason != "RegisteredNode" { var reasons []string for _, event := range fakeRecorder.Events { reasons = append(reasons, event.Reason) @@ -3249,7 +2935,6 @@ func TestFixDeprecatedTaintKey(t *testing.T) { } nodeController, _ := newNodeLifecycleControllerFromClient( - nil, fakeNodeHandler, evictionTimeout, testRateLimiterQPS, diff --git a/pkg/controller/podautoscaler/BUILD b/pkg/controller/podautoscaler/BUILD index 7ff398dea32..fc0c55bc7c9 100644 --- a/pkg/controller/podautoscaler/BUILD +++ b/pkg/controller/podautoscaler/BUILD @@ -5,7 +5,7 @@ go_library( srcs = [ "doc.go", "horizontal.go", - "rate_limitters.go", + "rate_limiters.go", "replica_calculator.go", ], importpath = "k8s.io/kubernetes/pkg/controller/podautoscaler", @@ -55,10 +55,10 @@ go_test( embed = [":go_default_library"], deps = [ "//pkg/api/legacyscheme:go_default_library", + "//pkg/apis/apps/install:go_default_library", "//pkg/apis/autoscaling:go_default_library", "//pkg/apis/autoscaling/install:go_default_library", "//pkg/apis/core/install:go_default_library", - "//pkg/apis/extensions/install:go_default_library", "//pkg/controller:go_default_library", "//pkg/controller/podautoscaler/metrics:go_default_library", "//staging/src/k8s.io/api/autoscaling/v1:go_default_library", diff --git a/pkg/controller/podautoscaler/horizontal.go b/pkg/controller/podautoscaler/horizontal.go index b043564abe8..4517b0d7299 100644 --- a/pkg/controller/podautoscaler/horizontal.go +++ b/pkg/controller/podautoscaler/horizontal.go @@ -179,7 +179,7 @@ func (a *HorizontalController) enqueueHPA(obj interface{}) { return } - // always add rate-limitted so we don't fetch metrics more that once per resync interval + // always add rate-limited so we don't fetch metrics more that once per resync interval a.queue.AddRateLimited(key) } @@ -207,14 +207,18 @@ func (a *HorizontalController) processNextWorkItem() bool { } defer a.queue.Done(key) - err := a.reconcileKey(key.(string)) - if err == nil { - // don't "forget" here because we want to only process a given HPA once per resync interval - return true + deleted, err := a.reconcileKey(key.(string)) + if err != nil { + utilruntime.HandleError(err) + } + // Add request processing HPA after resync interval just in case last resync didn't insert + // request into the queue. Request is not inserted into queue by resync if previous one wasn't processed yet. + // This happens quite often because requests from previous resync are removed from the queue at the same moment + // as next resync inserts new requests. + if !deleted { + a.queue.AddRateLimited(key) } - a.queue.AddRateLimited(key) - utilruntime.HandleError(err) return true } @@ -298,20 +302,20 @@ func (a *HorizontalController) computeReplicasForMetrics(hpa *autoscalingv2.Hori return replicas, metric, statuses, timestamp, nil } -func (a *HorizontalController) reconcileKey(key string) error { +func (a *HorizontalController) reconcileKey(key string) (deleted bool, err error) { namespace, name, err := cache.SplitMetaNamespaceKey(key) if err != nil { - return err + return true, err } hpa, err := a.hpaLister.HorizontalPodAutoscalers(namespace).Get(name) if errors.IsNotFound(err) { klog.Infof("Horizontal Pod Autoscaler %s has been deleted in %s", name, namespace) delete(a.recommendations, key) - return nil + return true, nil } - return a.reconcileAutoscaler(hpa, key) + return false, a.reconcileAutoscaler(hpa, key) } // computeStatusForObjectMetric computes the desired number of replicas for the specified metric of type ObjectMetricSourceType. diff --git a/pkg/controller/podautoscaler/horizontal_test.go b/pkg/controller/podautoscaler/horizontal_test.go index 0cc8922835f..e9f57836f4f 100644 --- a/pkg/controller/podautoscaler/horizontal_test.go +++ b/pkg/controller/podautoscaler/horizontal_test.go @@ -51,8 +51,8 @@ import ( "github.com/stretchr/testify/assert" + _ "k8s.io/kubernetes/pkg/apis/apps/install" _ "k8s.io/kubernetes/pkg/apis/autoscaling/install" - _ "k8s.io/kubernetes/pkg/apis/extensions/install" ) var statusOk = []autoscalingv2.HorizontalPodAutoscalerCondition{ @@ -862,7 +862,7 @@ func TestScaleUpDeployment(t *testing.T) { useMetricsAPI: true, resource: &fakeResource{ name: "test-dep", - apiVersion: "extensions/v1beta1", + apiVersion: "apps/v1", kind: "Deployment", }, } @@ -882,7 +882,7 @@ func TestScaleUpReplicaSet(t *testing.T) { useMetricsAPI: true, resource: &fakeResource{ name: "test-replicaset", - apiVersion: "extensions/v1beta1", + apiVersion: "apps/v1", kind: "ReplicaSet", }, } @@ -1033,7 +1033,7 @@ func TestScaleUpCMObject(t *testing.T) { Type: autoscalingv2.ObjectMetricSourceType, Object: &autoscalingv2.ObjectMetricSource{ DescribedObject: autoscalingv2.CrossVersionObjectReference{ - APIVersion: "extensions/v1beta1", + APIVersion: "apps/v1", Kind: "Deployment", Name: "some-deployment", }, @@ -1183,7 +1183,7 @@ func TestScaleDownCMObject(t *testing.T) { Type: autoscalingv2.ObjectMetricSourceType, Object: &autoscalingv2.ObjectMetricSource{ DescribedObject: autoscalingv2.CrossVersionObjectReference{ - APIVersion: "extensions/v1beta1", + APIVersion: "apps/v1", Kind: "Deployment", Name: "some-deployment", }, @@ -1392,7 +1392,7 @@ func TestToleranceCMObject(t *testing.T) { Type: autoscalingv2.ObjectMetricSourceType, Object: &autoscalingv2.ObjectMetricSource{ DescribedObject: autoscalingv2.CrossVersionObjectReference{ - APIVersion: "extensions/v1beta1", + APIVersion: "apps/v1", Kind: "Deployment", Name: "some-deployment", }, @@ -1860,7 +1860,7 @@ func TestConditionFailedGetMetrics(t *testing.T) { Type: autoscalingv2.ObjectMetricSourceType, Object: &autoscalingv2.ObjectMetricSource{ DescribedObject: autoscalingv2.CrossVersionObjectReference{ - APIVersion: "extensions/v1beta1", + APIVersion: "apps/v1", Kind: "Deployment", Name: "some-deployment", }, @@ -2176,7 +2176,7 @@ func TestComputedToleranceAlgImplementation(t *testing.T) { finalPods := int32(math.Ceil(resourcesUsedRatio * float64(startPods))) // To breach tolerance we will create a utilization ratio difference of tolerance to usageRatioToleranceValue) - tc := testCase{ + tc1 := testCase{ minReplicas: 0, maxReplicas: 1000, initialReplicas: startPods, @@ -2209,22 +2209,49 @@ func TestComputedToleranceAlgImplementation(t *testing.T) { useMetricsAPI: true, recommendations: []timestampedRecommendation{}, } + tc1.runTest(t) - tc.runTest(t) - - // Reuse the data structure above, now testing "unscaling". - // Now, we test that no scaling happens if we are in a very close margin to the tolerance target = math.Abs(1/(requestedToUsed*(1-defaultTestingTolerance))) + .004 finalCPUPercentTarget = int32(target * 100) - tc.CPUTarget = finalCPUPercentTarget - tc.initialReplicas = startPods - tc.expectedDesiredReplicas = startPods - tc.expectedConditions = statusOkWithOverrides(autoscalingv2.HorizontalPodAutoscalerCondition{ - Type: autoscalingv2.AbleToScale, - Status: v1.ConditionTrue, - Reason: "ReadyForNewScale", - }) - tc.runTest(t) + tc2 := testCase{ + minReplicas: 0, + maxReplicas: 1000, + initialReplicas: startPods, + expectedDesiredReplicas: startPods, + CPUTarget: finalCPUPercentTarget, + reportedLevels: []uint64{ + totalUsedCPUOfAllPods / 10, + totalUsedCPUOfAllPods / 10, + totalUsedCPUOfAllPods / 10, + totalUsedCPUOfAllPods / 10, + totalUsedCPUOfAllPods / 10, + totalUsedCPUOfAllPods / 10, + totalUsedCPUOfAllPods / 10, + totalUsedCPUOfAllPods / 10, + totalUsedCPUOfAllPods / 10, + totalUsedCPUOfAllPods / 10, + }, + reportedCPURequests: []resource.Quantity{ + resource.MustParse(fmt.Sprint(perPodRequested+100) + "m"), + resource.MustParse(fmt.Sprint(perPodRequested-100) + "m"), + resource.MustParse(fmt.Sprint(perPodRequested+10) + "m"), + resource.MustParse(fmt.Sprint(perPodRequested-10) + "m"), + resource.MustParse(fmt.Sprint(perPodRequested+2) + "m"), + resource.MustParse(fmt.Sprint(perPodRequested-2) + "m"), + resource.MustParse(fmt.Sprint(perPodRequested+1) + "m"), + resource.MustParse(fmt.Sprint(perPodRequested-1) + "m"), + resource.MustParse(fmt.Sprint(perPodRequested) + "m"), + resource.MustParse(fmt.Sprint(perPodRequested) + "m"), + }, + useMetricsAPI: true, + recommendations: []timestampedRecommendation{}, + expectedConditions: statusOkWithOverrides(autoscalingv2.HorizontalPodAutoscalerCondition{ + Type: autoscalingv2.AbleToScale, + Status: v1.ConditionTrue, + Reason: "ReadyForNewScale", + }), + } + tc2.runTest(t) } func TestScaleUpRCImmediately(t *testing.T) { diff --git a/pkg/controller/podautoscaler/legacy_horizontal_test.go b/pkg/controller/podautoscaler/legacy_horizontal_test.go index 6d0bf6cdc4a..4f97232a522 100644 --- a/pkg/controller/podautoscaler/legacy_horizontal_test.go +++ b/pkg/controller/podautoscaler/legacy_horizontal_test.go @@ -50,9 +50,9 @@ import ( "github.com/stretchr/testify/assert" + _ "k8s.io/kubernetes/pkg/apis/apps/install" _ "k8s.io/kubernetes/pkg/apis/autoscaling/install" _ "k8s.io/kubernetes/pkg/apis/core/install" - _ "k8s.io/kubernetes/pkg/apis/extensions/install" ) func (w fakeResponseWrapper) DoRaw() ([]byte, error) { @@ -100,6 +100,8 @@ type legacyTestCase struct { // Last scale time lastScaleTime *metav1.Time recommendations []timestampedRecommendation + + finished bool } // Needs to be called under a lock. @@ -462,12 +464,14 @@ func (tc *legacyTestCase) verifyResults(t *testing.T) { func (tc *legacyTestCase) runTest(t *testing.T) { testClient, testScaleClient := tc.prepareTestClient(t) metricsClient := metrics.NewHeapsterMetricsClient(testClient, metrics.DefaultHeapsterNamespace, metrics.DefaultHeapsterScheme, metrics.DefaultHeapsterService, metrics.DefaultHeapsterPort) - eventClient := &fake.Clientset{} eventClient.AddReactor("*", "events", func(action core.Action) (handled bool, ret runtime.Object, err error) { tc.Lock() defer tc.Unlock() + if tc.finished { + return true, &v1.Event{}, nil + } obj := action.(core.CreateAction).GetObject().(*v1.Event) if tc.verifyEvents { switch obj.Reason { @@ -514,7 +518,10 @@ func (tc *legacyTestCase) runTest(t *testing.T) { informerFactory.Start(stop) go hpaController.Run(stop) + // Wait for HPA to be processed. + <-tc.processed tc.Lock() + tc.finished = true if tc.verifyEvents { tc.Unlock() // We need to wait for events to be broadcasted (sleep for longer than record.sleepDuration). @@ -522,9 +529,8 @@ func (tc *legacyTestCase) runTest(t *testing.T) { } else { tc.Unlock() } - // Wait for HPA to be processed. - <-tc.processed tc.verifyResults(t) + } func TestLegacyScaleUp(t *testing.T) { @@ -588,7 +594,7 @@ func TestLegacyScaleUpDeployment(t *testing.T) { useMetricsAPI: true, resource: &fakeResource{ name: "test-dep", - apiVersion: "extensions/v1beta1", + apiVersion: "apps/v1", kind: "Deployment", }, } @@ -608,7 +614,7 @@ func TestLegacyScaleUpReplicaSet(t *testing.T) { useMetricsAPI: true, resource: &fakeResource{ name: "test-replicaset", - apiVersion: "extensions/v1beta1", + apiVersion: "apps/v1", kind: "ReplicaSet", }, } diff --git a/pkg/controller/podautoscaler/metrics/BUILD b/pkg/controller/podautoscaler/metrics/BUILD index 673b2859f83..a4ef29adeae 100644 --- a/pkg/controller/podautoscaler/metrics/BUILD +++ b/pkg/controller/podautoscaler/metrics/BUILD @@ -38,7 +38,7 @@ go_test( embed = [":go_default_library"], deps = [ "//pkg/api/legacyscheme:go_default_library", - "//pkg/apis/extensions/install:go_default_library", + "//pkg/apis/apps/install:go_default_library", "//staging/src/k8s.io/api/autoscaling/v2beta2:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/meta/testrestmapper:go_default_library", diff --git a/pkg/controller/podautoscaler/metrics/rest_metrics_client_test.go b/pkg/controller/podautoscaler/metrics/rest_metrics_client_test.go index d8de168fc41..d7475e65280 100644 --- a/pkg/controller/podautoscaler/metrics/rest_metrics_client_test.go +++ b/pkg/controller/podautoscaler/metrics/rest_metrics_client_test.go @@ -31,7 +31,7 @@ import ( "k8s.io/apimachinery/pkg/runtime/schema" core "k8s.io/client-go/testing" "k8s.io/kubernetes/pkg/api/legacyscheme" - _ "k8s.io/kubernetes/pkg/apis/extensions/install" + _ "k8s.io/kubernetes/pkg/apis/apps/install" cmapi "k8s.io/metrics/pkg/apis/custom_metrics/v1beta2" emapi "k8s.io/metrics/pkg/apis/external_metrics/v1beta1" metricsapi "k8s.io/metrics/pkg/apis/metrics/v1beta1" @@ -305,7 +305,7 @@ func TestRESTClientSingleObject(t *testing.T) { targetTimestamp: 1, reportedMetricPoints: []metricPoint{{10, 1}}, singleObject: &autoscalingapi.CrossVersionObjectReference{ - APIVersion: "extensions/v1beta1", + APIVersion: "apps/v1", Kind: "Deployment", Name: "some-dep", }, diff --git a/pkg/controller/podautoscaler/rate_limitters.go b/pkg/controller/podautoscaler/rate_limiters.go similarity index 94% rename from pkg/controller/podautoscaler/rate_limitters.go rename to pkg/controller/podautoscaler/rate_limiters.go index 06e36ec40a8..915cd5c151c 100644 --- a/pkg/controller/podautoscaler/rate_limitters.go +++ b/pkg/controller/podautoscaler/rate_limiters.go @@ -46,7 +46,7 @@ func (r *FixedItemIntervalRateLimiter) NumRequeues(item interface{}) int { func (r *FixedItemIntervalRateLimiter) Forget(item interface{}) { } -// NewDefaultHPARateLimiter creates a rate limitter which limits overall (as per the +// NewDefaultHPARateLimiter creates a rate limiter which limits overall (as per the // default controller rate limiter), as well as per the resync interval func NewDefaultHPARateLimiter(interval time.Duration) workqueue.RateLimiter { return NewFixedItemIntervalRateLimiter(interval) diff --git a/pkg/controller/podautoscaler/replica_calculator_test.go b/pkg/controller/podautoscaler/replica_calculator_test.go index ff71498278a..c3342d62605 100644 --- a/pkg/controller/podautoscaler/replica_calculator_test.go +++ b/pkg/controller/podautoscaler/replica_calculator_test.go @@ -623,7 +623,7 @@ func TestReplicaCalcScaleUpCMObject(t *testing.T) { expectedUtilization: 20000, singleObject: &autoscalingv2.CrossVersionObjectReference{ Kind: "Deployment", - APIVersion: "extensions/v1beta1", + APIVersion: "apps/v1", Name: "some-deployment", }, }, @@ -643,7 +643,7 @@ func TestReplicaCalcScaleUpCMObjectIgnoresUnreadyPods(t *testing.T) { expectedUtilization: 50000, singleObject: &autoscalingv2.CrossVersionObjectReference{ Kind: "Deployment", - APIVersion: "extensions/v1beta1", + APIVersion: "apps/v1", Name: "some-deployment", }, }, @@ -758,7 +758,7 @@ func TestReplicaCalcScaleDownCMObject(t *testing.T) { expectedUtilization: 12000, singleObject: &autoscalingv2.CrossVersionObjectReference{ Kind: "Deployment", - APIVersion: "extensions/v1beta1", + APIVersion: "apps/v1", Name: "some-deployment", }, }, @@ -916,7 +916,7 @@ func TestReplicaCalcToleranceCMObject(t *testing.T) { expectedUtilization: 20666, singleObject: &autoscalingv2.CrossVersionObjectReference{ Kind: "Deployment", - APIVersion: "extensions/v1beta1", + APIVersion: "apps/v1", Name: "some-deployment", }, }, diff --git a/pkg/controller/replication/BUILD b/pkg/controller/replication/BUILD index 344101c42b4..a016f6baf59 100644 --- a/pkg/controller/replication/BUILD +++ b/pkg/controller/replication/BUILD @@ -22,6 +22,7 @@ go_library( "//pkg/controller:go_default_library", "//pkg/controller/replicaset:go_default_library", "//staging/src/k8s.io/api/apps/v1:go_default_library", + "//staging/src/k8s.io/api/autoscaling/v1:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/labels:go_default_library", diff --git a/pkg/controller/replication/conversion.go b/pkg/controller/replication/conversion.go index 1c9ddb0ba16..3bb1df30a96 100644 --- a/pkg/controller/replication/conversion.go +++ b/pkg/controller/replication/conversion.go @@ -27,6 +27,7 @@ import ( "time" apps "k8s.io/api/apps/v1" + autoscalingv1 "k8s.io/api/autoscaling/v1" "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" @@ -239,6 +240,16 @@ func (c conversionClient) Patch(name string, pt types.PatchType, data []byte, su return nil, errors.New("Patch() is not implemented for conversionClient") } +func (c conversionClient) GetScale(name string, options metav1.GetOptions) (result *autoscalingv1.Scale, err error) { + // This is not used by RSC. + return nil, errors.New("GetScale() is not implemented for conversionClient") +} + +func (c conversionClient) UpdateScale(name string, scale *autoscalingv1.Scale) (result *autoscalingv1.Scale, err error) { + // This is not used by RSC. + return nil, errors.New("UpdateScale() is not implemented for conversionClient") +} + func convertSlice(rcList []*v1.ReplicationController) ([]*apps.ReplicaSet, error) { rsList := make([]*apps.ReplicaSet, 0, len(rcList)) for _, rc := range rcList { diff --git a/pkg/controller/serviceaccount/tokengetter.go b/pkg/controller/serviceaccount/tokengetter.go index ed86489639f..25baf01d8d9 100644 --- a/pkg/controller/serviceaccount/tokengetter.go +++ b/pkg/controller/serviceaccount/tokengetter.go @@ -20,30 +20,43 @@ import ( "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" clientset "k8s.io/client-go/kubernetes" + v1listers "k8s.io/client-go/listers/core/v1" "k8s.io/kubernetes/pkg/serviceaccount" ) // clientGetter implements ServiceAccountTokenGetter using a clientset.Interface type clientGetter struct { - client clientset.Interface + client clientset.Interface + secretLister v1listers.SecretLister + serviceAccountLister v1listers.ServiceAccountLister + podLister v1listers.PodLister } // NewGetterFromClient returns a ServiceAccountTokenGetter that // uses the specified client to retrieve service accounts and secrets. // The client should NOT authenticate using a service account token // the returned getter will be used to retrieve, or recursion will result. -func NewGetterFromClient(c clientset.Interface) serviceaccount.ServiceAccountTokenGetter { - return clientGetter{c} +func NewGetterFromClient(c clientset.Interface, secretLister v1listers.SecretLister, serviceAccountLister v1listers.ServiceAccountLister, podLister v1listers.PodLister) serviceaccount.ServiceAccountTokenGetter { + return clientGetter{c, secretLister, serviceAccountLister, podLister} } func (c clientGetter) GetServiceAccount(namespace, name string) (*v1.ServiceAccount, error) { + if serviceAccount, err := c.serviceAccountLister.ServiceAccounts(namespace).Get(name); err == nil { + return serviceAccount, nil + } return c.client.CoreV1().ServiceAccounts(namespace).Get(name, metav1.GetOptions{}) } func (c clientGetter) GetPod(namespace, name string) (*v1.Pod, error) { + if pod, err := c.podLister.Pods(namespace).Get(name); err == nil { + return pod, nil + } return c.client.CoreV1().Pods(namespace).Get(name, metav1.GetOptions{}) } func (c clientGetter) GetSecret(namespace, name string) (*v1.Secret, error) { + if secret, err := c.secretLister.Secrets(namespace).Get(name); err == nil { + return secret, nil + } return c.client.CoreV1().Secrets(namespace).Get(name, metav1.GetOptions{}) } diff --git a/pkg/controller/util/node/BUILD b/pkg/controller/util/node/BUILD index 2dc7c49166d..4b860e68ffc 100644 --- a/pkg/controller/util/node/BUILD +++ b/pkg/controller/util/node/BUILD @@ -18,10 +18,9 @@ go_library( "//staging/src/k8s.io/apimachinery/pkg/util/errors:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/runtime:go_default_library", "//staging/src/k8s.io/client-go/kubernetes:go_default_library", - "//staging/src/k8s.io/client-go/listers/extensions/v1beta1:go_default_library", + "//staging/src/k8s.io/client-go/listers/apps/v1:go_default_library", "//staging/src/k8s.io/client-go/tools/cache:go_default_library", "//staging/src/k8s.io/client-go/tools/record:go_default_library", - "//staging/src/k8s.io/cloud-provider:go_default_library", "//vendor/k8s.io/klog:go_default_library", ], ) diff --git a/pkg/controller/util/node/controller_utils.go b/pkg/controller/util/node/controller_utils.go index 9be6845d0b8..7d67118cc6b 100644 --- a/pkg/controller/util/node/controller_utils.go +++ b/pkg/controller/util/node/controller_utils.go @@ -17,8 +17,6 @@ limitations under the License. package node import ( - "context" - "errors" "fmt" "strings" @@ -33,8 +31,7 @@ import ( "k8s.io/api/core/v1" clientset "k8s.io/client-go/kubernetes" - extensionslisters "k8s.io/client-go/listers/extensions/v1beta1" - cloudprovider "k8s.io/cloud-provider" + appsv1listers "k8s.io/client-go/listers/apps/v1" api "k8s.io/kubernetes/pkg/apis/core" "k8s.io/kubernetes/pkg/controller" "k8s.io/kubernetes/pkg/kubelet/util/format" @@ -43,16 +40,10 @@ import ( "k8s.io/klog" ) -var ( - // ErrCloudInstance occurs when the cloud provider does not support - // the Instances API. - ErrCloudInstance = errors.New("cloud provider doesn't support instances") -) - // DeletePods will delete all pods from master running on given node, // and return true if any pods were deleted, or were found pending // deletion. -func DeletePods(kubeClient clientset.Interface, recorder record.EventRecorder, nodeName, nodeUID string, daemonStore extensionslisters.DaemonSetLister) (bool, error) { +func DeletePods(kubeClient clientset.Interface, recorder record.EventRecorder, nodeName, nodeUID string, daemonStore appsv1listers.DaemonSetLister) (bool, error) { remaining := false selector := fields.OneTermEqualSelector(api.PodHostField, nodeName).String() options := metav1.ListOptions{FieldSelector: selector} @@ -125,15 +116,6 @@ func SetPodTerminationReason(kubeClient clientset.Interface, pod *v1.Pod, nodeNa return updatedPod, nil } -// ForcefullyDeleteNode deletes the node immediately. The pods on the -// node are cleaned up by the podGC. -func ForcefullyDeleteNode(kubeClient clientset.Interface, nodeName string) error { - if err := kubeClient.CoreV1().Nodes().Delete(nodeName, nil); err != nil { - return fmt.Errorf("unable to delete node %q: %v", nodeName, err) - } - return nil -} - // MarkAllPodsNotReady updates ready status of all pods running on // given node from master return true if success func MarkAllPodsNotReady(kubeClient clientset.Interface, node *v1.Node) error { @@ -171,36 +153,6 @@ func MarkAllPodsNotReady(kubeClient clientset.Interface, node *v1.Node) error { return fmt.Errorf("%v", strings.Join(errMsg, "; ")) } -// ExistsInCloudProvider returns true if the node exists in the -// cloud provider. -func ExistsInCloudProvider(cloud cloudprovider.Interface, nodeName types.NodeName) (bool, error) { - instances, ok := cloud.Instances() - if !ok { - return false, fmt.Errorf("%v", ErrCloudInstance) - } - if _, err := instances.InstanceID(context.TODO(), nodeName); err != nil { - if err == cloudprovider.InstanceNotFound { - return false, nil - } - return false, err - } - return true, nil -} - -// ShutdownInCloudProvider returns true if the node is shutdowned in -// cloud provider. -func ShutdownInCloudProvider(ctx context.Context, cloud cloudprovider.Interface, node *v1.Node) (bool, error) { - instances, ok := cloud.Instances() - if !ok { - return false, fmt.Errorf("%v", ErrCloudInstance) - } - shutdown, err := instances.InstanceShutdownByProviderID(ctx, node.Spec.ProviderID) - if err == cloudprovider.NotImplemented { - return false, nil - } - return shutdown, err -} - // RecordNodeEvent records a event related to a node. func RecordNodeEvent(recorder record.EventRecorder, nodeName, nodeUID, eventtype, reason, event string) { ref := &v1.ObjectReference{ diff --git a/pkg/controller/volume/OWNERS b/pkg/controller/volume/OWNERS index f77dc41828f..16a78635fe2 100755 --- a/pkg/controller/volume/OWNERS +++ b/pkg/controller/volume/OWNERS @@ -2,6 +2,7 @@ approvers: - childsb - jsafrane - saad-ali +- msau42 reviewers: - childsb - saad-ali diff --git a/pkg/controller/volume/persistentvolume/BUILD b/pkg/controller/volume/persistentvolume/BUILD index aac87f389d9..d0c648f5cfb 100644 --- a/pkg/controller/volume/persistentvolume/BUILD +++ b/pkg/controller/volume/persistentvolume/BUILD @@ -99,6 +99,7 @@ go_test( "//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library", "//staging/src/k8s.io/apiserver/pkg/util/feature/testing:go_default_library", "//staging/src/k8s.io/client-go/informers:go_default_library", + "//staging/src/k8s.io/client-go/informers/core/v1:go_default_library", "//staging/src/k8s.io/client-go/kubernetes:go_default_library", "//staging/src/k8s.io/client-go/kubernetes/fake:go_default_library", "//staging/src/k8s.io/client-go/kubernetes/scheme:go_default_library", diff --git a/pkg/controller/volume/persistentvolume/pv_controller.go b/pkg/controller/volume/persistentvolume/pv_controller.go index e50da0ad4fa..cd9143e2800 100644 --- a/pkg/controller/volume/persistentvolume/pv_controller.go +++ b/pkg/controller/volume/persistentvolume/pv_controller.go @@ -286,10 +286,6 @@ func checkVolumeSatisfyClaim(volume *v1.PersistentVolume, claim *v1.PersistentVo } func (ctrl *PersistentVolumeController) shouldDelayBinding(claim *v1.PersistentVolumeClaim) (bool, error) { - if !utilfeature.DefaultFeatureGate.Enabled(features.VolumeScheduling) { - return false, nil - } - // When feature VolumeScheduling enabled, // Scheduler signal to the PV controller to start dynamic // provisioning by setting the "annSelectedNode" annotation diff --git a/pkg/controller/volume/persistentvolume/pv_controller_test.go b/pkg/controller/volume/persistentvolume/pv_controller_test.go index 514617e5f1d..37b223abf3f 100644 --- a/pkg/controller/volume/persistentvolume/pv_controller_test.go +++ b/pkg/controller/volume/persistentvolume/pv_controller_test.go @@ -24,15 +24,12 @@ import ( storagev1 "k8s.io/api/storage/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/watch" - utilfeature "k8s.io/apiserver/pkg/util/feature" - utilfeaturetesting "k8s.io/apiserver/pkg/util/feature/testing" "k8s.io/client-go/informers" "k8s.io/client-go/kubernetes/fake" core "k8s.io/client-go/testing" "k8s.io/client-go/tools/cache" "k8s.io/klog" "k8s.io/kubernetes/pkg/controller" - "k8s.io/kubernetes/pkg/features" ) var ( @@ -336,24 +333,3 @@ func TestDelayBinding(t *testing.T) { } } } - -func TestDelayBindingDisabled(t *testing.T) { - // When volumeScheduling feature gate is disabled, should always be immediate - defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.VolumeScheduling, false)() - - client := &fake.Clientset{} - informerFactory := informers.NewSharedInformerFactory(client, controller.NoResyncPeriodFunc()) - classInformer := informerFactory.Storage().V1().StorageClasses() - ctrl := &PersistentVolumeController{ - classLister: classInformer.Lister(), - } - - name := "volumeScheduling-feature-disabled" - shouldDelay, err := ctrl.shouldDelayBinding(makePVCClass(&classWaitMode, false)) - if err != nil { - t.Errorf("Test %q returned error: %v", name, err) - } - if shouldDelay { - t.Errorf("Test %q returned true, expected false", name) - } -} diff --git a/pkg/controller/volume/persistentvolume/scheduler_binder.go b/pkg/controller/volume/persistentvolume/scheduler_binder.go index 85fd71cf4eb..1d4918bbcd3 100644 --- a/pkg/controller/volume/persistentvolume/scheduler_binder.go +++ b/pkg/controller/volume/persistentvolume/scheduler_binder.go @@ -21,15 +21,14 @@ import ( "sort" "time" - "k8s.io/klog" - - "k8s.io/api/core/v1" + v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/util/wait" coreinformers "k8s.io/client-go/informers/core/v1" storageinformers "k8s.io/client-go/informers/storage/v1" clientset "k8s.io/client-go/kubernetes" + "k8s.io/klog" v1helper "k8s.io/kubernetes/pkg/apis/core/v1/helper" volumeutil "k8s.io/kubernetes/pkg/volume/util" ) @@ -99,8 +98,9 @@ type SchedulerVolumeBinder interface { type volumeBinder struct { ctrl *PersistentVolumeController - pvcCache PVCAssumeCache - pvCache PVAssumeCache + nodeInformer coreinformers.NodeInformer + pvcCache PVCAssumeCache + pvCache PVAssumeCache // Stores binding decisions that were made in FindPodVolumes for use in AssumePodVolumes. // AssumePodVolumes modifies the bindings again for use in BindPodVolumes. @@ -113,6 +113,7 @@ type volumeBinder struct { // NewVolumeBinder sets up all the caches needed for the scheduler to make volume binding decisions. func NewVolumeBinder( kubeClient clientset.Interface, + nodeInformer coreinformers.NodeInformer, pvcInformer coreinformers.PersistentVolumeClaimInformer, pvInformer coreinformers.PersistentVolumeInformer, storageClassInformer storageinformers.StorageClassInformer, @@ -126,6 +127,7 @@ func NewVolumeBinder( b := &volumeBinder{ ctrl: ctrl, + nodeInformer: nodeInformer, pvcCache: NewPVCAssumeCache(pvcInformer.Informer()), pvCache: NewPVAssumeCache(pvInformer.Informer()), podBindingCache: NewPodBindingCache(), @@ -139,7 +141,9 @@ func (b *volumeBinder) GetBindingsCache() PodBindingCache { return b.podBindingCache } -// FindPodVolumes caches the matching PVs and PVCs to provision per node in podBindingCache +// FindPodVolumes caches the matching PVs and PVCs to provision per node in podBindingCache. +// This method intentionally takes in a *v1.Node object instead of using volumebinder.nodeInformer. +// That's necessary because some operations will need to pass in to the predicate fake node objects. func (b *volumeBinder) FindPodVolumes(pod *v1.Pod, node *v1.Node) (unboundVolumesSatisfied, boundVolumesSatisfied bool, err error) { podName := getPodName(pod) @@ -382,6 +386,11 @@ func (b *volumeBinder) checkBindings(pod *v1.Pod, bindings []*bindingInfo, claim return false, fmt.Errorf("failed to get cached claims to provision for pod %q", podName) } + node, err := b.nodeInformer.Lister().Get(pod.Spec.NodeName) + if err != nil { + return false, fmt.Errorf("failed to get node %q: %v", pod.Spec.NodeName, err) + } + for _, binding := range bindings { // Check for any conditions that might require scheduling retry @@ -391,6 +400,11 @@ func (b *volumeBinder) checkBindings(pod *v1.Pod, bindings []*bindingInfo, claim return false, fmt.Errorf("failed to check pv binding: %v", err) } + // Check PV's node affinity (the node might not have the proper label) + if err := volumeutil.CheckNodeAffinity(pv, node.Labels); err != nil { + return false, fmt.Errorf("pv %q node affinity doesn't match node %q: %v", pv.Name, node.Name, err) + } + // Check if pv.ClaimRef got dropped by unbindVolume() if pv.Spec.ClaimRef == nil || pv.Spec.ClaimRef.UID == "" { return false, fmt.Errorf("ClaimRef got reset for pv %q", pv.Name) @@ -420,6 +434,17 @@ func (b *volumeBinder) checkBindings(pod *v1.Pod, bindings []*bindingInfo, claim return false, fmt.Errorf("selectedNode annotation value %q not set to scheduled node %q", selectedNode, pod.Spec.NodeName) } + // If the PVC is bound to a PV, check its node affinity + if pvc.Spec.VolumeName != "" { + pv, err := b.pvCache.GetPV(pvc.Spec.VolumeName) + if err != nil { + return false, fmt.Errorf("failed to get pv %q from cache: %v", pvc.Spec.VolumeName, err) + } + if err := volumeutil.CheckNodeAffinity(pv, node.Labels); err != nil { + return false, fmt.Errorf("pv %q node affinity doesn't match node %q: %v", pv.Name, node.Name, err) + } + } + if !bound { return false, nil } diff --git a/pkg/controller/volume/persistentvolume/scheduler_binder_test.go b/pkg/controller/volume/persistentvolume/scheduler_binder_test.go index 1e7af815154..789e464fc19 100644 --- a/pkg/controller/volume/persistentvolume/scheduler_binder_test.go +++ b/pkg/controller/volume/persistentvolume/scheduler_binder_test.go @@ -22,17 +22,17 @@ import ( "testing" "time" - "k8s.io/klog" - - "k8s.io/api/core/v1" + v1 "k8s.io/api/core/v1" storagev1 "k8s.io/api/storage/v1" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/diff" "k8s.io/client-go/informers" + coreinformers "k8s.io/client-go/informers/core/v1" clientset "k8s.io/client-go/kubernetes" "k8s.io/client-go/kubernetes/fake" + "k8s.io/klog" "k8s.io/kubernetes/pkg/api/testapi" "k8s.io/kubernetes/pkg/controller" ) @@ -55,7 +55,7 @@ var ( provisionedPVC = makeTestPVC("provisioned-pvc", "1Gi", "", pvcUnbound, "", "1", &waitClassWithProvisioner) provisionedPVC2 = makeTestPVC("provisioned-pvc2", "1Gi", "", pvcUnbound, "", "1", &waitClassWithProvisioner) provisionedPVCHigherVersion = makeTestPVC("provisioned-pvc2", "1Gi", "", pvcUnbound, "", "2", &waitClassWithProvisioner) - provisionedPVCBound = makeTestPVC("provisioned-pvc", "1Gi", "", pvcBound, "some-pv", "1", &waitClassWithProvisioner) + provisionedPVCBound = makeTestPVC("provisioned-pvc", "1Gi", "", pvcBound, "pv-bound", "1", &waitClassWithProvisioner) noProvisionerPVC = makeTestPVC("no-provisioner-pvc", "1Gi", "", pvcUnbound, "", "1", &waitClass) topoMismatchPVC = makeTestPVC("topo-mismatch-pvc", "1Gi", "", pvcUnbound, "", "1", &topoMismatchClass) @@ -89,18 +89,24 @@ var ( waitClassWithProvisioner = "waitClassWithProvisioner" topoMismatchClass = "topoMismatchClass" + // nodes objects + node1 = makeNode("node1", map[string]string{nodeLabelKey: "node1"}) + node2 = makeNode("node2", map[string]string{nodeLabelKey: "node2"}) + node1NoLabels = makeNode("node1", nil) + // node topology nodeLabelKey = "nodeKey" nodeLabelValue = "node1" ) type testEnv struct { - client clientset.Interface - reactor *volumeReactor - binder SchedulerVolumeBinder - internalBinder *volumeBinder - internalPVCache *pvAssumeCache - internalPVCCache *pvcAssumeCache + client clientset.Interface + reactor *volumeReactor + binder SchedulerVolumeBinder + internalBinder *volumeBinder + internalNodeInformer coreinformers.NodeInformer + internalPVCache *pvAssumeCache + internalPVCCache *pvcAssumeCache } func newTestBinder(t *testing.T) *testEnv { @@ -108,11 +114,13 @@ func newTestBinder(t *testing.T) *testEnv { reactor := newVolumeReactor(client, nil, nil, nil, nil) informerFactory := informers.NewSharedInformerFactory(client, controller.NoResyncPeriodFunc()) + nodeInformer := informerFactory.Core().V1().Nodes() pvcInformer := informerFactory.Core().V1().PersistentVolumeClaims() classInformer := informerFactory.Storage().V1().StorageClasses() binder := NewVolumeBinder( client, + nodeInformer, pvcInformer, informerFactory.Core().V1().PersistentVolumes(), classInformer, @@ -195,12 +203,20 @@ func newTestBinder(t *testing.T) *testEnv { } return &testEnv{ - client: client, - reactor: reactor, - binder: binder, - internalBinder: internalBinder, - internalPVCache: internalPVCache, - internalPVCCache: internalPVCCache, + client: client, + reactor: reactor, + binder: binder, + internalBinder: internalBinder, + internalNodeInformer: nodeInformer, + internalPVCache: internalPVCache, + internalPVCCache: internalPVCCache, + } +} + +func (env *testEnv) initNodes(cachedNodes []*v1.Node) { + nodeInformer := env.internalNodeInformer.Informer() + for _, node := range cachedNodes { + nodeInformer.GetIndexer().Add(node) } } @@ -540,6 +556,15 @@ func pvRemoveClaimUID(pv *v1.PersistentVolume) *v1.PersistentVolume { return newPV } +func makeNode(name string, labels map[string]string) *v1.Node { + return &v1.Node{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Labels: labels, + }, + } +} + func makePod(pvcs []*v1.PersistentVolumeClaim) *v1.Pod { pod := &v1.Pod{ ObjectMeta: metav1.ObjectMeta{ @@ -1210,6 +1235,7 @@ func TestCheckBindings(t *testing.T) { "provisioning-pvc-bound": { bindings: []*bindingInfo{}, provisionedPVCs: []*v1.PersistentVolumeClaim{addProvisionAnn(provisionedPVC)}, + cachedPVs: []*v1.PersistentVolume{pvBound}, cachedPVCs: []*v1.PersistentVolumeClaim{addProvisionAnn(provisionedPVCBound)}, expectedBound: true, }, @@ -1255,6 +1281,7 @@ func TestCheckBindings(t *testing.T) { // Setup pod := makePod(nil) testEnv := newTestBinder(t) + testEnv.initNodes([]*v1.Node{node1}) testEnv.initVolumes(scenario.cachedPVs, nil) testEnv.initClaims(scenario.cachedPVCs, nil) @@ -1278,14 +1305,16 @@ func TestBindPodVolumes(t *testing.T) { scenarios := map[string]struct { // Inputs // These tests only support a single pv and pvc and static binding - bindingsNil bool // Pass in nil bindings slice - binding *bindingInfo - cachedPV *v1.PersistentVolume - cachedPVC *v1.PersistentVolumeClaim - apiPV *v1.PersistentVolume + bindingsNil bool // Pass in nil bindings slice + binding *bindingInfo + cachedPVs []*v1.PersistentVolume + cachedPVCs []*v1.PersistentVolumeClaim + provisionedPVCs []*v1.PersistentVolumeClaim + apiPVs []*v1.PersistentVolume + nodes []*v1.Node // This function runs with a delay of 5 seconds - delayFunc func(*testing.T, *testEnv, *v1.Pod, *v1.PersistentVolume, *v1.PersistentVolumeClaim) + delayFunc func(*testing.T, *testEnv, *v1.Pod, *bindingInfo, []*v1.PersistentVolumeClaim) // Expected return values shouldFail bool @@ -1296,19 +1325,19 @@ func TestBindPodVolumes(t *testing.T) { }, "nothing-to-bind-empty": {}, "already-bound": { - binding: binding1aBound, - cachedPV: pvNode1aBound, - cachedPVC: boundPVCNode1a, + binding: binding1aBound, + cachedPVs: []*v1.PersistentVolume{pvNode1aBound}, + cachedPVCs: []*v1.PersistentVolumeClaim{boundPVCNode1a}, }, "binding-succeeds-after-time": { - binding: binding1aBound, - cachedPV: pvNode1a, - cachedPVC: unboundPVC, - delayFunc: func(t *testing.T, testEnv *testEnv, pod *v1.Pod, pv *v1.PersistentVolume, pvc *v1.PersistentVolumeClaim) { + binding: binding1aBound, + cachedPVs: []*v1.PersistentVolume{pvNode1a}, + cachedPVCs: []*v1.PersistentVolumeClaim{unboundPVC}, + delayFunc: func(t *testing.T, testEnv *testEnv, pod *v1.Pod, binding *bindingInfo, pvcs []*v1.PersistentVolumeClaim) { // Update PVC to be fully bound to PV - newPVC := pvc.DeepCopy() + newPVC := binding.pvc.DeepCopy() newPVC.ResourceVersion = "100" - newPVC.Spec.VolumeName = pv.Name + newPVC.Spec.VolumeName = binding.pv.Name metav1.SetMetaDataAnnotation(&newPVC.ObjectMeta, annBindCompleted, "yes") // Update pvc cache, fake client doesn't invoke informers @@ -1326,10 +1355,10 @@ func TestBindPodVolumes(t *testing.T) { }, }, "pod-deleted-after-time": { - binding: binding1aBound, - cachedPV: pvNode1a, - cachedPVC: unboundPVC, - delayFunc: func(t *testing.T, testEnv *testEnv, pod *v1.Pod, pv *v1.PersistentVolume, pvc *v1.PersistentVolumeClaim) { + binding: binding1aBound, + cachedPVs: []*v1.PersistentVolume{pvNode1a}, + cachedPVCs: []*v1.PersistentVolumeClaim{unboundPVC}, + delayFunc: func(t *testing.T, testEnv *testEnv, pod *v1.Pod, binding *bindingInfo, pvcs []*v1.PersistentVolumeClaim) { bindingsCache := testEnv.binder.GetBindingsCache() if bindingsCache == nil { t.Fatalf("Failed to get bindings cache") @@ -1348,22 +1377,22 @@ func TestBindPodVolumes(t *testing.T) { }, "binding-times-out": { binding: binding1aBound, - cachedPV: pvNode1a, - cachedPVC: unboundPVC, + cachedPVs: []*v1.PersistentVolume{pvNode1a}, + cachedPVCs: []*v1.PersistentVolumeClaim{unboundPVC}, shouldFail: true, }, "binding-fails": { binding: binding1bBound, - cachedPV: pvNode1b, - apiPV: pvNode1bBoundHigherVersion, - cachedPVC: unboundPVC2, + cachedPVs: []*v1.PersistentVolume{pvNode1b}, + apiPVs: []*v1.PersistentVolume{pvNode1bBoundHigherVersion}, + cachedPVCs: []*v1.PersistentVolumeClaim{unboundPVC2}, shouldFail: true, }, "check-fails": { - binding: binding1aBound, - cachedPV: pvNode1a, - cachedPVC: unboundPVC, - delayFunc: func(t *testing.T, testEnv *testEnv, pod *v1.Pod, pv *v1.PersistentVolume, pvc *v1.PersistentVolumeClaim) { + binding: binding1aBound, + cachedPVs: []*v1.PersistentVolume{pvNode1a}, + cachedPVCs: []*v1.PersistentVolumeClaim{unboundPVC}, + delayFunc: func(t *testing.T, testEnv *testEnv, pod *v1.Pod, binding *bindingInfo, pvcs []*v1.PersistentVolumeClaim) { // Delete PVC // Update pvc cache, fake client doesn't invoke informers internalBinder, ok := testEnv.binder.(*volumeBinder) @@ -1376,7 +1405,41 @@ func TestBindPodVolumes(t *testing.T) { if !ok { t.Fatalf("Failed to convert to internal PVC cache") } - internalPVCCache.delete(pvc) + internalPVCCache.delete(binding.pvc) + }, + shouldFail: true, + }, + "node-affinity-fails": { + binding: binding1aBound, + cachedPVs: []*v1.PersistentVolume{pvNode1aBound}, + cachedPVCs: []*v1.PersistentVolumeClaim{boundPVCNode1a}, + nodes: []*v1.Node{node1NoLabels}, + shouldFail: true, + }, + "node-affinity-fails-dynamic-provisioning": { + cachedPVs: []*v1.PersistentVolume{pvNode1a, pvNode2}, + cachedPVCs: []*v1.PersistentVolumeClaim{selectedNodePVC}, + provisionedPVCs: []*v1.PersistentVolumeClaim{selectedNodePVC}, + nodes: []*v1.Node{node1, node2}, + delayFunc: func(t *testing.T, testEnv *testEnv, pod *v1.Pod, binding *bindingInfo, pvcs []*v1.PersistentVolumeClaim) { + // Update PVC to be fully bound to a PV with a different node + newPVC := pvcs[0].DeepCopy() + newPVC.ResourceVersion = "100" + newPVC.Spec.VolumeName = pvNode2.Name + metav1.SetMetaDataAnnotation(&newPVC.ObjectMeta, annBindCompleted, "yes") + + // Update PVC cache, fake client doesn't invoke informers + internalBinder, ok := testEnv.binder.(*volumeBinder) + if !ok { + t.Fatalf("Failed to convert to internal binder") + } + + pvcCache := internalBinder.pvcCache + internalPVCCache, ok := pvcCache.(*pvcAssumeCache) + if !ok { + t.Fatalf("Failed to convert to internal PVC cache") + } + internalPVCCache.add(newPVC) }, shouldFail: true, }, @@ -1387,25 +1450,32 @@ func TestBindPodVolumes(t *testing.T) { // Setup pod := makePod(nil) - if scenario.apiPV == nil { - scenario.apiPV = scenario.cachedPV + if scenario.apiPVs == nil { + scenario.apiPVs = scenario.cachedPVs + } + if scenario.nodes == nil { + scenario.nodes = []*v1.Node{node1} + } + if scenario.provisionedPVCs == nil { + scenario.provisionedPVCs = []*v1.PersistentVolumeClaim{} } testEnv := newTestBinder(t) if !scenario.bindingsNil { + bindings := []*bindingInfo{} if scenario.binding != nil { - testEnv.initVolumes([]*v1.PersistentVolume{scenario.cachedPV}, []*v1.PersistentVolume{scenario.apiPV}) - testEnv.initClaims([]*v1.PersistentVolumeClaim{scenario.cachedPVC}, nil) - testEnv.assumeVolumes(t, name, "node1", pod, []*bindingInfo{scenario.binding}, []*v1.PersistentVolumeClaim{}) - } else { - testEnv.assumeVolumes(t, name, "node1", pod, []*bindingInfo{}, []*v1.PersistentVolumeClaim{}) + bindings = []*bindingInfo{scenario.binding} } + testEnv.initNodes(scenario.nodes) + testEnv.initVolumes(scenario.cachedPVs, scenario.apiPVs) + testEnv.initClaims(scenario.cachedPVCs, nil) + testEnv.assumeVolumes(t, name, "node1", pod, bindings, scenario.provisionedPVCs) } if scenario.delayFunc != nil { go func() { time.Sleep(5 * time.Second) klog.V(5).Infof("Running delay function") - scenario.delayFunc(t, testEnv, pod, scenario.binding.pv, scenario.binding.pvc) + scenario.delayFunc(t, testEnv, pod, scenario.binding, scenario.provisionedPVCs) }() } diff --git a/pkg/credentialprovider/aws/BUILD b/pkg/credentialprovider/aws/BUILD index 5161307a712..7a6b52b0b92 100644 --- a/pkg/credentialprovider/aws/BUILD +++ b/pkg/credentialprovider/aws/BUILD @@ -12,6 +12,7 @@ go_library( importpath = "k8s.io/kubernetes/pkg/credentialprovider/aws", deps = [ "//pkg/credentialprovider:go_default_library", + "//pkg/version:go_default_library", "//vendor/github.com/aws/aws-sdk-go/aws:go_default_library", "//vendor/github.com/aws/aws-sdk-go/aws/request:go_default_library", "//vendor/github.com/aws/aws-sdk-go/aws/session:go_default_library", diff --git a/pkg/credentialprovider/aws/aws_credentials.go b/pkg/credentialprovider/aws/aws_credentials.go index 89869e76eaa..05ce549d844 100644 --- a/pkg/credentialprovider/aws/aws_credentials.go +++ b/pkg/credentialprovider/aws/aws_credentials.go @@ -29,6 +29,7 @@ import ( "k8s.io/klog" "k8s.io/kubernetes/pkg/credentialprovider" + "k8s.io/kubernetes/pkg/version" ) const awsChinaRegionPrefix = "cn-" @@ -169,6 +170,10 @@ func (p *ecrProvider) Enabled() bool { Credentials: nil, Region: &p.region, }))} + getter.svc.Handlers.Build.PushFrontNamed(request.NamedHandler{ + Name: "k8s/user-agent", + Fn: request.MakeAddToUserAgentHandler("kubernetes", version.Get().String()), + }) getter.svc.Handlers.Sign.PushFrontNamed(request.NamedHandler{ Name: "k8s/logger", Fn: awsHandlerLogger, diff --git a/pkg/customers.yaml b/pkg/customers.yaml deleted file mode 100644 index 98111a0c856..00000000000 --- a/pkg/customers.yaml +++ /dev/null @@ -1,16 +0,0 @@ -apiVersion: storage.k8s.io/v1 -kind: StorageClass -metadata: - annotations: - name: standard-rdi-hdd-pool -parameters: - adminId: sam - adminSecretName: ceph-sec-admin-rdi - adminSecretNamespace: sam-system - monitors: 10.253.101.170:6789,10.253.101.154:6789,10.253.101.186:6789 - pool: sam - userId: sam - userSecretName: ceph-sec-user-rdi -provisioner: kubernetes.io/rbd -reclaimPolicy: Retain -volumeBindingMode: Immediate diff --git a/pkg/features/kube_features.go b/pkg/features/kube_features.go index f579aa21563..d4dde52cfe5 100644 --- a/pkg/features/kube_features.go +++ b/pkg/features/kube_features.go @@ -120,21 +120,16 @@ const ( // owner: @bsalamat // alpha: v1.8 + // beta: v1.11 // // Add priority to pods. Priority affects scheduling and preemption of pods. PodPriority utilfeature.Feature = "PodPriority" - // owner: @resouer - // alpha: v1.8 - // - // Enable equivalence class cache for scheduler. - EnableEquivalenceClassCache utilfeature.Feature = "EnableEquivalenceClassCache" - // owner: @k82cn // beta: v1.12 // // Taint nodes based on their condition status for 'NetworkUnavailable', - // 'MemoryPressure', 'OutOfDisk' and 'DiskPressure'. + // 'MemoryPressure', 'PIDPressure' and 'DiskPressure'. TaintNodesByCondition utilfeature.Feature = "TaintNodesByCondition" // owner: @jsafrane @@ -153,6 +148,7 @@ const ( // owner: @ConnorDoyle // alpha: v1.8 + // beta: v1.10 // // Alternative container-level CPU affinity policies. CPUManager utilfeature.Feature = "CPUManager" @@ -418,9 +414,8 @@ var defaultKubernetesFeatureGates = map[utilfeature.Feature]utilfeature.FeatureS DebugContainers: {Default: false, PreRelease: utilfeature.Alpha}, PodShareProcessNamespace: {Default: true, PreRelease: utilfeature.Beta}, PodPriority: {Default: true, PreRelease: utilfeature.Beta}, - EnableEquivalenceClassCache: {Default: false, PreRelease: utilfeature.Alpha}, TaintNodesByCondition: {Default: true, PreRelease: utilfeature.Beta}, - MountPropagation: {Default: true, PreRelease: utilfeature.GA}, + MountPropagation: {Default: true, PreRelease: utilfeature.GA, LockToDefault: true}, // remove in 1.14 QOSReserved: {Default: false, PreRelease: utilfeature.Alpha}, ExpandPersistentVolumes: {Default: true, PreRelease: utilfeature.Beta}, ExpandInUsePersistentVolumes: {Default: false, PreRelease: utilfeature.Alpha}, @@ -429,7 +424,7 @@ var defaultKubernetesFeatureGates = map[utilfeature.Feature]utilfeature.FeatureS CPUCFSQuotaPeriod: {Default: false, PreRelease: utilfeature.Alpha}, ServiceNodeExclusion: {Default: false, PreRelease: utilfeature.Alpha}, MountContainers: {Default: false, PreRelease: utilfeature.Alpha}, - VolumeScheduling: {Default: true, PreRelease: utilfeature.GA}, + VolumeScheduling: {Default: true, PreRelease: utilfeature.GA, LockToDefault: true}, // remove in 1.16 CSIPersistentVolume: {Default: true, PreRelease: utilfeature.GA}, CSIDriverRegistry: {Default: false, PreRelease: utilfeature.Alpha}, CSINodeInfo: {Default: false, PreRelease: utilfeature.Alpha}, @@ -455,7 +450,7 @@ var defaultKubernetesFeatureGates = map[utilfeature.Feature]utilfeature.FeatureS ResourceQuotaScopeSelectors: {Default: true, PreRelease: utilfeature.Beta}, CSIBlockVolume: {Default: false, PreRelease: utilfeature.Alpha}, RuntimeClass: {Default: false, PreRelease: utilfeature.Alpha}, - NodeLease: {Default: false, PreRelease: utilfeature.Alpha}, + NodeLease: {Default: true, PreRelease: utilfeature.Beta}, SCTPSupport: {Default: false, PreRelease: utilfeature.Alpha}, VolumeSnapshotDataSource: {Default: false, PreRelease: utilfeature.Alpha}, ProcMountType: {Default: false, PreRelease: utilfeature.Alpha}, diff --git a/pkg/generated/openapi/BUILD b/pkg/generated/openapi/BUILD index add075d92e4..0384ae0ad29 100644 --- a/pkg/generated/openapi/BUILD +++ b/pkg/generated/openapi/BUILD @@ -38,6 +38,7 @@ openapi_library( "k8s.io/api/batch/v1beta1", "k8s.io/api/batch/v2alpha1", "k8s.io/api/certificates/v1beta1", + "k8s.io/api/coordination/v1", "k8s.io/api/coordination/v1beta1", "k8s.io/api/core/v1", "k8s.io/api/events/v1beta1", @@ -82,6 +83,7 @@ openapi_library( "k8s.io/metrics/pkg/apis/external_metrics/v1beta1", "k8s.io/metrics/pkg/apis/metrics/v1alpha1", "k8s.io/metrics/pkg/apis/metrics/v1beta1", + "k8s.io/node-api/pkg/apis/node/v1alpha1", ], ) diff --git a/pkg/kubeapiserver/OWNERS b/pkg/kubeapiserver/OWNERS index 3196f46afd9..e2df84c11a3 100644 --- a/pkg/kubeapiserver/OWNERS +++ b/pkg/kubeapiserver/OWNERS @@ -8,6 +8,7 @@ reviewers: - lavalamp - liggitt - sttts +- cheftako labels: - sig/api-machinery - area/apiserver diff --git a/pkg/kubeapiserver/options/authorization.go b/pkg/kubeapiserver/options/authorization.go index 017aa4bfea3..b708074ce03 100644 --- a/pkg/kubeapiserver/options/authorization.go +++ b/pkg/kubeapiserver/options/authorization.go @@ -94,7 +94,7 @@ func (s *BuiltInAuthorizationOptions) AddFlags(fs *pflag.FlagSet) { strings.Join(authzmodes.AuthorizationModeChoices, ",")+".") fs.StringVar(&s.PolicyFile, "authorization-policy-file", s.PolicyFile, ""+ - "File with authorization policy in csv format, used with --authorization-mode=ABAC, on the secure port.") + "File with authorization policy in json line by line format, used with --authorization-mode=ABAC, on the secure port.") fs.StringVar(&s.WebhookConfigFile, "authorization-webhook-config-file", s.WebhookConfigFile, ""+ "File with webhook configuration in kubeconfig format, used with --authorization-mode=Webhook. "+ diff --git a/pkg/kubectl/.import-restrictions b/pkg/kubectl/.import-restrictions index 6cc204640d3..72be55c1893 100644 --- a/pkg/kubectl/.import-restrictions +++ b/pkg/kubectl/.import-restrictions @@ -121,7 +121,7 @@ "k8s.io/kubernetes/pkg/scheduler/algorithm/predicates", "k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/util", "k8s.io/kubernetes/pkg/scheduler/api", - "k8s.io/kubernetes/pkg/scheduler/cache", + "k8s.io/kubernetes/pkg/scheduler/nodeinfo", "k8s.io/kubernetes/pkg/scheduler/internal/cache", "k8s.io/kubernetes/pkg/scheduler/util", "k8s.io/kubernetes/pkg/scheduler/volumebinder", diff --git a/pkg/kubectl/cmd/annotate/annotate.go b/pkg/kubectl/cmd/annotate/annotate.go index 56fe5603fb4..dedc9e77ec9 100644 --- a/pkg/kubectl/cmd/annotate/annotate.go +++ b/pkg/kubectl/cmd/annotate/annotate.go @@ -109,6 +109,7 @@ var ( kubectl annotate pods foo description-`)) ) +// NewAnnotateOptions creates the options for annotate func NewAnnotateOptions(ioStreams genericclioptions.IOStreams) *AnnotateOptions { return &AnnotateOptions{ PrintFlags: genericclioptions.NewPrintFlags("annotated").WithTypeSetter(scheme.Scheme), @@ -119,6 +120,7 @@ func NewAnnotateOptions(ioStreams genericclioptions.IOStreams) *AnnotateOptions } } +// NewCmdAnnotate creates the `annotate` command func NewCmdAnnotate(parent string, f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command { o := NewAnnotateOptions(ioStreams) @@ -126,7 +128,7 @@ func NewCmdAnnotate(parent string, f cmdutil.Factory, ioStreams genericclioption Use: "annotate [--overwrite] (-f FILENAME | TYPE NAME) KEY_1=VAL_1 ... KEY_N=VAL_N [--resource-version=version]", DisableFlagsInUseLine: true, Short: i18n.T("Update the annotations on a resource"), - Long: annotateLong + "\n\n" + cmdutil.SuggestApiResources(parent), + Long: annotateLong + "\n\n" + cmdutil.SuggestAPIResources(parent), Example: annotateExample, Run: func(cmd *cobra.Command, args []string) { cmdutil.CheckErr(o.Complete(f, cmd, args)) diff --git a/pkg/kubectl/cmd/apiresources/apiresources.go b/pkg/kubectl/cmd/apiresources/apiresources.go index 2e3d90bf239..54da3c981b5 100644 --- a/pkg/kubectl/cmd/apiresources/apiresources.go +++ b/pkg/kubectl/cmd/apiresources/apiresources.go @@ -51,9 +51,9 @@ var ( kubectl api-resources --api-group=extensions`) ) -// ApiResourcesOptions is the start of the data required to perform the operation. As new fields are added, add them here instead of -// referencing the cmd.Flags() -type ApiResourcesOptions struct { +// APIResourceOptions is the start of the data required to perform the operation. +// As new fields are added, add them here instead of referencing the cmd.Flags() +type APIResourceOptions struct { Output string APIGroup string Namespaced bool @@ -70,8 +70,9 @@ type groupResource struct { APIResource metav1.APIResource } -func NewAPIResourceOptions(ioStreams genericclioptions.IOStreams) *ApiResourcesOptions { - return &ApiResourcesOptions{ +// NewAPIResourceOptions creates the options for APIResource +func NewAPIResourceOptions(ioStreams genericclioptions.IOStreams) *APIResourceOptions { + return &APIResourceOptions{ IOStreams: ioStreams, Namespaced: true, } @@ -89,7 +90,7 @@ func NewCmdAPIResources(f cmdutil.Factory, ioStreams genericclioptions.IOStreams Run: func(cmd *cobra.Command, args []string) { cmdutil.CheckErr(o.Complete(cmd, args)) cmdutil.CheckErr(o.Validate()) - cmdutil.CheckErr(o.RunApiResources(cmd, f)) + cmdutil.CheckErr(o.RunAPIResources(cmd, f)) }, } @@ -103,7 +104,8 @@ func NewCmdAPIResources(f cmdutil.Factory, ioStreams genericclioptions.IOStreams return cmd } -func (o *ApiResourcesOptions) Validate() error { +// Validate checks to the APIResourceOptions to see if there is sufficient information run the command +func (o *APIResourceOptions) Validate() error { supportedOutputTypes := sets.NewString("", "wide", "name") if !supportedOutputTypes.Has(o.Output) { return fmt.Errorf("--output %v is not available", o.Output) @@ -111,14 +113,16 @@ func (o *ApiResourcesOptions) Validate() error { return nil } -func (o *ApiResourcesOptions) Complete(cmd *cobra.Command, args []string) error { +// Complete adapts from the command line args and validates them +func (o *APIResourceOptions) Complete(cmd *cobra.Command, args []string) error { if len(args) != 0 { return cmdutil.UsageErrorf(cmd, "unexpected arguments: %v", args) } return nil } -func (o *ApiResourcesOptions) RunApiResources(cmd *cobra.Command, f cmdutil.Factory) error { +// RunAPIResources does the work +func (o *APIResourceOptions) RunAPIResources(cmd *cobra.Command, f cmdutil.Factory) error { w := printers.GetNewTabWriter(o.Out) defer w.Flush() diff --git a/pkg/kubectl/cmd/apiresources/apiversions.go b/pkg/kubectl/cmd/apiresources/apiversions.go index 738aa51b6b4..e12897c444c 100644 --- a/pkg/kubectl/cmd/apiresources/apiversions.go +++ b/pkg/kubectl/cmd/apiresources/apiversions.go @@ -36,21 +36,23 @@ var ( kubectl api-versions`)) ) -type ApiVersionsOptions struct { +// APIVersionsOptions have the data required for API versions +type APIVersionsOptions struct { discoveryClient discovery.CachedDiscoveryInterface genericclioptions.IOStreams } -func NewApiVersionsOptions(ioStreams genericclioptions.IOStreams) *ApiVersionsOptions { - return &ApiVersionsOptions{ +// NewAPIVersionsOptions creates the options for APIVersions +func NewAPIVersionsOptions(ioStreams genericclioptions.IOStreams) *APIVersionsOptions { + return &APIVersionsOptions{ IOStreams: ioStreams, } } // NewCmdAPIVersions creates the `api-versions` command func NewCmdAPIVersions(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command { - o := NewApiVersionsOptions(ioStreams) + o := NewAPIVersionsOptions(ioStreams) cmd := &cobra.Command{ Use: "api-versions", Short: "Print the supported API versions on the server, in the form of \"group/version\"", @@ -58,13 +60,14 @@ func NewCmdAPIVersions(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) Example: apiversionsExample, Run: func(cmd *cobra.Command, args []string) { cmdutil.CheckErr(o.Complete(f, cmd, args)) - cmdutil.CheckErr(o.RunApiVersions()) + cmdutil.CheckErr(o.RunAPIVersions()) }, } return cmd } -func (o *ApiVersionsOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error { +// Complete adapts from the command line args and factory to the data required +func (o *APIVersionsOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error { if len(args) != 0 { return cmdutil.UsageErrorf(cmd, "unexpected arguments: %v", args) } @@ -76,13 +79,14 @@ func (o *ApiVersionsOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, arg return nil } -func (o *ApiVersionsOptions) RunApiVersions() error { +// RunAPIVersions does the work +func (o *APIVersionsOptions) RunAPIVersions() error { // Always request fresh data from the server o.discoveryClient.Invalidate() groupList, err := o.discoveryClient.ServerGroups() if err != nil { - return fmt.Errorf("Couldn't get available api versions from server: %v\n", err) + return fmt.Errorf("couldn't get available api versions from server: %v", err) } apiVersions := metav1.ExtractGroupVersions(groupList) sort.Strings(apiVersions) diff --git a/pkg/kubectl/cmd/apply/BUILD b/pkg/kubectl/cmd/apply/BUILD index 8f954982581..89f2da19261 100644 --- a/pkg/kubectl/cmd/apply/BUILD +++ b/pkg/kubectl/cmd/apply/BUILD @@ -59,8 +59,8 @@ go_test( "//pkg/kubectl/cmd/util:go_default_library", "//pkg/kubectl/cmd/util/openapi:go_default_library", "//pkg/kubectl/scheme:go_default_library", + "//staging/src/k8s.io/api/apps/v1:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library", - "//staging/src/k8s.io/api/extensions/v1beta1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/meta:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library", diff --git a/pkg/kubectl/cmd/apply/apply.go b/pkg/kubectl/cmd/apply/apply.go index 348ab683651..41e49237816 100644 --- a/pkg/kubectl/cmd/apply/apply.go +++ b/pkg/kubectl/cmd/apply/apply.go @@ -76,7 +76,7 @@ type ApplyOptions struct { cmdBaseName string All bool Overwrite bool - OpenApiPatch bool + OpenAPIPatch bool PruneWhitelist []string ShouldIncludeUninitialized bool @@ -96,7 +96,7 @@ type ApplyOptions struct { const ( // maxPatchRetry is the maximum number of conflicts retry for during a patch operation before returning failure maxPatchRetry = 5 - // backOffPeriod is the period to back off when apply patch resutls in error. + // backOffPeriod is the period to back off when apply patch results in error. backOffPeriod = 1 * time.Second // how many times we can retry before back off triesBeforeBackOff = 1 @@ -136,7 +136,7 @@ func NewApplyOptions(ioStreams genericclioptions.IOStreams) *ApplyOptions { PrintFlags: genericclioptions.NewPrintFlags("created").WithTypeSetter(scheme.Scheme), Overwrite: true, - OpenApiPatch: true, + OpenAPIPatch: true, Recorder: genericclioptions.NoopRecorder{}, @@ -144,6 +144,7 @@ func NewApplyOptions(ioStreams genericclioptions.IOStreams) *ApplyOptions { } } +// NewCmdApply creates the `apply` command func NewCmdApply(baseName string, f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command { o := NewApplyOptions(ioStreams) @@ -177,7 +178,7 @@ func NewCmdApply(baseName string, f cmdutil.Factory, ioStreams genericclioptions cmd.Flags().StringVarP(&o.Selector, "selector", "l", o.Selector, "Selector (label query) to filter on, supports '=', '==', and '!='.(e.g. -l key1=value1,key2=value2)") cmd.Flags().BoolVar(&o.All, "all", o.All, "Select all resources in the namespace of the specified resource types.") cmd.Flags().StringArrayVar(&o.PruneWhitelist, "prune-whitelist", o.PruneWhitelist, "Overwrite the default whitelist with for --prune") - cmd.Flags().BoolVar(&o.OpenApiPatch, "openapi-patch", o.OpenApiPatch, "If true, use openapi to calculate diff when the openapi presents and the resource can be found in the openapi spec. Otherwise, fall back to use baked-in types.") + cmd.Flags().BoolVar(&o.OpenAPIPatch, "openapi-patch", o.OpenAPIPatch, "If true, use openapi to calculate diff when the openapi presents and the resource can be found in the openapi spec. Otherwise, fall back to use baked-in types.") cmd.Flags().BoolVar(&o.ServerDryRun, "server-dry-run", o.ServerDryRun, "If true, request will be sent to server with dry-run flag, which means the modifications won't be persisted. This is an alpha feature and flag.") cmdutil.AddDryRunFlag(cmd) cmdutil.AddIncludeUninitializedFlag(cmd) @@ -272,7 +273,7 @@ func validatePruneAll(prune, all bool, selector string) error { return fmt.Errorf("cannot set --all and --selector at the same time") } if prune && !all && selector == "" { - return fmt.Errorf("all resources selected for prune without explicitly passing --all. To prune all resources, pass the --all flag. If you did not mean to prune all resources, specify a label selector.") + return fmt.Errorf("all resources selected for prune without explicitly passing --all. To prune all resources, pass the --all flag. If you did not mean to prune all resources, specify a label selector") } return nil } @@ -320,7 +321,7 @@ func isIncompatibleServerError(err error) bool { func (o *ApplyOptions) Run() error { var openapiSchema openapi.Resources - if o.OpenApiPatch { + if o.OpenAPIPatch { openapiSchema = o.OpenAPISchema } @@ -367,6 +368,13 @@ func (o *ApplyOptions) Run() error { return err } + // If server-dry-run is requested but the type doesn't support it, fail right away. + if o.ServerDryRun { + if err := dryRunVerifier.HasSupport(info.Mapping.GroupVersionKind); err != nil { + return err + } + } + if info.Namespaced() { visitedNamespaces.Insert(info.Namespace) } @@ -434,12 +442,6 @@ func (o *ApplyOptions) Run() error { if !errors.IsNotFound(err) { return cmdutil.AddSourceToErr(fmt.Sprintf("retrieving current configuration of:\n%s\nfrom server for:", info.String()), info.Source, err) } - // If server-dry-run is requested but the type doesn't support it, fail right away. - if o.ServerDryRun { - if err := dryRunVerifier.HasSupport(info.Mapping.GroupVersionKind); err != nil { - return err - } - } // Create the resource if it doesn't exist // First, update the annotation used by kubectl apply @@ -642,12 +644,11 @@ func getRESTMappings(mapper meta.RESTMapper, pruneResources *[]pruneResource) (n {"", "v1", "Service", true}, {"batch", "v1", "Job", true}, {"batch", "v1beta1", "CronJob", true}, - {"extensions", "v1beta1", "DaemonSet", true}, - {"extensions", "v1beta1", "Deployment", true}, {"extensions", "v1beta1", "Ingress", true}, - {"extensions", "v1beta1", "ReplicaSet", true}, - {"apps", "v1beta1", "StatefulSet", true}, - {"apps", "v1beta1", "Deployment", true}, + {"apps", "v1", "DaemonSet", true}, + {"apps", "v1", "Deployment", true}, + {"apps", "v1", "ReplicaSet", true}, + {"apps", "v1", "StatefulSet", true}, } } @@ -969,7 +970,7 @@ func (p *Patcher) deleteAndCreate(original runtime.Object, modified []byte, name // but still propagate and advertise error to user recreated, recreateErr := p.Helper.Create(namespace, true, original, &options) if recreateErr != nil { - err = fmt.Errorf("An error occurred force-replacing the existing object with the newly provided one:\n\n%v.\n\nAdditionally, an error occurred attempting to restore the original object:\n\n%v\n", err, recreateErr) + err = fmt.Errorf("An error occurred force-replacing the existing object with the newly provided one:\n\n%v.\n\nAdditionally, an error occurred attempting to restore the original object:\n\n%v", err, recreateErr) } else { createdObject = recreated } diff --git a/pkg/kubectl/cmd/apply/apply_set_last_applied.go b/pkg/kubectl/cmd/apply/apply_set_last_applied.go index 23699f407fc..722f9efedfe 100644 --- a/pkg/kubectl/cmd/apply/apply_set_last_applied.go +++ b/pkg/kubectl/cmd/apply/apply_set_last_applied.go @@ -162,9 +162,8 @@ func (o *SetLastAppliedOptions) Validate() error { if err := info.Get(); err != nil { if errors.IsNotFound(err) { return err - } else { - return cmdutil.AddSourceToErr(fmt.Sprintf("retrieving current configuration of:\n%s\nfrom server for:", info.String()), info.Source, err) } + return cmdutil.AddSourceToErr(fmt.Sprintf("retrieving current configuration of:\n%s\nfrom server for:", info.String()), info.Source, err) } originalBuf, err := kubectl.GetOriginalConfiguration(info.Object) if err != nil { diff --git a/pkg/kubectl/cmd/apply/apply_test.go b/pkg/kubectl/cmd/apply/apply_test.go index 3bd088fae96..36fcad29f59 100644 --- a/pkg/kubectl/cmd/apply/apply_test.go +++ b/pkg/kubectl/cmd/apply/apply_test.go @@ -32,8 +32,8 @@ import ( "github.com/googleapis/gnostic/OpenAPIv2" "github.com/spf13/cobra" + appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" - extensionsv1beta1 "k8s.io/api/extensions/v1beta1" kubeerr "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" @@ -377,7 +377,7 @@ func TestRunApplyViewLastApplied(t *testing.T) { name: "view resource/name invalid format", filePath: "", outputFormat: "wide", - expectedErr: "error: Unexpected -o output mode: wide, the flag 'output' must be one of yaml|json\nSee 'view-last-applied -h' for help and examples.", + expectedErr: "error: Unexpected -o output mode: wide, the flag 'output' must be one of yaml|json\nSee 'view-last-applied -h' for help and examples", expectedOut: "", selector: "", args: []string{"replicationcontroller", "test-rc"}, @@ -648,7 +648,7 @@ func TestApplyRetry(t *testing.T) { case p == pathRC && m == "PATCH": if firstPatch { firstPatch = false - statusErr := kubeerr.NewConflict(schema.GroupResource{Group: "", Resource: "rc"}, "test-rc", fmt.Errorf("the object has been modified. Please apply at first.")) + statusErr := kubeerr.NewConflict(schema.GroupResource{Group: "", Resource: "rc"}, "test-rc", fmt.Errorf("the object has been modified. Please apply at first")) bodyBytes, _ := json.Marshal(statusErr) bodyErr := ioutil.NopCloser(bytes.NewReader(bodyBytes)) return &http.Response{StatusCode: http.StatusConflict, Header: cmdtesting.DefaultHeader(), Body: bodyErr}, nil @@ -876,7 +876,7 @@ const ( func readDeploymentFromFile(t *testing.T, file string) []byte { raw := readBytesFromFile(t, file) - obj := &extensionsv1beta1.Deployment{} + obj := &appsv1.Deployment{} if err := runtime.DecodeInto(codec, raw, obj); err != nil { t.Fatal(err) } @@ -948,7 +948,7 @@ func TestApplyNULLPreservation(t *testing.T) { cmd.Run(cmd, []string{}) - expected := "deployment.extensions/" + deploymentName + "\n" + expected := "deployment.apps/" + deploymentName + "\n" if buf.String() != expected { t.Fatalf("unexpected output: %s\nexpected: %s", buf.String(), expected) } @@ -1280,7 +1280,7 @@ func TestForceApply(t *testing.T) { case strings.HasSuffix(p, pathRC) && m == "PATCH": counts["patch"]++ if counts["patch"] <= 6 { - statusErr := kubeerr.NewConflict(schema.GroupResource{Group: "", Resource: "rc"}, "test-rc", fmt.Errorf("the object has been modified. Please apply at first.")) + statusErr := kubeerr.NewConflict(schema.GroupResource{Group: "", Resource: "rc"}, "test-rc", fmt.Errorf("the object has been modified. Please apply at first")) bodyBytes, _ := json.Marshal(statusErr) bodyErr := ioutil.NopCloser(bytes.NewReader(bodyBytes)) return &http.Response{StatusCode: http.StatusConflict, Header: cmdtesting.DefaultHeader(), Body: bodyErr}, nil diff --git a/pkg/kubectl/cmd/auth/auth.go b/pkg/kubectl/cmd/auth/auth.go index 3f1e5943d73..d53b30af6ff 100644 --- a/pkg/kubectl/cmd/auth/auth.go +++ b/pkg/kubectl/cmd/auth/auth.go @@ -23,6 +23,7 @@ import ( cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" ) +// NewCmdAuth returns an initialized Command instance for 'auth' sub command func NewCmdAuth(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command { // Parent command to which all subcommands are added. cmds := &cobra.Command{ diff --git a/pkg/kubectl/cmd/auth/cani.go b/pkg/kubectl/cmd/auth/cani.go index 31ce080dd1a..5b20a240a50 100644 --- a/pkg/kubectl/cmd/auth/cani.go +++ b/pkg/kubectl/cmd/auth/cani.go @@ -80,6 +80,7 @@ var ( kubectl auth can-i get /logs/`) ) +// NewCmdCanI returns an initialized Command for 'auth can-i' sub command func NewCmdCanI(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command { o := &CanIOptions{ IOStreams: streams, @@ -106,12 +107,13 @@ func NewCmdCanI(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.C }, } - cmd.Flags().BoolVar(&o.AllNamespaces, "all-namespaces", o.AllNamespaces, "If true, check the specified action in all namespaces.") + cmd.Flags().BoolVarP(&o.AllNamespaces, "all-namespaces", "A", o.AllNamespaces, "If true, check the specified action in all namespaces.") cmd.Flags().BoolVarP(&o.Quiet, "quiet", "q", o.Quiet, "If true, suppress output and just return the exit code.") cmd.Flags().StringVar(&o.Subresource, "subresource", o.Subresource, "SubResource such as pod/log or deployment/scale") return cmd } +// Complete completes all the required options func (o *CanIOptions) Complete(f cmdutil.Factory, args []string) error { if o.Quiet { o.Out = ioutil.Discard @@ -155,6 +157,7 @@ func (o *CanIOptions) Complete(f cmdutil.Factory, args []string) error { return nil } +// Validate makes sure provided values for CanIOptions are valid func (o *CanIOptions) Validate() error { if o.NonResourceURL != "" { if o.Subresource != "" { @@ -167,6 +170,7 @@ func (o *CanIOptions) Validate() error { return nil } +// RunAccessCheck checks if user has access to a certain resource or non resource URL func (o *CanIOptions) RunAccessCheck() (bool, error) { var sar *authorizationv1.SelfSubjectAccessReview if o.NonResourceURL == "" { diff --git a/pkg/kubectl/cmd/auth/reconcile.go b/pkg/kubectl/cmd/auth/reconcile.go index e2dafca743d..dfa84875cca 100644 --- a/pkg/kubectl/cmd/auth/reconcile.go +++ b/pkg/kubectl/cmd/auth/reconcile.go @@ -66,6 +66,7 @@ var ( kubectl auth reconcile -f my-rbac-rules.yaml`) ) +// NewReconcileOptions returns a new ReconcileOptions instance func NewReconcileOptions(ioStreams genericclioptions.IOStreams) *ReconcileOptions { return &ReconcileOptions{ FilenameOptions: &resource.FilenameOptions{}, @@ -74,6 +75,7 @@ func NewReconcileOptions(ioStreams genericclioptions.IOStreams) *ReconcileOption } } +// NewCmdReconcile holds the options for 'auth reconcile' sub command func NewCmdReconcile(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command { o := NewReconcileOptions(streams) @@ -101,6 +103,7 @@ func NewCmdReconcile(f cmdutil.Factory, streams genericclioptions.IOStreams) *co return cmd } +// Complete completes all the required options func (o *ReconcileOptions) Complete(cmd *cobra.Command, f cmdutil.Factory, args []string) error { if len(args) > 0 { return errors.New("no arguments are allowed") @@ -149,6 +152,7 @@ func (o *ReconcileOptions) Complete(cmd *cobra.Command, f cmdutil.Factory, args return nil } +// Validate makes sure provided values for ReconcileOptions are valid func (o *ReconcileOptions) Validate() error { if o.Visitor == nil { return errors.New("ReconcileOptions.Visitor must be set") @@ -171,6 +175,7 @@ func (o *ReconcileOptions) Validate() error { return nil } +// RunReconcile performs the execution func (o *ReconcileOptions) RunReconcile() error { return o.Visitor.Visit(func(info *resource.Info, err error) error { if err != nil { diff --git a/pkg/kubectl/cmd/autoscale/autoscale.go b/pkg/kubectl/cmd/autoscale/autoscale.go index 9f59e7bbd82..d26a52b5592 100644 --- a/pkg/kubectl/cmd/autoscale/autoscale.go +++ b/pkg/kubectl/cmd/autoscale/autoscale.go @@ -66,7 +66,7 @@ type AutoscaleOptions struct { Generator string Min int32 Max int32 - CpuPercent int32 + CPUPercent int32 createAnnotation bool args []string @@ -120,7 +120,7 @@ func NewCmdAutoscale(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) * cmd.Flags().Int32Var(&o.Min, "min", -1, "The lower limit for the number of pods that can be set by the autoscaler. If it's not specified or negative, the server will apply a default value.") cmd.Flags().Int32Var(&o.Max, "max", -1, "The upper limit for the number of pods that can be set by the autoscaler. Required.") cmd.MarkFlagRequired("max") - cmd.Flags().Int32Var(&o.CpuPercent, "cpu-percent", -1, fmt.Sprintf("The target average CPU utilization (represented as a percent of requested CPU) over all the pods. If it's not specified or negative, a default autoscaling policy will be used.")) + cmd.Flags().Int32Var(&o.CPUPercent, "cpu-percent", -1, fmt.Sprintf("The target average CPU utilization (represented as a percent of requested CPU) over all the pods. If it's not specified or negative, a default autoscaling policy will be used.")) cmd.Flags().StringVar(&o.Name, "name", "", i18n.T("The name for the newly created object. If not specified, the name of the input resource will be used.")) cmdutil.AddDryRunFlag(cmd) cmdutil.AddFilenameOptionFlags(cmd, o.FilenameOptions, "identifying the resource to autoscale.") @@ -156,7 +156,7 @@ func (o *AutoscaleOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args Name: name, MinReplicas: o.Min, MaxReplicas: o.Max, - CPUPercent: o.CpuPercent, + CPUPercent: o.CPUPercent, ScaleRefName: name, ScaleRefKind: mapping.GroupVersionKind.Kind, ScaleRefAPIVersion: mapping.GroupVersionKind.GroupVersion().String(), diff --git a/pkg/kubectl/cmd/certificates/certificates.go b/pkg/kubectl/cmd/certificates/certificates.go index fabc8d60da7..fb537f2dd68 100644 --- a/pkg/kubectl/cmd/certificates/certificates.go +++ b/pkg/kubectl/cmd/certificates/certificates.go @@ -68,6 +68,14 @@ type CertificateOptions struct { genericclioptions.IOStreams } +// NewCertificateOptions creates the options for certificate +func NewCertificateOptions(ioStreams genericclioptions.IOStreams) *CertificateOptions { + return &CertificateOptions{ + PrintFlags: genericclioptions.NewPrintFlags("approved").WithTypeSetter(scheme.Scheme), + IOStreams: ioStreams, + } +} + func (o *CertificateOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error { o.csrNames = args o.outputStyle = cmdutil.GetFlagString(cmd, "output") @@ -103,10 +111,8 @@ func (o *CertificateOptions) Validate() error { } func NewCmdCertificateApprove(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command { - options := CertificateOptions{ - PrintFlags: genericclioptions.NewPrintFlags("approved").WithTypeSetter(scheme.Scheme), - IOStreams: ioStreams, - } + o := NewCertificateOptions(ioStreams) + cmd := &cobra.Command{ Use: "approve (-f FILENAME | NAME)", DisableFlagsInUseLine: true, @@ -124,16 +130,16 @@ func NewCmdCertificateApprove(f cmdutil.Factory, ioStreams genericclioptions.IOS signed certificate can do. `), Run: func(cmd *cobra.Command, args []string) { - cmdutil.CheckErr(options.Complete(f, cmd, args)) - cmdutil.CheckErr(options.Validate()) - cmdutil.CheckErr(options.RunCertificateApprove(cmdutil.GetFlagBool(cmd, "force"))) + cmdutil.CheckErr(o.Complete(f, cmd, args)) + cmdutil.CheckErr(o.Validate()) + cmdutil.CheckErr(o.RunCertificateApprove(cmdutil.GetFlagBool(cmd, "force"))) }, } - options.PrintFlags.AddFlags(cmd) + o.PrintFlags.AddFlags(cmd) cmd.Flags().Bool("force", false, "Update the CSR even if it is already approved.") - cmdutil.AddFilenameOptionFlags(cmd, &options.FilenameOptions, "identifying the resource to update") + cmdutil.AddFilenameOptionFlags(cmd, &o.FilenameOptions, "identifying the resource to update") return cmd } @@ -160,10 +166,8 @@ func (o *CertificateOptions) RunCertificateApprove(force bool) error { } func NewCmdCertificateDeny(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command { - options := CertificateOptions{ - PrintFlags: genericclioptions.NewPrintFlags("denied").WithTypeSetter(scheme.Scheme), - IOStreams: ioStreams, - } + o := NewCertificateOptions(ioStreams) + cmd := &cobra.Command{ Use: "deny (-f FILENAME | NAME)", DisableFlagsInUseLine: true, @@ -176,16 +180,16 @@ func NewCmdCertificateDeny(f cmdutil.Factory, ioStreams genericclioptions.IOStre not to issue a certificate to the requestor. `), Run: func(cmd *cobra.Command, args []string) { - cmdutil.CheckErr(options.Complete(f, cmd, args)) - cmdutil.CheckErr(options.Validate()) - cmdutil.CheckErr(options.RunCertificateDeny(cmdutil.GetFlagBool(cmd, "force"))) + cmdutil.CheckErr(o.Complete(f, cmd, args)) + cmdutil.CheckErr(o.Validate()) + cmdutil.CheckErr(o.RunCertificateDeny(cmdutil.GetFlagBool(cmd, "force"))) }, } - options.PrintFlags.AddFlags(cmd) + o.PrintFlags.AddFlags(cmd) cmd.Flags().Bool("force", false, "Update the CSR even if it is already denied.") - cmdutil.AddFilenameOptionFlags(cmd, &options.FilenameOptions, "identifying the resource to update") + cmdutil.AddFilenameOptionFlags(cmd, &o.FilenameOptions, "identifying the resource to update") return cmd } @@ -211,13 +215,13 @@ func (o *CertificateOptions) RunCertificateDeny(force bool) error { }) } -func (options *CertificateOptions) modifyCertificateCondition(builder *resource.Builder, clientSet certificatesv1beta1client.CertificatesV1beta1Interface, force bool, modify func(csr *certificatesv1beta1.CertificateSigningRequest) (*certificatesv1beta1.CertificateSigningRequest, bool)) error { +func (o *CertificateOptions) modifyCertificateCondition(builder *resource.Builder, clientSet certificatesv1beta1client.CertificatesV1beta1Interface, force bool, modify func(csr *certificatesv1beta1.CertificateSigningRequest) (*certificatesv1beta1.CertificateSigningRequest, bool)) error { var found int r := builder. WithScheme(scheme.Scheme, scheme.Scheme.PrioritizedVersionsAllGroups()...). ContinueOnError(). - FilenameParam(false, &options.FilenameOptions). - ResourceNames("certificatesigningrequest", options.csrNames...). + FilenameParam(false, &o.FilenameOptions). + ResourceNames("certificatesigningrequest", o.csrNames...). RequireObject(true). Flatten(). Latest(). @@ -245,10 +249,10 @@ func (options *CertificateOptions) modifyCertificateCondition(builder *resource. } found++ - return options.PrintObj(info.Object, options.Out) + return o.PrintObj(info.Object, o.Out) }) if found == 0 { - fmt.Fprintf(options.Out, "No resources found\n") + fmt.Fprintf(o.Out, "No resources found\n") } return err } diff --git a/pkg/kubectl/cmd/clusterinfo/clusterinfo_dump.go b/pkg/kubectl/cmd/clusterinfo/clusterinfo_dump.go index c79e2a972f8..068baede499 100644 --- a/pkg/kubectl/cmd/clusterinfo/clusterinfo_dump.go +++ b/pkg/kubectl/cmd/clusterinfo/clusterinfo_dump.go @@ -61,7 +61,6 @@ type ClusterInfoDumpOptions struct { genericclioptions.IOStreams } -// NewCmdCreateSecret groups subcommands to create various types of secrets func NewCmdClusterInfoDump(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command { o := &ClusterInfoDumpOptions{ PrintFlags: genericclioptions.NewPrintFlags("").WithTypeSetter(scheme.Scheme).WithDefaultOutput("json"), @@ -84,7 +83,7 @@ func NewCmdClusterInfoDump(f cmdutil.Factory, ioStreams genericclioptions.IOStre cmd.Flags().StringVar(&o.OutputDir, "output-directory", o.OutputDir, i18n.T("Where to output the files. If empty or '-' uses stdout, otherwise creates a directory hierarchy in that directory")) cmd.Flags().StringSliceVar(&o.Namespaces, "namespaces", o.Namespaces, "A comma separated list of namespaces to dump.") - cmd.Flags().BoolVar(&o.AllNamespaces, "all-namespaces", o.AllNamespaces, "If true, dump all namespaces. If true, --namespaces is ignored.") + cmd.Flags().BoolVarP(&o.AllNamespaces, "all-namespaces", "A", o.AllNamespaces, "If true, dump all namespaces. If true, --namespaces is ignored.") cmdutil.AddPodRunningTimeoutFlag(cmd, defaultPodLogsTimeout) return cmd } diff --git a/pkg/kubectl/cmd/completion/completion.go b/pkg/kubectl/cmd/completion/completion.go index cd8fd36e0f1..855c8306ea6 100644 --- a/pkg/kubectl/cmd/completion/completion.go +++ b/pkg/kubectl/cmd/completion/completion.go @@ -44,7 +44,7 @@ const defaultBoilerPlate = ` ` var ( - completion_long = templates.LongDesc(i18n.T(` + completionLong = templates.LongDesc(i18n.T(` Output shell completion code for the specified shell (bash or zsh). The shell code must be evaluated to provide interactive completion of kubectl commands. This can be done by sourcing it from @@ -55,7 +55,7 @@ var ( Note for zsh users: [1] zsh completions are only supported in versions of zsh >= 5.2`)) - completion_example = templates.Examples(i18n.T(` + completionExample = templates.Examples(i18n.T(` # Installing bash completion on macOS using homebrew ## If running Bash 3.2 included with macOS brew install bash-completion @@ -86,7 +86,7 @@ var ( ) var ( - completion_shells = map[string]func(out io.Writer, boilerPlate string, cmd *cobra.Command) error{ + completionShells = map[string]func(out io.Writer, boilerPlate string, cmd *cobra.Command) error{ "bash": runCompletionBash, "zsh": runCompletionZsh, } @@ -94,7 +94,7 @@ var ( func NewCmdCompletion(out io.Writer, boilerPlate string) *cobra.Command { shells := []string{} - for s := range completion_shells { + for s := range completionShells { shells = append(shells, s) } @@ -102,8 +102,8 @@ func NewCmdCompletion(out io.Writer, boilerPlate string) *cobra.Command { Use: "completion SHELL", DisableFlagsInUseLine: true, Short: i18n.T("Output shell completion code for the specified shell (bash or zsh)"), - Long: completion_long, - Example: completion_example, + Long: completionLong, + Example: completionExample, Run: func(cmd *cobra.Command, args []string) { err := RunCompletion(out, boilerPlate, cmd, args) cmdutil.CheckErr(err) @@ -121,7 +121,7 @@ func RunCompletion(out io.Writer, boilerPlate string, cmd *cobra.Command, args [ if len(args) > 1 { return cmdutil.UsageErrorf(cmd, "Too many arguments. Expected only the shell type.") } - run, found := completion_shells[args[0]] + run, found := completionShells[args[0]] if !found { return cmdutil.UsageErrorf(cmd, "Unsupported shell type %q.", args[0]) } @@ -141,9 +141,9 @@ func runCompletionBash(out io.Writer, boilerPlate string, kubectl *cobra.Command } func runCompletionZsh(out io.Writer, boilerPlate string, kubectl *cobra.Command) error { - zsh_head := "#compdef kubectl\n" + zshHead := "#compdef kubectl\n" - out.Write([]byte(zsh_head)) + out.Write([]byte(zshHead)) if len(boilerPlate) == 0 { boilerPlate = defaultBoilerPlate @@ -152,7 +152,7 @@ func runCompletionZsh(out io.Writer, boilerPlate string, kubectl *cobra.Command) return err } - zsh_initialization := ` + zshInitialization := ` __kubectl_bash_source() { alias shopt=':' alias _expand=_bash_expand @@ -294,19 +294,19 @@ __kubectl_convert_bash_to_zsh() { -e "s/\\\$(type${RWORD}/\$(__kubectl_type/g" \ <<'BASH_COMPLETION_EOF' ` - out.Write([]byte(zsh_initialization)) + out.Write([]byte(zshInitialization)) buf := new(bytes.Buffer) kubectl.GenBashCompletion(buf) out.Write(buf.Bytes()) - zsh_tail := ` + zshTail := ` BASH_COMPLETION_EOF } __kubectl_bash_source <(__kubectl_convert_bash_to_zsh) _complete kubectl 2>/dev/null ` - out.Write([]byte(zsh_tail)) + out.Write([]byte(zshTail)) return nil } diff --git a/pkg/kubectl/cmd/config/BUILD b/pkg/kubectl/cmd/config/BUILD index 14396a12857..f47fcd00fbc 100644 --- a/pkg/kubectl/cmd/config/BUILD +++ b/pkg/kubectl/cmd/config/BUILD @@ -41,6 +41,7 @@ go_library( "//staging/src/k8s.io/client-go/tools/clientcmd:go_default_library", "//staging/src/k8s.io/client-go/tools/clientcmd/api:go_default_library", "//staging/src/k8s.io/client-go/tools/clientcmd/api/latest:go_default_library", + "//vendor/github.com/liggitt/tabwriter:go_default_library", "//vendor/github.com/spf13/cobra:go_default_library", ], ) diff --git a/pkg/kubectl/cmd/config/config.go b/pkg/kubectl/cmd/config/config.go index 4e1b63e623f..7a977dfd84b 100644 --- a/pkg/kubectl/cmd/config/config.go +++ b/pkg/kubectl/cmd/config/config.go @@ -46,7 +46,7 @@ func NewCmdConfig(f cmdutil.Factory, pathOptions *clientcmd.PathOptions, streams The loading order follows these rules: 1. If the --` + pathOptions.ExplicitFileFlag + ` flag is set, then only that file is loaded. The flag may only be set once and no merging takes place. - 2. If $` + pathOptions.EnvVar + ` environment variable is set, then it is used as a list of paths (normal path delimitting rules for your system). These paths are merged. When a value is modified, it is modified in the file that defines the stanza. When a value is created, it is created in the first file that exists. If no files in the chain exist, then it creates the last file in the list. + 2. If $` + pathOptions.EnvVar + ` environment variable is set, then it is used as a list of paths (normal path delimiting rules for your system). These paths are merged. When a value is modified, it is modified in the file that defines the stanza. When a value is created, it is created in the first file that exists. If no files in the chain exist, then it creates the last file in the list. 3. Otherwise, ` + path.Join("${HOME}", pathOptions.GlobalFileSubpath) + ` is used and no merging takes place.`), Run: cmdutil.DefaultSubCommandRun(streams.ErrOut), } @@ -88,5 +88,5 @@ func toBool(propertyValue string) (bool, error) { func helpErrorf(cmd *cobra.Command, format string, args ...interface{}) error { cmd.Help() msg := fmt.Sprintf(format, args...) - return fmt.Errorf("%s\n", msg) + return fmt.Errorf("%s", msg) } diff --git a/pkg/kubectl/cmd/config/create_authinfo.go b/pkg/kubectl/cmd/config/create_authinfo.go index 0dca066c1fd..5ac80dfe746 100644 --- a/pkg/kubectl/cmd/config/create_authinfo.go +++ b/pkg/kubectl/cmd/config/create_authinfo.go @@ -56,7 +56,7 @@ const ( ) var ( - create_authinfo_long = fmt.Sprintf(templates.LongDesc(` + createAuthInfoLong = fmt.Sprintf(templates.LongDesc(` Sets a user entry in kubeconfig Specifying a name that already exists will merge new fields on top of existing values. @@ -72,7 +72,7 @@ var ( Bearer token and basic auth are mutually exclusive.`), clientcmd.FlagCertFile, clientcmd.FlagKeyFile, clientcmd.FlagBearerToken, clientcmd.FlagUsername, clientcmd.FlagPassword) - create_authinfo_example = templates.Examples(` + createAuthInfoExample = templates.Examples(` # Set only the "client-key" field on the "cluster-admin" # entry, without touching other values: kubectl config set-credentials cluster-admin --client-key=~/.kube/admin.key @@ -93,6 +93,7 @@ var ( kubectl config set-credentials cluster-admin --auth-provider=oidc --auth-provider-arg=client-secret-`) ) +// NewCmdConfigSetAuthInfo returns an Command option instance for 'config set-credentials' sub command func NewCmdConfigSetAuthInfo(out io.Writer, configAccess clientcmd.ConfigAccess) *cobra.Command { options := &createAuthInfoOptions{configAccess: configAccess} return newCmdConfigSetAuthInfo(out, options) @@ -103,8 +104,8 @@ func newCmdConfigSetAuthInfo(out io.Writer, options *createAuthInfoOptions) *cob Use: fmt.Sprintf("set-credentials NAME [--%v=path/to/certfile] [--%v=path/to/keyfile] [--%v=bearer_token] [--%v=basic_user] [--%v=basic_password] [--%v=provider_name] [--%v=key=value]", clientcmd.FlagCertFile, clientcmd.FlagKeyFile, clientcmd.FlagBearerToken, clientcmd.FlagUsername, clientcmd.FlagPassword, flagAuthProvider, flagAuthProviderArg), DisableFlagsInUseLine: true, Short: i18n.T("Sets a user entry in kubeconfig"), - Long: create_authinfo_long, - Example: create_authinfo_example, + Long: createAuthInfoLong, + Example: createAuthInfoExample, Run: func(cmd *cobra.Command, args []string) { err := options.complete(cmd, out) if err != nil { @@ -247,13 +248,13 @@ func (o *createAuthInfoOptions) complete(cmd *cobra.Command, out io.Writer) erro authProviderArgs, err := cmd.Flags().GetStringSlice(flagAuthProviderArg) if err != nil { - return fmt.Errorf("Error: %s\n", err) + return fmt.Errorf("Error: %s", err) } if len(authProviderArgs) > 0 { newPairs, removePairs, err := cmdutil.ParsePairs(authProviderArgs, flagAuthProviderArg, true) if err != nil { - return fmt.Errorf("Error: %s\n", err) + return fmt.Errorf("Error: %s", err) } o.authProviderArgs = newPairs o.authProviderArgsToRemove = removePairs diff --git a/pkg/kubectl/cmd/config/create_cluster.go b/pkg/kubectl/cmd/config/create_cluster.go index a07dfd6c772..81d0560a98a 100644 --- a/pkg/kubectl/cmd/config/create_cluster.go +++ b/pkg/kubectl/cmd/config/create_cluster.go @@ -43,12 +43,12 @@ type createClusterOptions struct { } var ( - create_cluster_long = templates.LongDesc(` + createClusterLong = templates.LongDesc(` Sets a cluster entry in kubeconfig. Specifying a name that already exists will merge new fields on top of existing values for those fields.`) - create_cluster_example = templates.Examples(` + createClusterExample = templates.Examples(` # Set only the server field on the e2e cluster entry without touching other values. kubectl config set-cluster e2e --server=https://1.2.3.4 @@ -59,6 +59,7 @@ var ( kubectl config set-cluster e2e --insecure-skip-tls-verify=true`) ) +// NewCmdConfigSetCluster returns a Command instance for 'config set-cluster' sub command func NewCmdConfigSetCluster(out io.Writer, configAccess clientcmd.ConfigAccess) *cobra.Command { options := &createClusterOptions{configAccess: configAccess} @@ -66,8 +67,8 @@ func NewCmdConfigSetCluster(out io.Writer, configAccess clientcmd.ConfigAccess) Use: fmt.Sprintf("set-cluster NAME [--%v=server] [--%v=path/to/certificate/authority] [--%v=true]", clientcmd.FlagAPIServer, clientcmd.FlagCAFile, clientcmd.FlagInsecure), DisableFlagsInUseLine: true, Short: i18n.T("Sets a cluster entry in kubeconfig"), - Long: create_cluster_long, - Example: create_cluster_example, + Long: createClusterLong, + Example: createClusterExample, Run: func(cmd *cobra.Command, args []string) { cmdutil.CheckErr(options.complete(cmd)) cmdutil.CheckErr(options.run()) diff --git a/pkg/kubectl/cmd/config/create_context.go b/pkg/kubectl/cmd/config/create_context.go index 50b965cc629..59af1712e4a 100644 --- a/pkg/kubectl/cmd/config/create_context.go +++ b/pkg/kubectl/cmd/config/create_context.go @@ -41,16 +41,17 @@ type createContextOptions struct { } var ( - create_context_long = templates.LongDesc(` + createContextLong = templates.LongDesc(` Sets a context entry in kubeconfig Specifying a name that already exists will merge new fields on top of existing values for those fields.`) - create_context_example = templates.Examples(` + createContextExample = templates.Examples(` # Set the user field on the gce context entry without touching other values kubectl config set-context gce --user=cluster-admin`) ) +// NewCmdConfigSetContext returns a Command instance for 'config set-context' sub command func NewCmdConfigSetContext(out io.Writer, configAccess clientcmd.ConfigAccess) *cobra.Command { options := &createContextOptions{configAccess: configAccess} @@ -58,8 +59,8 @@ func NewCmdConfigSetContext(out io.Writer, configAccess clientcmd.ConfigAccess) Use: fmt.Sprintf("set-context [NAME | --current] [--%v=cluster_nickname] [--%v=user_nickname] [--%v=namespace]", clientcmd.FlagClusterName, clientcmd.FlagAuthInfoName, clientcmd.FlagNamespace), DisableFlagsInUseLine: true, Short: i18n.T("Sets a context entry in kubeconfig"), - Long: create_context_long, - Example: create_context_example, + Long: createContextLong, + Example: createContextExample, Run: func(cmd *cobra.Command, args []string) { cmdutil.CheckErr(options.complete(cmd)) name, exists, err := options.run() diff --git a/pkg/kubectl/cmd/config/current_context.go b/pkg/kubectl/cmd/config/current_context.go index 3751d8b25c9..eb2bb82606b 100644 --- a/pkg/kubectl/cmd/config/current_context.go +++ b/pkg/kubectl/cmd/config/current_context.go @@ -28,36 +28,38 @@ import ( "k8s.io/kubernetes/pkg/kubectl/util/templates" ) +// CurrentContextOptions holds the command-line options for 'config current-context' sub command type CurrentContextOptions struct { ConfigAccess clientcmd.ConfigAccess } var ( - current_context_long = templates.LongDesc(` + currentContextLong = templates.LongDesc(` Displays the current-context`) - current_context_example = templates.Examples(` + currentContextExample = templates.Examples(` # Display the current-context kubectl config current-context`) ) +// NewCmdConfigCurrentContext returns a Command instance for 'config current-context' sub command func NewCmdConfigCurrentContext(out io.Writer, configAccess clientcmd.ConfigAccess) *cobra.Command { options := &CurrentContextOptions{ConfigAccess: configAccess} cmd := &cobra.Command{ Use: "current-context", Short: i18n.T("Displays the current-context"), - Long: current_context_long, - Example: current_context_example, + Long: currentContextLong, + Example: currentContextExample, Run: func(cmd *cobra.Command, args []string) { - err := RunCurrentContext(out, options) - cmdutil.CheckErr(err) + cmdutil.CheckErr(RunCurrentContext(out, options)) }, } return cmd } +// RunCurrentContext performs the execution of 'config current-context' sub command func RunCurrentContext(out io.Writer, options *CurrentContextOptions) error { config, err := options.ConfigAccess.GetStartingConfig() if err != nil { @@ -65,7 +67,7 @@ func RunCurrentContext(out io.Writer, options *CurrentContextOptions) error { } if config.CurrentContext == "" { - err = fmt.Errorf("current-context is not set\n") + err = fmt.Errorf("current-context is not set") return err } diff --git a/pkg/kubectl/cmd/config/delete_cluster.go b/pkg/kubectl/cmd/config/delete_cluster.go index 9ae52e87c11..797fe11b8be 100644 --- a/pkg/kubectl/cmd/config/delete_cluster.go +++ b/pkg/kubectl/cmd/config/delete_cluster.go @@ -28,21 +28,21 @@ import ( ) var ( - delete_cluster_example = templates.Examples(` + deleteClusterExample = templates.Examples(` # Delete the minikube cluster kubectl config delete-cluster minikube`) ) +// NewCmdConfigDeleteCluster returns a Command instance for 'config delete-cluster' sub command func NewCmdConfigDeleteCluster(out io.Writer, configAccess clientcmd.ConfigAccess) *cobra.Command { cmd := &cobra.Command{ Use: "delete-cluster NAME", DisableFlagsInUseLine: true, Short: i18n.T("Delete the specified cluster from the kubeconfig"), Long: "Delete the specified cluster from the kubeconfig", - Example: delete_cluster_example, + Example: deleteClusterExample, Run: func(cmd *cobra.Command, args []string) { - err := runDeleteCluster(out, configAccess, cmd) - cmdutil.CheckErr(err) + cmdutil.CheckErr(runDeleteCluster(out, configAccess, cmd)) }, } diff --git a/pkg/kubectl/cmd/config/delete_context.go b/pkg/kubectl/cmd/config/delete_context.go index 76ae529fd7e..b9c6fefd7b7 100644 --- a/pkg/kubectl/cmd/config/delete_context.go +++ b/pkg/kubectl/cmd/config/delete_context.go @@ -28,21 +28,21 @@ import ( ) var ( - delete_context_example = templates.Examples(` + deleteContextExample = templates.Examples(` # Delete the context for the minikube cluster kubectl config delete-context minikube`) ) +// NewCmdConfigDeleteContext returns a Command instance for 'config delete-context' sub command func NewCmdConfigDeleteContext(out, errOut io.Writer, configAccess clientcmd.ConfigAccess) *cobra.Command { cmd := &cobra.Command{ Use: "delete-context NAME", DisableFlagsInUseLine: true, Short: i18n.T("Delete the specified context from the kubeconfig"), Long: "Delete the specified context from the kubeconfig", - Example: delete_context_example, + Example: deleteContextExample, Run: func(cmd *cobra.Command, args []string) { - err := runDeleteContext(out, errOut, configAccess, cmd) - cmdutil.CheckErr(err) + cmdutil.CheckErr(runDeleteContext(out, errOut, configAccess, cmd)) }, } diff --git a/pkg/kubectl/cmd/config/get_clusters.go b/pkg/kubectl/cmd/config/get_clusters.go index bbaebf9e7a7..d8d36d916a9 100644 --- a/pkg/kubectl/cmd/config/get_clusters.go +++ b/pkg/kubectl/cmd/config/get_clusters.go @@ -28,7 +28,7 @@ import ( ) var ( - get_clusters_example = templates.Examples(` + getClustersExample = templates.Examples(` # List the clusters kubectl knows about kubectl config get-clusters`) ) @@ -40,10 +40,9 @@ func NewCmdConfigGetClusters(out io.Writer, configAccess clientcmd.ConfigAccess) Use: "get-clusters", Short: i18n.T("Display clusters defined in the kubeconfig"), Long: "Display clusters defined in the kubeconfig.", - Example: get_clusters_example, + Example: getClustersExample, Run: func(cmd *cobra.Command, args []string) { - err := runGetClusters(out, configAccess) - cmdutil.CheckErr(err) + cmdutil.CheckErr(runGetClusters(out, configAccess)) }, } diff --git a/pkg/kubectl/cmd/config/get_contexts.go b/pkg/kubectl/cmd/config/get_contexts.go index 30f53db7945..0e59ac3fc73 100644 --- a/pkg/kubectl/cmd/config/get_contexts.go +++ b/pkg/kubectl/cmd/config/get_contexts.go @@ -21,8 +21,8 @@ import ( "io" "sort" "strings" - "text/tabwriter" + "github.com/liggitt/tabwriter" "github.com/spf13/cobra" utilerrors "k8s.io/apimachinery/pkg/util/errors" diff --git a/pkg/kubectl/cmd/config/rename_context.go b/pkg/kubectl/cmd/config/rename_context.go index 535a811102e..98f078e84a5 100644 --- a/pkg/kubectl/cmd/config/rename_context.go +++ b/pkg/kubectl/cmd/config/rename_context.go @@ -67,15 +67,9 @@ func NewCmdConfigRenameContext(out io.Writer, configAccess clientcmd.ConfigAcces Long: renameContextLong, Example: renameContextExample, Run: func(cmd *cobra.Command, args []string) { - if err := options.Complete(cmd, args, out); err != nil { - cmdutil.CheckErr(err) - } - if err := options.Validate(); err != nil { - cmdutil.CheckErr(cmdutil.UsageErrorf(cmd, err.Error())) - } - if err := options.RunRenameContext(out); err != nil { - cmdutil.CheckErr(err) - } + cmdutil.CheckErr(options.Complete(cmd, args, out)) + cmdutil.CheckErr(options.Validate()) + cmdutil.CheckErr(options.RunRenameContext(out)) }, } return cmd @@ -92,6 +86,7 @@ func (o *RenameContextOptions) Complete(cmd *cobra.Command, args []string, out i return nil } +// Validate makes sure that provided values for command-line options are valid func (o RenameContextOptions) Validate() error { if len(o.newName) == 0 { return errors.New("You must specify a new non-empty context name") @@ -99,6 +94,7 @@ func (o RenameContextOptions) Validate() error { return nil } +// RunRenameContext performs the execution for 'config rename-context' sub command func (o RenameContextOptions) RunRenameContext(out io.Writer) error { config, err := o.configAccess.GetStartingConfig() if err != nil { diff --git a/pkg/kubectl/cmd/config/rename_context_test.go b/pkg/kubectl/cmd/config/rename_context_test.go index cfe371497f1..01edde9fe76 100644 --- a/pkg/kubectl/cmd/config/rename_context_test.go +++ b/pkg/kubectl/cmd/config/rename_context_test.go @@ -36,7 +36,7 @@ const ( ) var ( - contextData *clientcmdapi.Context = clientcmdapi.NewContext() + contextData = clientcmdapi.NewContext() ) type renameContextTest struct { diff --git a/pkg/kubectl/cmd/config/set.go b/pkg/kubectl/cmd/config/set.go index 9117402bba1..2b5a37a27f4 100644 --- a/pkg/kubectl/cmd/config/set.go +++ b/pkg/kubectl/cmd/config/set.go @@ -40,13 +40,14 @@ type setOptions struct { setRawBytes flag.Tristate } -var set_long = templates.LongDesc(` +var setLong = templates.LongDesc(` Sets an individual value in a kubeconfig file PROPERTY_NAME is a dot delimited name where each token represents either an attribute name or a map key. Map keys may not contain dots. PROPERTY_VALUE is the new value you wish to set. Binary fields such as 'certificate-authority-data' expect a base64 encoded string unless the --set-raw-bytes flag is used.`) +// NewCmdConfigSet returns a Command instance for 'config set' sub command func NewCmdConfigSet(out io.Writer, configAccess clientcmd.ConfigAccess) *cobra.Command { options := &setOptions{configAccess: configAccess} @@ -54,7 +55,7 @@ func NewCmdConfigSet(out io.Writer, configAccess clientcmd.ConfigAccess) *cobra. Use: "set PROPERTY_NAME PROPERTY_VALUE", DisableFlagsInUseLine: true, Short: i18n.T("Sets an individual value in a kubeconfig file"), - Long: set_long, + Long: setLong, Run: func(cmd *cobra.Command, args []string) { cmdutil.CheckErr(options.complete(cmd)) cmdutil.CheckErr(options.run()) diff --git a/pkg/kubectl/cmd/config/unset.go b/pkg/kubectl/cmd/config/unset.go index 02a519cb42c..838957831c2 100644 --- a/pkg/kubectl/cmd/config/unset.go +++ b/pkg/kubectl/cmd/config/unset.go @@ -49,6 +49,7 @@ var ( kubectl config unset contexts.foo.namespace`) ) +// NewCmdConfigUnset returns a Command instance for 'config unset' sub command func NewCmdConfigUnset(out io.Writer, configAccess clientcmd.ConfigAccess) *cobra.Command { options := &unsetOptions{configAccess: configAccess} diff --git a/pkg/kubectl/cmd/config/use_context.go b/pkg/kubectl/cmd/config/use_context.go index b22251af261..0ff5a8e2536 100644 --- a/pkg/kubectl/cmd/config/use_context.go +++ b/pkg/kubectl/cmd/config/use_context.go @@ -31,7 +31,7 @@ import ( ) var ( - use_context_example = templates.Examples(` + useContextExample = templates.Examples(` # Use the context for the minikube cluster kubectl config use-context minikube`) ) @@ -41,6 +41,7 @@ type useContextOptions struct { contextName string } +// NewCmdConfigUseContext returns a Command instance for 'config use-context' sub command func NewCmdConfigUseContext(out io.Writer, configAccess clientcmd.ConfigAccess) *cobra.Command { options := &useContextOptions{configAccess: configAccess} @@ -50,7 +51,7 @@ func NewCmdConfigUseContext(out io.Writer, configAccess clientcmd.ConfigAccess) Short: i18n.T("Sets the current-context in a kubeconfig file"), Aliases: []string{"use"}, Long: `Sets the current-context in a kubeconfig file`, - Example: use_context_example, + Example: useContextExample, Run: func(cmd *cobra.Command, args []string) { cmdutil.CheckErr(options.complete(cmd)) cmdutil.CheckErr(options.run()) @@ -98,5 +99,5 @@ func (o useContextOptions) validate(config *clientcmdapi.Config) error { } } - return fmt.Errorf("no context exists with the name: %q.", o.contextName) + return fmt.Errorf("no context exists with the name: %q", o.contextName) } diff --git a/pkg/kubectl/cmd/config/view.go b/pkg/kubectl/cmd/config/view.go index 7017cb6a9cf..4df1f9a2824 100644 --- a/pkg/kubectl/cmd/config/view.go +++ b/pkg/kubectl/cmd/config/view.go @@ -33,6 +33,7 @@ import ( "k8s.io/kubernetes/pkg/kubectl/util/templates" ) +// ViewOptions holds the command-line options for 'config view' sub command type ViewOptions struct { PrintFlags *genericclioptions.PrintFlags PrintObject printers.ResourcePrinterFunc @@ -50,12 +51,12 @@ type ViewOptions struct { } var ( - view_long = templates.LongDesc(` + viewLong = templates.LongDesc(` Display merged kubeconfig settings or a specified kubeconfig file. You can use --output jsonpath={...} to extract specific values using a jsonpath expression.`) - view_example = templates.Examples(` + viewExample = templates.Examples(` # Show merged kubeconfig settings. kubectl config view @@ -68,6 +69,7 @@ var ( defaultOutputFormat = "yaml" ) +// NewCmdConfigView returns a Command instance for 'config view' sub command func NewCmdConfigView(f cmdutil.Factory, streams genericclioptions.IOStreams, ConfigAccess clientcmd.ConfigAccess) *cobra.Command { o := &ViewOptions{ PrintFlags: genericclioptions.NewPrintFlags("").WithTypeSetter(scheme.Scheme).WithDefaultOutput("yaml"), @@ -79,8 +81,8 @@ func NewCmdConfigView(f cmdutil.Factory, streams genericclioptions.IOStreams, Co cmd := &cobra.Command{ Use: "view", Short: i18n.T("Display merged kubeconfig settings or a specified kubeconfig file"), - Long: view_long, - Example: view_example, + Long: viewLong, + Example: viewExample, Run: func(cmd *cobra.Command, args []string) { cmdutil.CheckErr(o.Complete(cmd, args)) cmdutil.CheckErr(o.Validate()) @@ -99,6 +101,7 @@ func NewCmdConfigView(f cmdutil.Factory, streams genericclioptions.IOStreams, Co return cmd } +// Complete completes the required command-line options func (o *ViewOptions) Complete(cmd *cobra.Command, args []string) error { if len(args) != 0 { return cmdutil.UsageErrorf(cmd, "unexpected arguments: %v", args) @@ -119,6 +122,7 @@ func (o *ViewOptions) Complete(cmd *cobra.Command, args []string) error { return nil } +// Validate makes sure that provided values for command-line options are valid func (o ViewOptions) Validate() error { if !o.Merge.Value() && !o.ConfigAccess.IsExplicitFile() { return errors.New("if merge==false a precise file must to specified") @@ -127,6 +131,7 @@ func (o ViewOptions) Validate() error { return nil } +// Run performs the execution of 'config view' sub command func (o ViewOptions) Run() error { config, err := o.loadConfig() if err != nil { diff --git a/pkg/kubectl/cmd/convert/convert.go b/pkg/kubectl/cmd/convert/convert.go index a233b8cd1cb..506b7365774 100644 --- a/pkg/kubectl/cmd/convert/convert.go +++ b/pkg/kubectl/cmd/convert/convert.go @@ -37,7 +37,7 @@ import ( ) var ( - convert_long = templates.LongDesc(i18n.T(` + convertLong = templates.LongDesc(i18n.T(` Convert config files between different API versions. Both YAML and JSON formats are accepted. @@ -48,7 +48,7 @@ var ( The default output will be printed to stdout in YAML format. One can use -o option to change to output destination.`)) - convert_example = templates.Examples(i18n.T(` + convertExample = templates.Examples(i18n.T(` # Convert 'pod.yaml' to latest version and print to stdout. kubectl convert -f pod.yaml @@ -93,8 +93,8 @@ func NewCmdConvert(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *co Use: "convert -f FILENAME", DisableFlagsInUseLine: true, Short: i18n.T("Convert config files between different API versions"), - Long: convert_long, - Example: convert_example, + Long: convertLong, + Example: convertExample, Run: func(cmd *cobra.Command, args []string) { cmdutil.CheckErr(o.Complete(f, cmd)) cmdutil.CheckErr(o.RunConvert()) diff --git a/pkg/kubectl/cmd/create/create.go b/pkg/kubectl/cmd/create/create.go index 1a426bae616..1a8f230bc2d 100644 --- a/pkg/kubectl/cmd/create/create.go +++ b/pkg/kubectl/cmd/create/create.go @@ -45,6 +45,7 @@ import ( "k8s.io/kubernetes/pkg/kubectl/util/templates" ) +// CreateOptions is the commandline options for 'create' sub command type CreateOptions struct { PrintFlags *genericclioptions.PrintFlags RecordFlags *genericclioptions.RecordFlags @@ -79,6 +80,7 @@ var ( kubectl create -f docker-registry.yaml --edit -o json`)) ) +// NewCreateOptions returns an initialized CreateOptions instance func NewCreateOptions(ioStreams genericclioptions.IOStreams) *CreateOptions { return &CreateOptions{ PrintFlags: genericclioptions.NewPrintFlags("created").WithTypeSetter(scheme.Scheme), @@ -90,6 +92,7 @@ func NewCreateOptions(ioStreams genericclioptions.IOStreams) *CreateOptions { } } +// NewCmdCreate returns new initialized instance of create sub command func NewCmdCreate(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command { o := NewCreateOptions(ioStreams) @@ -146,6 +149,7 @@ func NewCmdCreate(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cob return cmd } +// ValidateArgs makes sure there is no discrepency in command options func (o *CreateOptions) ValidateArgs(cmd *cobra.Command, args []string) error { if len(args) != 0 { return cmdutil.UsageErrorf(cmd, "Unexpected args: %v", args) @@ -177,6 +181,7 @@ func (o *CreateOptions) ValidateArgs(cmd *cobra.Command, args []string) error { return nil } +// Complete completes all the required options func (o *CreateOptions) Complete(f cmdutil.Factory, cmd *cobra.Command) error { var err error @@ -203,6 +208,7 @@ func (o *CreateOptions) Complete(f cmdutil.Factory, cmd *cobra.Command) error { return nil } +// RunCreate performs the creation func (o *CreateOptions) RunCreate(f cmdutil.Factory, cmd *cobra.Command) error { // raw only makes sense for a single file resource multiple objects aren't likely to do what you want. // the validator enforces this, so @@ -300,6 +306,7 @@ func (o *CreateOptions) raw(f cmdutil.Factory) error { return nil } +// RunEditOnCreate performs edit on creation func RunEditOnCreate(f cmdutil.Factory, printFlags *genericclioptions.PrintFlags, recordFlags *genericclioptions.RecordFlags, ioStreams genericclioptions.IOStreams, cmd *cobra.Command, options *resource.FilenameOptions) error { editOptions := editor.NewEditOptions(editor.EditBeforeCreateMode, ioStreams) editOptions.FilenameOptions = *options @@ -363,6 +370,7 @@ type CreateSubcommandOptions struct { genericclioptions.IOStreams } +// NewCreateSubcommandOptions returns initialized CreateSubcommandOptions func NewCreateSubcommandOptions(ioStreams genericclioptions.IOStreams) *CreateSubcommandOptions { return &CreateSubcommandOptions{ PrintFlags: genericclioptions.NewPrintFlags("created").WithTypeSetter(scheme.Scheme), @@ -370,6 +378,7 @@ func NewCreateSubcommandOptions(ioStreams genericclioptions.IOStreams) *CreateSu } } +// Complete completes all the required options func (o *CreateSubcommandOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string, generator generate.StructuredGenerator) error { name, err := NameFromCommandArgs(cmd, args) if err != nil { @@ -411,7 +420,7 @@ func (o *CreateSubcommandOptions) Complete(f cmdutil.Factory, cmd *cobra.Command return nil } -// RunCreateSubcommand executes a create subcommand using the specified options +// Run executes a create subcommand using the specified options func (o *CreateSubcommandOptions) Run() error { obj, err := o.StructuredGenerator.StructuredGenerate() if err != nil { diff --git a/pkg/kubectl/cmd/create/create_clusterrole.go b/pkg/kubectl/cmd/create/create_clusterrole.go index ce170028275..276ae7f5891 100644 --- a/pkg/kubectl/cmd/create/create_clusterrole.go +++ b/pkg/kubectl/cmd/create/create_clusterrole.go @@ -58,13 +58,14 @@ var ( validNonResourceVerbs = []string{"*", "get", "post", "put", "delete", "patch", "head", "options"} ) +// CreateClusterRoleOptions is returned by NewCmdCreateClusterRole type CreateClusterRoleOptions struct { *CreateRoleOptions NonResourceURLs []string AggregationRule map[string]string } -// ClusterRole is a command to ease creating ClusterRoles. +// NewCmdCreateClusterRole initializes and returns new ClusterRoles command func NewCmdCreateClusterRole(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command { c := &CreateClusterRoleOptions{ CreateRoleOptions: NewCreateRoleOptions(ioStreams), @@ -97,6 +98,7 @@ func NewCmdCreateClusterRole(f cmdutil.Factory, ioStreams genericclioptions.IOSt return cmd } +// Complete completes all the required options func (c *CreateClusterRoleOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error { // Remove duplicate nonResourceURLs nonResourceURLs := []string{} @@ -110,6 +112,7 @@ func (c *CreateClusterRoleOptions) Complete(f cmdutil.Factory, cmd *cobra.Comman return c.CreateRoleOptions.Complete(f, cmd, args) } +// Validate makes sure there is no discrepency in CreateClusterRoleOptions func (c *CreateClusterRoleOptions) Validate() error { if c.Name == "" { return fmt.Errorf("name must be specified") @@ -170,6 +173,7 @@ func (c *CreateClusterRoleOptions) Validate() error { } +// RunCreateRole creates a new clusterRole func (c *CreateClusterRoleOptions) RunCreateRole() error { clusterRole := &rbacv1.ClusterRole{ // this is ok because we know exactly how we want to be serialized diff --git a/pkg/kubectl/cmd/create/create_clusterrolebinding.go b/pkg/kubectl/cmd/create/create_clusterrolebinding.go index 882da888cc3..acff50b6eff 100644 --- a/pkg/kubectl/cmd/create/create_clusterrolebinding.go +++ b/pkg/kubectl/cmd/create/create_clusterrolebinding.go @@ -36,13 +36,14 @@ var ( kubectl create clusterrolebinding cluster-admin --clusterrole=cluster-admin --user=user1 --user=user2 --group=group1`)) ) +// ClusterRoleBindingOpts is returned by NewCmdCreateClusterRoleBinding type ClusterRoleBindingOpts struct { CreateSubcommandOptions *CreateSubcommandOptions } -// ClusterRoleBinding is a command to ease creating ClusterRoleBindings. +// NewCmdCreateClusterRoleBinding returns an initialized command instance of ClusterRoleBinding func NewCmdCreateClusterRoleBinding(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command { - options := &ClusterRoleBindingOpts{ + o := &ClusterRoleBindingOpts{ CreateSubcommandOptions: NewCreateSubcommandOptions(ioStreams), } @@ -53,12 +54,12 @@ func NewCmdCreateClusterRoleBinding(f cmdutil.Factory, ioStreams genericclioptio Long: clusterRoleBindingLong, Example: clusterRoleBindingExample, Run: func(cmd *cobra.Command, args []string) { - cmdutil.CheckErr(options.Complete(f, cmd, args)) - cmdutil.CheckErr(options.Run()) + cmdutil.CheckErr(o.Complete(f, cmd, args)) + cmdutil.CheckErr(o.Run()) }, } - options.CreateSubcommandOptions.PrintFlags.AddFlags(cmd) + o.CreateSubcommandOptions.PrintFlags.AddFlags(cmd) cmdutil.AddApplyAnnotationFlags(cmd) cmdutil.AddValidateFlags(cmd) @@ -71,6 +72,7 @@ func NewCmdCreateClusterRoleBinding(f cmdutil.Factory, ioStreams genericclioptio return cmd } +// Complete completes all the required options func (o *ClusterRoleBindingOpts) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error { name, err := NameFromCommandArgs(cmd, args) if err != nil { @@ -94,7 +96,7 @@ func (o *ClusterRoleBindingOpts) Complete(f cmdutil.Factory, cmd *cobra.Command, return o.CreateSubcommandOptions.Complete(f, cmd, args, generator) } -// CreateClusterRoleBinding is the implementation of the create clusterrolebinding command. +// Run calls the CreateSubcommandOptions.Run in ClusterRoleBindingOpts instance func (o *ClusterRoleBindingOpts) Run() error { return o.CreateSubcommandOptions.Run() } diff --git a/pkg/kubectl/cmd/create/create_configmap.go b/pkg/kubectl/cmd/create/create_configmap.go index 4837d658f9e..63ea712300c 100644 --- a/pkg/kubectl/cmd/create/create_configmap.go +++ b/pkg/kubectl/cmd/create/create_configmap.go @@ -57,11 +57,12 @@ var ( kubectl create configmap my-config --from-env-file=path/to/bar.env`)) ) +// ConfigMapOpts holds properties for create configmap sub-command type ConfigMapOpts struct { CreateSubcommandOptions *CreateSubcommandOptions } -// ConfigMap is a command to ease creating ConfigMaps. +// NewCmdCreateConfigMap initializes and returns ConfigMapOpts func NewCmdCreateConfigMap(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command { options := &ConfigMapOpts{ CreateSubcommandOptions: NewCreateSubcommandOptions(ioStreams), @@ -92,6 +93,7 @@ func NewCmdCreateConfigMap(f cmdutil.Factory, ioStreams genericclioptions.IOStre return cmd } +// Complete completes all the required options func (o *ConfigMapOpts) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error { name, err := NameFromCommandArgs(cmd, args) if err != nil { @@ -115,7 +117,7 @@ func (o *ConfigMapOpts) Complete(f cmdutil.Factory, cmd *cobra.Command, args []s return o.CreateSubcommandOptions.Complete(f, cmd, args, generator) } -// CreateConfigMap is the implementation of the create configmap command. +// Run performs the execution of 'create' sub command options func (o *ConfigMapOpts) Run() error { return o.CreateSubcommandOptions.Run() } diff --git a/pkg/kubectl/cmd/create/create_deployment.go b/pkg/kubectl/cmd/create/create_deployment.go index 1a069f73ff2..ed98b790d03 100644 --- a/pkg/kubectl/cmd/create/create_deployment.go +++ b/pkg/kubectl/cmd/create/create_deployment.go @@ -36,6 +36,7 @@ var ( kubectl create deployment my-dep --image=busybox`)) ) +// DeploymentOpts is returned by NewCmdCreateDeployment type DeploymentOpts struct { CreateSubcommandOptions *CreateSubcommandOptions } @@ -112,6 +113,7 @@ func generatorFromName( return nil, false } +// Complete completes all the options func (o *DeploymentOpts) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error { name, err := NameFromCommandArgs(cmd, args) if err != nil { @@ -147,10 +149,7 @@ func (o *DeploymentOpts) Complete(f cmdutil.Factory, cmd *cobra.Command, args [] return o.CreateSubcommandOptions.Complete(f, cmd, args, generator) } -// createDeployment -// 1. Reads user config values from Cobra. -// 2. Sets up the correct Generator object. -// 3. Calls RunCreateSubcommand. +// Run performs the execution of 'create deployment' sub command func (o *DeploymentOpts) Run() error { return o.CreateSubcommandOptions.Run() } diff --git a/pkg/kubectl/cmd/create/create_job.go b/pkg/kubectl/cmd/create/create_job.go index a82348e1b8c..285e239fc2b 100644 --- a/pkg/kubectl/cmd/create/create_job.go +++ b/pkg/kubectl/cmd/create/create_job.go @@ -50,6 +50,7 @@ var ( kubectl create job test-job --from=cronjob/a-cronjob`)) ) +// CreateJobOptions is the command line options for 'create job' type CreateJobOptions struct { PrintFlags *genericclioptions.PrintFlags @@ -69,6 +70,7 @@ type CreateJobOptions struct { genericclioptions.IOStreams } +// NewCreateJobOptions initializes and returns new CreateJobOptions instance func NewCreateJobOptions(ioStreams genericclioptions.IOStreams) *CreateJobOptions { return &CreateJobOptions{ PrintFlags: genericclioptions.NewPrintFlags("created").WithTypeSetter(scheme.Scheme), @@ -102,6 +104,7 @@ func NewCmdCreateJob(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) * return cmd } +// Complete completes all the required options func (o *CreateJobOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error { name, err := NameFromCommandArgs(cmd, args) if err != nil { @@ -143,6 +146,7 @@ func (o *CreateJobOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args return nil } +// Validate makes sure provided values and valid Job options func (o *CreateJobOptions) Validate() error { if (len(o.Image) == 0 && len(o.From) == 0) || (len(o.Image) != 0 && len(o.From) != 0) { return fmt.Errorf("either --image or --from must be specified") @@ -153,6 +157,7 @@ func (o *CreateJobOptions) Validate() error { return nil } +// Run performs the execution of 'create job' sub command func (o *CreateJobOptions) Run() error { var job *batchv1.Job if len(o.Image) > 0 { diff --git a/pkg/kubectl/cmd/create/create_namespace.go b/pkg/kubectl/cmd/create/create_namespace.go index 04ea190cf8a..1a329efd163 100644 --- a/pkg/kubectl/cmd/create/create_namespace.go +++ b/pkg/kubectl/cmd/create/create_namespace.go @@ -36,6 +36,7 @@ var ( kubectl create namespace my-namespace`)) ) +// NamespaceOpts is the options for 'create namespare' sub command type NamespaceOpts struct { CreateSubcommandOptions *CreateSubcommandOptions } @@ -68,6 +69,7 @@ func NewCmdCreateNamespace(f cmdutil.Factory, ioStreams genericclioptions.IOStre return cmd } +// Complete completes all the required options func (o *NamespaceOpts) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error { name, err := NameFromCommandArgs(cmd, args) if err != nil { @@ -85,7 +87,7 @@ func (o *NamespaceOpts) Complete(f cmdutil.Factory, cmd *cobra.Command, args []s return o.CreateSubcommandOptions.Complete(f, cmd, args, generator) } -// CreateNamespace implements the behavior to run the create namespace command +// Run calls the CreateSubcommandOptions.Run in NamespaceOpts instance func (o *NamespaceOpts) Run() error { return o.CreateSubcommandOptions.Run() } diff --git a/pkg/kubectl/cmd/create/create_pdb.go b/pkg/kubectl/cmd/create/create_pdb.go index 7a0f5b91af5..b085509bbc4 100644 --- a/pkg/kubectl/cmd/create/create_pdb.go +++ b/pkg/kubectl/cmd/create/create_pdb.go @@ -41,6 +41,7 @@ var ( kubectl create pdb my-pdb --selector=app=nginx --min-available=50%`)) ) +// PodDisruptionBudgetOpts holds the command-line options for poddisruptionbudget sub command type PodDisruptionBudgetOpts struct { CreateSubcommandOptions *CreateSubcommandOptions } @@ -76,6 +77,7 @@ func NewCmdCreatePodDisruptionBudget(f cmdutil.Factory, ioStreams genericcliopti return cmd } +// Complete completes all the required options func (o *PodDisruptionBudgetOpts) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error { name, err := NameFromCommandArgs(cmd, args) if err != nil { @@ -104,7 +106,7 @@ func (o *PodDisruptionBudgetOpts) Complete(f cmdutil.Factory, cmd *cobra.Command return o.CreateSubcommandOptions.Complete(f, cmd, args, generator) } -// CreatePodDisruptionBudget implements the behavior to run the create pdb command. +// Run calls the CreateSubcommandOptions.Run in PodDisruptionBudgetOpts instance func (o *PodDisruptionBudgetOpts) Run() error { return o.CreateSubcommandOptions.Run() } diff --git a/pkg/kubectl/cmd/create/create_priorityclass.go b/pkg/kubectl/cmd/create/create_priorityclass.go index 5cf7f529204..7555593763c 100644 --- a/pkg/kubectl/cmd/create/create_priorityclass.go +++ b/pkg/kubectl/cmd/create/create_priorityclass.go @@ -39,6 +39,7 @@ var ( kubectl create priorityclass default-priority --value=1000 --global-default=true --description="default priority"`)) ) +// PriorityClassOpts holds the options for 'create priorityclass' sub command type PriorityClassOpts struct { CreateSubcommandOptions *CreateSubcommandOptions } @@ -74,6 +75,7 @@ func NewCmdCreatePriorityClass(f cmdutil.Factory, ioStreams genericclioptions.IO return cmd } +// Complete completes all the required options func (o *PriorityClassOpts) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error { name, err := NameFromCommandArgs(cmd, args) if err != nil { @@ -96,7 +98,7 @@ func (o *PriorityClassOpts) Complete(f cmdutil.Factory, cmd *cobra.Command, args return o.CreateSubcommandOptions.Complete(f, cmd, args, generator) } -// CreatePriorityClass implements the behavior to run the create priorityClass command. +// Run calls the CreateSubcommandOptions.Run in the PriorityClassOpts instance func (o *PriorityClassOpts) Run() error { return o.CreateSubcommandOptions.Run() } diff --git a/pkg/kubectl/cmd/create/create_quota.go b/pkg/kubectl/cmd/create/create_quota.go index 95676a18303..31c83c72f16 100644 --- a/pkg/kubectl/cmd/create/create_quota.go +++ b/pkg/kubectl/cmd/create/create_quota.go @@ -39,6 +39,7 @@ var ( kubectl create quota best-effort --hard=pods=100 --scopes=BestEffort`)) ) +// QuotaOpts holds the command-line options for 'create quota' sub command type QuotaOpts struct { CreateSubcommandOptions *CreateSubcommandOptions } @@ -72,6 +73,7 @@ func NewCmdCreateQuota(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) return cmd } +// Complete completes all the required options func (o *QuotaOpts) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error { name, err := NameFromCommandArgs(cmd, args) if err != nil { @@ -93,7 +95,7 @@ func (o *QuotaOpts) Complete(f cmdutil.Factory, cmd *cobra.Command, args []strin return o.CreateSubcommandOptions.Complete(f, cmd, args, generator) } -// CreateQuota implements the behavior to run the create quota command +// Run calls the CreateSubcommandOptions.Run in QuotaOpts instance func (o *QuotaOpts) Run() error { return o.CreateSubcommandOptions.Run() } diff --git a/pkg/kubectl/cmd/create/create_role.go b/pkg/kubectl/cmd/create/create_role.go index 7124c509e80..bb183438d94 100644 --- a/pkg/kubectl/cmd/create/create_role.go +++ b/pkg/kubectl/cmd/create/create_role.go @@ -105,12 +105,14 @@ var ( } ) +// ResourceOptions holds the related options for '--resource' option type ResourceOptions struct { Group string Resource string SubResource string } +// CreateRoleOptions holds the options for 'create role' sub command type CreateRoleOptions struct { PrintFlags *genericclioptions.PrintFlags @@ -129,6 +131,7 @@ type CreateRoleOptions struct { genericclioptions.IOStreams } +// NewCreateRoleOptions returns an initialized CreateRoleOptions instance func NewCreateRoleOptions(ioStreams genericclioptions.IOStreams) *CreateRoleOptions { return &CreateRoleOptions{ PrintFlags: genericclioptions.NewPrintFlags("created").WithTypeSetter(scheme.Scheme), @@ -137,7 +140,7 @@ func NewCreateRoleOptions(ioStreams genericclioptions.IOStreams) *CreateRoleOpti } } -// Role is a command to ease creating Roles. +// NewCmdCreateRole returnns an initialized Command instance for 'create role' sub command func NewCmdCreateRole(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command { o := NewCreateRoleOptions(ioStreams) @@ -166,6 +169,7 @@ func NewCmdCreateRole(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) return cmd } +// Complete completes all the required options func (o *CreateRoleOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error { name, err := NameFromCommandArgs(cmd, args) if err != nil { @@ -255,6 +259,7 @@ func (o *CreateRoleOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args return nil } +// Validate makes sure there is no discrepency in provided option values func (o *CreateRoleOptions) Validate() error { if o.Name == "" { return fmt.Errorf("name must be specified") @@ -317,6 +322,7 @@ func (o *CreateRoleOptions) validateResource() error { return nil } +// RunCreateRole performs the execution of 'create role' sub command func (o *CreateRoleOptions) RunCreateRole() error { role := &rbacv1.Role{ // this is ok because we know exactly how we want to be serialized diff --git a/pkg/kubectl/cmd/create/create_rolebinding.go b/pkg/kubectl/cmd/create/create_rolebinding.go index 4b8f2b28ed6..605909d14c6 100644 --- a/pkg/kubectl/cmd/create/create_rolebinding.go +++ b/pkg/kubectl/cmd/create/create_rolebinding.go @@ -36,13 +36,14 @@ var ( kubectl create rolebinding admin --clusterrole=admin --user=user1 --user=user2 --group=group1`)) ) +// RoleBindingOpts holds the options for 'create rolebinding' sub command type RoleBindingOpts struct { CreateSubcommandOptions *CreateSubcommandOptions } -// RoleBinding is a command to ease creating RoleBindings. +// NewCmdCreateRoleBinding returns an initialized Command instance for 'create rolebinding' sub command func NewCmdCreateRoleBinding(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command { - options := &RoleBindingOpts{ + o := &RoleBindingOpts{ CreateSubcommandOptions: NewCreateSubcommandOptions(ioStreams), } @@ -53,12 +54,12 @@ func NewCmdCreateRoleBinding(f cmdutil.Factory, ioStreams genericclioptions.IOSt Long: roleBindingLong, Example: roleBindingExample, Run: func(cmd *cobra.Command, args []string) { - cmdutil.CheckErr(options.Complete(f, cmd, args)) - cmdutil.CheckErr(options.Run()) + cmdutil.CheckErr(o.Complete(f, cmd, args)) + cmdutil.CheckErr(o.Run()) }, } - options.CreateSubcommandOptions.PrintFlags.AddFlags(cmd) + o.CreateSubcommandOptions.PrintFlags.AddFlags(cmd) cmdutil.AddApplyAnnotationFlags(cmd) cmdutil.AddValidateFlags(cmd) @@ -71,6 +72,7 @@ func NewCmdCreateRoleBinding(f cmdutil.Factory, ioStreams genericclioptions.IOSt return cmd } +// Complete completes all the required options func (o *RoleBindingOpts) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error { name, err := NameFromCommandArgs(cmd, args) if err != nil { @@ -95,6 +97,7 @@ func (o *RoleBindingOpts) Complete(f cmdutil.Factory, cmd *cobra.Command, args [ return o.CreateSubcommandOptions.Complete(f, cmd, args, generator) } +// Run calls the CreateSubcommandOptions.Run in RoleBindingOpts instance func (o *RoleBindingOpts) Run() error { return o.CreateSubcommandOptions.Run() } diff --git a/pkg/kubectl/cmd/create/create_secret.go b/pkg/kubectl/cmd/create/create_secret.go index 4512dffbda8..8ba703c2830 100644 --- a/pkg/kubectl/cmd/create/create_secret.go +++ b/pkg/kubectl/cmd/create/create_secret.go @@ -73,6 +73,7 @@ var ( kubectl create secret generic my-secret --from-env-file=path/to/bar.env`)) ) +// SecretGenericOpts holds the options for 'create secret' sub command type SecretGenericOpts struct { CreateSubcommandOptions *CreateSubcommandOptions } @@ -108,6 +109,7 @@ func NewCmdCreateSecretGeneric(f cmdutil.Factory, ioStreams genericclioptions.IO return cmd } +// Complete completes all the required options func (o *SecretGenericOpts) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error { name, err := NameFromCommandArgs(cmd, args) if err != nil { @@ -132,7 +134,7 @@ func (o *SecretGenericOpts) Complete(f cmdutil.Factory, cmd *cobra.Command, args return o.CreateSubcommandOptions.Complete(f, cmd, args, generator) } -// CreateSecretGeneric is the implementation of the create secret generic command +// Run calls the CreateSubcommandOptions.Run in SecretGenericOpts instance func (o *SecretGenericOpts) Run() error { return o.CreateSubcommandOptions.Run() } @@ -158,6 +160,7 @@ var ( kubectl create secret docker-registry my-secret --docker-server=DOCKER_REGISTRY_SERVER --docker-username=DOCKER_USER --docker-password=DOCKER_PASSWORD --docker-email=DOCKER_EMAIL`)) ) +// SecretDockerRegistryOpts holds the options for 'create secret docker-registry' sub command type SecretDockerRegistryOpts struct { CreateSubcommandOptions *CreateSubcommandOptions } @@ -197,6 +200,7 @@ func NewCmdCreateSecretDockerRegistry(f cmdutil.Factory, ioStreams genericcliopt return cmd } +// Complete completes all the required options func (o *SecretDockerRegistryOpts) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error { name, err := NameFromCommandArgs(cmd, args) if err != nil { @@ -232,7 +236,7 @@ func (o *SecretDockerRegistryOpts) Complete(f cmdutil.Factory, cmd *cobra.Comman return o.CreateSubcommandOptions.Complete(f, cmd, args, generator) } -// CreateSecretDockerRegistry is the implementation of the create secret docker-registry command +// Run calls CreateSubcommandOptions.Run in SecretDockerRegistryOpts instance func (o *SecretDockerRegistryOpts) Run() error { return o.CreateSubcommandOptions.Run() } @@ -249,6 +253,7 @@ var ( kubectl create secret tls tls-secret --cert=path/to/tls.cert --key=path/to/tls.key`)) ) +// SecretTLSOpts holds the options for 'create secret tls' sub command type SecretTLSOpts struct { CreateSubcommandOptions *CreateSubcommandOptions } @@ -282,6 +287,7 @@ func NewCmdCreateSecretTLS(f cmdutil.Factory, ioStreams genericclioptions.IOStre return cmd } +// Complete completes all the required options func (o *SecretTLSOpts) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error { name, err := NameFromCommandArgs(cmd, args) if err != nil { @@ -310,7 +316,7 @@ func (o *SecretTLSOpts) Complete(f cmdutil.Factory, cmd *cobra.Command, args []s return o.CreateSubcommandOptions.Complete(f, cmd, args, generator) } -// CreateSecretTLS is the implementation of the create secret tls command +// Run calls CreateSubcommandOptions.Run in the SecretTLSOpts instance func (o *SecretTLSOpts) Run() error { return o.CreateSubcommandOptions.Run() } diff --git a/pkg/kubectl/cmd/create/create_service.go b/pkg/kubectl/cmd/create/create_service.go index ee34f1814f7..f36fca9b482 100644 --- a/pkg/kubectl/cmd/create/create_service.go +++ b/pkg/kubectl/cmd/create/create_service.go @@ -61,6 +61,7 @@ func addPortFlags(cmd *cobra.Command) { cmd.Flags().StringSlice("tcp", []string{}, "Port pairs can be specified as ':'.") } +// ServiceClusterIPOpts holds the options for 'create service clusterip' sub command type ServiceClusterIPOpts struct { CreateSubcommandOptions *CreateSubcommandOptions } @@ -97,6 +98,7 @@ func errUnsupportedGenerator(cmd *cobra.Command, generatorName string) error { return cmdutil.UsageErrorf(cmd, "Generator %s not supported. ", generatorName) } +// Complete completes all the required options func (o *ServiceClusterIPOpts) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error { name, err := NameFromCommandArgs(cmd, args) if err != nil { @@ -119,7 +121,7 @@ func (o *ServiceClusterIPOpts) Complete(f cmdutil.Factory, cmd *cobra.Command, a return o.CreateSubcommandOptions.Complete(f, cmd, args, generator) } -// CreateServiceClusterIP is the implementation of the create service clusterip command +// Run calls the CreateSubcommandOptions.Run in ServiceClusterIPOpts instance func (o *ServiceClusterIPOpts) Run() error { return o.CreateSubcommandOptions.Run() } @@ -133,6 +135,7 @@ var ( kubectl create service nodeport my-ns --tcp=5678:8080`)) ) +// ServiceNodePortOpts holds the options for 'create service nodeport' sub command type ServiceNodePortOpts struct { CreateSubcommandOptions *CreateSubcommandOptions } @@ -165,6 +168,7 @@ func NewCmdCreateServiceNodePort(f cmdutil.Factory, ioStreams genericclioptions. return cmd } +// Complete completes all the required options func (o *ServiceNodePortOpts) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error { name, err := NameFromCommandArgs(cmd, args) if err != nil { @@ -188,7 +192,7 @@ func (o *ServiceNodePortOpts) Complete(f cmdutil.Factory, cmd *cobra.Command, ar return o.CreateSubcommandOptions.Complete(f, cmd, args, generator) } -// CreateServiceNodePort is the implementation of the create service nodeport command +// Run calls the CreateSubcommandOptions.Run in ServiceNodePortOpts instance func (o *ServiceNodePortOpts) Run() error { return o.CreateSubcommandOptions.Run() } @@ -202,6 +206,7 @@ var ( kubectl create service loadbalancer my-lbs --tcp=5678:8080`)) ) +// ServiceLoadBalancerOpts holds the options for 'create service loadbalancer' sub command type ServiceLoadBalancerOpts struct { CreateSubcommandOptions *CreateSubcommandOptions } @@ -233,6 +238,7 @@ func NewCmdCreateServiceLoadBalancer(f cmdutil.Factory, ioStreams genericcliopti return cmd } +// Complete completes all the required options func (o *ServiceLoadBalancerOpts) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error { name, err := NameFromCommandArgs(cmd, args) if err != nil { @@ -255,7 +261,7 @@ func (o *ServiceLoadBalancerOpts) Complete(f cmdutil.Factory, cmd *cobra.Command return o.CreateSubcommandOptions.Complete(f, cmd, args, generator) } -// CreateServiceLoadBalancer is the implementation of the create service loadbalancer command +// Run calls the CreateSubcommandOptions.Run in ServiceLoadBalancerOpts instance func (o *ServiceLoadBalancerOpts) Run() error { return o.CreateSubcommandOptions.Run() } @@ -273,6 +279,7 @@ var ( kubectl create service externalname my-ns --external-name bar.com`)) ) +// ServiceExternalNameOpts holds the options for 'create service externalname' sub command type ServiceExternalNameOpts struct { CreateSubcommandOptions *CreateSubcommandOptions } @@ -306,6 +313,7 @@ func NewCmdCreateServiceExternalName(f cmdutil.Factory, ioStreams genericcliopti return cmd } +// Complete completes all the required options func (o *ServiceExternalNameOpts) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error { name, err := NameFromCommandArgs(cmd, args) if err != nil { @@ -328,7 +336,7 @@ func (o *ServiceExternalNameOpts) Complete(f cmdutil.Factory, cmd *cobra.Command return o.CreateSubcommandOptions.Complete(f, cmd, args, generator) } -// CreateExternalNameService is the implementation of the create service externalname command +// Run calls the CreateSubcommandOptions.Run in ServiceExternalNameOpts instance func (o *ServiceExternalNameOpts) Run() error { return o.CreateSubcommandOptions.Run() } diff --git a/pkg/kubectl/cmd/create/create_serviceaccount.go b/pkg/kubectl/cmd/create/create_serviceaccount.go index 69090356106..bbf9eb98fb7 100644 --- a/pkg/kubectl/cmd/create/create_serviceaccount.go +++ b/pkg/kubectl/cmd/create/create_serviceaccount.go @@ -36,6 +36,7 @@ var ( kubectl create serviceaccount my-service-account`)) ) +// ServiceAccountOpts holds the options for 'create serviceaccount' sub command type ServiceAccountOpts struct { CreateSubcommandOptions *CreateSubcommandOptions } @@ -67,6 +68,7 @@ func NewCmdCreateServiceAccount(f cmdutil.Factory, ioStreams genericclioptions.I return cmd } +// Complete completes all the required options func (o *ServiceAccountOpts) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error { name, err := NameFromCommandArgs(cmd, args) if err != nil { @@ -84,7 +86,7 @@ func (o *ServiceAccountOpts) Complete(f cmdutil.Factory, cmd *cobra.Command, arg return o.CreateSubcommandOptions.Complete(f, cmd, args, generator) } -// CreateServiceAccount implements the behavior to run the create service account command +// Run calls the CreateSubcommandOptions.Run in ServiceAccountOpts instance func (o *ServiceAccountOpts) Run() error { return o.CreateSubcommandOptions.Run() } diff --git a/pkg/kubectl/cmd/delete/delete.go b/pkg/kubectl/cmd/delete/delete.go index 84b6db50bfe..dcb858f8105 100644 --- a/pkg/kubectl/cmd/delete/delete.go +++ b/pkg/kubectl/cmd/delete/delete.go @@ -33,13 +33,13 @@ import ( "k8s.io/cli-runtime/pkg/genericclioptions/resource" "k8s.io/client-go/dynamic" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" - kubectlwait "k8s.io/kubernetes/pkg/kubectl/cmd/wait" + cmdwait "k8s.io/kubernetes/pkg/kubectl/cmd/wait" "k8s.io/kubernetes/pkg/kubectl/util/i18n" "k8s.io/kubernetes/pkg/kubectl/util/templates" ) var ( - delete_long = templates.LongDesc(i18n.T(` + deleteLong = templates.LongDesc(i18n.T(` Delete resources by filenames, stdin, resources and names, or by resources and label selector. JSON and YAML formats are accepted. Only one type of the arguments may be specified: filenames, @@ -67,7 +67,7 @@ var ( update to a resource right when you submit a delete, their update will be lost along with the rest of the resource.`)) - delete_example = templates.Examples(i18n.T(` + deleteExample = templates.Examples(i18n.T(` # Delete a pod using the type and name specified in pod.json. kubectl delete -f ./pod.json @@ -121,8 +121,8 @@ func NewCmdDelete(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra Use: "delete ([-f FILENAME] | TYPE [(NAME | -l label | --all)])", DisableFlagsInUseLine: true, Short: i18n.T("Delete resources by filenames, stdin, resources and names, or by resources and label selector"), - Long: delete_long, - Example: delete_example, + Long: deleteLong, + Example: deleteExample, Run: func(cmd *cobra.Command, args []string) { o := deleteFlags.ToOptions(nil, streams) cmdutil.CheckErr(o.Complete(f, args, cmd)) @@ -196,7 +196,7 @@ func (o *DeleteOptions) Complete(f cmdutil.Factory, args []string, cmd *cobra.Co func (o *DeleteOptions) Validate() error { if o.Output != "" && o.Output != "name" { - return fmt.Errorf("unexpected -o output mode: %v. We only support '-o name'.", o.Output) + return fmt.Errorf("unexpected -o output mode: %v. We only support '-o name'", o.Output) } if o.DeleteAll && len(o.LabelSelector) > 0 { @@ -225,7 +225,7 @@ func (o *DeleteOptions) DeleteResult(r *resource.Result) error { r = r.IgnoreErrors(errors.IsNotFound) } deletedInfos := []*resource.Info{} - uidMap := kubectlwait.UIDMap{} + uidMap := cmdwait.UIDMap{} err := r.Visit(func(info *resource.Info, err error) error { if err != nil { return err @@ -247,7 +247,7 @@ func (o *DeleteOptions) DeleteResult(r *resource.Result) error { if err != nil { return err } - resourceLocation := kubectlwait.ResourceLocation{ + resourceLocation := cmdwait.ResourceLocation{ GroupResource: info.Mapping.Resource.GroupResource(), Namespace: info.Namespace, Name: info.Name, @@ -287,14 +287,14 @@ func (o *DeleteOptions) DeleteResult(r *resource.Result) error { // if we requested to wait forever, set it to a week. effectiveTimeout = 168 * time.Hour } - waitOptions := kubectlwait.WaitOptions{ + waitOptions := cmdwait.WaitOptions{ ResourceFinder: genericclioptions.ResourceFinderForResult(resource.InfoListVisitor(deletedInfos)), UIDMap: uidMap, DynamicClient: o.DynamicClient, Timeout: effectiveTimeout, Printer: printers.NewDiscardingPrinter(), - ConditionFn: kubectlwait.IsDeleted, + ConditionFn: cmdwait.IsDeleted, IOStreams: o.IOStreams, } err = waitOptions.RunWait() @@ -317,7 +317,7 @@ func (o *DeleteOptions) deleteResource(info *resource.Info, deleteOptions *metav return deleteResponse, nil } -// deletion printing is special because we do not have an object to print. +// PrintObj for deleted objects is special because we do not have an object to print. // This mirrors name printer behavior func (o *DeleteOptions) PrintObj(info *resource.Info) { operation := "deleted" diff --git a/pkg/kubectl/cmd/delete/delete_flags.go b/pkg/kubectl/cmd/delete/delete_flags.go index f6dcc74d95f..22751c697d0 100644 --- a/pkg/kubectl/cmd/delete/delete_flags.go +++ b/pkg/kubectl/cmd/delete/delete_flags.go @@ -25,7 +25,7 @@ import ( "k8s.io/client-go/dynamic" ) -// PrintFlags composes common printer flag structs +// DeleteFlags composes common printer flag structs // used for commands requiring deletion logic. type DeleteFlags struct { FileNameFlags *genericclioptions.FileNameFlags diff --git a/pkg/kubectl/cmd/describe/describe.go b/pkg/kubectl/cmd/describe/describe.go index c1c84cd1717..85616898af3 100644 --- a/pkg/kubectl/cmd/describe/describe.go +++ b/pkg/kubectl/cmd/describe/describe.go @@ -105,7 +105,7 @@ func NewCmdDescribe(parent string, f cmdutil.Factory, streams genericclioptions. Use: "describe (-f FILENAME | TYPE [NAME_PREFIX | -l label] | TYPE/NAME)", DisableFlagsInUseLine: true, Short: i18n.T("Show details of a specific resource or group of resources"), - Long: describeLong + "\n\n" + cmdutil.SuggestApiResources(parent), + Long: describeLong + "\n\n" + cmdutil.SuggestAPIResources(parent), Example: describeExample, Run: func(cmd *cobra.Command, args []string) { cmdutil.CheckErr(o.Complete(f, cmd, args)) @@ -115,7 +115,7 @@ func NewCmdDescribe(parent string, f cmdutil.Factory, streams genericclioptions. usage := "containing the resource to describe" cmdutil.AddFilenameOptionFlags(cmd, o.FilenameOptions, usage) cmd.Flags().StringVarP(&o.Selector, "selector", "l", o.Selector, "Selector (label query) to filter on, supports '=', '==', and '!='.(e.g. -l key1=value1,key2=value2)") - cmd.Flags().BoolVar(&o.AllNamespaces, "all-namespaces", o.AllNamespaces, "If present, list the requested object(s) across all namespaces. Namespace in current context is ignored even if specified with --namespace.") + cmd.Flags().BoolVarP(&o.AllNamespaces, "all-namespaces", "A", o.AllNamespaces, "If present, list the requested object(s) across all namespaces. Namespace in current context is ignored even if specified with --namespace.") cmd.Flags().BoolVar(&o.DescriberSettings.ShowEvents, "show-events", o.DescriberSettings.ShowEvents, "If true, display events related to the described object.") cmdutil.AddIncludeUninitializedFlag(cmd) return cmd @@ -133,7 +133,7 @@ func (o *DescribeOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args [ } if len(args) == 0 && cmdutil.IsFilenameSliceEmpty(o.FilenameOptions.Filenames) { - return fmt.Errorf("You must specify the type of resource to describe. %s\n", cmdutil.SuggestApiResources(o.CmdParent)) + return fmt.Errorf("You must specify the type of resource to describe. %s\n", cmdutil.SuggestAPIResources(o.CmdParent)) } o.BuilderArgs = args diff --git a/pkg/kubectl/cmd/diff/diff.go b/pkg/kubectl/cmd/diff/diff.go index beea85f068a..e64e8a0990d 100644 --- a/pkg/kubectl/cmd/diff/diff.go +++ b/pkg/kubectl/cmd/diff/diff.go @@ -331,7 +331,17 @@ func (obj InfoObject) Merged() (runtime.Object, error) { } func (obj InfoObject) Name() string { - return obj.Info.Name + group := "" + if obj.Info.Mapping.GroupVersionKind.Group != "" { + group = fmt.Sprintf("%v.", obj.Info.Mapping.GroupVersionKind.Group) + } + return group + fmt.Sprintf( + "%v.%v.%v.%v", + obj.Info.Mapping.GroupVersionKind.Version, + obj.Info.Mapping.GroupVersionKind.Kind, + obj.Info.Namespace, + obj.Info.Name, + ) } // Differ creates two DiffVersion and diffs them. diff --git a/pkg/kubectl/cmd/drain/BUILD b/pkg/kubectl/cmd/drain/BUILD index d90246eb875..b340ba7ef7e 100644 --- a/pkg/kubectl/cmd/drain/BUILD +++ b/pkg/kubectl/cmd/drain/BUILD @@ -40,9 +40,9 @@ go_test( "//pkg/kubectl/cmd/testing:go_default_library", "//pkg/kubectl/cmd/util:go_default_library", "//pkg/kubectl/scheme:go_default_library", + "//staging/src/k8s.io/api/apps/v1:go_default_library", "//staging/src/k8s.io/api/batch/v1:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library", - "//staging/src/k8s.io/api/extensions/v1beta1:go_default_library", "//staging/src/k8s.io/api/policy/v1beta1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", diff --git a/pkg/kubectl/cmd/drain/drain.go b/pkg/kubectl/cmd/drain/drain.go index d24ab8ac6bb..a7e50e9d7e8 100644 --- a/pkg/kubectl/cmd/drain/drain.go +++ b/pkg/kubectl/cmd/drain/drain.go @@ -84,79 +84,72 @@ const ( EvictionKind = "Eviction" EvictionSubresource = "pods/eviction" - kDaemonsetFatal = "DaemonSet-managed pods (use --ignore-daemonsets to ignore)" - kDaemonsetWarning = "Ignoring DaemonSet-managed pods" - kLocalStorageFatal = "pods with local storage (use --delete-local-data to override)" - kLocalStorageWarning = "Deleting pods with local storage" - kUnmanagedFatal = "pods not managed by ReplicationController, ReplicaSet, Job, DaemonSet or StatefulSet (use --force to override)" - kUnmanagedWarning = "Deleting pods not managed by ReplicationController, ReplicaSet, Job, DaemonSet or StatefulSet" + daemonsetFatal = "DaemonSet-managed Pods (use --ignore-daemonsets to ignore)" + daemonsetWarning = "ignoring DaemonSet-managed Pods" + localStorageFatal = "Pods with local storage (use --delete-local-data to override)" + localStorageWarning = "deleting Pods with local storage" + unmanagedFatal = "Pods not managed by ReplicationController, ReplicaSet, Job, DaemonSet or StatefulSet (use --force to override)" + unmanagedWarning = "deleting Pods not managed by ReplicationController, ReplicaSet, Job, DaemonSet or StatefulSet" ) var ( - cordon_long = templates.LongDesc(i18n.T(` + cordonLong = templates.LongDesc(i18n.T(` Mark node as unschedulable.`)) - cordon_example = templates.Examples(i18n.T(` + cordonExample = templates.Examples(i18n.T(` # Mark node "foo" as unschedulable. kubectl cordon foo`)) ) func NewCmdCordon(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command { - options := &DrainOptions{ - PrintFlags: genericclioptions.NewPrintFlags("cordoned").WithTypeSetter(scheme.Scheme), - - IOStreams: ioStreams, - } + o := NewDrainOptions(f, ioStreams) cmd := &cobra.Command{ Use: "cordon NODE", DisableFlagsInUseLine: true, Short: i18n.T("Mark node as unschedulable"), - Long: cordon_long, - Example: cordon_example, + Long: cordonLong, + Example: cordonExample, Run: func(cmd *cobra.Command, args []string) { - cmdutil.CheckErr(options.Complete(f, cmd, args)) - cmdutil.CheckErr(options.RunCordonOrUncordon(true)) + cmdutil.CheckErr(o.Complete(f, cmd, args)) + cmdutil.CheckErr(o.RunCordonOrUncordon(true)) }, } - cmd.Flags().StringVarP(&options.Selector, "selector", "l", options.Selector, "Selector (label query) to filter on") + cmd.Flags().StringVarP(&o.Selector, "selector", "l", o.Selector, "Selector (label query) to filter on") cmdutil.AddDryRunFlag(cmd) return cmd } var ( - uncordon_long = templates.LongDesc(i18n.T(` + uncordonLong = templates.LongDesc(i18n.T(` Mark node as schedulable.`)) - uncordon_example = templates.Examples(i18n.T(` + uncordonExample = templates.Examples(i18n.T(` # Mark node "foo" as schedulable. $ kubectl uncordon foo`)) ) func NewCmdUncordon(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command { - options := &DrainOptions{ - PrintFlags: genericclioptions.NewPrintFlags("uncordoned").WithTypeSetter(scheme.Scheme), - IOStreams: ioStreams, - } + o := NewDrainOptions(f, ioStreams) cmd := &cobra.Command{ Use: "uncordon NODE", DisableFlagsInUseLine: true, Short: i18n.T("Mark node as schedulable"), - Long: uncordon_long, - Example: uncordon_example, + Long: uncordonLong, + Example: uncordonExample, Run: func(cmd *cobra.Command, args []string) { - cmdutil.CheckErr(options.Complete(f, cmd, args)) - cmdutil.CheckErr(options.RunCordonOrUncordon(false)) + cmdutil.CheckErr(o.Complete(f, cmd, args)) + cmdutil.CheckErr(o.RunCordonOrUncordon(false)) }, } - cmd.Flags().StringVarP(&options.Selector, "selector", "l", options.Selector, "Selector (label query) to filter on") + cmd.Flags().StringVarP(&o.Selector, "selector", "l", o.Selector, "Selector (label query) to filter on") cmdutil.AddDryRunFlag(cmd) return cmd } var ( - drain_long = templates.LongDesc(i18n.T(` + drainLong = templates.LongDesc(i18n.T(` Drain node in preparation for maintenance. The given node will be marked unschedulable to prevent new pods from arriving. @@ -181,7 +174,7 @@ var ( ![Workflow](http://kubernetes.io/images/docs/kubectl_drain.svg)`)) - drain_example = templates.Examples(i18n.T(` + drainExample = templates.Examples(i18n.T(` # Drain node "foo", even if there are pods not managed by a ReplicationController, ReplicaSet, Job, DaemonSet or StatefulSet on it. $ kubectl drain foo --force @@ -199,26 +192,26 @@ func NewDrainOptions(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) * } func NewCmdDrain(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command { - options := NewDrainOptions(f, ioStreams) + o := NewDrainOptions(f, ioStreams) cmd := &cobra.Command{ Use: "drain NODE", DisableFlagsInUseLine: true, Short: i18n.T("Drain node in preparation for maintenance"), - Long: drain_long, - Example: drain_example, + Long: drainLong, + Example: drainExample, Run: func(cmd *cobra.Command, args []string) { - cmdutil.CheckErr(options.Complete(f, cmd, args)) - cmdutil.CheckErr(options.RunDrain()) + cmdutil.CheckErr(o.Complete(f, cmd, args)) + cmdutil.CheckErr(o.RunDrain()) }, } - cmd.Flags().BoolVar(&options.Force, "force", options.Force, "Continue even if there are pods not managed by a ReplicationController, ReplicaSet, Job, DaemonSet or StatefulSet.") - cmd.Flags().BoolVar(&options.IgnoreDaemonsets, "ignore-daemonsets", options.IgnoreDaemonsets, "Ignore DaemonSet-managed pods.") - cmd.Flags().BoolVar(&options.DeleteLocalData, "delete-local-data", options.DeleteLocalData, "Continue even if there are pods using emptyDir (local data that will be deleted when the node is drained).") - cmd.Flags().IntVar(&options.GracePeriodSeconds, "grace-period", options.GracePeriodSeconds, "Period of time in seconds given to each pod to terminate gracefully. If negative, the default value specified in the pod will be used.") - cmd.Flags().DurationVar(&options.Timeout, "timeout", options.Timeout, "The length of time to wait before giving up, zero means infinite") - cmd.Flags().StringVarP(&options.Selector, "selector", "l", options.Selector, "Selector (label query) to filter on") - cmd.Flags().StringVarP(&options.PodSelector, "pod-selector", "", options.PodSelector, "Label selector to filter pods on the node") + cmd.Flags().BoolVar(&o.Force, "force", o.Force, "Continue even if there are pods not managed by a ReplicationController, ReplicaSet, Job, DaemonSet or StatefulSet.") + cmd.Flags().BoolVar(&o.IgnoreDaemonsets, "ignore-daemonsets", o.IgnoreDaemonsets, "Ignore DaemonSet-managed pods.") + cmd.Flags().BoolVar(&o.DeleteLocalData, "delete-local-data", o.DeleteLocalData, "Continue even if there are pods using emptyDir (local data that will be deleted when the node is drained).") + cmd.Flags().IntVar(&o.GracePeriodSeconds, "grace-period", o.GracePeriodSeconds, "Period of time in seconds given to each pod to terminate gracefully. If negative, the default value specified in the pod will be used.") + cmd.Flags().DurationVar(&o.Timeout, "timeout", o.Timeout, "The length of time to wait before giving up, zero means infinite") + cmd.Flags().StringVarP(&o.Selector, "selector", "l", o.Selector, "Selector (label query) to filter on") + cmd.Flags().StringVarP(&o.PodSelector, "pod-selector", "", o.PodSelector, "Label selector to filter pods on the node") cmdutil.AddDryRunFlag(cmd) return cmd @@ -386,10 +379,10 @@ func (o *DrainOptions) unreplicatedFilter(pod corev1.Pod) (bool, *warning, *fata return true, nil, nil } if o.Force { - return true, &warning{kUnmanagedWarning}, nil + return true, &warning{unmanagedWarning}, nil } - return false, nil, &fatal{kUnmanagedFatal} + return false, nil, &fatal{unmanagedFatal} } func (o *DrainOptions) daemonsetFilter(pod corev1.Pod) (bool, *warning, *fatal) { @@ -408,7 +401,7 @@ func (o *DrainOptions) daemonsetFilter(pod corev1.Pod) (bool, *warning, *fatal) return true, nil, nil } - if _, err := o.client.ExtensionsV1beta1().DaemonSets(pod.Namespace).Get(controllerRef.Name, metav1.GetOptions{}); err != nil { + if _, err := o.client.AppsV1().DaemonSets(pod.Namespace).Get(controllerRef.Name, metav1.GetOptions{}); err != nil { // remove orphaned pods with a warning if --force is used if apierrors.IsNotFound(err) && o.Force { return true, &warning{err.Error()}, nil @@ -418,10 +411,10 @@ func (o *DrainOptions) daemonsetFilter(pod corev1.Pod) (bool, *warning, *fatal) } if !o.IgnoreDaemonsets { - return false, nil, &fatal{kDaemonsetFatal} + return false, nil, &fatal{daemonsetFatal} } - return false, &warning{kDaemonsetWarning}, nil + return false, &warning{daemonsetWarning}, nil } func mirrorPodFilter(pod corev1.Pod) (bool, *warning, *fatal) { @@ -450,10 +443,10 @@ func (o *DrainOptions) localStorageFilter(pod corev1.Pod) (bool, *warning, *fata return true, nil, nil } if !o.DeleteLocalData { - return false, nil, &fatal{kLocalStorageFatal} + return false, nil, &fatal{localStorageFatal} } - return true, &warning{kLocalStorageWarning}, nil + return true, &warning{localStorageWarning}, nil } // Map of status message to a list of pod names having that status. diff --git a/pkg/kubectl/cmd/drain/drain_test.go b/pkg/kubectl/cmd/drain/drain_test.go index 0d4d2bbf1a5..d0c3eb66233 100644 --- a/pkg/kubectl/cmd/drain/drain_test.go +++ b/pkg/kubectl/cmd/drain/drain_test.go @@ -33,9 +33,9 @@ import ( "github.com/spf13/cobra" "k8s.io/cli-runtime/pkg/genericclioptions" + appsv1 "k8s.io/api/apps/v1" batchv1 "k8s.io/api/batch/v1" corev1 "k8s.io/api/core/v1" - extensionsv1beta1 "k8s.io/api/extensions/v1beta1" policyv1beta1 "k8s.io/api/policy/v1beta1" apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -57,7 +57,7 @@ const ( ) var node *corev1.Node -var cordoned_node *corev1.Node +var cordonedNode *corev1.Node func boolptr(b bool) *bool { return &b } @@ -72,8 +72,8 @@ func TestMain(m *testing.M) { } // A copy of the same node, but cordoned. - cordoned_node = node.DeepCopy() - cordoned_node.Spec.Unschedulable = true + cordonedNode = node.DeepCopy() + cordonedNode.Spec.Unschedulable = true os.Exit(m.Run()) } @@ -88,7 +88,7 @@ func TestCordon(t *testing.T) { }{ { description: "node/node syntax", - node: cordoned_node, + node: cordonedNode, expected: node, cmd: NewCmdUncordon, arg: "node/node", @@ -96,7 +96,7 @@ func TestCordon(t *testing.T) { }, { description: "uncordon for real", - node: cordoned_node, + node: cordonedNode, expected: node, cmd: NewCmdUncordon, arg: "node", @@ -112,8 +112,8 @@ func TestCordon(t *testing.T) { }, { description: "cordon does nothing", - node: cordoned_node, - expected: cordoned_node, + node: cordonedNode, + expected: cordonedNode, cmd: NewCmdCordon, arg: "node", expectFatal: false, @@ -121,7 +121,7 @@ func TestCordon(t *testing.T) { { description: "cordon for real", node: node, - expected: cordoned_node, + expected: cordonedNode, cmd: NewCmdCordon, arg: "node", expectFatal: false, @@ -145,14 +145,14 @@ func TestCordon(t *testing.T) { { description: "cordon for multiple nodes", node: node, - expected: cordoned_node, + expected: cordonedNode, cmd: NewCmdCordon, arg: "node node1 node2", expectFatal: false, }, { description: "uncordon for multiple nodes", - node: cordoned_node, + node: cordonedNode, expected: node, cmd: NewCmdUncordon, arg: "node node1 node2", @@ -168,7 +168,7 @@ func TestCordon(t *testing.T) { codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) ns := scheme.Codecs - new_node := &corev1.Node{} + newNode := &corev1.Node{} updated := false tf.Client = &fake.RESTClient{ GroupVersion: schema.GroupVersion{Group: "", Version: "v1"}, @@ -202,14 +202,14 @@ func TestCordon(t *testing.T) { if err != nil { t.Fatalf("%s: unexpected error: %v", test.description, err) } - if err := runtime.DecodeInto(codec, appliedPatch, new_node); err != nil { + if err := runtime.DecodeInto(codec, appliedPatch, newNode); err != nil { t.Fatalf("%s: unexpected error: %v", test.description, err) } - if !reflect.DeepEqual(test.expected.Spec, new_node.Spec) { - t.Fatalf("%s: expected:\n%v\nsaw:\n%v\n", test.description, test.expected.Spec.Unschedulable, new_node.Spec.Unschedulable) + if !reflect.DeepEqual(test.expected.Spec, newNode.Spec) { + t.Fatalf("%s: expected:\n%v\nsaw:\n%v\n", test.description, test.expected.Spec.Unschedulable, newNode.Spec.Unschedulable) } updated = true - return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, new_node)}, nil + return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, newNode)}, nil default: t.Fatalf("%s: unexpected request: %v %#v\n%#v", test.description, req.Method, req.URL, req) return nil, nil @@ -221,7 +221,7 @@ func TestCordon(t *testing.T) { ioStreams, _, _, _ := genericclioptions.NewTestIOStreams() cmd := test.cmd(tf, ioStreams) - saw_fatal := false + sawFatal := false func() { defer func() { // Recover from the panic below. @@ -230,7 +230,7 @@ func TestCordon(t *testing.T) { cmdutil.DefaultBehaviorOnFatal() }() cmdutil.BehaviorOnFatal(func(e string, code int) { - saw_fatal = true + sawFatal = true panic(e) }) cmd.SetArgs(strings.Split(test.arg, " ")) @@ -238,7 +238,7 @@ func TestCordon(t *testing.T) { }() if test.expectFatal { - if !saw_fatal { + if !sawFatal { t.Fatalf("%s: unexpected non-error", test.description) } if updated { @@ -246,7 +246,7 @@ func TestCordon(t *testing.T) { } } - if !test.expectFatal && saw_fatal { + if !test.expectFatal && sawFatal { t.Fatalf("%s: unexpected error", test.description) } if !reflect.DeepEqual(test.expected.Spec, test.node.Spec) && !updated { @@ -272,7 +272,7 @@ func TestDrain(t *testing.T) { }, } - rc_pod := corev1.Pod{ + rcPod := corev1.Pod{ ObjectMeta: metav1.ObjectMeta{ Name: "bar", Namespace: "default", @@ -294,18 +294,18 @@ func TestDrain(t *testing.T) { }, } - ds := extensionsv1beta1.DaemonSet{ + ds := appsv1.DaemonSet{ ObjectMeta: metav1.ObjectMeta{ Name: "ds", Namespace: "default", CreationTimestamp: metav1.Time{Time: time.Now()}, }, - Spec: extensionsv1beta1.DaemonSetSpec{ + Spec: appsv1.DaemonSetSpec{ Selector: &metav1.LabelSelector{MatchLabels: labels}, }, } - ds_pod := corev1.Pod{ + dsPod := corev1.Pod{ ObjectMeta: metav1.ObjectMeta{ Name: "bar", Namespace: "default", @@ -313,7 +313,7 @@ func TestDrain(t *testing.T) { Labels: labels, OwnerReferences: []metav1.OwnerReference{ { - APIVersion: "extensions/v1beta1", + APIVersion: "apps/v1", Kind: "DaemonSet", Name: "ds", BlockOwnerDeletion: boolptr(true), @@ -326,7 +326,7 @@ func TestDrain(t *testing.T) { }, } - ds_terminated_pod := corev1.Pod{ + dsTerminatedPod := corev1.Pod{ ObjectMeta: metav1.ObjectMeta{ Name: "bar", Namespace: "default", @@ -334,7 +334,7 @@ func TestDrain(t *testing.T) { Labels: labels, OwnerReferences: []metav1.OwnerReference{ { - APIVersion: "extensions/v1beta1", + APIVersion: "apps/v1", Kind: "DaemonSet", Name: "ds", BlockOwnerDeletion: boolptr(true), @@ -350,7 +350,7 @@ func TestDrain(t *testing.T) { }, } - ds_pod_with_emptyDir := corev1.Pod{ + dsPodWithEmptyDir := corev1.Pod{ ObjectMeta: metav1.ObjectMeta{ Name: "bar", Namespace: "default", @@ -358,7 +358,7 @@ func TestDrain(t *testing.T) { Labels: labels, OwnerReferences: []metav1.OwnerReference{ { - APIVersion: "extensions/v1beta1", + APIVersion: "apps/v1", Kind: "DaemonSet", Name: "ds", BlockOwnerDeletion: boolptr(true), @@ -377,7 +377,7 @@ func TestDrain(t *testing.T) { }, } - orphaned_ds_pod := corev1.Pod{ + orphanedDsPod := corev1.Pod{ ObjectMeta: metav1.ObjectMeta{ Name: "bar", Namespace: "default", @@ -400,7 +400,7 @@ func TestDrain(t *testing.T) { }, } - job_pod := corev1.Pod{ + jobPod := corev1.Pod{ ObjectMeta: metav1.ObjectMeta{ Name: "bar", Namespace: "default", @@ -427,7 +427,7 @@ func TestDrain(t *testing.T) { }, } - terminated_job_pod_with_local_storage := corev1.Pod{ + terminatedJobPodWithLocalStorage := corev1.Pod{ ObjectMeta: metav1.ObjectMeta{ Name: "bar", Namespace: "default", @@ -457,19 +457,19 @@ func TestDrain(t *testing.T) { }, } - rs := extensionsv1beta1.ReplicaSet{ + rs := appsv1.ReplicaSet{ ObjectMeta: metav1.ObjectMeta{ Name: "rs", Namespace: "default", CreationTimestamp: metav1.Time{Time: time.Now()}, Labels: labels, }, - Spec: extensionsv1beta1.ReplicaSetSpec{ + Spec: appsv1.ReplicaSetSpec{ Selector: &metav1.LabelSelector{MatchLabels: labels}, }, } - rs_pod := corev1.Pod{ + rsPod := corev1.Pod{ ObjectMeta: metav1.ObjectMeta{ Name: "bar", Namespace: "default", @@ -490,7 +490,7 @@ func TestDrain(t *testing.T) { }, } - naked_pod := corev1.Pod{ + nakedPod := corev1.Pod{ ObjectMeta: metav1.ObjectMeta{ Name: "bar", Namespace: "default", @@ -502,7 +502,7 @@ func TestDrain(t *testing.T) { }, } - emptydir_pod := corev1.Pod{ + emptydirPod := corev1.Pod{ ObjectMeta: metav1.ObjectMeta{ Name: "bar", Namespace: "default", @@ -519,7 +519,7 @@ func TestDrain(t *testing.T) { }, }, } - emptydir_terminated_pod := corev1.Pod{ + emptydirTerminatedPod := corev1.Pod{ ObjectMeta: metav1.ObjectMeta{ Name: "bar", Namespace: "default", @@ -546,7 +546,7 @@ func TestDrain(t *testing.T) { expected *corev1.Node pods []corev1.Pod rcs []corev1.ReplicationController - replicaSets []extensionsv1beta1.ReplicaSet + replicaSets []appsv1.ReplicaSet args []string expectWarning string expectFatal bool @@ -555,8 +555,8 @@ func TestDrain(t *testing.T) { { description: "RC-managed pod", node: node, - expected: cordoned_node, - pods: []corev1.Pod{rc_pod}, + expected: cordonedNode, + pods: []corev1.Pod{rcPod}, rcs: []corev1.ReplicationController{rc}, args: []string{"node"}, expectFatal: false, @@ -565,8 +565,8 @@ func TestDrain(t *testing.T) { { description: "DS-managed pod", node: node, - expected: cordoned_node, - pods: []corev1.Pod{ds_pod}, + expected: cordonedNode, + pods: []corev1.Pod{dsPod}, rcs: []corev1.ReplicationController{rc}, args: []string{"node"}, expectFatal: true, @@ -575,8 +575,8 @@ func TestDrain(t *testing.T) { { description: "DS-managed terminated pod", node: node, - expected: cordoned_node, - pods: []corev1.Pod{ds_terminated_pod}, + expected: cordonedNode, + pods: []corev1.Pod{dsTerminatedPod}, rcs: []corev1.ReplicationController{rc}, args: []string{"node"}, expectFatal: false, @@ -585,8 +585,8 @@ func TestDrain(t *testing.T) { { description: "orphaned DS-managed pod", node: node, - expected: cordoned_node, - pods: []corev1.Pod{orphaned_ds_pod}, + expected: cordonedNode, + pods: []corev1.Pod{orphanedDsPod}, rcs: []corev1.ReplicationController{}, args: []string{"node"}, expectFatal: true, @@ -595,8 +595,8 @@ func TestDrain(t *testing.T) { { description: "orphaned DS-managed pod with --force", node: node, - expected: cordoned_node, - pods: []corev1.Pod{orphaned_ds_pod}, + expected: cordonedNode, + pods: []corev1.Pod{orphanedDsPod}, rcs: []corev1.ReplicationController{}, args: []string{"node", "--force"}, expectFatal: false, @@ -605,8 +605,8 @@ func TestDrain(t *testing.T) { { description: "DS-managed pod with --ignore-daemonsets", node: node, - expected: cordoned_node, - pods: []corev1.Pod{ds_pod}, + expected: cordonedNode, + pods: []corev1.Pod{dsPod}, rcs: []corev1.ReplicationController{rc}, args: []string{"node", "--ignore-daemonsets"}, expectFatal: false, @@ -615,19 +615,19 @@ func TestDrain(t *testing.T) { { description: "DS-managed pod with emptyDir with --ignore-daemonsets", node: node, - expected: cordoned_node, - pods: []corev1.Pod{ds_pod_with_emptyDir}, + expected: cordonedNode, + pods: []corev1.Pod{dsPodWithEmptyDir}, rcs: []corev1.ReplicationController{rc}, args: []string{"node", "--ignore-daemonsets"}, - expectWarning: "WARNING: Ignoring DaemonSet-managed pods: bar", + expectWarning: "WARNING: ignoring DaemonSet-managed Pods: bar", expectFatal: false, expectDelete: false, }, { description: "Job-managed pod with local storage", node: node, - expected: cordoned_node, - pods: []corev1.Pod{job_pod}, + expected: cordonedNode, + pods: []corev1.Pod{jobPod}, rcs: []corev1.ReplicationController{rc}, args: []string{"node", "--force", "--delete-local-data=true"}, expectFatal: false, @@ -636,8 +636,8 @@ func TestDrain(t *testing.T) { { description: "Job-managed terminated pod", node: node, - expected: cordoned_node, - pods: []corev1.Pod{terminated_job_pod_with_local_storage}, + expected: cordonedNode, + pods: []corev1.Pod{terminatedJobPodWithLocalStorage}, rcs: []corev1.ReplicationController{rc}, args: []string{"node"}, expectFatal: false, @@ -646,9 +646,9 @@ func TestDrain(t *testing.T) { { description: "RS-managed pod", node: node, - expected: cordoned_node, - pods: []corev1.Pod{rs_pod}, - replicaSets: []extensionsv1beta1.ReplicaSet{rs}, + expected: cordonedNode, + pods: []corev1.Pod{rsPod}, + replicaSets: []appsv1.ReplicaSet{rs}, args: []string{"node"}, expectFatal: false, expectDelete: true, @@ -656,8 +656,8 @@ func TestDrain(t *testing.T) { { description: "naked pod", node: node, - expected: cordoned_node, - pods: []corev1.Pod{naked_pod}, + expected: cordonedNode, + pods: []corev1.Pod{nakedPod}, rcs: []corev1.ReplicationController{}, args: []string{"node"}, expectFatal: true, @@ -666,8 +666,8 @@ func TestDrain(t *testing.T) { { description: "naked pod with --force", node: node, - expected: cordoned_node, - pods: []corev1.Pod{naked_pod}, + expected: cordonedNode, + pods: []corev1.Pod{nakedPod}, rcs: []corev1.ReplicationController{}, args: []string{"node", "--force"}, expectFatal: false, @@ -676,8 +676,8 @@ func TestDrain(t *testing.T) { { description: "pod with EmptyDir", node: node, - expected: cordoned_node, - pods: []corev1.Pod{emptydir_pod}, + expected: cordonedNode, + pods: []corev1.Pod{emptydirPod}, args: []string{"node", "--force"}, expectFatal: true, expectDelete: false, @@ -685,8 +685,8 @@ func TestDrain(t *testing.T) { { description: "terminated pod with emptyDir", node: node, - expected: cordoned_node, - pods: []corev1.Pod{emptydir_terminated_pod}, + expected: cordonedNode, + pods: []corev1.Pod{emptydirTerminatedPod}, rcs: []corev1.ReplicationController{rc}, args: []string{"node"}, expectFatal: false, @@ -695,8 +695,8 @@ func TestDrain(t *testing.T) { { description: "pod with EmptyDir and --delete-local-data", node: node, - expected: cordoned_node, - pods: []corev1.Pod{emptydir_pod}, + expected: cordonedNode, + pods: []corev1.Pod{emptydirPod}, args: []string{"node", "--force", "--delete-local-data=true"}, expectFatal: false, expectDelete: true, @@ -704,7 +704,7 @@ func TestDrain(t *testing.T) { { description: "empty node", node: node, - expected: cordoned_node, + expected: cordonedNode, pods: []corev1.Pod{}, rcs: []corev1.ReplicationController{rc}, args: []string{"node"}, @@ -724,7 +724,7 @@ func TestDrain(t *testing.T) { } for _, test := range tests { t.Run(test.description, func(t *testing.T) { - new_node := &corev1.Node{} + newNode := &corev1.Node{} deleted := false evicted := false tf := cmdtesting.NewTestFactory() @@ -776,7 +776,7 @@ func TestDrain(t *testing.T) { case m.isFor("GET", "/namespaces/default/daemonsets/ds"): return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &ds)}, nil case m.isFor("GET", "/namespaces/default/daemonsets/missing-ds"): - return &http.Response{StatusCode: 404, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &extensionsv1beta1.DaemonSet{})}, nil + return &http.Response{StatusCode: 404, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &appsv1.DaemonSet{})}, nil case m.isFor("GET", "/namespaces/default/jobs/job"): return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &job)}, nil case m.isFor("GET", "/namespaces/default/replicasets/rs"): @@ -788,10 +788,10 @@ func TestDrain(t *testing.T) { if err != nil { t.Fatalf("%s: unexpected error: %v", test.description, err) } - get_params := make(url.Values) - get_params["fieldSelector"] = []string{"spec.nodeName=node"} - if !reflect.DeepEqual(get_params, values) { - t.Fatalf("%s: expected:\n%v\nsaw:\n%v\n", test.description, get_params, values) + getParams := make(url.Values) + getParams["fieldSelector"] = []string{"spec.nodeName=node"} + if !reflect.DeepEqual(getParams, values) { + t.Fatalf("%s: expected:\n%v\nsaw:\n%v\n", test.description, getParams, values) } return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &corev1.PodList{Items: test.pods})}, nil case m.isFor("GET", "/replicationcontrollers"): @@ -810,13 +810,13 @@ func TestDrain(t *testing.T) { if err != nil { t.Fatalf("%s: unexpected error: %v", test.description, err) } - if err := runtime.DecodeInto(codec, appliedPatch, new_node); err != nil { + if err := runtime.DecodeInto(codec, appliedPatch, newNode); err != nil { t.Fatalf("%s: unexpected error: %v", test.description, err) } - if !reflect.DeepEqual(test.expected.Spec, new_node.Spec) { - t.Fatalf("%s: expected:\n%v\nsaw:\n%v\n", test.description, test.expected.Spec, new_node.Spec) + if !reflect.DeepEqual(test.expected.Spec, newNode.Spec) { + t.Fatalf("%s: expected:\n%v\nsaw:\n%v\n", test.description, test.expected.Spec, newNode.Spec) } - return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, new_node)}, nil + return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, newNode)}, nil case m.isFor("DELETE", "/namespaces/default/pods/bar"): deleted = true return &http.Response{StatusCode: 204, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &test.pods[0])}, nil @@ -834,8 +834,8 @@ func TestDrain(t *testing.T) { ioStreams, _, _, errBuf := genericclioptions.NewTestIOStreams() cmd := NewCmdDrain(tf, ioStreams) - saw_fatal := false - fatal_msg := "" + sawFatal := false + fatalMsg := "" func() { defer func() { // Recover from the panic below. @@ -843,17 +843,17 @@ func TestDrain(t *testing.T) { // Restore cmdutil behavior cmdutil.DefaultBehaviorOnFatal() }() - cmdutil.BehaviorOnFatal(func(e string, code int) { saw_fatal = true; fatal_msg = e; panic(e) }) + cmdutil.BehaviorOnFatal(func(e string, code int) { sawFatal = true; fatalMsg = e; panic(e) }) cmd.SetArgs(test.args) cmd.Execute() }() if test.expectFatal { - if !saw_fatal { + if !sawFatal { t.Fatalf("%s: unexpected non-error when using %s", test.description, currMethod) } } else { - if saw_fatal { - t.Fatalf("%s: unexpected error when using %s: %s", test.description, currMethod, fatal_msg) + if sawFatal { + t.Fatalf("%s: unexpected error when using %s: %s", test.description, currMethod, fatalMsg) } } @@ -1027,6 +1027,6 @@ func (m *MyReq) isFor(method string, path string) bool { return method == req.Method && (req.URL.Path == path || req.URL.Path == strings.Join([]string{"/api/v1", path}, "") || - req.URL.Path == strings.Join([]string{"/apis/extensions/v1beta1", path}, "") || + req.URL.Path == strings.Join([]string{"/apis/apps/v1", path}, "") || req.URL.Path == strings.Join([]string{"/apis/batch/v1", path}, "")) } diff --git a/pkg/kubectl/cmd/edit/testdata/testcase-edit-from-empty/test.yaml b/pkg/kubectl/cmd/edit/testdata/testcase-edit-from-empty/test.yaml index 1111145af99..7b7ecf8956c 100755 --- a/pkg/kubectl/cmd/edit/testdata/testcase-edit-from-empty/test.yaml +++ b/pkg/kubectl/cmd/edit/testdata/testcase-edit-from-empty/test.yaml @@ -4,7 +4,7 @@ args: - configmap namespace: "edit-test" expectedStderr: -- edit cancelled, no objects found. +- edit cancelled, no objects found expectedExitCode: 1 steps: - type: request diff --git a/pkg/kubectl/cmd/exec/exec.go b/pkg/kubectl/cmd/exec/exec.go index 2cf2aa57bb6..9f27a8a79d7 100644 --- a/pkg/kubectl/cmd/exec/exec.go +++ b/pkg/kubectl/cmd/exec/exec.go @@ -39,7 +39,7 @@ import ( ) var ( - exec_example = templates.Examples(i18n.T(` + execExample = templates.Examples(i18n.T(` # Get output from running 'date' from pod 123456-7890, using the first container by default kubectl exec 123456-7890 date @@ -76,7 +76,7 @@ func NewCmdExec(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.C DisableFlagsInUseLine: true, Short: i18n.T("Execute a command in a container"), Long: "Execute a command in a container.", - Example: exec_example, + Example: execExample, Run: func(cmd *cobra.Command, args []string) { argsLenAtDash := cmd.ArgsLenAtDash() cmdutil.CheckErr(options.Complete(f, cmd, args, argsLenAtDash)) diff --git a/pkg/kubectl/cmd/explain/explain.go b/pkg/kubectl/cmd/explain/explain.go index 73f6289fb4c..05ab3d89554 100644 --- a/pkg/kubectl/cmd/explain/explain.go +++ b/pkg/kubectl/cmd/explain/explain.go @@ -55,7 +55,7 @@ type ExplainOptions struct { genericclioptions.IOStreams CmdParent string - ApiVersion string + APIVersion string Recursive bool Mapper meta.RESTMapper @@ -77,7 +77,7 @@ func NewCmdExplain(parent string, f cmdutil.Factory, streams genericclioptions.I Use: "explain RESOURCE", DisableFlagsInUseLine: true, Short: i18n.T("Documentation of resources"), - Long: explainLong + "\n\n" + cmdutil.SuggestApiResources(parent), + Long: explainLong + "\n\n" + cmdutil.SuggestAPIResources(parent), Example: explainExamples, Run: func(cmd *cobra.Command, args []string) { cmdutil.CheckErr(o.Complete(f, cmd)) @@ -86,7 +86,7 @@ func NewCmdExplain(parent string, f cmdutil.Factory, streams genericclioptions.I }, } cmd.Flags().BoolVar(&o.Recursive, "recursive", o.Recursive, "Print the fields of fields (Currently only 1 level deep)") - cmd.Flags().StringVar(&o.ApiVersion, "api-version", o.ApiVersion, "Get different explanations for particular API version") + cmd.Flags().StringVar(&o.APIVersion, "api-version", o.APIVersion, "Get different explanations for particular API version") return cmd } @@ -106,7 +106,7 @@ func (o *ExplainOptions) Complete(f cmdutil.Factory, cmd *cobra.Command) error { func (o *ExplainOptions) Validate(args []string) error { if len(args) == 0 { - return fmt.Errorf("You must specify the type of resource to explain. %s\n", cmdutil.SuggestApiResources(o.CmdParent)) + return fmt.Errorf("You must specify the type of resource to explain. %s\n", cmdutil.SuggestAPIResources(o.CmdParent)) } if len(args) > 1 { return fmt.Errorf("We accept only this format: explain RESOURCE\n") @@ -118,7 +118,7 @@ func (o *ExplainOptions) Validate(args []string) error { // Run executes the appropriate steps to print a model's documentation func (o *ExplainOptions) Run(args []string) error { recursive := o.Recursive - apiVersionString := o.ApiVersion + apiVersionString := o.APIVersion // TODO: After we figured out the new syntax to separate group and resource, allow // the users to use it in explain (kubectl explain ). diff --git a/pkg/kubectl/cmd/get/BUILD b/pkg/kubectl/cmd/get/BUILD index c63ccad3fd1..3f15092e541 100644 --- a/pkg/kubectl/cmd/get/BUILD +++ b/pkg/kubectl/cmd/get/BUILD @@ -55,6 +55,7 @@ go_library( "//staging/src/k8s.io/client-go/tools/watch:go_default_library", "//staging/src/k8s.io/client-go/util/integer:go_default_library", "//staging/src/k8s.io/client-go/util/jsonpath:go_default_library", + "//vendor/github.com/liggitt/tabwriter:go_default_library", "//vendor/github.com/spf13/cobra:go_default_library", "//vendor/k8s.io/klog:go_default_library", "//vendor/vbom.ml/util/sortorder:go_default_library", diff --git a/pkg/kubectl/cmd/get/customcolumn.go b/pkg/kubectl/cmd/get/customcolumn.go index 576d4995af4..a5f6fa6dadf 100644 --- a/pkg/kubectl/cmd/get/customcolumn.go +++ b/pkg/kubectl/cmd/get/customcolumn.go @@ -24,7 +24,8 @@ import ( "reflect" "regexp" "strings" - "text/tabwriter" + + "github.com/liggitt/tabwriter" "k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/runtime" diff --git a/pkg/kubectl/cmd/get/get.go b/pkg/kubectl/cmd/get/get.go index 82a3d2f971b..751b591a0f3 100644 --- a/pkg/kubectl/cmd/get/get.go +++ b/pkg/kubectl/cmd/get/get.go @@ -153,7 +153,7 @@ func NewCmdGet(parent string, f cmdutil.Factory, streams genericclioptions.IOStr Use: "get [(-o|--output=)json|yaml|wide|custom-columns=...|custom-columns-file=...|go-template=...|go-template-file=...|jsonpath=...|jsonpath-file=...] (TYPE[.VERSION][.GROUP] [NAME | -l label] | TYPE[.VERSION][.GROUP]/NAME ...) [flags]", DisableFlagsInUseLine: true, Short: i18n.T("Display one or many resources"), - Long: getLong + "\n\n" + cmdutil.SuggestApiResources(parent), + Long: getLong + "\n\n" + cmdutil.SuggestAPIResources(parent), Example: getExample, Run: func(cmd *cobra.Command, args []string) { cmdutil.CheckErr(o.Complete(f, cmd, args)) @@ -172,7 +172,7 @@ func NewCmdGet(parent string, f cmdutil.Factory, streams genericclioptions.IOStr cmd.Flags().BoolVar(&o.IgnoreNotFound, "ignore-not-found", o.IgnoreNotFound, "If the requested object does not exist the command will return exit code 0.") cmd.Flags().StringVarP(&o.LabelSelector, "selector", "l", o.LabelSelector, "Selector (label query) to filter on, supports '=', '==', and '!='.(e.g. -l key1=value1,key2=value2)") cmd.Flags().StringVar(&o.FieldSelector, "field-selector", o.FieldSelector, "Selector (field query) to filter on, supports '=', '==', and '!='.(e.g. --field-selector key1=value1,key2=value2). The server only supports a limited number of field queries per type.") - cmd.Flags().BoolVar(&o.AllNamespaces, "all-namespaces", o.AllNamespaces, "If present, list the requested object(s) across all namespaces. Namespace in current context is ignored even if specified with --namespace.") + cmd.Flags().BoolVarP(&o.AllNamespaces, "all-namespaces", "A", o.AllNamespaces, "If present, list the requested object(s) across all namespaces. Namespace in current context is ignored even if specified with --namespace.") cmdutil.AddIncludeUninitializedFlag(cmd) addOpenAPIPrintColumnFlags(cmd, o) addServerPrintColumnFlags(cmd, o) @@ -261,7 +261,7 @@ func (o *GetOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []stri o.IncludeUninitialized = cmdutil.ShouldIncludeUninitialized(cmd, len(args) == 2) default: if len(args) == 0 && cmdutil.IsFilenameSliceEmpty(o.Filenames) { - fmt.Fprintf(o.ErrOut, "You must specify the type of resource to get. %s\n\n", cmdutil.SuggestApiResources(o.CmdParent)) + fmt.Fprintf(o.ErrOut, "You must specify the type of resource to get. %s\n\n", cmdutil.SuggestAPIResources(o.CmdParent)) fullCmdName := cmd.Parent().CommandPath() usageString := "Required resource not specified." if len(fullCmdName) > 0 && cmdutil.IsSiblingCommandExists(cmd, "explain") { @@ -296,16 +296,20 @@ func (o *GetOptions) Validate(cmd *cobra.Command) error { return nil } +// OriginalPositioner and NopPositioner is required for swap/sort operations of data in table format type OriginalPositioner interface { OriginalPosition(int) int } +// NopPositioner and OriginalPositioner is required for swap/sort operations of data in table format type NopPositioner struct{} +// OriginalPosition returns the original position from NopPositioner object func (t *NopPositioner) OriginalPosition(ix int) int { return ix } +// RuntimeSorter holds the required objects to perform sorting of runtime objects type RuntimeSorter struct { field string decoder runtime.Decoder @@ -313,6 +317,7 @@ type RuntimeSorter struct { positioner OriginalPositioner } +// Sort performs the sorting of runtime objects func (r *RuntimeSorter) Sort() error { // a list is only considered "sorted" if there are 0 or 1 items in it // AND (if 1 item) the item is not a Table object @@ -334,8 +339,10 @@ func (r *RuntimeSorter) Sort() error { case *metav1beta1.Table: includesTable = true - if err := NewTableSorter(t, r.field).Sort(); err != nil { - continue + if sorter, err := NewTableSorter(t, r.field); err != nil { + return err + } else if err := sorter.Sort(); err != nil { + return err } default: includesRuntimeObjs = true @@ -363,6 +370,7 @@ func (r *RuntimeSorter) Sort() error { return nil } +// OriginalPosition returns the original position of a runtime object func (r *RuntimeSorter) OriginalPosition(ix int) int { if r.positioner == nil { return 0 @@ -370,12 +378,13 @@ func (r *RuntimeSorter) OriginalPosition(ix int) int { return r.positioner.OriginalPosition(ix) } -// allows custom decoder to be set for testing +// WithDecoder allows custom decoder to be set for testing func (r *RuntimeSorter) WithDecoder(decoder runtime.Decoder) *RuntimeSorter { r.decoder = decoder return r } +// NewRuntimeSorter returns a new instance of RuntimeSorter func NewRuntimeSorter(objects []runtime.Object, sortBy string) *RuntimeSorter { parsedField, err := RelaxedJSONPathExpression(sortBy) if err != nil { @@ -528,6 +537,7 @@ func (o *GetOptions) Run(f cmdutil.Factory, cmd *cobra.Command, args []string) e if shouldGetNewPrinterForMapping(printer, lastMapping, mapping) { w.Flush() + w.SetRememberedWidths(nil) // TODO: this doesn't belong here // add linebreak between resource groups (if there is more than one) @@ -645,10 +655,11 @@ func (o *GetOptions) watch(f cmdutil.Factory, cmd *cobra.Command, args []string) } } + writer := utilprinters.GetNewTabWriter(o.Out) + // print the current object if !o.WatchOnly { var objsToPrint []runtime.Object - writer := utilprinters.GetNewTabWriter(o.Out) if isList { objsToPrint, _ = meta.ExtractList(obj) @@ -693,9 +704,10 @@ func (o *GetOptions) watch(f cmdutil.Factory, cmd *cobra.Command, args []string) internalGV := mapping.GroupVersionKind.GroupKind().WithVersion(runtime.APIVersionInternal).GroupVersion() objToPrint = attemptToConvertToInternal(e.Object, legacyscheme.Scheme, internalGV) } - if err := printer.PrintObj(objToPrint, o.Out); err != nil { + if err := printer.PrintObj(objToPrint, writer); err != nil { return false, err } + writer.Flush() return false, nil }) return err diff --git a/pkg/kubectl/cmd/get/get_flags.go b/pkg/kubectl/cmd/get/get_flags.go index 93700a85524..fcba4e5aa74 100644 --- a/pkg/kubectl/cmd/get/get_flags.go +++ b/pkg/kubectl/cmd/get/get_flags.go @@ -64,6 +64,7 @@ func (f *PrintFlags) Copy() PrintFlags { return printFlags } +// AllowedFormats is the list of formats in which data can be displayed func (f *PrintFlags) AllowedFormats() []string { formats := f.JSONYamlPrintFlags.AllowedFormats() formats = append(formats, f.NamePrintFlags.AllowedFormats()...) diff --git a/pkg/kubectl/cmd/get/get_test.go b/pkg/kubectl/cmd/get/get_test.go index 9d12a895794..bb17fad5c9c 100644 --- a/pkg/kubectl/cmd/get/get_test.go +++ b/pkg/kubectl/cmd/get/get_test.go @@ -1211,8 +1211,8 @@ func TestWatchLabelSelector(t *testing.T) { expected := `NAME READY STATUS RESTARTS AGE bar 0/0 0 foo 0/0 0 -foo 0/0 0 -foo 0/0 0 +foo 0/0 0 +foo 0/0 0 ` if e, a := expected, buf.String(); e != a { t.Errorf("expected\n%v\ngot\n%v", e, a) @@ -1262,8 +1262,8 @@ func TestWatchFieldSelector(t *testing.T) { expected := `NAME READY STATUS RESTARTS AGE bar 0/0 0 foo 0/0 0 -foo 0/0 0 -foo 0/0 0 +foo 0/0 0 +foo 0/0 0 ` if e, a := expected, buf.String(); e != a { t.Errorf("expected\n%v\ngot\n%v", e, a) @@ -1305,8 +1305,8 @@ func TestWatchResource(t *testing.T) { expected := `NAME READY STATUS RESTARTS AGE foo 0/0 0 -foo 0/0 0 -foo 0/0 0 +foo 0/0 0 +foo 0/0 0 ` if e, a := expected, buf.String(); e != a { t.Errorf("expected\n%v\ngot\n%v", e, a) @@ -1349,8 +1349,8 @@ func TestWatchResourceIdentifiedByFile(t *testing.T) { expected := `NAME READY STATUS RESTARTS AGE foo 0/0 0 -foo 0/0 0 -foo 0/0 0 +foo 0/0 0 +foo 0/0 0 ` if e, a := expected, buf.String(); e != a { t.Errorf("expected\n%v\ngot\n%v", e, a) @@ -1392,7 +1392,7 @@ func TestWatchOnlyResource(t *testing.T) { expected := `NAME READY STATUS RESTARTS AGE foo 0/0 0 -foo 0/0 0 +foo 0/0 0 ` if e, a := expected, buf.String(); e != a { t.Errorf("expected\n%v\ngot\n%v", e, a) @@ -1437,7 +1437,7 @@ func TestWatchOnlyList(t *testing.T) { expected := `NAME READY STATUS RESTARTS AGE foo 0/0 0 -foo 0/0 0 +foo 0/0 0 ` if e, a := expected, buf.String(); e != a { t.Errorf("expected\n%v\ngot\n%v", e, a) diff --git a/pkg/kubectl/cmd/get/humanreadable_flags.go b/pkg/kubectl/cmd/get/humanreadable_flags.go index fa7bbca883a..efd597c4598 100644 --- a/pkg/kubectl/cmd/get/humanreadable_flags.go +++ b/pkg/kubectl/cmd/get/humanreadable_flags.go @@ -61,6 +61,7 @@ func (f *HumanPrintFlags) EnsureWithNamespace() error { return nil } +// AllowedFormats returns more customized formating options func (f *HumanPrintFlags) AllowedFormats() []string { return []string{"wide"} } diff --git a/pkg/kubectl/cmd/get/sorter.go b/pkg/kubectl/cmd/get/sorter.go index cd8bb28b8d8..d806decd19a 100644 --- a/pkg/kubectl/cmd/get/sorter.go +++ b/pkg/kubectl/cmd/get/sorter.go @@ -318,13 +318,18 @@ func (t *TableSorter) Len() int { func (t *TableSorter) Swap(i, j int) { t.obj.Rows[i], t.obj.Rows[j] = t.obj.Rows[j], t.obj.Rows[i] + t.parsedRows[i], t.parsedRows[j] = t.parsedRows[j], t.parsedRows[i] } func (t *TableSorter) Less(i, j int) bool { iValues := t.parsedRows[i] jValues := t.parsedRows[j] - if len(iValues) == 0 || len(iValues[0]) == 0 || len(jValues) == 0 || len(jValues[0]) == 0 { - klog.Fatalf("couldn't find any field with path %q in the list of objects", t.field) + + if len(iValues) == 0 || len(iValues[0]) == 0 { + return true + } + if len(jValues) == 0 || len(jValues[0]) == 0 { + return false } iField := iValues[0][0] @@ -342,28 +347,36 @@ func (t *TableSorter) Sort() error { return nil } -func NewTableSorter(table *metav1beta1.Table, field string) *TableSorter { +func NewTableSorter(table *metav1beta1.Table, field string) (*TableSorter, error) { var parsedRows [][][]reflect.Value parser := jsonpath.New("sorting").AllowMissingKeys(true) err := parser.Parse(field) if err != nil { - klog.Fatalf("sorting error: %v\n", err) + return nil, fmt.Errorf("sorting error: %v", err) } + fieldFoundOnce := false for i := range table.Rows { parsedRow, err := findJSONPathResults(parser, table.Rows[i].Object.Object) if err != nil { - klog.Fatalf("Failed to get values for %#v using %s (%#v)", parsedRow, field, err) + return nil, fmt.Errorf("Failed to get values for %#v using %s (%#v)", parsedRow, field, err) } parsedRows = append(parsedRows, parsedRow) + if len(parsedRow) > 0 && len(parsedRow[0]) > 0 { + fieldFoundOnce = true + } + } + + if len(table.Rows) > 0 && !fieldFoundOnce { + return nil, fmt.Errorf("couldn't find any field with path %q in the list of objects", field) } return &TableSorter{ obj: table, field: field, parsedRows: parsedRows, - } + }, nil } func findJSONPathResults(parser *jsonpath.JSONPath, from runtime.Object) ([][]reflect.Value, error) { if unstructuredObj, ok := from.(*unstructured.Unstructured); ok { diff --git a/pkg/kubectl/cmd/get/sorter_test.go b/pkg/kubectl/cmd/get/sorter_test.go index c85d5d1bf5a..be2abd57f9b 100644 --- a/pkg/kubectl/cmd/get/sorter_test.go +++ b/pkg/kubectl/cmd/get/sorter_test.go @@ -17,6 +17,7 @@ limitations under the License. package get import ( + "encoding/json" "reflect" "strings" "testing" @@ -25,10 +26,20 @@ import ( "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + metav1beta1 "k8s.io/apimachinery/pkg/apis/meta/v1beta1" "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/util/diff" "k8s.io/kubernetes/pkg/kubectl/scheme" ) +func toUnstructuredOrDie(data []byte) *unstructured.Unstructured { + unstrBody := map[string]interface{}{} + err := json.Unmarshal(data, &unstrBody) + if err != nil { + panic(err) + } + return &unstructured.Unstructured{Object: unstrBody} +} func encodeOrDie(obj runtime.Object) []byte { data, err := runtime.Encode(scheme.Codecs.LegacyCodec(corev1.SchemeGroupVersion), obj) if err != nil { @@ -65,6 +76,16 @@ func TestSortingPrinter(t *testing.T) { name string expectedErr string }{ + { + name: "empty", + obj: &corev1.PodList{ + Items: []corev1.Pod{}, + }, + sort: &corev1.PodList{ + Items: []corev1.Pod{}, + }, + field: "{.metadata.name}", + }, { name: "in-order-already", obj: &corev1.PodList{ @@ -237,16 +258,16 @@ func TestSortingPrinter(t *testing.T) { name: "v1.List in order", obj: &corev1.List{ Items: []runtime.RawExtension{ - {Raw: encodeOrDie(a)}, - {Raw: encodeOrDie(b)}, - {Raw: encodeOrDie(c)}, + {Object: a, Raw: encodeOrDie(a)}, + {Object: b, Raw: encodeOrDie(b)}, + {Object: c, Raw: encodeOrDie(c)}, }, }, sort: &corev1.List{ Items: []runtime.RawExtension{ - {Raw: encodeOrDie(a)}, - {Raw: encodeOrDie(b)}, - {Raw: encodeOrDie(c)}, + {Object: a, Raw: encodeOrDie(a)}, + {Object: b, Raw: encodeOrDie(b)}, + {Object: c, Raw: encodeOrDie(c)}, }, }, field: "{.metadata.name}", @@ -255,16 +276,16 @@ func TestSortingPrinter(t *testing.T) { name: "v1.List in reverse", obj: &corev1.List{ Items: []runtime.RawExtension{ - {Raw: encodeOrDie(c)}, - {Raw: encodeOrDie(b)}, - {Raw: encodeOrDie(a)}, + {Object: c, Raw: encodeOrDie(c)}, + {Object: b, Raw: encodeOrDie(b)}, + {Object: a, Raw: encodeOrDie(a)}, }, }, sort: &corev1.List{ Items: []runtime.RawExtension{ - {Raw: encodeOrDie(a)}, - {Raw: encodeOrDie(b)}, - {Raw: encodeOrDie(c)}, + {Object: a, Raw: encodeOrDie(a)}, + {Object: b, Raw: encodeOrDie(b)}, + {Object: c, Raw: encodeOrDie(c)}, }, }, field: "{.metadata.name}", @@ -390,6 +411,43 @@ func TestSortingPrinter(t *testing.T) { }, } for _, tt := range tests { + t.Run(tt.name+" table", func(t *testing.T) { + table := &metav1beta1.Table{} + meta.EachListItem(tt.obj, func(item runtime.Object) error { + table.Rows = append(table.Rows, metav1beta1.TableRow{ + Object: runtime.RawExtension{Object: toUnstructuredOrDie(encodeOrDie(item))}, + }) + return nil + }) + + expectedTable := &metav1beta1.Table{} + meta.EachListItem(tt.sort, func(item runtime.Object) error { + expectedTable.Rows = append(expectedTable.Rows, metav1beta1.TableRow{ + Object: runtime.RawExtension{Object: toUnstructuredOrDie(encodeOrDie(item))}, + }) + return nil + }) + + sorter, err := NewTableSorter(table, tt.field) + if err == nil { + err = sorter.Sort() + } + if err != nil { + if len(tt.expectedErr) > 0 { + if strings.Contains(err.Error(), tt.expectedErr) { + return + } + t.Fatalf("%s: expected error containing: %q, got: \"%v\"", tt.name, tt.expectedErr, err) + } + t.Fatalf("%s: unexpected error: %v", tt.name, err) + } + if len(tt.expectedErr) > 0 { + t.Fatalf("%s: expected error containing: %q, got none", tt.name, tt.expectedErr) + } + if !reflect.DeepEqual(table, expectedTable) { + t.Errorf("[%s]\nexpected/saw:\n%s", tt.name, diff.ObjectReflectDiff(expectedTable, table)) + } + }) t.Run(tt.name, func(t *testing.T) { sort := &SortingPrinter{SortField: tt.field, Decoder: scheme.Codecs.UniversalDecoder()} err := sort.sortObj(tt.obj) diff --git a/pkg/kubectl/cmd/label/label.go b/pkg/kubectl/cmd/label/label.go index 11251a278d2..a342b90c92f 100644 --- a/pkg/kubectl/cmd/label/label.go +++ b/pkg/kubectl/cmd/label/label.go @@ -344,8 +344,7 @@ func (o *LabelOptions) RunLabel() error { if err != nil { return err } - printer.PrintObj(info.Object, o.Out) - return nil + return printer.PrintObj(info.Object, o.Out) }) } diff --git a/pkg/kubectl/cmd/plugin/plugin.go b/pkg/kubectl/cmd/plugin/plugin.go index 528ede0e70c..7196804cafe 100644 --- a/pkg/kubectl/cmd/plugin/plugin.go +++ b/pkg/kubectl/cmd/plugin/plugin.go @@ -34,13 +34,13 @@ import ( ) var ( - plugin_long = templates.LongDesc(` + pluginLong = templates.LongDesc(` Provides utilities for interacting with plugins. Plugins provide extended functionality that is not part of the major command-line distribution. Please refer to the documentation and examples for more information about how write your own plugins.`) - plugin_list_long = templates.LongDesc(` + pluginListLong = templates.LongDesc(` List all available plugin files on a user's PATH. Available plugin files are those that are: @@ -55,7 +55,7 @@ func NewCmdPlugin(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra Use: "plugin [flags]", DisableFlagsInUseLine: true, Short: i18n.T("Provides utilities for interacting with plugins."), - Long: plugin_long, + Long: pluginLong, Run: func(cmd *cobra.Command, args []string) { cmdutil.DefaultSubCommandRun(streams.ErrOut)(cmd, args) }, @@ -81,7 +81,7 @@ func NewCmdPluginList(f cmdutil.Factory, streams genericclioptions.IOStreams) *c cmd := &cobra.Command{ Use: "list", Short: "list all visible plugin executables on a user's PATH", - Long: plugin_list_long, + Long: pluginListLong, Run: func(cmd *cobra.Command, args []string) { cmdutil.CheckErr(o.Complete(cmd)) cmdutil.CheckErr(o.Run()) diff --git a/pkg/kubectl/cmd/rollout/rollout.go b/pkg/kubectl/cmd/rollout/rollout.go index 38b2c529753..f724a3063d3 100644 --- a/pkg/kubectl/cmd/rollout/rollout.go +++ b/pkg/kubectl/cmd/rollout/rollout.go @@ -27,17 +27,17 @@ import ( ) var ( - rollout_long = templates.LongDesc(` - Manage the rollout of a resource.` + rollout_valid_resources) + rolloutLong = templates.LongDesc(` + Manage the rollout of a resource.` + rolloutValidResources) - rollout_example = templates.Examples(` + rolloutExample = templates.Examples(` # Rollback to the previous deployment kubectl rollout undo deployment/abc # Check the rollout status of a daemonset kubectl rollout status daemonset/foo`) - rollout_valid_resources = dedent.Dedent(` + rolloutValidResources = dedent.Dedent(` Valid resource types include: * deployments @@ -46,13 +46,14 @@ var ( `) ) +// NewCmdRollout returns a Command instance for 'rollout' sub command func NewCmdRollout(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command { cmd := &cobra.Command{ Use: "rollout SUBCOMMAND", DisableFlagsInUseLine: true, Short: i18n.T("Manage the rollout of a resource"), - Long: rollout_long, - Example: rollout_example, + Long: rolloutLong, + Example: rolloutExample, Run: cmdutil.DefaultSubCommandRun(streams.Out), } // subcommands diff --git a/pkg/kubectl/cmd/rollout/rollout_history.go b/pkg/kubectl/cmd/rollout/rollout_history.go index 009c8d76ca4..d9245508184 100644 --- a/pkg/kubectl/cmd/rollout/rollout_history.go +++ b/pkg/kubectl/cmd/rollout/rollout_history.go @@ -32,10 +32,10 @@ import ( ) var ( - history_long = templates.LongDesc(` + historyLong = templates.LongDesc(` View previous rollout revisions and configurations.`) - history_example = templates.Examples(` + historyExample = templates.Examples(` # View the rollout history of a deployment kubectl rollout history deployment/abc @@ -43,6 +43,7 @@ var ( kubectl rollout history daemonset/abc --revision=3`) ) +// RolloutHistoryOptions holds the options for 'rollout history' sub command type RolloutHistoryOptions struct { PrintFlags *genericclioptions.PrintFlags ToPrinter func(string) (printers.ResourcePrinter, error) @@ -61,6 +62,7 @@ type RolloutHistoryOptions struct { genericclioptions.IOStreams } +// NewRolloutHistoryOptions returns an initialized RolloutHistoryOptions instance func NewRolloutHistoryOptions(streams genericclioptions.IOStreams) *RolloutHistoryOptions { return &RolloutHistoryOptions{ PrintFlags: genericclioptions.NewPrintFlags("").WithTypeSetter(scheme.Scheme), @@ -68,6 +70,7 @@ func NewRolloutHistoryOptions(streams genericclioptions.IOStreams) *RolloutHisto } } +// NewCmdRolloutHistory returns a Command instance for RolloutHistory sub command func NewCmdRolloutHistory(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command { o := NewRolloutHistoryOptions(streams) @@ -77,8 +80,8 @@ func NewCmdRolloutHistory(f cmdutil.Factory, streams genericclioptions.IOStreams Use: "history (TYPE NAME | TYPE/NAME) [flags]", DisableFlagsInUseLine: true, Short: i18n.T("View rollout history"), - Long: history_long, - Example: history_example, + Long: historyLong, + Example: historyExample, Run: func(cmd *cobra.Command, args []string) { cmdutil.CheckErr(o.Complete(f, cmd, args)) cmdutil.CheckErr(o.Validate()) @@ -97,6 +100,7 @@ func NewCmdRolloutHistory(f cmdutil.Factory, streams genericclioptions.IOStreams return cmd } +// Complete completes al the required options func (o *RolloutHistoryOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error { o.Resources = args @@ -117,6 +121,7 @@ func (o *RolloutHistoryOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, return nil } +// Validate makes sure all the provided values for command-line options are valid func (o *RolloutHistoryOptions) Validate() error { if len(o.Resources) == 0 && cmdutil.IsFilenameSliceEmpty(o.Filenames) { return fmt.Errorf("required resource not specified") @@ -128,6 +133,7 @@ func (o *RolloutHistoryOptions) Validate() error { return nil } +// Run performs the execution of 'rollout history' sub command func (o *RolloutHistoryOptions) Run() error { r := o.Builder(). diff --git a/pkg/kubectl/cmd/rollout/rollout_pause.go b/pkg/kubectl/cmd/rollout/rollout_pause.go index 70c5af4a698..b29963d6497 100644 --- a/pkg/kubectl/cmd/rollout/rollout_pause.go +++ b/pkg/kubectl/cmd/rollout/rollout_pause.go @@ -51,20 +51,21 @@ type PauseOptions struct { } var ( - pause_long = templates.LongDesc(` + pauseLong = templates.LongDesc(` Mark the provided resource as paused Paused resources will not be reconciled by a controller. Use "kubectl rollout resume" to resume a paused resource. Currently only deployments support being paused.`) - pause_example = templates.Examples(` + pauseExample = templates.Examples(` # Mark the nginx deployment as paused. Any current state of # the deployment will continue its function, new updates to the deployment will not # have an effect as long as the deployment is paused. kubectl rollout pause deployment/nginx`) ) +// NewCmdRolloutPause returns a Command instance for 'rollout pause' sub command func NewCmdRolloutPause(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command { o := &PauseOptions{ PrintFlags: genericclioptions.NewPrintFlags("paused").WithTypeSetter(scheme.Scheme), @@ -77,8 +78,8 @@ func NewCmdRolloutPause(f cmdutil.Factory, streams genericclioptions.IOStreams) Use: "pause RESOURCE", DisableFlagsInUseLine: true, Short: i18n.T("Mark the provided resource as paused"), - Long: pause_long, - Example: pause_example, + Long: pauseLong, + Example: pauseExample, Run: func(cmd *cobra.Command, args []string) { cmdutil.CheckErr(o.Complete(f, cmd, args)) cmdutil.CheckErr(o.Validate()) @@ -94,6 +95,7 @@ func NewCmdRolloutPause(f cmdutil.Factory, streams genericclioptions.IOStreams) return cmd } +// Complete completes all the required options func (o *PauseOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error { o.Pauser = polymorphichelpers.ObjectPauserFn @@ -121,7 +123,8 @@ func (o *PauseOptions) Validate() error { return nil } -func (o PauseOptions) RunPause() error { +// RunPause performs the execution of 'rollout pause' sub command +func (o *PauseOptions) RunPause() error { r := o.Builder(). WithScheme(scheme.Scheme, scheme.Scheme.PrioritizedVersionsAllGroups()...). NamespaceParam(o.Namespace).DefaultNamespace(). diff --git a/pkg/kubectl/cmd/rollout/rollout_resume.go b/pkg/kubectl/cmd/rollout/rollout_resume.go index e97c807173c..f1f9e4e33db 100644 --- a/pkg/kubectl/cmd/rollout/rollout_resume.go +++ b/pkg/kubectl/cmd/rollout/rollout_resume.go @@ -52,18 +52,19 @@ type ResumeOptions struct { } var ( - resume_long = templates.LongDesc(` + resumeLong = templates.LongDesc(` Resume a paused resource Paused resources will not be reconciled by a controller. By resuming a resource, we allow it to be reconciled again. Currently only deployments support being resumed.`) - resume_example = templates.Examples(` + resumeExample = templates.Examples(` # Resume an already paused deployment kubectl rollout resume deployment/nginx`) ) +// NewRolloutResumeOptions returns an initialized ResumeOptions instance func NewRolloutResumeOptions(streams genericclioptions.IOStreams) *ResumeOptions { return &ResumeOptions{ PrintFlags: genericclioptions.NewPrintFlags("resumed").WithTypeSetter(scheme.Scheme), @@ -71,6 +72,7 @@ func NewRolloutResumeOptions(streams genericclioptions.IOStreams) *ResumeOptions } } +// NewCmdRolloutResume returns a Command instance for 'rollout resume' sub command func NewCmdRolloutResume(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command { o := NewRolloutResumeOptions(streams) @@ -80,8 +82,8 @@ func NewCmdRolloutResume(f cmdutil.Factory, streams genericclioptions.IOStreams) Use: "resume RESOURCE", DisableFlagsInUseLine: true, Short: i18n.T("Resume a paused resource"), - Long: resume_long, - Example: resume_example, + Long: resumeLong, + Example: resumeExample, Run: func(cmd *cobra.Command, args []string) { cmdutil.CheckErr(o.Complete(f, cmd, args)) cmdutil.CheckErr(o.Validate()) @@ -96,6 +98,7 @@ func NewCmdRolloutResume(f cmdutil.Factory, streams genericclioptions.IOStreams) return cmd } +// Complete completes all the required options func (o *ResumeOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error { o.Resources = args @@ -124,6 +127,7 @@ func (o *ResumeOptions) Validate() error { return nil } +// RunResume performs the execution of 'rollout resume' sub command func (o ResumeOptions) RunResume() error { r := o.Builder(). WithScheme(scheme.Scheme, scheme.Scheme.PrioritizedVersionsAllGroups()...). diff --git a/pkg/kubectl/cmd/rollout/rollout_status.go b/pkg/kubectl/cmd/rollout/rollout_status.go index 311c9c88d90..fde72df1d8b 100644 --- a/pkg/kubectl/cmd/rollout/rollout_status.go +++ b/pkg/kubectl/cmd/rollout/rollout_status.go @@ -45,7 +45,7 @@ import ( ) var ( - status_long = templates.LongDesc(` + statusLong = templates.LongDesc(` Show the status of the rollout. By default 'rollout status' will watch the status of the latest rollout @@ -55,11 +55,12 @@ var ( pin to a specific revision and abort if it is rolled over by another revision, use --revision=N where N is the revision you need to watch for.`) - status_example = templates.Examples(` + statusExample = templates.Examples(` # Watch the rollout status of a deployment kubectl rollout status deployment/nginx`) ) +// RolloutStatusOptions holds the command-line options for 'rollout status' sub command type RolloutStatusOptions struct { PrintFlags *genericclioptions.PrintFlags @@ -79,6 +80,7 @@ type RolloutStatusOptions struct { genericclioptions.IOStreams } +// NewRolloutStatusOptions returns an initialized RolloutStatusOptions instance func NewRolloutStatusOptions(streams genericclioptions.IOStreams) *RolloutStatusOptions { return &RolloutStatusOptions{ PrintFlags: genericclioptions.NewPrintFlags("").WithTypeSetter(scheme.Scheme), @@ -89,6 +91,7 @@ func NewRolloutStatusOptions(streams genericclioptions.IOStreams) *RolloutStatus } } +// NewCmdRolloutStatus returns a Command instance for the 'rollout status' sub command func NewCmdRolloutStatus(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command { o := NewRolloutStatusOptions(streams) @@ -98,8 +101,8 @@ func NewCmdRolloutStatus(f cmdutil.Factory, streams genericclioptions.IOStreams) Use: "status (TYPE NAME | TYPE/NAME) [flags]", DisableFlagsInUseLine: true, Short: i18n.T("Show the status of the rollout"), - Long: status_long, - Example: status_example, + Long: statusLong, + Example: statusExample, Run: func(cmd *cobra.Command, args []string) { cmdutil.CheckErr(o.Complete(f, args)) cmdutil.CheckErr(o.Validate()) @@ -117,6 +120,7 @@ func NewCmdRolloutStatus(f cmdutil.Factory, streams genericclioptions.IOStreams) return cmd } +// Complete completes all the required options func (o *RolloutStatusOptions) Complete(f cmdutil.Factory, args []string) error { o.Builder = f.NewBuilder @@ -142,6 +146,7 @@ func (o *RolloutStatusOptions) Complete(f cmdutil.Factory, args []string) error return nil } +// Validate makes sure all the provided values for command-line options are valid func (o *RolloutStatusOptions) Validate() error { if len(o.BuilderArgs) == 0 && cmdutil.IsFilenameSliceEmpty(o.FilenameOptions.Filenames) { return fmt.Errorf("required resource not specified") @@ -154,6 +159,7 @@ func (o *RolloutStatusOptions) Validate() error { return nil } +// Run performs the execution of 'rollout status' sub command func (o *RolloutStatusOptions) Run() error { r := o.Builder(). WithScheme(scheme.Scheme, scheme.Scheme.PrioritizedVersionsAllGroups()...). diff --git a/pkg/kubectl/cmd/rollout/rollout_undo.go b/pkg/kubectl/cmd/rollout/rollout_undo.go index 2ab7a028871..c4db88af208 100644 --- a/pkg/kubectl/cmd/rollout/rollout_undo.go +++ b/pkg/kubectl/cmd/rollout/rollout_undo.go @@ -50,10 +50,10 @@ type UndoOptions struct { } var ( - undo_long = templates.LongDesc(` + undoLong = templates.LongDesc(` Rollback to a previous rollout.`) - undo_example = templates.Examples(` + undoExample = templates.Examples(` # Rollback to the previous deployment kubectl rollout undo deployment/abc @@ -64,6 +64,7 @@ var ( kubectl rollout undo --dry-run=true deployment/abc`) ) +// NewRolloutUndoOptions returns an initialized UndoOptions instance func NewRolloutUndoOptions(streams genericclioptions.IOStreams) *UndoOptions { return &UndoOptions{ PrintFlags: genericclioptions.NewPrintFlags("rolled back").WithTypeSetter(scheme.Scheme), @@ -72,6 +73,7 @@ func NewRolloutUndoOptions(streams genericclioptions.IOStreams) *UndoOptions { } } +// NewCmdRolloutUndo returns a Command instance for the 'rollout undo' sub command func NewCmdRolloutUndo(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command { o := NewRolloutUndoOptions(streams) @@ -81,8 +83,8 @@ func NewCmdRolloutUndo(f cmdutil.Factory, streams genericclioptions.IOStreams) * Use: "undo (TYPE NAME | TYPE/NAME) [flags]", DisableFlagsInUseLine: true, Short: i18n.T("Undo a previous rollout"), - Long: undo_long, - Example: undo_example, + Long: undoLong, + Example: undoExample, Run: func(cmd *cobra.Command, args []string) { cmdutil.CheckErr(o.Complete(f, cmd, args)) cmdutil.CheckErr(o.Validate()) @@ -99,6 +101,7 @@ func NewCmdRolloutUndo(f cmdutil.Factory, streams genericclioptions.IOStreams) * return cmd } +// Complete completes al the required options func (o *UndoOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error { o.Resources = args o.DryRun = cmdutil.GetDryRunFlag(cmd) @@ -129,6 +132,7 @@ func (o *UndoOptions) Validate() error { return nil } +// RunUndo performs the execution of 'rollout undo' sub command func (o *UndoOptions) RunUndo() error { r := o.Builder(). WithScheme(scheme.Scheme, scheme.Scheme.PrioritizedVersionsAllGroups()...). diff --git a/pkg/kubectl/cmd/run/run.go b/pkg/kubectl/cmd/run/run.go index fdd47b287a8..3fc4bf65fbd 100644 --- a/pkg/kubectl/cmd/run/run.go +++ b/pkg/kubectl/cmd/run/run.go @@ -360,9 +360,9 @@ func (o *RunOptions) Run(f cmdutil.Factory, cmd *cobra.Command, args []string) e runObject, err := o.createGeneratedObject(f, cmd, generator, names, params, cmdutil.GetFlagString(cmd, "overrides"), namespace) if err != nil { return err - } else { - createdObjects = append(createdObjects, runObject) } + createdObjects = append(createdObjects, runObject) + allErrs := []error{} if o.Expose { serviceGenerator := cmdutil.GetFlagString(cmd, "service-generator") @@ -567,9 +567,8 @@ func getRestartPolicy(cmd *cobra.Command, interactive bool) (corev1.RestartPolic if len(restart) == 0 { if interactive { return corev1.RestartPolicyOnFailure, nil - } else { - return corev1.RestartPolicyAlways, nil } + return corev1.RestartPolicyAlways, nil } switch corev1.RestartPolicy(restart) { case corev1.RestartPolicyAlways: diff --git a/pkg/kubectl/cmd/set/set.go b/pkg/kubectl/cmd/set/set.go index a50b7f95374..0617f88caec 100644 --- a/pkg/kubectl/cmd/set/set.go +++ b/pkg/kubectl/cmd/set/set.go @@ -25,18 +25,19 @@ import ( ) var ( - set_long = templates.LongDesc(` + setLong = templates.LongDesc(` Configure application resources These commands help you make changes to existing application resources.`) ) +// NewCmdSet returns an initialized Command instance for 'set' sub command func NewCmdSet(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command { cmd := &cobra.Command{ Use: "set SUBCOMMAND", DisableFlagsInUseLine: true, Short: i18n.T("Set specific features on objects"), - Long: set_long, + Long: setLong, Run: cmdutil.DefaultSubCommandRun(streams.ErrOut), } diff --git a/pkg/kubectl/cmd/set/set_env.go b/pkg/kubectl/cmd/set/set_env.go index 62aed433dfe..0cc00cbcfc6 100644 --- a/pkg/kubectl/cmd/set/set_env.go +++ b/pkg/kubectl/cmd/set/set_env.go @@ -97,6 +97,7 @@ var ( env | grep RAILS_ | kubectl set env -e - deployment/registry`) ) +// EnvOptions holds values for 'set env' command-lone options type EnvOptions struct { PrintFlags *genericclioptions.PrintFlags resource.FilenameOptions @@ -202,6 +203,7 @@ func contains(key string, keyList []string) bool { return false } +// Complete completes all required options func (o *EnvOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error { if o.All && len(o.Selector) > 0 { return fmt.Errorf("cannot set --all and --selector at the same time") @@ -242,6 +244,7 @@ func (o *EnvOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []stri return nil } +// Validate makes sure provided values for EnvOptions are valid func (o *EnvOptions) Validate() error { if len(o.Filenames) == 0 && len(o.resources) < 1 { return fmt.Errorf("one or more resources must be specified as or /") @@ -471,7 +474,7 @@ func (o *EnvOptions) RunEnv() error { for _, patch := range patches { info := patch.Info if patch.Err != nil { - allErrs = append(allErrs, fmt.Errorf("error: %s/%s %v\n", info.Mapping.Resource, info.Name, patch.Err)) + allErrs = append(allErrs, fmt.Errorf("error: %s/%s %v", info.Mapping.Resource, info.Name, patch.Err)) continue } @@ -489,7 +492,7 @@ func (o *EnvOptions) RunEnv() error { actual, err := resource.NewHelper(info.Client, info.Mapping).Patch(info.Namespace, info.Name, types.StrategicMergePatchType, patch.Patch, nil) if err != nil { - allErrs = append(allErrs, fmt.Errorf("failed to patch env update to pod template: %v\n", err)) + allErrs = append(allErrs, fmt.Errorf("failed to patch env update to pod template: %v", err)) continue } diff --git a/pkg/kubectl/cmd/set/set_image.go b/pkg/kubectl/cmd/set/set_image.go index 38677a803f0..5fe8b0516f2 100644 --- a/pkg/kubectl/cmd/set/set_image.go +++ b/pkg/kubectl/cmd/set/set_image.go @@ -63,16 +63,16 @@ type SetImageOptions struct { } var ( - image_resources = ` + imageResources = ` pod (po), replicationcontroller (rc), deployment (deploy), daemonset (ds), replicaset (rs)` - image_long = templates.LongDesc(` + imageLong = templates.LongDesc(` Update existing container image(s) of resources. Possible resources include (case insensitive): - ` + image_resources) + ` + imageResources) - image_example = templates.Examples(` + imageExample = templates.Examples(` # Set a deployment's nginx container image to 'nginx:1.9.1', and its busybox container image to 'busybox'. kubectl set image deployment/nginx busybox=busybox nginx=nginx:1.9.1 @@ -86,6 +86,7 @@ var ( kubectl set image -f path/to/file.yaml nginx=nginx:1.9.1 --local -o yaml`) ) +// NewImageOptions returns an initialized SetImageOptions instance func NewImageOptions(streams genericclioptions.IOStreams) *SetImageOptions { return &SetImageOptions{ PrintFlags: genericclioptions.NewPrintFlags("image updated").WithTypeSetter(scheme.Scheme), @@ -97,6 +98,7 @@ func NewImageOptions(streams genericclioptions.IOStreams) *SetImageOptions { } } +// NewCmdImage returns an initialized Command instance for the 'set image' sub command func NewCmdImage(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command { o := NewImageOptions(streams) @@ -104,8 +106,8 @@ func NewCmdImage(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra. Use: "image (-f FILENAME | TYPE NAME) CONTAINER_NAME_1=CONTAINER_IMAGE_1 ... CONTAINER_NAME_N=CONTAINER_IMAGE_N", DisableFlagsInUseLine: true, Short: i18n.T("Update image of a pod template"), - Long: image_long, - Example: image_example, + Long: imageLong, + Example: imageExample, Run: func(cmd *cobra.Command, args []string) { cmdutil.CheckErr(o.Complete(f, cmd, args)) cmdutil.CheckErr(o.Validate()) @@ -126,6 +128,7 @@ func NewCmdImage(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra. return cmd } +// Complete completes all required options func (o *SetImageOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error { var err error @@ -191,6 +194,7 @@ func (o *SetImageOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args [ return nil } +// Validate makes sure provided values in SetImageOptions are valid func (o *SetImageOptions) Validate() error { errors := []error{} if o.All && len(o.Selector) > 0 { @@ -207,6 +211,7 @@ func (o *SetImageOptions) Validate() error { return utilerrors.NewAggregate(errors) } +// Run performs the execution of 'set image' sub command func (o *SetImageOptions) Run() error { allErrs := []error{} @@ -265,7 +270,7 @@ func (o *SetImageOptions) Run() error { for _, patch := range patches { info := patch.Info if patch.Err != nil { - allErrs = append(allErrs, fmt.Errorf("error: %s/%s %v\n", info.Mapping.Resource, info.Name, patch.Err)) + allErrs = append(allErrs, fmt.Errorf("error: %s/%s %v", info.Mapping.Resource, info.Name, patch.Err)) continue } @@ -284,7 +289,7 @@ func (o *SetImageOptions) Run() error { // patch the change actual, err := resource.NewHelper(info.Client, info.Mapping).Patch(info.Namespace, info.Name, types.StrategicMergePatchType, patch.Patch, nil) if err != nil { - allErrs = append(allErrs, fmt.Errorf("failed to patch image update to pod template: %v\n", err)) + allErrs = append(allErrs, fmt.Errorf("failed to patch image update to pod template: %v", err)) continue } diff --git a/pkg/kubectl/cmd/set/set_resources.go b/pkg/kubectl/cmd/set/set_resources.go index b7328a0cb45..e4e2dd14bba 100644 --- a/pkg/kubectl/cmd/set/set_resources.go +++ b/pkg/kubectl/cmd/set/set_resources.go @@ -38,14 +38,14 @@ import ( ) var ( - resources_long = templates.LongDesc(` + resourcesLong = templates.LongDesc(` Specify compute resource requirements (cpu, memory) for any resource that defines a pod template. If a pod is successfully scheduled, it is guaranteed the amount of resource requested, but may burst up to its specified limits. for each compute resource, if a limit is specified and a request is omitted, the request will default to the limit. Possible resources include (case insensitive): %s.`) - resources_example = templates.Examples(` + resourcesExample = templates.Examples(` # Set a deployments nginx container cpu limits to "200m" and memory to "512Mi" kubectl set resources deployment nginx -c=nginx --limits=cpu=200m,memory=512Mi @@ -59,7 +59,7 @@ var ( kubectl set resources -f path/to/file.yaml --limits=cpu=200m,memory=512Mi --local -o yaml`) ) -// ResourcesOptions is the start of the data required to perform the operation. As new fields are added, add them here instead of +// SetResourcesOptions is the start of the data required to perform the operation. As new fields are added, add them here instead of // referencing the cmd.Flags type SetResourcesOptions struct { resource.FilenameOptions @@ -104,6 +104,7 @@ func NewResourcesOptions(streams genericclioptions.IOStreams) *SetResourcesOptio } } +// NewCmdResources returns initialized Command instance for the 'set resources' sub command func NewCmdResources(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command { o := NewResourcesOptions(streams) @@ -111,8 +112,8 @@ func NewCmdResources(f cmdutil.Factory, streams genericclioptions.IOStreams) *co Use: "resources (-f FILENAME | TYPE NAME) ([--limits=LIMITS & --requests=REQUESTS]", DisableFlagsInUseLine: true, Short: i18n.T("Update resource requests/limits on objects with pod templates"), - Long: fmt.Sprintf(resources_long, cmdutil.SuggestApiResources("kubectl")), - Example: resources_example, + Long: fmt.Sprintf(resourcesLong, cmdutil.SuggestAPIResources("kubectl")), + Example: resourcesExample, Run: func(cmd *cobra.Command, args []string) { cmdutil.CheckErr(o.Complete(f, cmd, args)) cmdutil.CheckErr(o.Validate()) @@ -138,6 +139,7 @@ func NewCmdResources(f cmdutil.Factory, streams genericclioptions.IOStreams) *co return cmd } +// Complete completes all required options func (o *SetResourcesOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error { var err error @@ -197,6 +199,7 @@ func (o *SetResourcesOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, ar return nil } +// Validate makes sure that provided values in ResourcesOptions are valid func (o *SetResourcesOptions) Validate() error { var err error if o.All && len(o.Selector) > 0 { @@ -214,6 +217,7 @@ func (o *SetResourcesOptions) Validate() error { return nil } +// Run performs the execution of 'set resources' sub command func (o *SetResourcesOptions) Run() error { allErrs := []error{} patches := CalculatePatches(o.Infos, scheme.DefaultJSONEncoder(), func(obj runtime.Object) ([]byte, error) { @@ -259,13 +263,13 @@ func (o *SetResourcesOptions) Run() error { for _, patch := range patches { info := patch.Info if patch.Err != nil { - allErrs = append(allErrs, fmt.Errorf("error: %s/%s %v\n", info.Mapping.Resource, info.Name, patch.Err)) + allErrs = append(allErrs, fmt.Errorf("error: %s/%s %v", info.Mapping.Resource, info.Name, patch.Err)) continue } //no changes if string(patch.Patch) == "{}" || len(patch.Patch) == 0 { - allErrs = append(allErrs, fmt.Errorf("info: %s %q was not changed\n", info.Mapping.Resource, info.Name)) + allErrs = append(allErrs, fmt.Errorf("info: %s %q was not changed", info.Mapping.Resource, info.Name)) continue } @@ -278,7 +282,7 @@ func (o *SetResourcesOptions) Run() error { actual, err := resource.NewHelper(info.Client, info.Mapping).Patch(info.Namespace, info.Name, types.StrategicMergePatchType, patch.Patch, nil) if err != nil { - allErrs = append(allErrs, fmt.Errorf("failed to patch limit update to pod template %v\n", err)) + allErrs = append(allErrs, fmt.Errorf("failed to patch limit update to pod template %v", err)) continue } diff --git a/pkg/kubectl/cmd/set/set_selector.go b/pkg/kubectl/cmd/set/set_selector.go index 167ae747170..ddc4ba489b8 100644 --- a/pkg/kubectl/cmd/set/set_selector.go +++ b/pkg/kubectl/cmd/set/set_selector.go @@ -36,7 +36,7 @@ import ( "k8s.io/kubernetes/pkg/kubectl/util/templates" ) -// SelectorOptions is the start of the data required to perform the operation. As new fields are added, add them here instead of +// SetSelectorOptions is the start of the data required to perform the operation. As new fields are added, add them here instead of // referencing the cmd.Flags() type SetSelectorOptions struct { // Bound @@ -73,6 +73,7 @@ var ( kubectl create deployment my-dep -o yaml --dry-run | kubectl label --local -f - environment=qa -o yaml | kubectl create -f -`) ) +// NewSelectorOptions returns an initialized SelectorOptions instance func NewSelectorOptions(streams genericclioptions.IOStreams) *SetSelectorOptions { return &SetSelectorOptions{ ResourceBuilderFlags: genericclioptions.NewResourceBuilderFlags(). diff --git a/pkg/kubectl/cmd/set/set_serviceaccount.go b/pkg/kubectl/cmd/set/set_serviceaccount.go index eced76f7e9c..b0d58527090 100644 --- a/pkg/kubectl/cmd/set/set_serviceaccount.go +++ b/pkg/kubectl/cmd/set/set_serviceaccount.go @@ -56,7 +56,7 @@ var ( `)) ) -// serviceAccountConfig encapsulates the data required to perform the operation. +// SetServiceAccountOptions encapsulates the data required to perform the operation. type SetServiceAccountOptions struct { PrintFlags *genericclioptions.PrintFlags RecordFlags *genericclioptions.RecordFlags @@ -77,6 +77,7 @@ type SetServiceAccountOptions struct { genericclioptions.IOStreams } +// NewSetServiceAccountOptions returns an initialized SetServiceAccountOptions instance func NewSetServiceAccountOptions(streams genericclioptions.IOStreams) *SetServiceAccountOptions { return &SetServiceAccountOptions{ PrintFlags: genericclioptions.NewPrintFlags("serviceaccount updated").WithTypeSetter(scheme.Scheme), @@ -193,7 +194,7 @@ func (o *SetServiceAccountOptions) Run() error { for _, patch := range patches { info := patch.Info if patch.Err != nil { - patchErrs = append(patchErrs, fmt.Errorf("error: %s/%s %v\n", info.Mapping.Resource, info.Name, patch.Err)) + patchErrs = append(patchErrs, fmt.Errorf("error: %s/%s %v", info.Mapping.Resource, info.Name, patch.Err)) continue } if o.local || o.dryRun { diff --git a/pkg/kubectl/cmd/set/set_subject.go b/pkg/kubectl/cmd/set/set_subject.go index a4a245e2855..a18032d9031 100644 --- a/pkg/kubectl/cmd/set/set_subject.go +++ b/pkg/kubectl/cmd/set/set_subject.go @@ -37,10 +37,10 @@ import ( ) var ( - subject_long = templates.LongDesc(` + subjectLong = templates.LongDesc(` Update User, Group or ServiceAccount in a RoleBinding/ClusterRoleBinding.`) - subject_example = templates.Examples(` + subjectExample = templates.Examples(` # Update a ClusterRoleBinding for serviceaccount1 kubectl set subject clusterrolebinding admin --serviceaccount=namespace:serviceaccount1 @@ -79,6 +79,7 @@ type SubjectOptions struct { genericclioptions.IOStreams } +// NewSubjectOptions returns an initialized SubjectOptions instance func NewSubjectOptions(streams genericclioptions.IOStreams) *SubjectOptions { return &SubjectOptions{ PrintFlags: genericclioptions.NewPrintFlags("subjects updated").WithTypeSetter(scheme.Scheme), @@ -87,14 +88,15 @@ func NewSubjectOptions(streams genericclioptions.IOStreams) *SubjectOptions { } } +// NewCmdSubject returns the "new subject" sub command func NewCmdSubject(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command { o := NewSubjectOptions(streams) cmd := &cobra.Command{ Use: "subject (-f FILENAME | TYPE NAME) [--user=username] [--group=groupname] [--serviceaccount=namespace:serviceaccountname] [--dry-run]", DisableFlagsInUseLine: true, Short: i18n.T("Update User, Group or ServiceAccount in a RoleBinding/ClusterRoleBinding"), - Long: subject_long, - Example: subject_example, + Long: subjectLong, + Example: subjectExample, Run: func(cmd *cobra.Command, args []string) { cmdutil.CheckErr(o.Complete(f, cmd, args)) cmdutil.CheckErr(o.Validate()) @@ -116,6 +118,7 @@ func NewCmdSubject(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobr return cmd } +// Complete completes all required options func (o *SubjectOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error { o.Output = cmdutil.GetFlagString(cmd, "output") o.DryRun = cmdutil.GetDryRunFlag(cmd) @@ -167,6 +170,7 @@ func (o *SubjectOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args [] return nil } +// Validate makes sure provided values in SubjectOptions are valid func (o *SubjectOptions) Validate() error { if o.All && len(o.Selector) > 0 { return fmt.Errorf("cannot set --all and --selector at the same time") @@ -192,6 +196,7 @@ func (o *SubjectOptions) Validate() error { return nil } +// Run performs the execution of "set subject" sub command func (o *SubjectOptions) Run(fn updateSubjects) error { patches := CalculatePatches(o.Infos, scheme.DefaultJSONEncoder(), func(obj runtime.Object) ([]byte, error) { subjects := []rbacv1.Subject{} @@ -238,13 +243,13 @@ func (o *SubjectOptions) Run(fn updateSubjects) error { for _, patch := range patches { info := patch.Info if patch.Err != nil { - allErrs = append(allErrs, fmt.Errorf("error: %s/%s %v\n", info.Mapping.Resource, info.Name, patch.Err)) + allErrs = append(allErrs, fmt.Errorf("error: %s/%s %v", info.Mapping.Resource, info.Name, patch.Err)) continue } //no changes if string(patch.Patch) == "{}" || len(patch.Patch) == 0 { - allErrs = append(allErrs, fmt.Errorf("info: %s %q was not changed\n", info.Mapping.Resource, info.Name)) + allErrs = append(allErrs, fmt.Errorf("info: %s %q was not changed", info.Mapping.Resource, info.Name)) continue } @@ -257,7 +262,7 @@ func (o *SubjectOptions) Run(fn updateSubjects) error { actual, err := resource.NewHelper(info.Client, info.Mapping).Patch(info.Namespace, info.Name, types.StrategicMergePatchType, patch.Patch, nil) if err != nil { - allErrs = append(allErrs, fmt.Errorf("failed to patch subjects to rolebinding: %v\n", err)) + allErrs = append(allErrs, fmt.Errorf("failed to patch subjects to rolebinding: %v", err)) continue } diff --git a/pkg/kubectl/cmd/taint/taint_test.go b/pkg/kubectl/cmd/taint/taint_test.go index 8e68516730c..3b4a9f540e5 100644 --- a/pkg/kubectl/cmd/taint/taint_test.go +++ b/pkg/kubectl/cmd/taint/taint_test.go @@ -237,7 +237,7 @@ func TestTaint(t *testing.T) { for _, test := range tests { t.Run(test.description, func(t *testing.T) { oldNode, expectNewNode := generateNodeAndTaintedNode(test.oldTaints, test.newTaints) - new_node := &corev1.Node{} + newNode := &corev1.Node{} tainted := false tf := cmdtesting.NewTestFactory() defer tf.Cleanup() @@ -274,13 +274,13 @@ func TestTaint(t *testing.T) { } // decode the patch - if err := runtime.DecodeInto(codec, appliedPatch, new_node); err != nil { + if err := runtime.DecodeInto(codec, appliedPatch, newNode); err != nil { t.Fatalf("%s: unexpected error: %v", test.description, err) } - if !equalTaints(expectNewNode.Spec.Taints, new_node.Spec.Taints) { - t.Fatalf("%s: expected:\n%v\nsaw:\n%v\n", test.description, expectNewNode.Spec.Taints, new_node.Spec.Taints) + if !equalTaints(expectNewNode.Spec.Taints, newNode.Spec.Taints) { + t.Fatalf("%s: expected:\n%v\nsaw:\n%v\n", test.description, expectNewNode.Spec.Taints, newNode.Spec.Taints) } - return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, new_node)}, nil + return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, newNode)}, nil case m.isFor("PUT", "/nodes/node-name"): tainted = true data, err := ioutil.ReadAll(req.Body) @@ -288,13 +288,13 @@ func TestTaint(t *testing.T) { t.Fatalf("%s: unexpected error: %v", test.description, err) } defer req.Body.Close() - if err := runtime.DecodeInto(codec, data, new_node); err != nil { + if err := runtime.DecodeInto(codec, data, newNode); err != nil { t.Fatalf("%s: unexpected error: %v", test.description, err) } - if !equalTaints(expectNewNode.Spec.Taints, new_node.Spec.Taints) { - t.Fatalf("%s: expected:\n%v\nsaw:\n%v\n", test.description, expectNewNode.Spec.Taints, new_node.Spec.Taints) + if !equalTaints(expectNewNode.Spec.Taints, newNode.Spec.Taints) { + t.Fatalf("%s: expected:\n%v\nsaw:\n%v\n", test.description, expectNewNode.Spec.Taints, newNode.Spec.Taints) } - return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, new_node)}, nil + return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, newNode)}, nil default: t.Fatalf("%s: unexpected request: %v %#v\n%#v", test.description, req.Method, req.URL, req) return nil, nil @@ -305,7 +305,7 @@ func TestTaint(t *testing.T) { cmd := NewCmdTaint(tf, genericclioptions.NewTestIOStreamsDiscard()) - saw_fatal := false + sawFatal := false func() { defer func() { // Recover from the panic below. @@ -316,13 +316,13 @@ func TestTaint(t *testing.T) { // Restore cmdutil behavior cmdutil.DefaultBehaviorOnFatal() }() - cmdutil.BehaviorOnFatal(func(e string, code int) { saw_fatal = true; panic(e) }) + cmdutil.BehaviorOnFatal(func(e string, code int) { sawFatal = true; panic(e) }) cmd.SetArgs(test.args) cmd.Execute() }() if test.expectFatal { - if !saw_fatal { + if !sawFatal { t.Fatalf("%s: unexpected non-error", test.description) } } diff --git a/pkg/kubectl/cmd/testing/fake.go b/pkg/kubectl/cmd/testing/fake.go index 4268b1ecacb..ac116373db6 100644 --- a/pkg/kubectl/cmd/testing/fake.go +++ b/pkg/kubectl/cmd/testing/fake.go @@ -51,6 +51,7 @@ import ( "k8s.io/kubernetes/pkg/kubectl/validation" ) +// InternalType is the schema for internal type // +k8s:deepcopy-gen=true // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object type InternalType struct { @@ -60,6 +61,7 @@ type InternalType struct { Name string } +// ExternalType is the schema for external type // +k8s:deepcopy-gen=true // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object type ExternalType struct { @@ -69,6 +71,7 @@ type ExternalType struct { Name string `json:"name"` } +// ExternalType2 is another schema for external type // +k8s:deepcopy-gen=true // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object type ExternalType2 struct { @@ -78,28 +81,46 @@ type ExternalType2 struct { Name string `json:"name"` } +// GetObjectKind returns the ObjectKind schema func (obj *InternalType) GetObjectKind() schema.ObjectKind { return obj } + +// SetGroupVersionKind sets the version and kind func (obj *InternalType) SetGroupVersionKind(gvk schema.GroupVersionKind) { obj.APIVersion, obj.Kind = gvk.ToAPIVersionAndKind() } + +// GroupVersionKind returns GroupVersionKind schema func (obj *InternalType) GroupVersionKind() schema.GroupVersionKind { return schema.FromAPIVersionAndKind(obj.APIVersion, obj.Kind) } + +// GetObjectKind returns the ObjectKind schema func (obj *ExternalType) GetObjectKind() schema.ObjectKind { return obj } + +// SetGroupVersionKind returns the GroupVersionKind schema func (obj *ExternalType) SetGroupVersionKind(gvk schema.GroupVersionKind) { obj.APIVersion, obj.Kind = gvk.ToAPIVersionAndKind() } + +// GroupVersionKind returns the GroupVersionKind schema func (obj *ExternalType) GroupVersionKind() schema.GroupVersionKind { return schema.FromAPIVersionAndKind(obj.APIVersion, obj.Kind) } + +// GetObjectKind returns the ObjectKind schema func (obj *ExternalType2) GetObjectKind() schema.ObjectKind { return obj } + +// SetGroupVersionKind sets the API version and obj kind from schema func (obj *ExternalType2) SetGroupVersionKind(gvk schema.GroupVersionKind) { obj.APIVersion, obj.Kind = gvk.ToAPIVersionAndKind() } + +// GroupVersionKind returns the FromAPIVersionAndKind schema func (obj *ExternalType2) GroupVersionKind() schema.GroupVersionKind { return schema.FromAPIVersionAndKind(obj.APIVersion, obj.Kind) } +// NewInternalType returns an initialized InternalType instance func NewInternalType(kind, apiversion, name string) *InternalType { item := InternalType{Kind: kind, APIVersion: apiversion, @@ -107,6 +128,7 @@ func NewInternalType(kind, apiversion, name string) *InternalType { return &item } +// InternalNamespacedType schema for internal namespaced types // +k8s:deepcopy-gen=true // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object type InternalNamespacedType struct { @@ -117,6 +139,7 @@ type InternalNamespacedType struct { Namespace string } +// ExternalNamespacedType schema for external namespaced types // +k8s:deepcopy-gen=true // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object type ExternalNamespacedType struct { @@ -127,6 +150,7 @@ type ExternalNamespacedType struct { Namespace string `json:"namespace"` } +// ExternalNamespacedType2 schema for external namespaced types // +k8s:deepcopy-gen=true // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object type ExternalNamespacedType2 struct { @@ -137,28 +161,46 @@ type ExternalNamespacedType2 struct { Namespace string `json:"namespace"` } +// GetObjectKind returns the ObjectKind schema func (obj *InternalNamespacedType) GetObjectKind() schema.ObjectKind { return obj } + +// SetGroupVersionKind sets the API group and kind from schema func (obj *InternalNamespacedType) SetGroupVersionKind(gvk schema.GroupVersionKind) { obj.APIVersion, obj.Kind = gvk.ToAPIVersionAndKind() } + +// GroupVersionKind returns the GroupVersionKind schema func (obj *InternalNamespacedType) GroupVersionKind() schema.GroupVersionKind { return schema.FromAPIVersionAndKind(obj.APIVersion, obj.Kind) } + +// GetObjectKind returns the ObjectKind schema func (obj *ExternalNamespacedType) GetObjectKind() schema.ObjectKind { return obj } + +// SetGroupVersionKind sets the API version and kind from schema func (obj *ExternalNamespacedType) SetGroupVersionKind(gvk schema.GroupVersionKind) { obj.APIVersion, obj.Kind = gvk.ToAPIVersionAndKind() } + +// GroupVersionKind returns the GroupVersionKind schema func (obj *ExternalNamespacedType) GroupVersionKind() schema.GroupVersionKind { return schema.FromAPIVersionAndKind(obj.APIVersion, obj.Kind) } + +// GetObjectKind returns the ObjectKind schema func (obj *ExternalNamespacedType2) GetObjectKind() schema.ObjectKind { return obj } + +// SetGroupVersionKind sets the API version and kind from schema func (obj *ExternalNamespacedType2) SetGroupVersionKind(gvk schema.GroupVersionKind) { obj.APIVersion, obj.Kind = gvk.ToAPIVersionAndKind() } + +// GroupVersionKind returns the GroupVersionKind schema func (obj *ExternalNamespacedType2) GroupVersionKind() schema.GroupVersionKind { return schema.FromAPIVersionAndKind(obj.APIVersion, obj.Kind) } +// NewInternalNamespacedType returns an initialized instance of InternalNamespacedType func NewInternalNamespacedType(kind, apiversion, name, namespace string) *InternalNamespacedType { item := InternalNamespacedType{Kind: kind, APIVersion: apiversion, @@ -167,26 +209,35 @@ func NewInternalNamespacedType(kind, apiversion, name, namespace string) *Intern return &item } -var versionErr = errors.New("not a version") +var errInvalidVersion = errors.New("not a version") func versionErrIfFalse(b bool) error { if b { return nil } - return versionErr + return errInvalidVersion } +// ValidVersion of API var ValidVersion = "v1" + +// InternalGV is the internal group version object var InternalGV = schema.GroupVersion{Group: "apitest", Version: runtime.APIVersionInternal} + +// UnlikelyGV is a group version object for unrecognised version var UnlikelyGV = schema.GroupVersion{Group: "apitest", Version: "unlikelyversion"} + +// ValidVersionGV is the valid group version object var ValidVersionGV = schema.GroupVersion{Group: "apitest", Version: ValidVersion} +// NewExternalScheme returns required objects for ExternalScheme func NewExternalScheme() (*runtime.Scheme, meta.RESTMapper, runtime.Codec) { scheme := runtime.NewScheme() mapper, codec := AddToScheme(scheme) return scheme, mapper, codec } +// AddToScheme adds required objects into scheme func AddToScheme(scheme *runtime.Scheme) (meta.RESTMapper, runtime.Codec) { scheme.AddKnownTypeWithName(InternalGV.WithKind("Type"), &InternalType{}) scheme.AddKnownTypeWithName(UnlikelyGV.WithKind("Type"), &ExternalType{}) @@ -228,6 +279,7 @@ func (d *fakeCachedDiscoveryClient) ServerResources() ([]*metav1.APIResourceList return []*metav1.APIResourceList{}, nil } +// TestFactory extends cmdutil.Factory type TestFactory struct { cmdutil.Factory @@ -245,6 +297,7 @@ type TestFactory struct { OpenAPISchemaFunc func() (openapi.Resources, error) } +// NewTestFactory returns an initialized TestFactory instance func NewTestFactory() *TestFactory { // specify an optionalClientConfig to explicitly use in testing // to avoid polluting an existing user config. @@ -281,11 +334,13 @@ func NewTestFactory() *TestFactory { } } +// WithNamespace is used to mention namespace reactively func (f *TestFactory) WithNamespace(ns string) *TestFactory { f.kubeConfigFlags.WithNamespace(ns) return f } +// Cleanup cleans up TestFactory temp config file func (f *TestFactory) Cleanup() { if f.tempConfigFile == nil { return @@ -294,14 +349,17 @@ func (f *TestFactory) Cleanup() { os.Remove(f.tempConfigFile.Name()) } +// ToRESTConfig is used to get ClientConfigVal from a TestFactory func (f *TestFactory) ToRESTConfig() (*restclient.Config, error) { return f.ClientConfigVal, nil } +// ClientForMapping is used to Client from a TestFactory func (f *TestFactory) ClientForMapping(mapping *meta.RESTMapping) (resource.RESTClient, error) { return f.Client, nil } +// UnstructuredClientForMapping is used to get UnstructuredClient from a TestFactory func (f *TestFactory) UnstructuredClientForMapping(mapping *meta.RESTMapping) (resource.RESTClient, error) { if f.UnstructuredClientForMappingFunc != nil { return f.UnstructuredClientForMappingFunc(mapping.GroupVersionKind.GroupVersion()) @@ -309,10 +367,12 @@ func (f *TestFactory) UnstructuredClientForMapping(mapping *meta.RESTMapping) (r return f.UnstructuredClient, nil } +// Validator returns a validation schema func (f *TestFactory) Validator(validate bool) (validation.Schema, error) { return validation.NullSchema{}, nil } +// OpenAPISchema returns openapi resources func (f *TestFactory) OpenAPISchema() (openapi.Resources, error) { if f.OpenAPISchemaFunc != nil { return f.OpenAPISchemaFunc() @@ -320,6 +380,7 @@ func (f *TestFactory) OpenAPISchema() (openapi.Resources, error) { return openapitesting.EmptyResources{}, nil } +// NewBuilder returns an initialized resource.Builder instance func (f *TestFactory) NewBuilder() *resource.Builder { return resource.NewFakeBuilder( func(version schema.GroupVersion) (resource.RESTClient, error) { @@ -338,6 +399,7 @@ func (f *TestFactory) NewBuilder() *resource.Builder { ) } +// KubernetesClientSet initializes and returns the Clientset using TestFactory func (f *TestFactory) KubernetesClientSet() (*kubernetes.Clientset, error) { fakeClient := f.Client.(*fake.RESTClient) clientset := kubernetes.NewForConfigOrDie(f.ClientConfigVal) @@ -359,12 +421,14 @@ func (f *TestFactory) KubernetesClientSet() (*kubernetes.Clientset, error) { clientset.StorageV1beta1().RESTClient().(*restclient.RESTClient).Client = fakeClient.Client clientset.AppsV1beta1().RESTClient().(*restclient.RESTClient).Client = fakeClient.Client clientset.AppsV1beta2().RESTClient().(*restclient.RESTClient).Client = fakeClient.Client + clientset.AppsV1().RESTClient().(*restclient.RESTClient).Client = fakeClient.Client clientset.PolicyV1beta1().RESTClient().(*restclient.RESTClient).Client = fakeClient.Client clientset.DiscoveryClient.RESTClient().(*restclient.RESTClient).Client = fakeClient.Client return clientset, nil } +// DynamicClient returns a dynamic client from TestFactory func (f *TestFactory) DynamicClient() (dynamic.Interface, error) { if f.FakeDynamicClient != nil { return f.FakeDynamicClient, nil @@ -372,6 +436,7 @@ func (f *TestFactory) DynamicClient() (dynamic.Interface, error) { return f.Factory.DynamicClient() } +// RESTClient returns a REST client from TestFactory func (f *TestFactory) RESTClient() (*restclient.RESTClient, error) { // Swap out the HTTP client out of the client with the fake's version. fakeClient := f.Client.(*fake.RESTClient) @@ -383,6 +448,7 @@ func (f *TestFactory) RESTClient() (*restclient.RESTClient, error) { return restClient, nil } +// DiscoveryClient returns a discovery client from TestFactory func (f *TestFactory) DiscoveryClient() (discovery.CachedDiscoveryInterface, error) { fakeClient := f.Client.(*fake.RESTClient) @@ -413,6 +479,7 @@ func testRESTMapper() meta.RESTMapper { return expander } +// ScaleClient returns the ScalesGetter from a TestFactory func (f *TestFactory) ScaleClient() (scaleclient.ScalesGetter, error) { return f.ScaleGetter, nil } diff --git a/pkg/kubectl/cmd/top/top_node_test.go b/pkg/kubectl/cmd/top/top_node_test.go index b610d201a88..d350489a509 100644 --- a/pkg/kubectl/cmd/top/top_node_test.go +++ b/pkg/kubectl/cmd/top/top_node_test.go @@ -46,7 +46,7 @@ const ( func TestTopNodeAllMetrics(t *testing.T) { cmdtesting.InitTestErrorHandler(t) metrics, nodes := testNodeV1alpha1MetricsData() - expectedMetricsPath := fmt.Sprintf("%s/%s/nodes", baseMetricsAddress, metricsApiVersion) + expectedMetricsPath := fmt.Sprintf("%s/%s/nodes", baseMetricsAddress, metricsAPIVersion) expectedNodePath := fmt.Sprintf("/%s/%s/nodes", apiPrefix, apiVersion) tf := cmdtesting.NewTestFactory().WithNamespace("test") @@ -102,7 +102,7 @@ func TestTopNodeAllMetricsCustomDefaults(t *testing.T) { cmdtesting.InitTestErrorHandler(t) metrics, nodes := testNodeV1alpha1MetricsData() - expectedMetricsPath := fmt.Sprintf("%s/%s/nodes", customBaseMetricsAddress, metricsApiVersion) + expectedMetricsPath := fmt.Sprintf("%s/%s/nodes", customBaseMetricsAddress, metricsAPIVersion) expectedNodePath := fmt.Sprintf("/%s/%s/nodes", apiPrefix, apiVersion) tf := cmdtesting.NewTestFactory().WithNamespace("test") @@ -165,7 +165,7 @@ func TestTopNodeWithNameMetrics(t *testing.T) { ListMeta: metrics.ListMeta, Items: metrics.Items[1:], } - expectedPath := fmt.Sprintf("%s/%s/nodes/%s", baseMetricsAddress, metricsApiVersion, expectedMetrics.Name) + expectedPath := fmt.Sprintf("%s/%s/nodes/%s", baseMetricsAddress, metricsAPIVersion, expectedMetrics.Name) expectedNodePath := fmt.Sprintf("/%s/%s/nodes/%s", apiPrefix, apiVersion, expectedMetrics.Name) tf := cmdtesting.NewTestFactory().WithNamespace("test") @@ -230,7 +230,7 @@ func TestTopNodeWithLabelSelectorMetrics(t *testing.T) { Items: metrics.Items[1:], } label := "key=value" - expectedPath := fmt.Sprintf("%s/%s/nodes", baseMetricsAddress, metricsApiVersion) + expectedPath := fmt.Sprintf("%s/%s/nodes", baseMetricsAddress, metricsAPIVersion) expectedQuery := fmt.Sprintf("labelSelector=%s", url.QueryEscape(label)) expectedNodePath := fmt.Sprintf("/%s/%s/nodes", apiPrefix, apiVersion) diff --git a/pkg/kubectl/cmd/top/top_pod.go b/pkg/kubectl/cmd/top/top_pod.go index 5c9a3712761..1ba4c722166 100644 --- a/pkg/kubectl/cmd/top/top_pod.go +++ b/pkg/kubectl/cmd/top/top_pod.go @@ -103,7 +103,7 @@ func NewCmdTopPod(f cmdutil.Factory, o *TopPodOptions, streams genericclioptions } cmd.Flags().StringVarP(&o.Selector, "selector", "l", o.Selector, "Selector (label query) to filter on, supports '=', '==', and '!='.(e.g. -l key1=value1,key2=value2)") cmd.Flags().BoolVar(&o.PrintContainers, "containers", o.PrintContainers, "If present, print usage of containers within a pod.") - cmd.Flags().BoolVar(&o.AllNamespaces, "all-namespaces", o.AllNamespaces, "If present, list the requested object(s) across all namespaces. Namespace in current context is ignored even if specified with --namespace.") + cmd.Flags().BoolVarP(&o.AllNamespaces, "all-namespaces", "A", o.AllNamespaces, "If present, list the requested object(s) across all namespaces. Namespace in current context is ignored even if specified with --namespace.") cmd.Flags().BoolVar(&o.NoHeaders, "no-headers", o.NoHeaders, "If present, print output without headers.") o.HeapsterOptions.Bind(cmd.Flags()) return cmd diff --git a/pkg/kubectl/cmd/top/top_pod_test.go b/pkg/kubectl/cmd/top/top_pod_test.go index f0ab8b0010f..1d28b4c6a5d 100644 --- a/pkg/kubectl/cmd/top/top_pod_test.go +++ b/pkg/kubectl/cmd/top/top_pod_test.go @@ -45,7 +45,7 @@ import ( ) const ( - topPathPrefix = baseMetricsAddress + "/" + metricsApiVersion + topPathPrefix = baseMetricsAddress + "/" + metricsAPIVersion topMetricsAPIPathPrefix = "/apis/metrics.k8s.io/v1beta1" apibody = `{ "kind": "APIVersions", @@ -440,7 +440,7 @@ func (d *fakeDiscovery) RESTClient() restclient.Interface { func TestTopPodCustomDefaults(t *testing.T) { customBaseHeapsterServiceAddress := "/api/v1/namespaces/custom-namespace/services/https:custom-heapster-service:/proxy" customBaseMetricsAddress := customBaseHeapsterServiceAddress + "/apis/metrics" - customTopPathPrefix := customBaseMetricsAddress + "/" + metricsApiVersion + customTopPathPrefix := customBaseMetricsAddress + "/" + metricsAPIVersion testNS := "custom-namespace" testCases := []struct { diff --git a/pkg/kubectl/cmd/top/top_test.go b/pkg/kubectl/cmd/top/top_test.go index 834dd36004d..eaa6856444c 100644 --- a/pkg/kubectl/cmd/top/top_test.go +++ b/pkg/kubectl/cmd/top/top_test.go @@ -38,7 +38,7 @@ const ( baseHeapsterServiceAddress = "/api/v1/namespaces/kube-system/services/http:heapster:/proxy" baseMetricsAddress = baseHeapsterServiceAddress + "/apis/metrics" baseMetricsServerAddress = "/apis/metrics.k8s.io/v1beta1" - metricsApiVersion = "v1alpha1" + metricsAPIVersion = "v1alpha1" ) func TestTopSubcommandsExist(t *testing.T) { diff --git a/pkg/kubectl/cmd/util/editor/editoptions.go b/pkg/kubectl/cmd/util/editor/editoptions.go index 2b2add45859..0293df42729 100644 --- a/pkg/kubectl/cmd/util/editor/editoptions.go +++ b/pkg/kubectl/cmd/util/editor/editoptions.go @@ -81,6 +81,7 @@ type EditOptions struct { updatedResultGetter func(data []byte) *resource.Result } +// NewEditOptions returns an initialized EditOptions instance func NewEditOptions(editMode EditMode, ioStreams genericclioptions.IOStreams) *EditOptions { return &EditOptions{ RecordFlags: genericclioptions.NewRecordFlags(), @@ -216,6 +217,7 @@ func (o *EditOptions) Validate() error { return nil } +// Run performs the execution func (o *EditOptions) Run() error { edit := NewDefaultEditor(editorEnvs()) // editFn is invoked for each edit session (once with a list for normal edit, once for each individual resource in a edit-on-create invocation) @@ -399,7 +401,7 @@ func (o *EditOptions) Run() error { return err } if len(infos) == 0 { - return errors.New("edit cancelled, no objects found.") + return errors.New("edit cancelled, no objects found") } return editFn(infos) case ApplyEditMode: @@ -459,12 +461,12 @@ func (o *EditOptions) visitToApplyEditPatch(originalInfos []*resource.Info, patc return fmt.Errorf("no original object found for %#v", info.Object) } - originalJS, err := encodeToJson(originalInfo.Object.(runtime.Unstructured)) + originalJS, err := encodeToJSON(originalInfo.Object.(runtime.Unstructured)) if err != nil { return err } - editedJS, err := encodeToJson(info.Object.(runtime.Unstructured)) + editedJS, err := encodeToJSON(info.Object.(runtime.Unstructured)) if err != nil { return err } @@ -474,21 +476,18 @@ func (o *EditOptions) visitToApplyEditPatch(originalInfos []*resource.Info, patc if err != nil { return err } - printer.PrintObj(info.Object, o.Out) - return nil - } else { - err := o.annotationPatch(info) - if err != nil { - return err - } - - printer, err := o.ToPrinter("edited") - if err != nil { - return err - } - printer.PrintObj(info.Object, o.Out) - return nil + return printer.PrintObj(info.Object, o.Out) } + err = o.annotationPatch(info) + if err != nil { + return err + } + + printer, err := o.ToPrinter("edited") + if err != nil { + return err + } + return printer.PrintObj(info.Object, o.Out) }) return err } @@ -511,8 +510,9 @@ func (o *EditOptions) annotationPatch(update *resource.Info) error { return nil } +// GetApplyPatch is used to get and apply patches func GetApplyPatch(obj runtime.Unstructured) ([]byte, []byte, types.PatchType, error) { - beforeJSON, err := encodeToJson(obj) + beforeJSON, err := encodeToJSON(obj) if err != nil { return nil, []byte(""), types.MergePatchType, err } @@ -527,7 +527,7 @@ func GetApplyPatch(obj runtime.Unstructured) ([]byte, []byte, types.PatchType, e } annotations[corev1.LastAppliedConfigAnnotation] = string(beforeJSON) accessor.SetAnnotations(objCopy, annotations) - afterJSON, err := encodeToJson(objCopy.(runtime.Unstructured)) + afterJSON, err := encodeToJSON(objCopy.(runtime.Unstructured)) if err != nil { return nil, beforeJSON, types.MergePatchType, err } @@ -535,7 +535,7 @@ func GetApplyPatch(obj runtime.Unstructured) ([]byte, []byte, types.PatchType, e return patch, beforeJSON, types.MergePatchType, err } -func encodeToJson(obj runtime.Unstructured) ([]byte, error) { +func encodeToJSON(obj runtime.Unstructured) ([]byte, error) { serialization, err := runtime.Encode(unstructured.UnstructuredJSONScheme, obj) if err != nil { return nil, err @@ -569,12 +569,12 @@ func (o *EditOptions) visitToPatch(originalInfos []*resource.Info, patchVisitor return fmt.Errorf("no original object found for %#v", info.Object) } - originalJS, err := encodeToJson(originalInfo.Object.(runtime.Unstructured)) + originalJS, err := encodeToJSON(originalInfo.Object.(runtime.Unstructured)) if err != nil { return err } - editedJS, err := encodeToJson(info.Object.(runtime.Unstructured)) + editedJS, err := encodeToJSON(info.Object.(runtime.Unstructured)) if err != nil { return err } @@ -585,8 +585,7 @@ func (o *EditOptions) visitToPatch(originalInfos []*resource.Info, patchVisitor if err != nil { return err } - printer.PrintObj(info.Object, o.Out) - return nil + return printer.PrintObj(info.Object, o.Out) } preconditions := []mergepatch.PreconditionFunc{ @@ -643,8 +642,7 @@ func (o *EditOptions) visitToPatch(originalInfos []*resource.Info, patchVisitor if err != nil { return err } - printer.PrintObj(info.Object, o.Out) - return nil + return printer.PrintObj(info.Object, o.Out) }) return err } @@ -658,8 +656,7 @@ func (o *EditOptions) visitToCreate(createVisitor resource.Visitor) error { if err != nil { return err } - printer.PrintObj(info.Object, o.Out) - return nil + return printer.PrintObj(info.Object, o.Out) }) return err } @@ -683,12 +680,18 @@ func (o *EditOptions) visitAnnotation(annotationVisitor resource.Visitor) error return err } +// EditMode can be either NormalEditMode, EditBeforeCreateMode or ApplyEditMode type EditMode string const ( - NormalEditMode EditMode = "normal_mode" + // NormalEditMode is an edit mode + NormalEditMode EditMode = "normal_mode" + + // EditBeforeCreateMode is an edit mode EditBeforeCreateMode EditMode = "edit_before_create_mode" - ApplyEditMode EditMode = "edit_last_applied_mode" + + // ApplyEditMode is an edit mode + ApplyEditMode EditMode = "edit_last_applied_mode" ) // editReason preserves a message about the reason this file must be edited again diff --git a/pkg/kubectl/cmd/util/editor/editor.go b/pkg/kubectl/cmd/util/editor/editor.go index e7229870ec7..ef7831ca110 100644 --- a/pkg/kubectl/cmd/util/editor/editor.go +++ b/pkg/kubectl/cmd/util/editor/editor.go @@ -43,6 +43,7 @@ const ( windowsShell = "cmd" ) +// Editor holds the command-line args to fire up the editor type Editor struct { Args []string Shell bool diff --git a/pkg/kubectl/cmd/util/helpers.go b/pkg/kubectl/cmd/util/helpers.go index d06df848486..e208e3537d2 100644 --- a/pkg/kubectl/cmd/util/helpers.go +++ b/pkg/kubectl/cmd/util/helpers.go @@ -289,7 +289,7 @@ func messageForError(err error) string { func UsageErrorf(cmd *cobra.Command, format string, args ...interface{}) error { msg := fmt.Sprintf(format, args...) - return fmt.Errorf("%s\nSee '%s -h' for help and examples.", msg, cmd.CommandPath()) + return fmt.Errorf("%s\nSee '%s -h' for help and examples", msg, cmd.CommandPath()) } func IsFilenameSliceEmpty(filenames []string) bool { diff --git a/pkg/kubectl/cmd/util/kubectl_match_version.go b/pkg/kubectl/cmd/util/kubectl_match_version.go index 99ba2baeec6..675f8e1d91d 100644 --- a/pkg/kubectl/cmd/util/kubectl_match_version.go +++ b/pkg/kubectl/cmd/util/kubectl_match_version.go @@ -92,7 +92,7 @@ func (f *MatchVersionFlags) ToDiscoveryClient() (discovery.CachedDiscoveryInterf return f.Delegate.ToDiscoveryClient() } -// RESTMapper returns a mapper. +// ToRESTMapper returns a mapper. func (f *MatchVersionFlags) ToRESTMapper() (meta.RESTMapper, error) { if err := f.checkMatchingServerVersion(); err != nil { return nil, err diff --git a/pkg/kubectl/cmd/util/openapi/validation/validation_test.go b/pkg/kubectl/cmd/util/openapi/validation/validation_test.go index ea2ddc93a49..89807c971a7 100644 --- a/pkg/kubectl/cmd/util/openapi/validation/validation_test.go +++ b/pkg/kubectl/cmd/util/openapi/validation/validation_test.go @@ -24,6 +24,7 @@ import ( utilerrors "k8s.io/apimachinery/pkg/util/errors" "k8s.io/kube-openapi/pkg/util/proto/validation" + // This dependency is needed to register API types. "k8s.io/kube-openapi/pkg/util/proto/testing" "k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi" @@ -44,7 +45,7 @@ var _ = Describe("resource validation using OpenAPI Schema", func() { It("finds Deployment in Schema and validates it", func() { err := validator.ValidateBytes([]byte(` -apiVersion: extensions/v1beta1 +apiVersion: apps/v1 kind: Deployment metadata: labels: @@ -52,6 +53,9 @@ metadata: name: name spec: replicas: 1 + selector: + matchLabels: + app: redis template: metadata: labels: diff --git a/pkg/kubectl/cmd/util/printing.go b/pkg/kubectl/cmd/util/printing.go index 75b73c62048..f093940d8a4 100644 --- a/pkg/kubectl/cmd/util/printing.go +++ b/pkg/kubectl/cmd/util/printing.go @@ -22,8 +22,8 @@ import ( "k8s.io/kubernetes/pkg/kubectl/util/templates" ) -// SuggestApiResources returns a suggestion to use the "api-resources" command +// SuggestAPIResources returns a suggestion to use the "api-resources" command // to retrieve a supported list of resources -func SuggestApiResources(parent string) string { +func SuggestAPIResources(parent string) string { return templates.LongDesc(fmt.Sprintf("Use \"%s api-resources\" for a complete list of supported resources.", parent)) } diff --git a/pkg/kubectl/cmd/util/sanity/cmd_sanity.go b/pkg/kubectl/cmd/util/sanity/cmd_sanity.go index 21d2a291d29..4ec078d1e12 100644 --- a/pkg/kubectl/cmd/util/sanity/cmd_sanity.go +++ b/pkg/kubectl/cmd/util/sanity/cmd_sanity.go @@ -28,20 +28,27 @@ import ( "k8s.io/kubernetes/pkg/kubectl/util/templates" ) +// CmdCheck is the commom type of functions to check cobra commands type CmdCheck func(cmd *cobra.Command) []error + +// GlobalCheck is the common type of functions to check global flags type GlobalCheck func() []error var ( + // AllCmdChecks is the list of CmdCheck type functions AllCmdChecks = []CmdCheck{ CheckLongDesc, CheckExamples, CheckFlags, } + + // AllGlobalChecks is the list of GlobalCheck type functions AllGlobalChecks = []GlobalCheck{ CheckGlobalVarFlags, } ) +// RunGlobalChecks runs all the GlobalCheck functions passed and checks for error func RunGlobalChecks(globalChecks []GlobalCheck) []error { fmt.Fprint(os.Stdout, "---+ RUNNING GLOBAL CHECKS\n") errors := []error{} @@ -51,6 +58,7 @@ func RunGlobalChecks(globalChecks []GlobalCheck) []error { return errors } +// RunCmdChecks runs all the CmdCheck functions passed, skipping skippable commands and looks for error func RunCmdChecks(cmd *cobra.Command, cmdChecks []CmdCheck, skipCmd []string) []error { cmdPath := cmd.CommandPath() @@ -80,6 +88,7 @@ func RunCmdChecks(cmd *cobra.Command, cmdChecks []CmdCheck, skipCmd []string) [] return errors } +// CheckLongDesc checks if the long description is valid func CheckLongDesc(cmd *cobra.Command) []error { fmt.Fprint(os.Stdout, " ↳ checking long description\n") cmdPath := cmd.CommandPath() @@ -92,6 +101,7 @@ func CheckLongDesc(cmd *cobra.Command) []error { return nil } +// CheckExamples checks if the command examples are valid func CheckExamples(cmd *cobra.Command) []error { fmt.Fprint(os.Stdout, " ↳ checking examples\n") cmdPath := cmd.CommandPath() @@ -110,6 +120,7 @@ func CheckExamples(cmd *cobra.Command) []error { return errors } +// CheckFlags checks if the command-line flags are valid func CheckFlags(cmd *cobra.Command) []error { allFlagsSlice := []*pflag.Flag{} @@ -140,6 +151,7 @@ func CheckFlags(cmd *cobra.Command) []error { return errors } +// CheckGlobalVarFlags checks if the global flags are valid func CheckGlobalVarFlags() []error { fmt.Fprint(os.Stdout, " ↳ checking flags from global vars\n") errors := []error{} diff --git a/pkg/kubectl/cmd/wait/wait.go b/pkg/kubectl/cmd/wait/wait.go index 6a1e075e816..7e85fbcf7b9 100644 --- a/pkg/kubectl/cmd/wait/wait.go +++ b/pkg/kubectl/cmd/wait/wait.go @@ -44,7 +44,7 @@ import ( ) var ( - wait_long = templates.LongDesc(` + waitLong = templates.LongDesc(` Experimental: Wait for a specific condition on one or many resources. The command takes multiple resources and waits until the specified condition @@ -56,7 +56,7 @@ var ( A successful message will be printed to stdout indicating when the specified condition has been met. One can use -o option to change to output destination.`) - wait_example = templates.Examples(` + waitExample = templates.Examples(` # Wait for the pod "busybox1" to contain the status condition of type "Ready". kubectl wait --for=condition=Ready pod/busybox1 @@ -90,6 +90,7 @@ func NewWaitFlags(restClientGetter genericclioptions.RESTClientGetter, streams g ResourceBuilderFlags: genericclioptions.NewResourceBuilderFlags(). WithLabelSelector(""). WithAllNamespaces(false). + WithAll(false). WithLatest(), Timeout: 30 * time.Second, @@ -106,8 +107,8 @@ func NewCmdWait(restClientGetter genericclioptions.RESTClientGetter, streams gen Use: "wait resource.group/name [--for=delete|--for condition=available]", DisableFlagsInUseLine: true, Short: "Experimental: Wait for a specific condition on one or many resources.", - Long: wait_long, - Example: wait_example, + Long: waitLong, + Example: waitExample, Run: func(cmd *cobra.Command, args []string) { o, err := flags.ToOptions(args) cmdutil.CheckErr(err) @@ -191,12 +192,14 @@ func conditionFuncFor(condition string, errOut io.Writer) (ConditionFunc, error) return nil, fmt.Errorf("unrecognized condition: %q", condition) } +// ResourceLocation holds the location of a resource type ResourceLocation struct { GroupResource schema.GroupResource Namespace string Name string } +// UIDMap maps ResourceLocation with UID type UIDMap map[ResourceLocation]types.UID // WaitOptions is a set of options that allows you to wait. This is the object reflects the runtime needs of a wait diff --git a/pkg/kubectl/describe/versioned/describe.go b/pkg/kubectl/describe/versioned/describe.go index b3bb2c739b4..289c4affb97 100644 --- a/pkg/kubectl/describe/versioned/describe.go +++ b/pkg/kubectl/describe/versioned/describe.go @@ -881,8 +881,8 @@ func printProjectedVolumeSource(projected *corev1.ProjectedVolumeSource, w Prefi " ConfigMapOptional:\t%v\n", source.ConfigMap.Name, source.ConfigMap.Optional) } else if source.ServiceAccountToken != nil { - w.Write(LEVEL_2, "TokenExpirationSeconds:\t%v\n", - source.ServiceAccountToken.ExpirationSeconds) + w.Write(LEVEL_2, "TokenExpirationSeconds:\t%d\n", + *source.ServiceAccountToken.ExpirationSeconds) } } } @@ -1041,18 +1041,18 @@ func printCinderVolumeSource(cinder *corev1.CinderVolumeSource, w PrefixWriter) w.Write(LEVEL_2, "Type:\tCinder (a Persistent Disk resource in OpenStack)\n"+ " VolumeID:\t%v\n"+ " FSType:\t%v\n"+ - " ReadOnly:\t%v\n", - " SecretRef:\t%v\n"+ - cinder.VolumeID, cinder.FSType, cinder.ReadOnly, cinder.SecretRef) + " ReadOnly:\t%v\n"+ + " SecretRef:\t%v\n", + cinder.VolumeID, cinder.FSType, cinder.ReadOnly, cinder.SecretRef) } func printCinderPersistentVolumeSource(cinder *corev1.CinderPersistentVolumeSource, w PrefixWriter) { w.Write(LEVEL_2, "Type:\tCinder (a Persistent Disk resource in OpenStack)\n"+ " VolumeID:\t%v\n"+ " FSType:\t%v\n"+ - " ReadOnly:\t%v\n", - " SecretRef:\t%v\n"+ - cinder.VolumeID, cinder.SecretRef, cinder.FSType, cinder.ReadOnly, cinder.SecretRef) + " ReadOnly:\t%v\n"+ + " SecretRef:\t%v\n", + cinder.VolumeID, cinder.FSType, cinder.ReadOnly, cinder.SecretRef) } func printScaleIOVolumeSource(sio *corev1.ScaleIOVolumeSource, w PrefixWriter) { @@ -2073,6 +2073,16 @@ func describeCronJob(cronJob *batchv1beta1.CronJob, events *corev1.EventList) (s w.Write(LEVEL_0, "Schedule:\t%s\n", cronJob.Spec.Schedule) w.Write(LEVEL_0, "Concurrency Policy:\t%s\n", cronJob.Spec.ConcurrencyPolicy) w.Write(LEVEL_0, "Suspend:\t%s\n", printBoolPtr(cronJob.Spec.Suspend)) + if cronJob.Spec.SuccessfulJobsHistoryLimit != nil { + w.Write(LEVEL_0, "Successful Job History Limit:\t%d\n", cronJob.Spec.SuccessfulJobsHistoryLimit) + } else { + w.Write(LEVEL_0, "Successful Job History Limit:\t\n") + } + if cronJob.Spec.FailedJobsHistoryLimit != nil { + w.Write(LEVEL_0, "Failed Job History Limit:\t%d\n", *cronJob.Spec.FailedJobsHistoryLimit) + } else { + w.Write(LEVEL_0, "Failed Job History Limit:\t\n") + } if cronJob.Spec.StartingDeadlineSeconds != nil { w.Write(LEVEL_0, "Starting Deadline Seconds:\t%ds\n", *cronJob.Spec.StartingDeadlineSeconds) } else { diff --git a/pkg/kubectl/generate/versioned/secret_for_docker_registry.go b/pkg/kubectl/generate/versioned/secret_for_docker_registry.go index db9d38448c2..bae9f05aa1a 100644 --- a/pkg/kubectl/generate/versioned/secret_for_docker_registry.go +++ b/pkg/kubectl/generate/versioned/secret_for_docker_registry.go @@ -17,6 +17,7 @@ limitations under the License. package versioned import ( + "encoding/base64" "encoding/json" "fmt" @@ -152,6 +153,7 @@ func handleDockerCfgJSONContent(username, password, email, server string) ([]byt Username: username, Password: password, Email: email, + Auth: encodeDockerConfigFieldAuth(username, password), } dockerCfgJSON := DockerConfigJSON{ @@ -161,6 +163,11 @@ func handleDockerCfgJSONContent(username, password, email, server string) ([]byt return json.Marshal(dockerCfgJSON) } +func encodeDockerConfigFieldAuth(username, password string) string { + fieldValue := username + ":" + password + return base64.StdEncoding.EncodeToString([]byte(fieldValue)) +} + // DockerConfigJSON represents a local docker auth config file // for pulling images. type DockerConfigJSON struct { @@ -175,7 +182,8 @@ type DockerConfigJSON struct { type DockerConfig map[string]DockerConfigEntry type DockerConfigEntry struct { - Username string - Password string - Email string + Username string `json:"username,omitempty"` + Password string `json:"password,omitempty"` + Email string `json:"email,omitempty"` + Auth string `json:"auth,omitempty"` } diff --git a/pkg/kubectl/generate/versioned/secret_for_docker_registry_test.go b/pkg/kubectl/generate/versioned/secret_for_docker_registry_test.go index 2b90e186ef9..304cf400b37 100644 --- a/pkg/kubectl/generate/versioned/secret_for_docker_registry_test.go +++ b/pkg/kubectl/generate/versioned/secret_for_docker_registry_test.go @@ -73,7 +73,7 @@ func TestSecretForDockerRegistryGenerate(t *testing.T) { }, expected: &v1.Secret{ ObjectMeta: metav1.ObjectMeta{ - Name: "foo-7566tc6mgc", + Name: "foo-548cm7fgdh", }, Data: map[string][]byte{ v1.DockerConfigJsonKey: secretData, diff --git a/pkg/kubectl/polymorphichelpers/mapbasedselectorforobject_test.go b/pkg/kubectl/polymorphichelpers/mapbasedselectorforobject_test.go index 1ca8d1c7a94..96044d64357 100644 --- a/pkg/kubectl/polymorphichelpers/mapbasedselectorforobject_test.go +++ b/pkg/kubectl/polymorphichelpers/mapbasedselectorforobject_test.go @@ -382,6 +382,92 @@ func TestMapBasedSelectorForObject(t *testing.T) { expectErr: true, }, // Node can not be exposed -- error + { + object: &appsv1.Deployment{ + Spec: appsv1.DeploymentSpec{ + Selector: &metav1.LabelSelector{ + MatchLabels: map[string]string{ + "foo": "bar", + }, + }, + }, + }, + expectSelector: "foo=bar", + }, + { + object: &appsv1.Deployment{ + Spec: appsv1.DeploymentSpec{ + Selector: &metav1.LabelSelector{ + MatchExpressions: []metav1.LabelSelectorRequirement{ + { + Key: "foo", + }, + }, + }, + }, + }, + expectErr: true, + }, + { + object: &appsv1.ReplicaSet{ + Spec: appsv1.ReplicaSetSpec{ + Selector: &metav1.LabelSelector{ + MatchLabels: map[string]string{ + "foo": "bar", + }, + }, + }, + }, + expectSelector: "foo=bar", + }, + { + object: &appsv1.ReplicaSet{ + Spec: appsv1.ReplicaSetSpec{ + Selector: &metav1.LabelSelector{ + MatchExpressions: []metav1.LabelSelectorRequirement{ + { + Key: "foo", + }, + }, + }, + }, + }, + expectErr: true, + }, + + { + object: &appsv1.Deployment{ + Spec: appsv1.DeploymentSpec{ + Selector: nil, + }, + }, + expectErr: true, + }, + { + object: &appsv1.Deployment{ + Spec: appsv1.DeploymentSpec{ + Selector: nil, + }, + }, + expectErr: true, + }, + { + object: &appsv1.ReplicaSet{ + Spec: appsv1.ReplicaSetSpec{ + Selector: nil, + }, + }, + expectErr: true, + }, + { + object: &appsv1.ReplicaSet{ + Spec: appsv1.ReplicaSetSpec{ + Selector: nil, + }, + }, + expectErr: true, + }, + { object: &corev1.Node{}, expectErr: true, diff --git a/pkg/kubectl/rollback.go b/pkg/kubectl/rollback.go index 8851d574105..bd7e2c7c855 100644 --- a/pkg/kubectl/rollback.go +++ b/pkg/kubectl/rollback.go @@ -293,7 +293,7 @@ func (r *DaemonSetRollbacker) Rollback(obj runtime.Object, updatedAnnotations ma } // Restore revision - if _, err = r.c.ExtensionsV1beta1().DaemonSets(accessor.GetNamespace()).Patch(accessor.GetName(), types.StrategicMergePatchType, toHistory.Data.Raw); err != nil { + if _, err = r.c.AppsV1().DaemonSets(accessor.GetNamespace()).Patch(accessor.GetName(), types.StrategicMergePatchType, toHistory.Data.Raw); err != nil { return "", fmt.Errorf("failed restoring revision %d: %v", toRevision, err) } diff --git a/pkg/kubectl/util/printers/BUILD b/pkg/kubectl/util/printers/BUILD index 80a8c446ee1..1687a952eaf 100644 --- a/pkg/kubectl/util/printers/BUILD +++ b/pkg/kubectl/util/printers/BUILD @@ -5,6 +5,7 @@ go_library( srcs = ["tabwriter.go"], importpath = "k8s.io/kubernetes/pkg/kubectl/util/printers", visibility = ["//visibility:public"], + deps = ["//vendor/github.com/liggitt/tabwriter:go_default_library"], ) filegroup( diff --git a/pkg/kubectl/util/printers/tabwriter.go b/pkg/kubectl/util/printers/tabwriter.go index aadb888b7ef..f0ebb5dda08 100644 --- a/pkg/kubectl/util/printers/tabwriter.go +++ b/pkg/kubectl/util/printers/tabwriter.go @@ -18,7 +18,8 @@ package printers import ( "io" - "text/tabwriter" + + "github.com/liggitt/tabwriter" ) const ( @@ -26,7 +27,7 @@ const ( tabwriterWidth = 4 tabwriterPadding = 3 tabwriterPadChar = ' ' - tabwriterFlags = 0 + tabwriterFlags = tabwriter.RememberWidths ) // GetNewTabWriter returns a tabwriter that translates tabbed columns in input into properly aligned text. diff --git a/pkg/kubelet/BUILD b/pkg/kubelet/BUILD index 182e53517c9..61e9e649ed1 100644 --- a/pkg/kubelet/BUILD +++ b/pkg/kubelet/BUILD @@ -165,6 +165,7 @@ go_test( "kubelet_pods_windows_test.go", "kubelet_resources_test.go", "kubelet_test.go", + "kubelet_volumes_linux_test.go", "kubelet_volumes_test.go", "oom_watcher_test.go", "pod_container_deletor_test.go", @@ -208,7 +209,7 @@ go_test( "//pkg/kubelet/util/sliceutils:go_default_library", "//pkg/kubelet/volumemanager:go_default_library", "//pkg/scheduler/api:go_default_library", - "//pkg/scheduler/cache:go_default_library", + "//pkg/scheduler/nodeinfo:go_default_library", "//pkg/util/mount:go_default_library", "//pkg/util/taints:go_default_library", "//pkg/version:go_default_library", diff --git a/pkg/kubelet/apis/stats/v1alpha1/types.go b/pkg/kubelet/apis/stats/v1alpha1/types.go index ecffb8bc344..1a09fe4ffcc 100644 --- a/pkg/kubelet/apis/stats/v1alpha1/types.go +++ b/pkg/kubelet/apis/stats/v1alpha1/types.go @@ -324,7 +324,7 @@ type UserDefinedMetricDescriptor struct { Labels map[string]string `json:"labels,omitempty"` } -// UserDefinedMetric represents a metric defined and generate by users. +// UserDefinedMetric represents a metric defined and generated by users. type UserDefinedMetric struct { UserDefinedMetricDescriptor `json:",inline"` // The time at which these stats were updated. diff --git a/pkg/kubelet/cadvisor/cadvisor_linux.go b/pkg/kubelet/cadvisor/cadvisor_linux.go index d15907fe869..0f02a811426 100644 --- a/pkg/kubelet/cadvisor/cadvisor_linux.go +++ b/pkg/kubelet/cadvisor/cadvisor_linux.go @@ -100,7 +100,6 @@ func containerLabels(c *cadvisorapi.ContainerInfo) map[string]string { return set } -// New creates a cAdvisor and exports its API on the specified port if port > 0. func New(imageFsInfoProvider ImageFsInfoProvider, rootPath string, usingLegacyStats bool) (Interface, error) { sysFs := sysfs.NewRealSysFs() diff --git a/pkg/kubelet/certificate/bootstrap/bootstrap.go b/pkg/kubelet/certificate/bootstrap/bootstrap.go index efe34ef1510..46491a45cb2 100644 --- a/pkg/kubelet/certificate/bootstrap/bootstrap.go +++ b/pkg/kubelet/certificate/bootstrap/bootstrap.go @@ -47,13 +47,65 @@ import ( const tmpPrivateKeyFile = "kubelet-client.key.tmp" +// LoadClientConfig tries to load the appropriate client config for retrieving certs and for use by users. +// If bootstrapPath is empty, only kubeconfigPath is checked. If bootstrap path is set and the contents +// of kubeconfigPath are valid, both certConfig and userConfig will point to that file. Otherwise the +// kubeconfigPath on disk is populated based on bootstrapPath but pointing to the location of the client cert +// in certDir. This preserves the historical behavior of bootstrapping where on subsequent restarts the +// most recent client cert is used to request new client certs instead of the initial token. +func LoadClientConfig(kubeconfigPath, bootstrapPath, certDir string) (certConfig, userConfig *restclient.Config, err error) { + if len(bootstrapPath) == 0 { + clientConfig, err := loadRESTClientConfig(kubeconfigPath) + if err != nil { + return nil, nil, fmt.Errorf("unable to load kubeconfig: %v", err) + } + klog.V(2).Infof("No bootstrapping requested, will use kubeconfig") + return clientConfig, restclient.CopyConfig(clientConfig), nil + } + + store, err := certificate.NewFileStore("kubelet-client", certDir, certDir, "", "") + if err != nil { + return nil, nil, fmt.Errorf("unable to build bootstrap cert store") + } + + ok, err := isClientConfigStillValid(kubeconfigPath) + if err != nil { + return nil, nil, err + } + + // use the current client config + if ok { + clientConfig, err := loadRESTClientConfig(kubeconfigPath) + if err != nil { + return nil, nil, fmt.Errorf("unable to load kubeconfig: %v", err) + } + klog.V(2).Infof("Current kubeconfig file contents are still valid, no bootstrap necessary") + return clientConfig, restclient.CopyConfig(clientConfig), nil + } + + bootstrapClientConfig, err := loadRESTClientConfig(bootstrapPath) + if err != nil { + return nil, nil, fmt.Errorf("unable to load bootstrap kubeconfig: %v", err) + } + + clientConfig := restclient.AnonymousClientConfig(bootstrapClientConfig) + pemPath := store.CurrentPath() + clientConfig.KeyFile = pemPath + clientConfig.CertFile = pemPath + if err := writeKubeconfigFromBootstrapping(clientConfig, kubeconfigPath, pemPath); err != nil { + return nil, nil, err + } + klog.V(2).Infof("Use the bootstrap credentials to request a cert, and set kubeconfig to point to the certificate dir") + return bootstrapClientConfig, clientConfig, nil +} + // LoadClientCert requests a client cert for kubelet if the kubeconfigPath file does not exist. // The kubeconfig at bootstrapPath is used to request a client certificate from the API server. // On success, a kubeconfig file referencing the generated key and obtained certificate is written to kubeconfigPath. // The certificate and key file are stored in certDir. -func LoadClientCert(kubeconfigPath string, bootstrapPath string, certDir string, nodeName types.NodeName) error { +func LoadClientCert(kubeconfigPath, bootstrapPath, certDir string, nodeName types.NodeName) error { // Short-circuit if the kubeconfig file exists and is valid. - ok, err := verifyBootstrapClientConfig(kubeconfigPath) + ok, err := isClientConfigStillValid(kubeconfigPath) if err != nil { return err } @@ -117,8 +169,10 @@ func LoadClientCert(kubeconfigPath string, bootstrapPath string, certDir string, klog.V(2).Infof("failed cleaning up private key file %q: %v", privKeyPath, err) } - pemPath := store.CurrentPath() + return writeKubeconfigFromBootstrapping(bootstrapClientConfig, kubeconfigPath, store.CurrentPath()) +} +func writeKubeconfigFromBootstrapping(bootstrapClientConfig *restclient.Config, kubeconfigPath, pemPath string) error { // Get the CA data from the bootstrap client config. caFile, caData := bootstrapClientConfig.CAFile, []byte{} if len(caFile) == 0 { @@ -168,10 +222,10 @@ func loadRESTClientConfig(kubeconfig string) (*restclient.Config, error) { ).ClientConfig() } -// verifyBootstrapClientConfig checks the provided kubeconfig to see if it has a valid +// isClientConfigStillValid checks the provided kubeconfig to see if it has a valid // client certificate. It returns true if the kubeconfig is valid, or an error if bootstrapping // should stop immediately. -func verifyBootstrapClientConfig(kubeconfigPath string) (bool, error) { +func isClientConfigStillValid(kubeconfigPath string) (bool, error) { _, err := os.Stat(kubeconfigPath) if os.IsNotExist(err) { return false, nil diff --git a/pkg/kubelet/certificate/kubelet.go b/pkg/kubelet/certificate/kubelet.go index e55594f8e84..cf106c84e10 100644 --- a/pkg/kubelet/certificate/kubelet.go +++ b/pkg/kubelet/certificate/kubelet.go @@ -17,6 +17,7 @@ limitations under the License. package certificate import ( + "crypto/tls" "crypto/x509" "crypto/x509/pkix" "fmt" @@ -29,7 +30,7 @@ import ( "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/types" clientset "k8s.io/client-go/kubernetes" - clientcertificates "k8s.io/client-go/kubernetes/typed/certificates/v1beta1" + certificatesclient "k8s.io/client-go/kubernetes/typed/certificates/v1beta1" "k8s.io/client-go/util/certificate" kubeletconfig "k8s.io/kubernetes/pkg/kubelet/apis/config" "k8s.io/kubernetes/pkg/kubelet/metrics" @@ -38,7 +39,7 @@ import ( // NewKubeletServerCertificateManager creates a certificate manager for the kubelet when retrieving a server certificate // or returns an error. func NewKubeletServerCertificateManager(kubeClient clientset.Interface, kubeCfg *kubeletconfig.KubeletConfiguration, nodeName types.NodeName, getAddresses func() []v1.NodeAddress, certDirectory string) (certificate.Manager, error) { - var certSigningRequestClient clientcertificates.CertificateSigningRequestInterface + var certSigningRequestClient certificatesclient.CertificateSigningRequestInterface if kubeClient != nil && kubeClient.CertificatesV1beta1() != nil { certSigningRequestClient = kubeClient.CertificatesV1beta1().CertificateSigningRequests() } @@ -78,8 +79,10 @@ func NewKubeletServerCertificateManager(kubeClient clientset.Interface, kubeCfg } m, err := certificate.NewManager(&certificate.Config{ - CertificateSigningRequestClient: certSigningRequestClient, - GetTemplate: getTemplate, + ClientFn: func(current *tls.Certificate) (certificatesclient.CertificateSigningRequestInterface, error) { + return certSigningRequestClient, nil + }, + GetTemplate: getTemplate, Usages: []certificates.KeyUsage{ // https://tools.ietf.org/html/rfc5280#section-4.2.1.3 // @@ -142,10 +145,18 @@ func addressesToHostnamesAndIPs(addresses []v1.NodeAddress) (dnsNames []string, } // NewKubeletClientCertificateManager sets up a certificate manager without a -// client that can be used to sign new certificates (or rotate). It answers with -// whatever certificate it is initialized with. If a CSR client is set later, it -// may begin rotating/renewing the client cert -func NewKubeletClientCertificateManager(certDirectory string, nodeName types.NodeName, certData []byte, keyData []byte, certFile string, keyFile string) (certificate.Manager, error) { +// client that can be used to sign new certificates (or rotate). If a CSR +// client is set later, it may begin rotating/renewing the client cert. +func NewKubeletClientCertificateManager( + certDirectory string, + nodeName types.NodeName, + bootstrapCertData []byte, + bootstrapKeyData []byte, + certFile string, + keyFile string, + clientFn certificate.CSRClientFunc, +) (certificate.Manager, error) { + certificateStore, err := certificate.NewFileStore( "kubelet-client", certDirectory, @@ -163,9 +174,10 @@ func NewKubeletClientCertificateManager(certDirectory string, nodeName types.Nod Help: "Gauge of the lifetime of a certificate. The value is the date the certificate will expire in seconds since January 1, 1970 UTC.", }, ) - prometheus.MustRegister(certificateExpiration) + prometheus.Register(certificateExpiration) m, err := certificate.NewManager(&certificate.Config{ + ClientFn: clientFn, Template: &x509.CertificateRequest{ Subject: pkix.Name{ CommonName: fmt.Sprintf("system:node:%s", nodeName), @@ -187,10 +199,16 @@ func NewKubeletClientCertificateManager(certDirectory string, nodeName types.Nod // authenticate itself to the TLS server. certificates.UsageClientAuth, }, - CertificateStore: certificateStore, - BootstrapCertificatePEM: certData, - BootstrapKeyPEM: keyData, - CertificateExpiration: certificateExpiration, + + // For backwards compatibility, the kubelet supports the ability to + // provide a higher privileged certificate as initial data that will + // then be rotated immediately. This code path is used by kubeadm on + // the masters. + BootstrapCertificatePEM: bootstrapCertData, + BootstrapKeyPEM: bootstrapKeyData, + + CertificateStore: certificateStore, + CertificateExpiration: certificateExpiration, }) if err != nil { return nil, fmt.Errorf("failed to initialize client certificate manager: %v", err) diff --git a/pkg/kubelet/certificate/transport_test.go b/pkg/kubelet/certificate/transport_test.go index ef8ea8c7291..78f26a49007 100644 --- a/pkg/kubelet/certificate/transport_test.go +++ b/pkg/kubelet/certificate/transport_test.go @@ -124,7 +124,9 @@ func (f *fakeManager) SetCertificateSigningRequestClient(certificatesclient.Cert func (f *fakeManager) ServerHealthy() bool { return f.healthy } -func (f *fakeManager) Start() {} +func (f *fakeManager) Start() {} +func (f *fakeManager) Stop() {} +func (f *fakeManager) RotateCerts() (bool, error) { return false, nil } func (f *fakeManager) Current() *tls.Certificate { if val := f.cert.Load(); val != nil { diff --git a/pkg/kubelet/cm/BUILD b/pkg/kubelet/cm/BUILD index 6ead9ea8c3d..e6e44b4435a 100644 --- a/pkg/kubelet/cm/BUILD +++ b/pkg/kubelet/cm/BUILD @@ -35,7 +35,7 @@ go_library( "//pkg/kubelet/lifecycle:go_default_library", "//pkg/kubelet/status:go_default_library", "//pkg/kubelet/util/pluginwatcher:go_default_library", - "//pkg/scheduler/cache:go_default_library", + "//pkg/scheduler/nodeinfo:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/resource:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/types:go_default_library", diff --git a/pkg/kubelet/cm/container_manager.go b/pkg/kubelet/cm/container_manager.go index a9fe926ee04..bb7b21c3983 100644 --- a/pkg/kubelet/cm/container_manager.go +++ b/pkg/kubelet/cm/container_manager.go @@ -30,7 +30,7 @@ import ( "k8s.io/kubernetes/pkg/kubelet/lifecycle" "k8s.io/kubernetes/pkg/kubelet/status" "k8s.io/kubernetes/pkg/kubelet/util/pluginwatcher" - schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" + schedulernodeinfo "k8s.io/kubernetes/pkg/scheduler/nodeinfo" "fmt" "strconv" @@ -90,7 +90,7 @@ type ContainerManager interface { // Otherwise, it updates allocatableResource in nodeInfo if necessary, // to make sure it is at least equal to the pod's requested capacity for // any registered device plugin resource - UpdatePluginResources(*schedulercache.NodeInfo, *lifecycle.PodAdmitAttributes) error + UpdatePluginResources(*schedulernodeinfo.NodeInfo, *lifecycle.PodAdmitAttributes) error InternalContainerLifecycle() InternalContainerLifecycle diff --git a/pkg/kubelet/cm/container_manager_linux.go b/pkg/kubelet/cm/container_manager_linux.go index 9432fc71adc..ea0a5ad2151 100644 --- a/pkg/kubelet/cm/container_manager_linux.go +++ b/pkg/kubelet/cm/container_manager_linux.go @@ -55,7 +55,7 @@ import ( "k8s.io/kubernetes/pkg/kubelet/qos" "k8s.io/kubernetes/pkg/kubelet/status" "k8s.io/kubernetes/pkg/kubelet/util/pluginwatcher" - schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" + schedulernodeinfo "k8s.io/kubernetes/pkg/scheduler/nodeinfo" utilfile "k8s.io/kubernetes/pkg/util/file" "k8s.io/kubernetes/pkg/util/mount" "k8s.io/kubernetes/pkg/util/oom" @@ -628,7 +628,7 @@ func (cm *containerManagerImpl) GetResources(pod *v1.Pod, container *v1.Containe return opts, nil } -func (cm *containerManagerImpl) UpdatePluginResources(node *schedulercache.NodeInfo, attrs *lifecycle.PodAdmitAttributes) error { +func (cm *containerManagerImpl) UpdatePluginResources(node *schedulernodeinfo.NodeInfo, attrs *lifecycle.PodAdmitAttributes) error { return cm.deviceManager.Allocate(node, attrs) } diff --git a/pkg/kubelet/cm/container_manager_stub.go b/pkg/kubelet/cm/container_manager_stub.go index 4563dc53048..c4b0924d994 100644 --- a/pkg/kubelet/cm/container_manager_stub.go +++ b/pkg/kubelet/cm/container_manager_stub.go @@ -29,7 +29,7 @@ import ( "k8s.io/kubernetes/pkg/kubelet/lifecycle" "k8s.io/kubernetes/pkg/kubelet/status" "k8s.io/kubernetes/pkg/kubelet/util/pluginwatcher" - schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" + schedulernodeinfo "k8s.io/kubernetes/pkg/scheduler/nodeinfo" ) type containerManagerStub struct{} @@ -94,7 +94,7 @@ func (cm *containerManagerStub) GetResources(pod *v1.Pod, container *v1.Containe return &kubecontainer.RunContainerOptions{}, nil } -func (cm *containerManagerStub) UpdatePluginResources(*schedulercache.NodeInfo, *lifecycle.PodAdmitAttributes) error { +func (cm *containerManagerStub) UpdatePluginResources(*schedulernodeinfo.NodeInfo, *lifecycle.PodAdmitAttributes) error { return nil } diff --git a/pkg/kubelet/cm/container_manager_windows.go b/pkg/kubelet/cm/container_manager_windows.go index a8a84d5f22d..48ec1ce076b 100644 --- a/pkg/kubelet/cm/container_manager_windows.go +++ b/pkg/kubelet/cm/container_manager_windows.go @@ -39,7 +39,7 @@ import ( "k8s.io/kubernetes/pkg/kubelet/lifecycle" "k8s.io/kubernetes/pkg/kubelet/status" "k8s.io/kubernetes/pkg/kubelet/util/pluginwatcher" - schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" + schedulernodeinfo "k8s.io/kubernetes/pkg/scheduler/nodeinfo" "k8s.io/kubernetes/pkg/util/mount" ) @@ -156,7 +156,7 @@ func (cm *containerManagerImpl) GetResources(pod *v1.Pod, container *v1.Containe return &kubecontainer.RunContainerOptions{}, nil } -func (cm *containerManagerImpl) UpdatePluginResources(*schedulercache.NodeInfo, *lifecycle.PodAdmitAttributes) error { +func (cm *containerManagerImpl) UpdatePluginResources(*schedulernodeinfo.NodeInfo, *lifecycle.PodAdmitAttributes) error { return nil } diff --git a/pkg/kubelet/cm/cpumanager/cpu_manager.go b/pkg/kubelet/cm/cpumanager/cpu_manager.go index 4ccddd554da..43e37848984 100644 --- a/pkg/kubelet/cm/cpumanager/cpu_manager.go +++ b/pkg/kubelet/cm/cpumanager/cpu_manager.go @@ -44,7 +44,7 @@ type runtimeService interface { type policyName string -// cpuManagerStateFileName is the name file name where cpu manager stores it's state +// cpuManagerStateFileName is the file name where cpu manager stores its state const cpuManagerStateFileName = "cpu_manager_state" // Manager interface provides methods for Kubelet to manage pod cpus. diff --git a/pkg/kubelet/cm/devicemanager/BUILD b/pkg/kubelet/cm/devicemanager/BUILD index 885f783db79..f45f3fc9897 100644 --- a/pkg/kubelet/cm/devicemanager/BUILD +++ b/pkg/kubelet/cm/devicemanager/BUILD @@ -25,7 +25,7 @@ go_library( "//pkg/kubelet/lifecycle:go_default_library", "//pkg/kubelet/metrics:go_default_library", "//pkg/kubelet/util/pluginwatcher:go_default_library", - "//pkg/scheduler/cache:go_default_library", + "//pkg/scheduler/nodeinfo:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/resource:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library", @@ -47,7 +47,7 @@ go_test( "//pkg/kubelet/checkpointmanager:go_default_library", "//pkg/kubelet/lifecycle:go_default_library", "//pkg/kubelet/util/pluginwatcher:go_default_library", - "//pkg/scheduler/cache:go_default_library", + "//pkg/scheduler/nodeinfo:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/resource:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", diff --git a/pkg/kubelet/cm/devicemanager/manager.go b/pkg/kubelet/cm/devicemanager/manager.go index fde7f52b075..5ae0405665c 100644 --- a/pkg/kubelet/cm/devicemanager/manager.go +++ b/pkg/kubelet/cm/devicemanager/manager.go @@ -41,7 +41,7 @@ import ( "k8s.io/kubernetes/pkg/kubelet/lifecycle" "k8s.io/kubernetes/pkg/kubelet/metrics" watcher "k8s.io/kubernetes/pkg/kubelet/util/pluginwatcher" - schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" + schedulernodeinfo "k8s.io/kubernetes/pkg/scheduler/nodeinfo" ) // ActivePodsFunc is a function that returns a list of pods to reconcile. @@ -313,7 +313,7 @@ func (m *ManagerImpl) isVersionCompatibleWithPlugin(versions []string) bool { // Allocate is the call that you can use to allocate a set of devices // from the registered device plugins. -func (m *ManagerImpl) Allocate(node *schedulercache.NodeInfo, attrs *lifecycle.PodAdmitAttributes) error { +func (m *ManagerImpl) Allocate(node *schedulernodeinfo.NodeInfo, attrs *lifecycle.PodAdmitAttributes) error { pod := attrs.Pod devicesToReuse := make(map[string]sets.String) for _, container := range pod.Spec.InitContainers { @@ -769,8 +769,8 @@ func (m *ManagerImpl) callPreStartContainerIfNeeded(podUID, contName, resource s // and if necessary, updates allocatableResource in nodeInfo to at least equal to // the allocated capacity. This allows pods that have already been scheduled on // the node to pass GeneralPredicates admission checking even upon device plugin failure. -func (m *ManagerImpl) sanitizeNodeAllocatable(node *schedulercache.NodeInfo) { - var newAllocatableResource *schedulercache.Resource +func (m *ManagerImpl) sanitizeNodeAllocatable(node *schedulernodeinfo.NodeInfo) { + var newAllocatableResource *schedulernodeinfo.Resource allocatableResource := node.AllocatableResource() if allocatableResource.ScalarResources == nil { allocatableResource.ScalarResources = make(map[v1.ResourceName]int64) diff --git a/pkg/kubelet/cm/devicemanager/manager_stub.go b/pkg/kubelet/cm/devicemanager/manager_stub.go index e32b671ffb2..a4309c78a40 100644 --- a/pkg/kubelet/cm/devicemanager/manager_stub.go +++ b/pkg/kubelet/cm/devicemanager/manager_stub.go @@ -22,7 +22,7 @@ import ( "k8s.io/kubernetes/pkg/kubelet/config" "k8s.io/kubernetes/pkg/kubelet/lifecycle" "k8s.io/kubernetes/pkg/kubelet/util/pluginwatcher" - schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" + schedulernodeinfo "k8s.io/kubernetes/pkg/scheduler/nodeinfo" ) // ManagerStub provides a simple stub implementation for the Device Manager. @@ -44,7 +44,7 @@ func (h *ManagerStub) Stop() error { } // Allocate simply returns nil. -func (h *ManagerStub) Allocate(node *schedulercache.NodeInfo, attrs *lifecycle.PodAdmitAttributes) error { +func (h *ManagerStub) Allocate(node *schedulernodeinfo.NodeInfo, attrs *lifecycle.PodAdmitAttributes) error { return nil } diff --git a/pkg/kubelet/cm/devicemanager/manager_test.go b/pkg/kubelet/cm/devicemanager/manager_test.go index 475be8667a4..6cd969412cf 100644 --- a/pkg/kubelet/cm/devicemanager/manager_test.go +++ b/pkg/kubelet/cm/devicemanager/manager_test.go @@ -37,7 +37,7 @@ import ( "k8s.io/kubernetes/pkg/kubelet/checkpointmanager" "k8s.io/kubernetes/pkg/kubelet/lifecycle" "k8s.io/kubernetes/pkg/kubelet/util/pluginwatcher" - schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" + schedulernodeinfo "k8s.io/kubernetes/pkg/scheduler/nodeinfo" ) const ( @@ -635,13 +635,13 @@ func getTestManager(tmpDir string, activePods ActivePodsFunc, testRes []TestReso return testManager, nil } -func getTestNodeInfo(allocatable v1.ResourceList) *schedulercache.NodeInfo { +func getTestNodeInfo(allocatable v1.ResourceList) *schedulernodeinfo.NodeInfo { cachedNode := &v1.Node{ Status: v1.NodeStatus{ Allocatable: allocatable, }, } - nodeInfo := &schedulercache.NodeInfo{} + nodeInfo := &schedulernodeinfo.NodeInfo{} nodeInfo.SetNode(cachedNode) return nodeInfo } @@ -875,7 +875,7 @@ func TestSanitizeNodeAllocatable(t *testing.T) { }, }, } - nodeInfo := &schedulercache.NodeInfo{} + nodeInfo := &schedulernodeinfo.NodeInfo{} nodeInfo.SetNode(cachedNode) testManager.sanitizeNodeAllocatable(nodeInfo) diff --git a/pkg/kubelet/cm/devicemanager/types.go b/pkg/kubelet/cm/devicemanager/types.go index 8396378b407..a420cf6541f 100644 --- a/pkg/kubelet/cm/devicemanager/types.go +++ b/pkg/kubelet/cm/devicemanager/types.go @@ -25,7 +25,7 @@ import ( kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" "k8s.io/kubernetes/pkg/kubelet/lifecycle" watcher "k8s.io/kubernetes/pkg/kubelet/util/pluginwatcher" - schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" + schedulernodeinfo "k8s.io/kubernetes/pkg/scheduler/nodeinfo" ) // Manager manages all the Device Plugins running on a node. @@ -41,7 +41,7 @@ type Manager interface { // variables, mount points and device files). The node object is provided // for the device manager to update the node capacity to reflect the // currently available devices. - Allocate(node *schedulercache.NodeInfo, attrs *lifecycle.PodAdmitAttributes) error + Allocate(node *schedulernodeinfo.NodeInfo, attrs *lifecycle.PodAdmitAttributes) error // Stop stops the manager. Stop() error diff --git a/pkg/kubelet/config/defaults.go b/pkg/kubelet/config/defaults.go index 96ab9cebac8..43f7162bfd8 100644 --- a/pkg/kubelet/config/defaults.go +++ b/pkg/kubelet/config/defaults.go @@ -19,6 +19,7 @@ package config const ( DefaultKubeletPodsDirName = "pods" DefaultKubeletVolumesDirName = "volumes" + DefaultKubeletVolumeSubpathsDirName = "volume-subpaths" DefaultKubeletVolumeDevicesDirName = "volumeDevices" DefaultKubeletPluginsDirName = "plugins" DefaultKubeletPluginsRegistrationDirName = "plugins_registry" diff --git a/pkg/kubelet/dockershim/docker_sandbox.go b/pkg/kubelet/dockershim/docker_sandbox.go index 0443793d8db..01d7f9b4951 100644 --- a/pkg/kubelet/dockershim/docker_sandbox.go +++ b/pkg/kubelet/dockershim/docker_sandbox.go @@ -593,7 +593,9 @@ func (ds *dockerService) makeSandboxDockerConfig(c *runtimeapi.PodSandboxConfig, // TODO(random-liu): Deprecate this label once container metrics is directly got from CRI. labels[types.KubernetesContainerNameLabel] = sandboxContainerName - hc := &dockercontainer.HostConfig{} + hc := &dockercontainer.HostConfig{ + IpcMode: dockercontainer.IpcMode("shareable"), + } createConfig := &dockertypes.ContainerCreateConfig{ Name: makeSandboxName(c), Config: &dockercontainer.Config{ diff --git a/pkg/kubelet/eviction/helpers.go b/pkg/kubelet/eviction/helpers.go index ef34b97a0ba..6b5d7eb7db3 100644 --- a/pkg/kubelet/eviction/helpers.go +++ b/pkg/kubelet/eviction/helpers.go @@ -390,16 +390,6 @@ func podDiskUsage(podStats statsapi.PodStats, pod *v1.Pod, statsToMeasure []fsSt }, nil } -// podMemoryUsage aggregates pod memory usage. -func podMemoryUsage(podStats statsapi.PodStats) (v1.ResourceList, error) { - memory := resource.Quantity{Format: resource.BinarySI} - for _, container := range podStats.Containers { - // memory usage (if known) - memory.Add(*memoryUsage(container.Memory)) - } - return v1.ResourceList{v1.ResourceMemory: memory}, nil -} - // localEphemeralVolumeNames returns the set of ephemeral volumes for the pod that are local func localEphemeralVolumeNames(pod *v1.Pod) []string { result := []string{} @@ -544,15 +534,8 @@ func exceedMemoryRequests(stats statsFunc) cmpFunc { return cmpBool(!p1Found, !p2Found) } - p1Usage, p1Err := podMemoryUsage(p1Stats) - p2Usage, p2Err := podMemoryUsage(p2Stats) - if p1Err != nil || p2Err != nil { - // prioritize evicting the pod which had an error getting stats - return cmpBool(p1Err != nil, p2Err != nil) - } - - p1Memory := p1Usage[v1.ResourceMemory] - p2Memory := p2Usage[v1.ResourceMemory] + p1Memory := memoryUsage(p1Stats.Memory) + p2Memory := memoryUsage(p2Stats.Memory) p1ExceedsRequests := p1Memory.Cmp(podRequest(p1, v1.ResourceMemory)) == 1 p2ExceedsRequests := p2Memory.Cmp(podRequest(p2, v1.ResourceMemory)) == 1 // prioritize evicting the pod which exceeds its requests @@ -570,24 +553,17 @@ func memory(stats statsFunc) cmpFunc { return cmpBool(!p1Found, !p2Found) } - p1Usage, p1Err := podMemoryUsage(p1Stats) - p2Usage, p2Err := podMemoryUsage(p2Stats) - if p1Err != nil || p2Err != nil { - // prioritize evicting the pod which had an error getting stats - return cmpBool(p1Err != nil, p2Err != nil) - } - // adjust p1, p2 usage relative to the request (if any) - p1Memory := p1Usage[v1.ResourceMemory] + p1Memory := memoryUsage(p1Stats.Memory) p1Request := podRequest(p1, v1.ResourceMemory) p1Memory.Sub(p1Request) - p2Memory := p2Usage[v1.ResourceMemory] + p2Memory := memoryUsage(p2Stats.Memory) p2Request := podRequest(p2, v1.ResourceMemory) p2Memory.Sub(p2Request) // prioritize evicting the pod which has the larger consumption of memory - return p2Memory.Cmp(p1Memory) + return p2Memory.Cmp(*p1Memory) } } diff --git a/pkg/kubelet/eviction/helpers_test.go b/pkg/kubelet/eviction/helpers_test.go index 6077f184cbf..b627f7f40de 100644 --- a/pkg/kubelet/eviction/helpers_test.go +++ b/pkg/kubelet/eviction/helpers_test.go @@ -1019,23 +1019,17 @@ func (f *fakeSummaryProvider) GetCPUAndMemoryStats() (*statsapi.Summary, error) // newPodStats returns a pod stat where each container is using the specified working set // each pod must have a Name, UID, Namespace -func newPodStats(pod *v1.Pod, containerWorkingSetBytes int64) statsapi.PodStats { - result := statsapi.PodStats{ +func newPodStats(pod *v1.Pod, podWorkingSetBytes uint64) statsapi.PodStats { + return statsapi.PodStats{ PodRef: statsapi.PodReference{ Name: pod.Name, Namespace: pod.Namespace, UID: string(pod.UID), }, + Memory: &statsapi.MemoryStats{ + WorkingSetBytes: &podWorkingSetBytes, + }, } - val := uint64(containerWorkingSetBytes) - for range pod.Spec.Containers { - result.Containers = append(result.Containers, statsapi.ContainerStats{ - Memory: &statsapi.MemoryStats{ - WorkingSetBytes: &val, - }, - }) - } - return result } func TestMakeSignalObservations(t *testing.T) { @@ -1100,9 +1094,9 @@ func TestMakeSignalObservations(t *testing.T) { podMaker("pod1", "ns2", "uuid2", 1), podMaker("pod3", "ns3", "uuid3", 1), } - containerWorkingSetBytes := int64(1024 * 1024 * 1024) + podWorkingSetBytes := uint64(1024 * 1024 * 1024) for _, pod := range pods { - fakeStats.Pods = append(fakeStats.Pods, newPodStats(pod, containerWorkingSetBytes)) + fakeStats.Pods = append(fakeStats.Pods, newPodStats(pod, podWorkingSetBytes)) } res := quantityMustParse("5Gi") // Allocatable thresholds are always 100%. Verify that Threshold == Capacity. @@ -1175,11 +1169,8 @@ func TestMakeSignalObservations(t *testing.T) { if !found { t.Errorf("Pod stats were not found for pod %v", pod.UID) } - for _, container := range podStats.Containers { - actual := int64(*container.Memory.WorkingSetBytes) - if containerWorkingSetBytes != actual { - t.Errorf("Container working set expected %v, actual: %v", containerWorkingSetBytes, actual) - } + if *podStats.Memory.WorkingSetBytes != podWorkingSetBytes { + t.Errorf("Pod working set expected %v, actual: %v", podWorkingSetBytes, *podStats.Memory.WorkingSetBytes) } } } @@ -1855,20 +1846,15 @@ func newPodDiskStats(pod *v1.Pod, rootFsUsed, logsUsed, perLocalVolumeUsed resou } func newPodMemoryStats(pod *v1.Pod, workingSet resource.Quantity) statsapi.PodStats { - result := statsapi.PodStats{ + workingSetBytes := uint64(workingSet.Value()) + return statsapi.PodStats{ PodRef: statsapi.PodReference{ Name: pod.Name, Namespace: pod.Namespace, UID: string(pod.UID), }, + Memory: &statsapi.MemoryStats{ + WorkingSetBytes: &workingSetBytes, + }, } - for range pod.Spec.Containers { - workingSetBytes := uint64(workingSet.Value()) - result.Containers = append(result.Containers, statsapi.ContainerStats{ - Memory: &statsapi.MemoryStats{ - WorkingSetBytes: &workingSetBytes, - }, - }) - } - return result } func newResourceList(cpu, memory, disk string) v1.ResourceList { diff --git a/pkg/kubelet/kubelet.go b/pkg/kubelet/kubelet.go index 055e8e0815f..7fafae41095 100644 --- a/pkg/kubelet/kubelet.go +++ b/pkg/kubelet/kubelet.go @@ -590,6 +590,8 @@ func NewMainKubelet(kubeCfg *kubeletconfiginternal.KubeletConfiguration, // podManager is also responsible for keeping secretManager and configMapManager contents up-to-date. klet.podManager = kubepod.NewBasicPodManager(kubepod.NewBasicMirrorClient(klet.kubeClient), secretManager, configMapManager, checkpointManager) + klet.statusManager = status.NewManager(klet.kubeClient, klet.podManager, klet) + if remoteRuntimeEndpoint != "" { // remoteImageEndpoint is same as remoteRuntimeEndpoint if not explicitly specified if remoteImageEndpoint == "" { @@ -705,7 +707,8 @@ func NewMainKubelet(kubeCfg *kubeletconfiginternal.KubeletConfiguration, klet.resourceAnalyzer, klet.podManager, klet.runtimeCache, - klet.containerRuntime) + klet.containerRuntime, + klet.statusManager) } else { klet.StatsProvider = stats.NewCRIStatsProvider( klet.cadvisor, @@ -754,8 +757,6 @@ func NewMainKubelet(kubeCfg *kubeletconfiginternal.KubeletConfiguration, klet.containerLogManager = logs.NewStubContainerLogManager() } - klet.statusManager = status.NewManager(klet.kubeClient, klet.podManager, klet) - if kubeCfg.ServerTLSBootstrap && kubeDeps.TLSOptions != nil && utilfeature.DefaultFeatureGate.Enabled(features.RotateKubeletServerCertificate) { klet.serverCertificateManager, err = kubeletcertificate.NewKubeletServerCertificateManager(klet.kubeClient, kubeCfg, klet.nodeName, klet.getLastObservedNodeAddresses, certDirectory) if err != nil { @@ -1221,29 +1222,6 @@ type Kubelet struct { runtimeClassManager *runtimeclass.Manager } -func allGlobalUnicastIPs() ([]net.IP, error) { - interfaces, err := net.Interfaces() - if err != nil { - return nil, fmt.Errorf("could not list network interfaces: %v", err) - } - var ips []net.IP - for _, i := range interfaces { - addresses, err := i.Addrs() - if err != nil { - return nil, fmt.Errorf("could not list the addresses for network interface %v: %v", i, err) - } - for _, address := range addresses { - switch v := address.(type) { - case *net.IPNet: - if v.IP.IsGlobalUnicast() { - ips = append(ips, v.IP) - } - } - } - } - return ips, nil -} - // setupDataDirs creates: // 1. the root directory // 2. the pods directory diff --git a/pkg/kubelet/kubelet_getters.go b/pkg/kubelet/kubelet_getters.go index eb05a578c07..a577a6bfad7 100644 --- a/pkg/kubelet/kubelet_getters.go +++ b/pkg/kubelet/kubelet_getters.go @@ -25,7 +25,7 @@ import ( cadvisorapiv1 "github.com/google/cadvisor/info/v1" "k8s.io/klog" - "k8s.io/api/core/v1" + v1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/types" "k8s.io/kubernetes/pkg/kubelet/cm" "k8s.io/kubernetes/pkg/kubelet/config" @@ -99,6 +99,13 @@ func (kl *Kubelet) getPodDir(podUID types.UID) string { return filepath.Join(kl.getPodsDir(), string(podUID)) } +// getPodVolumesSubpathsDir returns the full path to the per-pod subpaths directory under +// which subpath volumes are created for the specified pod. This directory may not +// exist if the pod does not exist or subpaths are not specified. +func (kl *Kubelet) getPodVolumeSubpathsDir(podUID types.UID) string { + return filepath.Join(kl.getPodDir(podUID), config.DefaultKubeletVolumeSubpathsDirName) +} + // getPodVolumesDir returns the full path to the per-pod data directory under // which volumes are created for the specified pod. This directory may not // exist if the pod does not exist. @@ -315,6 +322,19 @@ func (kl *Kubelet) getMountedVolumePathListFromDisk(podUID types.UID) ([]string, return mountedVolumes, nil } +// podVolumesSubpathsDirExists returns true if the pod volume-subpaths directory for +// a given pod exists +func (kl *Kubelet) podVolumeSubpathsDirExists(podUID types.UID) (bool, error) { + podVolDir := kl.getPodVolumeSubpathsDir(podUID) + + if pathExists, pathErr := volumeutil.PathExists(podVolDir); pathErr != nil { + return true, fmt.Errorf("Error checking if path %q exists: %v", podVolDir, pathErr) + } else if !pathExists { + return false, nil + } + return true, nil +} + // GetVersionInfo returns information about the version of cAdvisor in use. func (kl *Kubelet) GetVersionInfo() (*cadvisorapiv1.VersionInfo, error) { return kl.cadvisor.VersionInfo() diff --git a/pkg/kubelet/kubelet_pods.go b/pkg/kubelet/kubelet_pods.go index 59a2fd60bb4..60a158ac42a 100644 --- a/pkg/kubelet/kubelet_pods.go +++ b/pkg/kubelet/kubelet_pods.go @@ -384,7 +384,6 @@ func truncatePodHostnameIfNeeded(podName, hostname string) (string, error) { // GeneratePodHostNameAndDomain creates a hostname and domain name for a pod, // given that pod's spec and annotations or returns an error. func (kl *Kubelet) GeneratePodHostNameAndDomain(pod *v1.Pod) (string, string, error) { - // TODO(vmarmol): Handle better. clusterDomain := kl.dnsConfigurer.ClusterDomain hostname := pod.Name @@ -852,7 +851,7 @@ func (kl *Kubelet) podIsTerminated(pod *v1.Pod) bool { return status.Phase == v1.PodFailed || status.Phase == v1.PodSucceeded || (pod.DeletionTimestamp != nil && notRunning(status.ContainerStatuses)) } -// IsPodTerminated returns trus if the pod with the provided UID is in a terminated state ("Failed" or "Succeeded") +// IsPodTerminated returns true if the pod with the provided UID is in a terminated state ("Failed" or "Succeeded") // or if the pod has been deleted or removed func (kl *Kubelet) IsPodTerminated(uid types.UID) bool { pod, podFound := kl.podManager.GetPodByUID(uid) diff --git a/pkg/kubelet/kubelet_test.go b/pkg/kubelet/kubelet_test.go index 51f4629121f..192060bda84 100644 --- a/pkg/kubelet/kubelet_test.go +++ b/pkg/kubelet/kubelet_test.go @@ -66,7 +66,7 @@ import ( kubetypes "k8s.io/kubernetes/pkg/kubelet/types" "k8s.io/kubernetes/pkg/kubelet/util/queue" kubeletvolume "k8s.io/kubernetes/pkg/kubelet/volumemanager" - schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" + schedulernodeinfo "k8s.io/kubernetes/pkg/scheduler/nodeinfo" "k8s.io/kubernetes/pkg/util/mount" "k8s.io/kubernetes/pkg/volume" "k8s.io/kubernetes/pkg/volume/awsebs" @@ -264,7 +264,8 @@ func newTestKubeletWithImageList( kubelet.resourceAnalyzer, kubelet.podManager, kubelet.runtimeCache, - fakeRuntime) + fakeRuntime, + kubelet.statusManager) fakeImageGCPolicy := images.ImageGCPolicy{ HighThresholdPercent: 90, LowThresholdPercent: 80, @@ -659,7 +660,7 @@ func TestHandlePluginResources(t *testing.T) { } kl.nodeInfo = testNodeInfo{nodes: nodes} - updatePluginResourcesFunc := func(node *schedulercache.NodeInfo, attrs *lifecycle.PodAdmitAttributes) error { + updatePluginResourcesFunc := func(node *schedulernodeinfo.NodeInfo, attrs *lifecycle.PodAdmitAttributes) error { // Maps from resourceName to the value we use to set node.allocatableResource[resourceName]. // A resource with invalid value (< 0) causes the function to return an error // to emulate resource Allocation failure. diff --git a/pkg/kubelet/kubelet_volumes.go b/pkg/kubelet/kubelet_volumes.go index 7681ee6529e..88b34c5efd1 100644 --- a/pkg/kubelet/kubelet_volumes.go +++ b/pkg/kubelet/kubelet_volumes.go @@ -19,7 +19,7 @@ package kubelet import ( "fmt" - "k8s.io/api/core/v1" + v1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/types" utilerrors "k8s.io/apimachinery/pkg/util/errors" "k8s.io/apimachinery/pkg/util/sets" @@ -114,6 +114,8 @@ func (kl *Kubelet) cleanupOrphanedPodDirs(pods []*v1.Pod, runningPods []*kubecon } // If volumes have not been unmounted/detached, do not delete directory. // Doing so may result in corruption of data. + // TODO: getMountedVolumePathListFromDisk() call may be redundant with + // kl.getPodVolumePathListFromDisk(). Can this be cleaned up? if podVolumesExist := kl.podVolumesExist(uid); podVolumesExist { klog.V(3).Infof("Orphaned pod %q found, but volumes are not cleaned up", uid) continue @@ -128,6 +130,18 @@ func (kl *Kubelet) cleanupOrphanedPodDirs(pods []*v1.Pod, runningPods []*kubecon orphanVolumeErrors = append(orphanVolumeErrors, fmt.Errorf("Orphaned pod %q found, but volume paths are still present on disk", uid)) continue } + + // If there are any volume-subpaths, do not cleanup directories + volumeSubpathExists, err := kl.podVolumeSubpathsDirExists(uid) + if err != nil { + orphanVolumeErrors = append(orphanVolumeErrors, fmt.Errorf("Orphaned pod %q found, but error %v occurred during reading of volume-subpaths dir from disk", uid, err)) + continue + } + if volumeSubpathExists { + orphanVolumeErrors = append(orphanVolumeErrors, fmt.Errorf("Orphaned pod %q found, but volume subpaths are still present on disk", uid)) + continue + } + klog.V(3).Infof("Orphaned pod %q found, removing", uid) if err := removeall.RemoveAllOneFilesystem(kl.mounter, kl.getPodDir(uid)); err != nil { klog.Errorf("Failed to remove orphaned pod %q dir; err: %v", uid, err) diff --git a/pkg/kubelet/kubelet_volumes_linux_test.go b/pkg/kubelet/kubelet_volumes_linux_test.go new file mode 100644 index 00000000000..7f08ff4d5cc --- /dev/null +++ b/pkg/kubelet/kubelet_volumes_linux_test.go @@ -0,0 +1,156 @@ +// +build linux + +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package kubelet + +import ( + "fmt" + "io/ioutil" + "os" + "path/filepath" + "testing" + + v1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + _ "k8s.io/kubernetes/pkg/apis/core/install" +) + +func validateDirExists(dir string) error { + _, err := ioutil.ReadDir(dir) + if err != nil { + return err + } + return nil +} + +func validateDirNotExists(dir string) error { + _, err := ioutil.ReadDir(dir) + if os.IsNotExist(err) { + return nil + } + if err != nil { + return err + } + return fmt.Errorf("dir %q still exists", dir) +} + +func TestCleanupOrphanedPodDirs(t *testing.T) { + testCases := map[string]struct { + pods []*v1.Pod + prepareFunc func(kubelet *Kubelet) error + validateFunc func(kubelet *Kubelet) error + expectErr bool + }{ + "nothing-to-do": {}, + "pods-dir-not-found": { + prepareFunc: func(kubelet *Kubelet) error { + return os.Remove(kubelet.getPodsDir()) + }, + expectErr: true, + }, + "pod-doesnot-exist-novolume": { + prepareFunc: func(kubelet *Kubelet) error { + podDir := kubelet.getPodDir("pod1uid") + return os.MkdirAll(filepath.Join(podDir, "not/a/volume"), 0750) + }, + validateFunc: func(kubelet *Kubelet) error { + podDir := kubelet.getPodDir("pod1uid") + return validateDirNotExists(filepath.Join(podDir, "not")) + }, + }, + "pod-exists-with-volume": { + pods: []*v1.Pod{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "pod1", + UID: "pod1uid", + }, + }, + }, + prepareFunc: func(kubelet *Kubelet) error { + podDir := kubelet.getPodDir("pod1uid") + return os.MkdirAll(filepath.Join(podDir, "volumes/plugin/name"), 0750) + }, + validateFunc: func(kubelet *Kubelet) error { + podDir := kubelet.getPodDir("pod1uid") + return validateDirExists(filepath.Join(podDir, "volumes/plugin/name")) + }, + }, + "pod-doesnot-exist-with-volume": { + prepareFunc: func(kubelet *Kubelet) error { + podDir := kubelet.getPodDir("pod1uid") + return os.MkdirAll(filepath.Join(podDir, "volumes/plugin/name"), 0750) + }, + validateFunc: func(kubelet *Kubelet) error { + podDir := kubelet.getPodDir("pod1uid") + return validateDirExists(filepath.Join(podDir, "volumes/plugin/name")) + }, + }, + "pod-doesnot-exist-with-subpath": { + prepareFunc: func(kubelet *Kubelet) error { + podDir := kubelet.getPodDir("pod1uid") + return os.MkdirAll(filepath.Join(podDir, "volume-subpaths/volume/container/index"), 0750) + }, + validateFunc: func(kubelet *Kubelet) error { + podDir := kubelet.getPodDir("pod1uid") + return validateDirExists(filepath.Join(podDir, "volume-subpaths/volume/container/index")) + }, + }, + "pod-doesnot-exist-with-subpath-top": { + prepareFunc: func(kubelet *Kubelet) error { + podDir := kubelet.getPodDir("pod1uid") + return os.MkdirAll(filepath.Join(podDir, "volume-subpaths"), 0750) + }, + validateFunc: func(kubelet *Kubelet) error { + podDir := kubelet.getPodDir("pod1uid") + return validateDirExists(filepath.Join(podDir, "volume-subpaths")) + }, + }, + // TODO: test volume in volume-manager + } + + for name, tc := range testCases { + t.Run(name, func(t *testing.T) { + testKubelet := newTestKubelet(t, false /* controllerAttachDetachEnabled */) + defer testKubelet.Cleanup() + kubelet := testKubelet.kubelet + + if tc.prepareFunc != nil { + if err := tc.prepareFunc(kubelet); err != nil { + t.Fatalf("%s failed preparation: %v", name, err) + } + } + + err := kubelet.cleanupOrphanedPodDirs(tc.pods, nil) + if tc.expectErr && err == nil { + t.Errorf("%s failed: expected error, got success", name) + } + if !tc.expectErr && err != nil { + t.Errorf("%s failed: got error %v", name, err) + } + + if tc.validateFunc != nil { + if err := tc.validateFunc(kubelet); err != nil { + t.Errorf("%s failed validation: %v", name, err) + } + } + + }) + } +} diff --git a/pkg/kubelet/kubeletconfig/checkpoint/store/fsstore.go b/pkg/kubelet/kubeletconfig/checkpoint/store/fsstore.go index 382f04b5379..26c48d06f26 100644 --- a/pkg/kubelet/kubeletconfig/checkpoint/store/fsstore.go +++ b/pkg/kubelet/kubeletconfig/checkpoint/store/fsstore.go @@ -95,7 +95,7 @@ func (s *fsStore) Exists(source checkpoint.RemoteConfigSource) (bool, error) { func (s *fsStore) Save(payload checkpoint.Payload) error { // Note: Payload interface guarantees UID() and ResourceVersion() to be non-empty path := s.checkpointPath(payload.UID(), payload.ResourceVersion()) - // ensure the parent dir (checkpoints/uid) exists, since ReplaceDir requires the parent of the replacee + // ensure the parent dir (checkpoints/uid) exists, since ReplaceDir requires the parent of the replace // to exist, and we checkpoint as checkpoints/uid/resourceVersion/files-from-configmap if err := utilfiles.EnsureDir(s.fs, filepath.Dir(path)); err != nil { return err diff --git a/pkg/kubelet/kuberuntime/kuberuntime_container.go b/pkg/kubelet/kuberuntime/kuberuntime_container.go index 4126d7ea9c3..d0624ee0483 100644 --- a/pkg/kubelet/kuberuntime/kuberuntime_container.go +++ b/pkg/kubelet/kuberuntime/kuberuntime_container.go @@ -584,7 +584,7 @@ func (m *kubeGenericRuntimeManager) killContainer(pod *v1.Pod, containerID kubec klog.V(3).Infof("Container %q exited normally", containerID.String()) } - message := fmt.Sprintf("Killing container with id %s", containerID.String()) + message := fmt.Sprintf("Killing container %s", containerID.String()) if reason != "" { message = fmt.Sprint(message, ":", reason) } diff --git a/pkg/kubelet/kuberuntime/kuberuntime_manager.go b/pkg/kubelet/kuberuntime/kuberuntime_manager.go index 05d2aea3a62..3e6313bf46b 100644 --- a/pkg/kubelet/kuberuntime/kuberuntime_manager.go +++ b/pkg/kubelet/kuberuntime/kuberuntime_manager.go @@ -20,6 +20,7 @@ import ( "errors" "fmt" "os" + "sync" "time" cadvisorapi "github.com/google/cadvisor/info/v1" @@ -131,6 +132,7 @@ type kubeGenericRuntimeManager struct { // Time last per-container error message was printed errorPrinted map[string]time.Time + errorMapLock sync.Mutex } // KubeGenericRuntime is a interface contains interfaces for container runtime and command. @@ -830,6 +832,8 @@ func (m *kubeGenericRuntimeManager) killPodWithSyncResult(pod *v1.Pod, runningPo } func (m *kubeGenericRuntimeManager) cleanupErrorTimeouts() { + m.errorMapLock.Lock() + defer m.errorMapLock.Unlock() for name, timeout := range m.errorPrinted { if time.Now().Sub(timeout) >= identicalErrorDelay { delete(m.errorPrinted, name) @@ -886,6 +890,8 @@ func (m *kubeGenericRuntimeManager) GetPodStatus(uid kubetypes.UID, name, namesp // Get statuses of all containers visible in the pod. containerStatuses, err := m.getPodContainerStatuses(uid, name, namespace) + m.errorMapLock.Lock() + defer m.errorMapLock.Unlock() if err != nil { lastMsg, ok := m.lastError[podFullName] if !ok || err.Error() != lastMsg || time.Now().Sub(m.errorPrinted[podFullName]) >= identicalErrorDelay { diff --git a/pkg/kubelet/kuberuntime/kuberuntime_sandbox.go b/pkg/kubelet/kuberuntime/kuberuntime_sandbox.go index dd51bda32ca..cf0db44db06 100644 --- a/pkg/kubelet/kuberuntime/kuberuntime_sandbox.go +++ b/pkg/kubelet/kuberuntime/kuberuntime_sandbox.go @@ -57,6 +57,9 @@ func (m *kubeGenericRuntimeManager) createPodSandbox(pod *v1.Pod, attempt uint32 message := fmt.Sprintf("CreatePodSandbox for pod %q failed: %v", format.Pod(pod), err) return "", message, err } + if runtimeHandler != "" { + klog.V(2).Infof("Running pod %s with RuntimeHandler %q", format.Pod(pod), runtimeHandler) + } } podSandBoxID, err := m.runtimeService.RunPodSandbox(podSandboxConfig, runtimeHandler) diff --git a/pkg/kubelet/lifecycle/BUILD b/pkg/kubelet/lifecycle/BUILD index ff518ddfdf1..427370b17f0 100644 --- a/pkg/kubelet/lifecycle/BUILD +++ b/pkg/kubelet/lifecycle/BUILD @@ -21,9 +21,8 @@ go_library( "//pkg/kubelet/container:go_default_library", "//pkg/kubelet/types:go_default_library", "//pkg/kubelet/util/format:go_default_library", - "//pkg/scheduler/algorithm:go_default_library", "//pkg/scheduler/algorithm/predicates:go_default_library", - "//pkg/scheduler/cache:go_default_library", + "//pkg/scheduler/nodeinfo:go_default_library", "//pkg/security/apparmor:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/types:go_default_library", @@ -42,7 +41,7 @@ go_test( deps = [ "//pkg/kubelet/container:go_default_library", "//pkg/kubelet/util/format:go_default_library", - "//pkg/scheduler/cache:go_default_library", + "//pkg/scheduler/nodeinfo:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/resource:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/intstr:go_default_library", diff --git a/pkg/kubelet/lifecycle/admission_failure_handler_stub.go b/pkg/kubelet/lifecycle/admission_failure_handler_stub.go index 7184392ead9..0fedf8c5c3b 100644 --- a/pkg/kubelet/lifecycle/admission_failure_handler_stub.go +++ b/pkg/kubelet/lifecycle/admission_failure_handler_stub.go @@ -18,7 +18,7 @@ package lifecycle import ( "k8s.io/api/core/v1" - "k8s.io/kubernetes/pkg/scheduler/algorithm" + "k8s.io/kubernetes/pkg/scheduler/algorithm/predicates" ) // AdmissionFailureHandlerStub is an AdmissionFailureHandler that does not perform any handling of admission failure. @@ -31,6 +31,6 @@ func NewAdmissionFailureHandlerStub() *AdmissionFailureHandlerStub { return &AdmissionFailureHandlerStub{} } -func (n *AdmissionFailureHandlerStub) HandleAdmissionFailure(admitPod *v1.Pod, failureReasons []algorithm.PredicateFailureReason) (bool, []algorithm.PredicateFailureReason, error) { +func (n *AdmissionFailureHandlerStub) HandleAdmissionFailure(admitPod *v1.Pod, failureReasons []predicates.PredicateFailureReason) (bool, []predicates.PredicateFailureReason, error) { return false, failureReasons, nil } diff --git a/pkg/kubelet/lifecycle/predicate.go b/pkg/kubelet/lifecycle/predicate.go index df4a32d1add..04eab48ffb2 100644 --- a/pkg/kubelet/lifecycle/predicate.go +++ b/pkg/kubelet/lifecycle/predicate.go @@ -24,19 +24,18 @@ import ( "k8s.io/api/core/v1" v1helper "k8s.io/kubernetes/pkg/apis/core/v1/helper" "k8s.io/kubernetes/pkg/kubelet/util/format" - "k8s.io/kubernetes/pkg/scheduler/algorithm" "k8s.io/kubernetes/pkg/scheduler/algorithm/predicates" - schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" + schedulernodeinfo "k8s.io/kubernetes/pkg/scheduler/nodeinfo" ) type getNodeAnyWayFuncType func() (*v1.Node, error) -type pluginResourceUpdateFuncType func(*schedulercache.NodeInfo, *PodAdmitAttributes) error +type pluginResourceUpdateFuncType func(*schedulernodeinfo.NodeInfo, *PodAdmitAttributes) error // AdmissionFailureHandler is an interface which defines how to deal with a failure to admit a pod. // This allows for the graceful handling of pod admission failure. type AdmissionFailureHandler interface { - HandleAdmissionFailure(admitPod *v1.Pod, failureReasons []algorithm.PredicateFailureReason) (bool, []algorithm.PredicateFailureReason, error) + HandleAdmissionFailure(admitPod *v1.Pod, failureReasons []predicates.PredicateFailureReason) (bool, []predicates.PredicateFailureReason, error) } type predicateAdmitHandler struct { @@ -67,7 +66,7 @@ func (w *predicateAdmitHandler) Admit(attrs *PodAdmitAttributes) PodAdmitResult } admitPod := attrs.Pod pods := attrs.OtherPods - nodeInfo := schedulercache.NewNodeInfo(pods...) + nodeInfo := schedulernodeinfo.NewNodeInfo(pods...) nodeInfo.SetNode(node) // ensure the node has enough plugin resources for that required in pods if err = w.pluginResourceUpdateFunc(nodeInfo, attrs); err != nil { @@ -155,7 +154,7 @@ func (w *predicateAdmitHandler) Admit(attrs *PodAdmitAttributes) PodAdmitResult } } -func removeMissingExtendedResources(pod *v1.Pod, nodeInfo *schedulercache.NodeInfo) *v1.Pod { +func removeMissingExtendedResources(pod *v1.Pod, nodeInfo *schedulernodeinfo.NodeInfo) *v1.Pod { podCopy := pod.DeepCopy() for i, c := range pod.Spec.Containers { // We only handle requests in Requests but not Limits because the diff --git a/pkg/kubelet/lifecycle/predicate_test.go b/pkg/kubelet/lifecycle/predicate_test.go index 47b792fbbde..af4cc617902 100644 --- a/pkg/kubelet/lifecycle/predicate_test.go +++ b/pkg/kubelet/lifecycle/predicate_test.go @@ -22,7 +22,7 @@ import ( "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" - schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" + schedulernodeinfo "k8s.io/kubernetes/pkg/scheduler/nodeinfo" ) var ( @@ -81,7 +81,7 @@ func TestRemoveMissingExtendedResources(t *testing.T) { ), }, } { - nodeInfo := schedulercache.NewNodeInfo() + nodeInfo := schedulernodeinfo.NewNodeInfo() nodeInfo.SetNode(test.node) pod := removeMissingExtendedResources(test.pod, nodeInfo) if !reflect.DeepEqual(pod, test.expectedPod) { diff --git a/pkg/kubelet/metrics/collectors/BUILD b/pkg/kubelet/metrics/collectors/BUILD index 64022f36676..d98893388cb 100644 --- a/pkg/kubelet/metrics/collectors/BUILD +++ b/pkg/kubelet/metrics/collectors/BUILD @@ -21,7 +21,6 @@ go_library( go_test( name = "go_default_test", srcs = [ - "helper_test.go", "log_metrics_test.go", "volume_stats_test.go", ], @@ -31,8 +30,7 @@ go_test( "//pkg/kubelet/server/stats/testing:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/github.com/prometheus/client_golang/prometheus:go_default_library", - "//vendor/github.com/prometheus/client_model/go:go_default_library", - "//vendor/github.com/prometheus/common/expfmt:go_default_library", + "//vendor/github.com/prometheus/client_golang/prometheus/testutil:go_default_library", ], ) diff --git a/pkg/kubelet/metrics/collectors/helper_test.go b/pkg/kubelet/metrics/collectors/helper_test.go deleted file mode 100644 index a63f80b932f..00000000000 --- a/pkg/kubelet/metrics/collectors/helper_test.go +++ /dev/null @@ -1,182 +0,0 @@ -/* -Copyright 2018 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// testing helpers copied from k8s.io/kube-state-metrics/collectors/deployment_test.go -// TODO: share in a public package? - -package collectors - -import ( - "bytes" - "fmt" - "reflect" - "sort" - "strings" - - "github.com/prometheus/client_golang/prometheus" - dto "github.com/prometheus/client_model/go" - "github.com/prometheus/common/expfmt" -) - -// gatherAndCompare retrieves all metrics exposed by a collector and compares it -// to an expected output in the Prometheus text exposition format. -// metricNames allows only comparing the given metrics. All are compared if it's nil. -func gatherAndCompare(c prometheus.Collector, expected string, metricNames []string) error { - expected = removeUnusedWhitespace(expected) - - reg := prometheus.NewPedanticRegistry() - if err := reg.Register(c); err != nil { - return fmt.Errorf("registering collector failed: %s", err) - } - metrics, err := reg.Gather() - if err != nil { - return fmt.Errorf("gathering metrics failed: %s", err) - } - if metricNames != nil { - metrics = filterMetrics(metrics, metricNames) - } - var tp expfmt.TextParser - expectedMetrics, err := tp.TextToMetricFamilies(bytes.NewReader([]byte(expected))) - if err != nil { - return fmt.Errorf("parsing expected metrics failed: %s", err) - } - - if !reflect.DeepEqual(metrics, normalizeMetricFamilies(expectedMetrics)) { - // Encode the gathered output to the readbale text format for comparison. - var buf1 bytes.Buffer - enc := expfmt.NewEncoder(&buf1, expfmt.FmtText) - for _, mf := range metrics { - if err := enc.Encode(mf); err != nil { - return fmt.Errorf("encoding result failed: %s", err) - } - } - // Encode normalized expected metrics again to generate them in the same ordering - // the registry does to spot differences more easily. - var buf2 bytes.Buffer - enc = expfmt.NewEncoder(&buf2, expfmt.FmtText) - for _, mf := range normalizeMetricFamilies(expectedMetrics) { - if err := enc.Encode(mf); err != nil { - return fmt.Errorf("encoding result failed: %s", err) - } - } - - return fmt.Errorf(`metric output does not match expectation; want: -%s - -got: - -%s`, buf2.String(), buf1.String()) - } - return nil -} - -func filterMetrics(metrics []*dto.MetricFamily, names []string) []*dto.MetricFamily { - var filtered []*dto.MetricFamily - for _, m := range metrics { - drop := true - for _, name := range names { - if m.GetName() == name { - drop = false - break - } - } - if !drop { - filtered = append(filtered, m) - } - } - return filtered -} - -func removeUnusedWhitespace(s string) string { - var ( - trimmedLine string - trimmedLines []string - lines = strings.Split(s, "\n") - ) - - for _, l := range lines { - trimmedLine = strings.TrimSpace(l) - - if len(trimmedLine) > 0 { - trimmedLines = append(trimmedLines, trimmedLine) - } - } - - // The Prometheus metrics representation parser expects an empty line at the - // end otherwise fails with an unexpected EOF error. - return strings.Join(trimmedLines, "\n") + "\n" -} - -// The below sorting code is copied form the Prometheus client library modulo the added -// label pair sorting. -// https://github.com/prometheus/client_golang/blob/ea6e1db4cb8127eeb0b6954f7320363e5451820f/prometheus/registry.go#L642-L684 - -// metricSorter is a sortable slice of *dto.Metric. -type metricSorter []*dto.Metric - -func (s metricSorter) Len() int { - return len(s) -} - -func (s metricSorter) Swap(i, j int) { - s[i], s[j] = s[j], s[i] -} - -func (s metricSorter) Less(i, j int) bool { - sort.Sort(prometheus.LabelPairSorter(s[i].Label)) - sort.Sort(prometheus.LabelPairSorter(s[j].Label)) - - if len(s[i].Label) != len(s[j].Label) { - return len(s[i].Label) < len(s[j].Label) - } - - for n, lp := range s[i].Label { - vi := lp.GetValue() - vj := s[j].Label[n].GetValue() - if vi != vj { - return vi < vj - } - } - - if s[i].TimestampMs == nil { - return false - } - if s[j].TimestampMs == nil { - return true - } - return s[i].GetTimestampMs() < s[j].GetTimestampMs() -} - -// normalizeMetricFamilies returns a MetricFamily slice with empty -// MetricFamilies pruned and the remaining MetricFamilies sorted by name within -// the slice, with the contained Metrics sorted within each MetricFamily. -func normalizeMetricFamilies(metricFamiliesByName map[string]*dto.MetricFamily) []*dto.MetricFamily { - for _, mf := range metricFamiliesByName { - sort.Sort(metricSorter(mf.Metric)) - } - names := make([]string, 0, len(metricFamiliesByName)) - for name, mf := range metricFamiliesByName { - if len(mf.Metric) > 0 { - names = append(names, name) - } - } - sort.Strings(names) - result := make([]*dto.MetricFamily, 0, len(names)) - for _, name := range names { - result = append(result, metricFamiliesByName[name]) - } - return result -} diff --git a/pkg/kubelet/metrics/collectors/log_metrics_test.go b/pkg/kubelet/metrics/collectors/log_metrics_test.go index 62cc22a1f77..40ffc0e0ab5 100644 --- a/pkg/kubelet/metrics/collectors/log_metrics_test.go +++ b/pkg/kubelet/metrics/collectors/log_metrics_test.go @@ -17,9 +17,11 @@ limitations under the License. package collectors import ( + "strings" "testing" "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/client_golang/prometheus/testutil" statsapi "k8s.io/kubernetes/pkg/kubelet/apis/stats/v1alpha1" ) @@ -63,11 +65,11 @@ func TestMetricsCollected(t *testing.T) { }, } - err := gatherAndCompare(collector, ` + err := testutil.CollectAndCompare(collector, strings.NewReader(` # HELP kubelet_container_log_filesystem_used_bytes Bytes used by the container's logs on the filesystem. # TYPE kubelet_container_log_filesystem_used_bytes gauge kubelet_container_log_filesystem_used_bytes{container="containerName1",namespace="some-namespace",pod="podName1"} 18 -`, nil) +`), "kubelet_container_log_filesystem_used_bytes") if err != nil { t.Fatal(err) } diff --git a/pkg/kubelet/metrics/collectors/volume_stats_test.go b/pkg/kubelet/metrics/collectors/volume_stats_test.go index 3e4d07e1deb..b2b6973dc8a 100644 --- a/pkg/kubelet/metrics/collectors/volume_stats_test.go +++ b/pkg/kubelet/metrics/collectors/volume_stats_test.go @@ -17,8 +17,10 @@ limitations under the License. package collectors import ( + "strings" "testing" + "github.com/prometheus/client_golang/prometheus/testutil" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" statsapi "k8s.io/kubernetes/pkg/kubelet/apis/stats/v1alpha1" statstest "k8s.io/kubernetes/pkg/kubelet/server/stats/testing" @@ -129,7 +131,7 @@ func TestVolumeStatsCollector(t *testing.T) { mockStatsProvider := new(statstest.StatsProvider) mockStatsProvider.On("ListPodStats").Return(podStats, nil) - if err := gatherAndCompare(&volumeStatsCollector{statsProvider: mockStatsProvider}, want, metrics); err != nil { + if err := testutil.CollectAndCompare(&volumeStatsCollector{statsProvider: mockStatsProvider}, strings.NewReader(want), metrics...); err != nil { t.Errorf("unexpected collecting result:\n%s", err) } } diff --git a/pkg/kubelet/preemption/BUILD b/pkg/kubelet/preemption/BUILD index 8fab53ffa81..08f24ee0f2b 100644 --- a/pkg/kubelet/preemption/BUILD +++ b/pkg/kubelet/preemption/BUILD @@ -18,7 +18,6 @@ go_library( "//pkg/kubelet/lifecycle:go_default_library", "//pkg/kubelet/types:go_default_library", "//pkg/kubelet/util/format:go_default_library", - "//pkg/scheduler/algorithm:go_default_library", "//pkg/scheduler/algorithm/predicates:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library", "//staging/src/k8s.io/client-go/tools/record:go_default_library", diff --git a/pkg/kubelet/preemption/preemption.go b/pkg/kubelet/preemption/preemption.go index 94a3afad6b5..751fcc246c9 100644 --- a/pkg/kubelet/preemption/preemption.go +++ b/pkg/kubelet/preemption/preemption.go @@ -30,7 +30,6 @@ import ( "k8s.io/kubernetes/pkg/kubelet/lifecycle" kubetypes "k8s.io/kubernetes/pkg/kubelet/types" "k8s.io/kubernetes/pkg/kubelet/util/format" - "k8s.io/kubernetes/pkg/scheduler/algorithm" "k8s.io/kubernetes/pkg/scheduler/algorithm/predicates" ) @@ -61,13 +60,13 @@ func NewCriticalPodAdmissionHandler(getPodsFunc eviction.ActivePodsFunc, killPod // HandleAdmissionFailure gracefully handles admission rejection, and, in some cases, // to allow admission of the pod despite its previous failure. -func (c *CriticalPodAdmissionHandler) HandleAdmissionFailure(admitPod *v1.Pod, failureReasons []algorithm.PredicateFailureReason) (bool, []algorithm.PredicateFailureReason, error) { +func (c *CriticalPodAdmissionHandler) HandleAdmissionFailure(admitPod *v1.Pod, failureReasons []predicates.PredicateFailureReason) (bool, []predicates.PredicateFailureReason, error) { if !kubetypes.IsCriticalPod(admitPod) { return false, failureReasons, nil } // InsufficientResourceError is not a reason to reject a critical pod. // Instead of rejecting, we free up resources to admit it, if no other reasons for rejection exist. - nonResourceReasons := []algorithm.PredicateFailureReason{} + nonResourceReasons := []predicates.PredicateFailureReason{} resourceReasons := []*admissionRequirement{} for _, reason := range failureReasons { if r, ok := reason.(*predicates.InsufficientResourceError); ok { diff --git a/pkg/kubelet/remote/remote_runtime.go b/pkg/kubelet/remote/remote_runtime.go index c1cc69085b1..88b9bce9530 100644 --- a/pkg/kubelet/remote/remote_runtime.go +++ b/pkg/kubelet/remote/remote_runtime.go @@ -21,6 +21,7 @@ import ( "errors" "fmt" "strings" + "sync" "time" "google.golang.org/grpc" @@ -40,6 +41,7 @@ type RemoteRuntimeService struct { lastError map[string]string // Time last per-container error message was printed errorPrinted map[string]time.Time + errorMapLock sync.Mutex } const ( @@ -236,8 +238,10 @@ func (r *RemoteRuntimeService) StopContainer(containerID string, timeout int64) ctx, cancel := getContextWithTimeout(t) defer cancel() + r.errorMapLock.Lock() delete(r.lastError, containerID) delete(r.errorPrinted, containerID) + r.errorMapLock.Unlock() _, err := r.runtimeClient.StopContainer(ctx, &runtimeapi.StopContainerRequest{ ContainerId: containerID, Timeout: timeout, @@ -256,8 +260,10 @@ func (r *RemoteRuntimeService) RemoveContainer(containerID string) error { ctx, cancel := getContextWithTimeout(r.timeout) defer cancel() + r.errorMapLock.Lock() delete(r.lastError, containerID) delete(r.errorPrinted, containerID) + r.errorMapLock.Unlock() _, err := r.runtimeClient.RemoveContainer(ctx, &runtimeapi.RemoveContainerRequest{ ContainerId: containerID, }) @@ -287,6 +293,8 @@ func (r *RemoteRuntimeService) ListContainers(filter *runtimeapi.ContainerFilter // Clean up any expired last-error timers func (r *RemoteRuntimeService) cleanupErrorTimeouts() { + r.errorMapLock.Lock() + defer r.errorMapLock.Unlock() for ID, timeout := range r.errorPrinted { if time.Now().Sub(timeout) >= identicalErrorDelay { delete(r.lastError, ID) @@ -304,6 +312,8 @@ func (r *RemoteRuntimeService) ContainerStatus(containerID string) (*runtimeapi. ContainerId: containerID, }) r.cleanupErrorTimeouts() + r.errorMapLock.Lock() + defer r.errorMapLock.Unlock() if err != nil { // Don't spam the log with endless messages about the same failure. lastMsg, ok := r.lastError[containerID] @@ -491,6 +501,8 @@ func (r *RemoteRuntimeService) ContainerStats(containerID string) (*runtimeapi.C ContainerId: containerID, }) r.cleanupErrorTimeouts() + r.errorMapLock.Lock() + defer r.errorMapLock.Unlock() if err != nil { lastMsg, ok := r.lastError[containerID] if !ok || err.Error() != lastMsg || time.Now().Sub(r.errorPrinted[containerID]) >= identicalErrorDelay { diff --git a/pkg/kubelet/server/stats/BUILD b/pkg/kubelet/server/stats/BUILD index 6fec6f2eb99..dde9b3cbc7d 100644 --- a/pkg/kubelet/server/stats/BUILD +++ b/pkg/kubelet/server/stats/BUILD @@ -18,6 +18,7 @@ go_library( "//pkg/kubelet/apis/stats/v1alpha1:go_default_library", "//pkg/kubelet/cm:go_default_library", "//pkg/kubelet/container:go_default_library", + "//pkg/kubelet/util:go_default_library", "//pkg/kubelet/util/format:go_default_library", "//pkg/volume:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library", diff --git a/pkg/kubelet/server/stats/summary.go b/pkg/kubelet/server/stats/summary.go index fb646c5d2f3..93aef69ed87 100644 --- a/pkg/kubelet/server/stats/summary.go +++ b/pkg/kubelet/server/stats/summary.go @@ -19,7 +19,11 @@ package stats import ( "fmt" + "k8s.io/klog" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" statsapi "k8s.io/kubernetes/pkg/kubelet/apis/stats/v1alpha1" + "k8s.io/kubernetes/pkg/kubelet/util" ) type SummaryProvider interface { @@ -32,6 +36,11 @@ type SummaryProvider interface { // summaryProviderImpl implements the SummaryProvider interface. type summaryProviderImpl struct { + // kubeletCreationTime is the time at which the summaryProvider was created. + kubeletCreationTime metav1.Time + // systemBootTime is the time at which the system was started + systemBootTime metav1.Time + provider StatsProvider } @@ -40,7 +49,18 @@ var _ SummaryProvider = &summaryProviderImpl{} // NewSummaryProvider returns a SummaryProvider using the stats provided by the // specified statsProvider. func NewSummaryProvider(statsProvider StatsProvider) SummaryProvider { - return &summaryProviderImpl{statsProvider} + kubeletCreationTime := metav1.Now() + bootTime, err := util.GetBootTime() + if err != nil { + // bootTime will be zero if we encounter an error getting the boot time. + klog.Warningf("Error getting system boot time. Node metrics will have an incorrect start time: %v", err) + } + + return &summaryProviderImpl{ + kubeletCreationTime: kubeletCreationTime, + systemBootTime: metav1.NewTime(bootTime), + provider: statsProvider, + } } func (sp *summaryProviderImpl) Get(updateStats bool) (*statsapi.Summary, error) { @@ -77,7 +97,7 @@ func (sp *summaryProviderImpl) Get(updateStats bool) (*statsapi.Summary, error) CPU: rootStats.CPU, Memory: rootStats.Memory, Network: networkStats, - StartTime: rootStats.StartTime, + StartTime: sp.systemBootTime, Fs: rootFsStats, Runtime: &statsapi.RuntimeStats{ImageFs: imageFsStats}, Rlimit: rlimit, diff --git a/pkg/kubelet/server/stats/summary_sys_containers.go b/pkg/kubelet/server/stats/summary_sys_containers.go index baaff0ab1bd..4526f2a7695 100644 --- a/pkg/kubelet/server/stats/summary_sys_containers.go +++ b/pkg/kubelet/server/stats/summary_sys_containers.go @@ -21,6 +21,7 @@ package stats import ( "k8s.io/klog" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" statsapi "k8s.io/kubernetes/pkg/kubelet/apis/stats/v1alpha1" "k8s.io/kubernetes/pkg/kubelet/cm" ) @@ -29,11 +30,12 @@ func (sp *summaryProviderImpl) GetSystemContainersStats(nodeConfig cm.NodeConfig systemContainers := map[string]struct { name string forceStatsUpdate bool + startTime metav1.Time }{ - statsapi.SystemContainerKubelet: {nodeConfig.KubeletCgroupsName, false}, - statsapi.SystemContainerRuntime: {nodeConfig.RuntimeCgroupsName, false}, - statsapi.SystemContainerMisc: {nodeConfig.SystemCgroupsName, false}, - statsapi.SystemContainerPods: {sp.provider.GetPodCgroupRoot(), updateStats}, + statsapi.SystemContainerKubelet: {name: nodeConfig.KubeletCgroupsName, forceStatsUpdate: false, startTime: sp.kubeletCreationTime}, + statsapi.SystemContainerRuntime: {name: nodeConfig.RuntimeCgroupsName, forceStatsUpdate: false}, + statsapi.SystemContainerMisc: {name: nodeConfig.SystemCgroupsName, forceStatsUpdate: false}, + statsapi.SystemContainerPods: {name: sp.provider.GetPodCgroupRoot(), forceStatsUpdate: updateStats}, } for sys, cont := range systemContainers { // skip if cgroup name is undefined (not all system containers are required) @@ -48,6 +50,11 @@ func (sp *summaryProviderImpl) GetSystemContainersStats(nodeConfig cm.NodeConfig // System containers don't have a filesystem associated with them. s.Logs, s.Rootfs = nil, nil s.Name = sys + + // if we know the start time of a system container, use that instead of the start time provided by cAdvisor + if !cont.startTime.IsZero() { + s.StartTime = cont.startTime + } stats = append(stats, *s) } @@ -58,11 +65,12 @@ func (sp *summaryProviderImpl) GetSystemContainersCPUAndMemoryStats(nodeConfig c systemContainers := map[string]struct { name string forceStatsUpdate bool + startTime metav1.Time }{ - statsapi.SystemContainerKubelet: {nodeConfig.KubeletCgroupsName, false}, - statsapi.SystemContainerRuntime: {nodeConfig.RuntimeCgroupsName, false}, - statsapi.SystemContainerMisc: {nodeConfig.SystemCgroupsName, false}, - statsapi.SystemContainerPods: {sp.provider.GetPodCgroupRoot(), updateStats}, + statsapi.SystemContainerKubelet: {name: nodeConfig.KubeletCgroupsName, forceStatsUpdate: false, startTime: sp.kubeletCreationTime}, + statsapi.SystemContainerRuntime: {name: nodeConfig.RuntimeCgroupsName, forceStatsUpdate: false}, + statsapi.SystemContainerMisc: {name: nodeConfig.SystemCgroupsName, forceStatsUpdate: false}, + statsapi.SystemContainerPods: {name: sp.provider.GetPodCgroupRoot(), forceStatsUpdate: updateStats}, } for sys, cont := range systemContainers { // skip if cgroup name is undefined (not all system containers are required) @@ -75,6 +83,11 @@ func (sp *summaryProviderImpl) GetSystemContainersCPUAndMemoryStats(nodeConfig c continue } s.Name = sys + + // if we know the start time of a system container, use that instead of the start time provided by cAdvisor + if !cont.startTime.IsZero() { + s.StartTime = cont.startTime + } stats = append(stats, *s) } diff --git a/pkg/kubelet/server/stats/summary_test.go b/pkg/kubelet/server/stats/summary_test.go index d210298f59f..081036855a2 100644 --- a/pkg/kubelet/server/stats/summary_test.go +++ b/pkg/kubelet/server/stats/summary_test.go @@ -83,12 +83,14 @@ func TestSummaryProviderGetStats(t *testing.T) { On("GetCgroupStats", "/kubelet", false).Return(cgroupStatsMap["/kubelet"].cs, cgroupStatsMap["/kubelet"].ns, nil). On("GetCgroupStats", "/kubepods", true).Return(cgroupStatsMap["/pods"].cs, cgroupStatsMap["/pods"].ns, nil) - provider := NewSummaryProvider(mockStatsProvider) + kubeletCreationTime := metav1.Now() + systemBootTime := metav1.Now() + provider := summaryProviderImpl{kubeletCreationTime: kubeletCreationTime, systemBootTime: systemBootTime, provider: mockStatsProvider} summary, err := provider.Get(true) assert.NoError(err) assert.Equal(summary.Node.NodeName, "test-node") - assert.Equal(summary.Node.StartTime, cgroupStatsMap["/"].cs.StartTime) + assert.Equal(summary.Node.StartTime, systemBootTime) assert.Equal(summary.Node.CPU, cgroupStatsMap["/"].cs.CPU) assert.Equal(summary.Node.Memory, cgroupStatsMap["/"].cs.Memory) assert.Equal(summary.Node.Network, cgroupStatsMap["/"].ns) @@ -98,7 +100,7 @@ func TestSummaryProviderGetStats(t *testing.T) { assert.Equal(len(summary.Node.SystemContainers), 4) assert.Contains(summary.Node.SystemContainers, statsapi.ContainerStats{ Name: "kubelet", - StartTime: cgroupStatsMap["/kubelet"].cs.StartTime, + StartTime: kubeletCreationTime, CPU: cgroupStatsMap["/kubelet"].cs.CPU, Memory: cgroupStatsMap["/kubelet"].cs.Memory, Accelerators: cgroupStatsMap["/kubelet"].cs.Accelerators, diff --git a/pkg/kubelet/stats/BUILD b/pkg/kubelet/stats/BUILD index 07ca1b54540..ca3efe32f00 100644 --- a/pkg/kubelet/stats/BUILD +++ b/pkg/kubelet/stats/BUILD @@ -24,6 +24,7 @@ go_library( "//pkg/kubelet/leaky:go_default_library", "//pkg/kubelet/pod:go_default_library", "//pkg/kubelet/server/stats:go_default_library", + "//pkg/kubelet/status:go_default_library", "//pkg/kubelet/types:go_default_library", "//pkg/volume:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", @@ -71,8 +72,10 @@ go_test( "//pkg/kubelet/leaky:go_default_library", "//pkg/kubelet/pod/testing:go_default_library", "//pkg/kubelet/server/stats:go_default_library", + "//pkg/kubelet/status/testing:go_default_library", "//pkg/kubelet/types:go_default_library", "//pkg/volume:go_default_library", + "//staging/src/k8s.io/api/core/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/resource:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/types:go_default_library", diff --git a/pkg/kubelet/stats/cadvisor_stats_provider.go b/pkg/kubelet/stats/cadvisor_stats_provider.go index 9549c12a1a6..a8abfb26646 100644 --- a/pkg/kubelet/stats/cadvisor_stats_provider.go +++ b/pkg/kubelet/stats/cadvisor_stats_provider.go @@ -33,6 +33,7 @@ import ( kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" "k8s.io/kubernetes/pkg/kubelet/leaky" "k8s.io/kubernetes/pkg/kubelet/server/stats" + "k8s.io/kubernetes/pkg/kubelet/status" kubetypes "k8s.io/kubernetes/pkg/kubelet/types" ) @@ -47,6 +48,8 @@ type cadvisorStatsProvider struct { resourceAnalyzer stats.ResourceAnalyzer // imageService is used to get the stats of the image filesystem. imageService kubecontainer.ImageService + // statusProvider is used to get pod metadata + statusProvider status.PodStatusProvider } // newCadvisorStatsProvider returns a containerStatsProvider that provides @@ -55,11 +58,13 @@ func newCadvisorStatsProvider( cadvisor cadvisor.Interface, resourceAnalyzer stats.ResourceAnalyzer, imageService kubecontainer.ImageService, + statusProvider status.PodStatusProvider, ) containerStatsProvider { return &cadvisorStatsProvider{ cadvisor: cadvisor, resourceAnalyzer: resourceAnalyzer, imageService: imageService, + statusProvider: statusProvider, } } @@ -114,7 +119,6 @@ func (p *cadvisorStatsProvider) ListPodStats() ([]statsapi.PodStats, error) { // Special case for infrastructure container which is hidden from // the user and has network stats. podStats.Network = cadvisorInfoToNetworkStats("pod:"+ref.Namespace+"_"+ref.Name, &cinfo) - podStats.StartTime = metav1.NewTime(cinfo.Spec.CreationTime) } else { podStats.Containers = append(podStats.Containers, *cadvisorInfoToContainerStats(containerName, &cinfo, &rootFsInfo, &imageFsInfo)) } @@ -139,7 +143,13 @@ func (p *cadvisorStatsProvider) ListPodStats() ([]statsapi.PodStats, error) { podStats.CPU = cpu podStats.Memory = memory } - result = append(result, *podStats) + + status, found := p.statusProvider.GetPodStatus(podUID) + if found && status.StartTime != nil && !status.StartTime.IsZero() { + podStats.StartTime = *status.StartTime + // only append stats if we were able to get the start time of the pod + result = append(result, *podStats) + } } return result, nil diff --git a/pkg/kubelet/stats/cadvisor_stats_provider_test.go b/pkg/kubelet/stats/cadvisor_stats_provider_test.go index 68a41acb1b9..9c4b6ddd78a 100644 --- a/pkg/kubelet/stats/cadvisor_stats_provider_test.go +++ b/pkg/kubelet/stats/cadvisor_stats_provider_test.go @@ -22,12 +22,16 @@ import ( cadvisorapiv2 "github.com/google/cadvisor/info/v2" "github.com/stretchr/testify/assert" + "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" statsapi "k8s.io/kubernetes/pkg/kubelet/apis/stats/v1alpha1" cadvisortest "k8s.io/kubernetes/pkg/kubelet/cadvisor/testing" kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" containertest "k8s.io/kubernetes/pkg/kubelet/container/testing" "k8s.io/kubernetes/pkg/kubelet/leaky" serverstats "k8s.io/kubernetes/pkg/kubelet/server/stats" + statustest "k8s.io/kubernetes/pkg/kubelet/status/testing" ) func TestRemoveTerminatedContainerInfo(t *testing.T) { @@ -196,10 +200,17 @@ func TestCadvisorListPodStats(t *testing.T) { EphemeralVolumes: ephemeralVolumes, PersistentVolumes: persistentVolumes, } + p0Time := metav1.Now() + p1Time := metav1.Now() + p2Time := metav1.Now() + mockStatus := new(statustest.MockStatusProvider) + mockStatus.On("GetPodStatus", types.UID("UID"+pName0)).Return(v1.PodStatus{StartTime: &p0Time}, true) + mockStatus.On("GetPodStatus", types.UID("UID"+pName1)).Return(v1.PodStatus{StartTime: &p1Time}, true) + mockStatus.On("GetPodStatus", types.UID("UID"+pName2)).Return(v1.PodStatus{StartTime: &p2Time}, true) resourceAnalyzer := &fakeResourceAnalyzer{podVolumeStats: volumeStats} - p := NewCadvisorStatsProvider(mockCadvisor, resourceAnalyzer, nil, nil, mockRuntime) + p := NewCadvisorStatsProvider(mockCadvisor, resourceAnalyzer, nil, nil, mockRuntime, mockStatus) pods, err := p.ListPodStats() assert.NoError(t, err) @@ -227,7 +238,7 @@ func TestCadvisorListPodStats(t *testing.T) { checkCPUStats(t, "Pod0Container1", seedPod0Container1, con.CPU) checkMemoryStats(t, "Pod0Container1", seedPod0Container1, infos["/pod0-c1"], con.Memory) - assert.EqualValues(t, testTime(creationTime, seedPod0Infra).Unix(), ps.StartTime.Time.Unix()) + assert.EqualValues(t, p0Time.Unix(), ps.StartTime.Time.Unix()) checkNetworkStats(t, "Pod0", seedPod0Infra, ps.Network) checkEphemeralStats(t, "Pod0", []int{seedPod0Container0, seedPod0Container1}, []int{seedEphemeralVolume1, seedEphemeralVolume2}, ps.EphemeralStorage) if ps.CPU != nil { @@ -349,7 +360,7 @@ func TestCadvisorListPodCPUAndMemoryStats(t *testing.T) { resourceAnalyzer := &fakeResourceAnalyzer{podVolumeStats: volumeStats} - p := NewCadvisorStatsProvider(mockCadvisor, resourceAnalyzer, nil, nil, nil) + p := NewCadvisorStatsProvider(mockCadvisor, resourceAnalyzer, nil, nil, nil, nil) pods, err := p.ListPodCPUAndMemoryStats() assert.NoError(t, err) @@ -435,7 +446,7 @@ func TestCadvisorImagesFsStats(t *testing.T) { mockCadvisor.On("ImagesFsInfo").Return(imageFsInfo, nil) mockRuntime.On("ImageStats").Return(imageStats, nil) - provider := newCadvisorStatsProvider(mockCadvisor, &fakeResourceAnalyzer{}, mockRuntime) + provider := newCadvisorStatsProvider(mockCadvisor, &fakeResourceAnalyzer{}, mockRuntime, nil) stats, err := provider.ImageFsStats() assert.NoError(err) diff --git a/pkg/kubelet/stats/stats_provider.go b/pkg/kubelet/stats/stats_provider.go index 903f8678a64..b06c7a8ad8a 100644 --- a/pkg/kubelet/stats/stats_provider.go +++ b/pkg/kubelet/stats/stats_provider.go @@ -28,6 +28,7 @@ import ( kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" kubepod "k8s.io/kubernetes/pkg/kubelet/pod" "k8s.io/kubernetes/pkg/kubelet/server/stats" + "k8s.io/kubernetes/pkg/kubelet/status" ) // NewCRIStatsProvider returns a StatsProvider that provides the node stats @@ -52,8 +53,9 @@ func NewCadvisorStatsProvider( podManager kubepod.Manager, runtimeCache kubecontainer.RuntimeCache, imageService kubecontainer.ImageService, + statusProvider status.PodStatusProvider, ) *StatsProvider { - return newStatsProvider(cadvisor, podManager, runtimeCache, newCadvisorStatsProvider(cadvisor, resourceAnalyzer, imageService)) + return newStatsProvider(cadvisor, podManager, runtimeCache, newCadvisorStatsProvider(cadvisor, resourceAnalyzer, imageService, statusProvider)) } // newStatsProvider returns a new StatsProvider that provides node stats from diff --git a/pkg/kubelet/status/status_manager.go b/pkg/kubelet/status/status_manager.go index 37d5bfa0354..2436cb2670a 100644 --- a/pkg/kubelet/status/status_manager.go +++ b/pkg/kubelet/status/status_manager.go @@ -131,7 +131,7 @@ func isPodStatusByKubeletEqual(oldStatus, status *v1.PodStatus) bool { for _, c := range status.Conditions { if kubetypes.PodConditionByKubelet(c.Type) { _, oc := podutil.GetPodCondition(oldCopy, c.Type) - if oc == nil || oc.Status != c.Status { + if oc == nil || oc.Status != c.Status || oc.Message != c.Message || oc.Reason != c.Reason { return false } } diff --git a/pkg/kubelet/status/testing/BUILD b/pkg/kubelet/status/testing/BUILD index 4bc79aca4ec..c335925ad29 100644 --- a/pkg/kubelet/status/testing/BUILD +++ b/pkg/kubelet/status/testing/BUILD @@ -7,9 +7,16 @@ load( go_library( name = "go_default_library", - srcs = ["fake_pod_deletion_safety.go"], + srcs = [ + "fake_pod_deletion_safety.go", + "mock_pod_status_provider.go", + ], importpath = "k8s.io/kubernetes/pkg/kubelet/status/testing", - deps = ["//staging/src/k8s.io/api/core/v1:go_default_library"], + deps = [ + "//staging/src/k8s.io/api/core/v1:go_default_library", + "//staging/src/k8s.io/apimachinery/pkg/types:go_default_library", + "//vendor/github.com/stretchr/testify/mock:go_default_library", + ], ) filegroup( diff --git a/staging/src/k8s.io/code-generator/cmd/client-gen/generators/tags.go b/pkg/kubelet/status/testing/mock_pod_status_provider.go similarity index 60% rename from staging/src/k8s.io/code-generator/cmd/client-gen/generators/tags.go rename to pkg/kubelet/status/testing/mock_pod_status_provider.go index b0040810368..cef85222ada 100644 --- a/staging/src/k8s.io/code-generator/cmd/client-gen/generators/tags.go +++ b/pkg/kubelet/status/testing/mock_pod_status_provider.go @@ -1,5 +1,5 @@ /* -Copyright 2016 The Kubernetes Authors. +Copyright 2018 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -14,19 +14,20 @@ See the License for the specific language governing permissions and limitations under the License. */ -package generators +package testing import ( - "k8s.io/gengo/types" + "github.com/stretchr/testify/mock" + + "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/types" ) -// extractTag gets the comment-tags for the key. If the tag did not exist, it -// returns the empty string. -func extractTag(key string, lines []string) string { - val, present := types.ExtractCommentTags("+", lines)[key] - if !present || len(val) < 1 { - return "" - } - - return val[0] +type MockStatusProvider struct { + mock.Mock +} + +func (m *MockStatusProvider) GetPodStatus(uid types.UID) (v1.PodStatus, bool) { + args := m.Called(uid) + return args.Get(0).(v1.PodStatus), args.Bool(1) } diff --git a/pkg/kubelet/util/BUILD b/pkg/kubelet/util/BUILD index 4165864e0a3..7b590024861 100644 --- a/pkg/kubelet/util/BUILD +++ b/pkg/kubelet/util/BUILD @@ -34,6 +34,8 @@ go_test( go_library( name = "go_default_library", srcs = [ + "boottime_util_darwin.go", + "boottime_util_linux.go", "doc.go", "util.go", "util_unix.go", diff --git a/pkg/kubelet/util/boottime_util_darwin.go b/pkg/kubelet/util/boottime_util_darwin.go new file mode 100644 index 00000000000..09d3b8865da --- /dev/null +++ b/pkg/kubelet/util/boottime_util_darwin.go @@ -0,0 +1,44 @@ +// +build darwin + +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package util + +import ( + "fmt" + "syscall" + "time" + "unsafe" + + "golang.org/x/sys/unix" +) + +// GetBootTime returns the time at which the machine was started, truncated to the nearest second +func GetBootTime() (time.Time, error) { + output, err := unix.SysctlRaw("kern.boottime") + if err != nil { + return time.Time{}, err + } + var timeval syscall.Timeval + if len(output) != int(unsafe.Sizeof(timeval)) { + return time.Time{}, fmt.Errorf("unexpected output when calling syscall kern.bootime. Expected len(output) to be %v, but got %v", + int(unsafe.Sizeof(timeval)), len(output)) + } + timeval = *(*syscall.Timeval)(unsafe.Pointer(&output[0])) + sec, nsec := timeval.Unix() + return time.Unix(sec, nsec).Truncate(time.Second), nil +} diff --git a/staging/src/k8s.io/sample-apiserver/pkg/client/listers/wardle/internalversion/expansion_generated.go b/pkg/kubelet/util/boottime_util_linux.go similarity index 50% rename from staging/src/k8s.io/sample-apiserver/pkg/client/listers/wardle/internalversion/expansion_generated.go rename to pkg/kubelet/util/boottime_util_linux.go index 89892308b42..f00e7c06bfa 100644 --- a/staging/src/k8s.io/sample-apiserver/pkg/client/listers/wardle/internalversion/expansion_generated.go +++ b/pkg/kubelet/util/boottime_util_linux.go @@ -1,5 +1,7 @@ +// +build freebsd linux + /* -Copyright The Kubernetes Authors. +Copyright 2018 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -14,18 +16,21 @@ See the License for the specific language governing permissions and limitations under the License. */ -// Code generated by lister-gen. DO NOT EDIT. +package util -package internalversion +import ( + "fmt" + "time" -// FischerListerExpansion allows custom methods to be added to -// FischerLister. -type FischerListerExpansion interface{} + "golang.org/x/sys/unix" +) -// FlunderListerExpansion allows custom methods to be added to -// FlunderLister. -type FlunderListerExpansion interface{} - -// FlunderNamespaceListerExpansion allows custom methods to be added to -// FlunderNamespaceLister. -type FlunderNamespaceListerExpansion interface{} +// GetBootTime returns the time at which the machine was started, truncated to the nearest second +func GetBootTime() (time.Time, error) { + currentTime := time.Now() + var info unix.Sysinfo_t + if err := unix.Sysinfo(&info); err != nil { + return time.Time{}, fmt.Errorf("error getting system uptime: %s", err) + } + return currentTime.Add(-time.Duration(info.Uptime) * time.Second).Truncate(time.Second), nil +} diff --git a/pkg/kubelet/util/util_unsupported.go b/pkg/kubelet/util/util_unsupported.go index 6661678aced..68a2bdf01b7 100644 --- a/pkg/kubelet/util/util_unsupported.go +++ b/pkg/kubelet/util/util_unsupported.go @@ -45,3 +45,8 @@ func UnlockPath(fileHandles []uintptr) { func LocalEndpoint(path, file string) string { return "" } + +// GetBootTime empty implementation +func GetBootTime() (time.Time, error) { + return time.Time{}, fmt.Errorf("GetBootTime is unsupported in this build") +} diff --git a/pkg/kubelet/util/util_windows.go b/pkg/kubelet/util/util_windows.go index 7123728ff94..92accc55e14 100644 --- a/pkg/kubelet/util/util_windows.go +++ b/pkg/kubelet/util/util_windows.go @@ -23,6 +23,7 @@ import ( "net" "net/url" "strings" + "syscall" "time" "github.com/Microsoft/go-winio" @@ -112,3 +113,15 @@ func LocalEndpoint(path, file string) string { } return u.String() + "//./pipe/" + file } + +var tickCount = syscall.NewLazyDLL("kernel32.dll").NewProc("GetTickCount64") + +// GetBootTime returns the time at which the machine was started, truncated to the nearest second +func GetBootTime() (time.Time, error) { + currentTime := time.Now() + output, _, err := tickCount.Call() + if errno, ok := err.(syscall.Errno); !ok || errno != 0 { + return time.Time{}, err + } + return currentTime.Add(-time.Duration(output) * time.Millisecond).Truncate(time.Second), nil +} diff --git a/pkg/kubelet/volumemanager/cache/desired_state_of_world.go b/pkg/kubelet/volumemanager/cache/desired_state_of_world.go index d4745ee0b1b..1c748505a26 100644 --- a/pkg/kubelet/volumemanager/cache/desired_state_of_world.go +++ b/pkg/kubelet/volumemanager/cache/desired_state_of_world.go @@ -203,11 +203,12 @@ func (dsw *desiredStateOfWorld) AddPodToVolume( var volumeName v1.UniqueVolumeName - // The unique volume name used depends on whether the volume is attachable + // The unique volume name used depends on whether the volume is attachable/device-mountable // or not. attachable := dsw.isAttachableVolume(volumeSpec) - if attachable { - // For attachable volumes, use the unique volume name as reported by + deviceMountable := dsw.isDeviceMountableVolume(volumeSpec) + if attachable || deviceMountable { + // For attachable/device-mountable volumes, use the unique volume name as reported by // the plugin. volumeName, err = util.GetUniqueVolumeNameFromSpec(volumePlugin, volumeSpec) @@ -219,13 +220,11 @@ func (dsw *desiredStateOfWorld) AddPodToVolume( err) } } else { - // For non-attachable volumes, generate a unique name based on the pod + // For non-attachable and non-device-mountable volumes, generate a unique name based on the pod // namespace and name and the name of the volume within the pod. - volumeName = util.GetUniqueVolumeNameForNonAttachableVolume(podName, volumePlugin, volumeSpec) + volumeName = util.GetUniqueVolumeNameFromSpecWithPod(podName, volumePlugin, volumeSpec) } - deviceMountable := dsw.isDeviceMountableVolume(volumeSpec) - if _, volumeExists := dsw.volumesToMount[volumeName]; !volumeExists { dsw.volumesToMount[volumeName] = volumeToMount{ volumeName: volumeName, diff --git a/pkg/kubelet/volumemanager/cache/desired_state_of_world_test.go b/pkg/kubelet/volumemanager/cache/desired_state_of_world_test.go index 42707169d92..b7df006316e 100644 --- a/pkg/kubelet/volumemanager/cache/desired_state_of_world_test.go +++ b/pkg/kubelet/volumemanager/cache/desired_state_of_world_test.go @@ -117,6 +117,168 @@ func Test_AddPodToVolume_Positive_ExistingPodExistingVolume(t *testing.T) { verifyVolumeExistsWithSpecNameInVolumeDsw(t, podName, volumeSpec.Name(), dsw) } +// Call AddPodToVolume() on different pods for different kinds of volumes +// Verities generated names are same for different pods if volume is device mountable or attachable +// Verities generated names are different for different pods if volume is not device mountble and attachable +func Test_AddPodToVolume_Positive_NamesForDifferentPodsAndDifferentVolumes(t *testing.T) { + // Arrange + fakeVolumeHost := volumetesting.NewFakeVolumeHost( + "", /* rootDir */ + nil, /* kubeClient */ + nil, /* plugins */ + ) + plugins := []volume.VolumePlugin{ + &volumetesting.FakeBasicVolumePlugin{ + Plugin: volumetesting.FakeVolumePlugin{ + PluginName: "basic", + }, + }, + &volumetesting.FakeDeviceMountableVolumePlugin{ + FakeBasicVolumePlugin: volumetesting.FakeBasicVolumePlugin{ + Plugin: volumetesting.FakeVolumePlugin{ + PluginName: "device-mountable", + }, + }, + }, + &volumetesting.FakeAttachableVolumePlugin{ + FakeDeviceMountableVolumePlugin: volumetesting.FakeDeviceMountableVolumePlugin{ + FakeBasicVolumePlugin: volumetesting.FakeBasicVolumePlugin{ + Plugin: volumetesting.FakeVolumePlugin{ + PluginName: "attachable", + }, + }, + }, + }, + } + volumePluginMgr := volume.VolumePluginMgr{} + volumePluginMgr.InitPlugins(plugins, nil /* prober */, fakeVolumeHost) + dsw := NewDesiredStateOfWorld(&volumePluginMgr) + + testcases := map[string]struct { + pod1 *v1.Pod + pod2 *v1.Pod + same bool + }{ + "basic": { + &v1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "pod1", + UID: "pod1uid", + }, + Spec: v1.PodSpec{ + Volumes: []v1.Volume{ + { + Name: "basic", + VolumeSource: v1.VolumeSource{}, + }, + }, + }, + }, + &v1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "pod2", + UID: "pod2uid", + }, + Spec: v1.PodSpec{ + Volumes: []v1.Volume{ + { + Name: "basic", + VolumeSource: v1.VolumeSource{}, + }, + }, + }, + }, + false, + }, + "device-mountable": { + &v1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "pod1", + UID: "pod1uid", + }, + Spec: v1.PodSpec{ + Volumes: []v1.Volume{ + { + Name: "device-mountable", + VolumeSource: v1.VolumeSource{}, + }, + }, + }, + }, + &v1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "pod2", + UID: "pod2uid", + }, + Spec: v1.PodSpec{ + Volumes: []v1.Volume{ + { + Name: "device-mountable", + VolumeSource: v1.VolumeSource{}, + }, + }, + }, + }, + true, + }, + "attachable": { + &v1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "pod1", + UID: "pod1uid", + }, + Spec: v1.PodSpec{ + Volumes: []v1.Volume{ + { + Name: "attachable", + VolumeSource: v1.VolumeSource{}, + }, + }, + }, + }, + &v1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "pod2", + UID: "pod2uid", + }, + Spec: v1.PodSpec{ + Volumes: []v1.Volume{ + { + Name: "attachable", + VolumeSource: v1.VolumeSource{}, + }, + }, + }, + }, + true, + }, + } + + // Act & Assert + for name, v := range testcases { + volumeSpec1 := &volume.Spec{Volume: &v.pod1.Spec.Volumes[0]} + volumeSpec2 := &volume.Spec{Volume: &v.pod2.Spec.Volumes[0]} + generatedVolumeName1, err1 := dsw.AddPodToVolume(util.GetUniquePodName(v.pod1), v.pod1, volumeSpec1, volumeSpec1.Name(), "") + generatedVolumeName2, err2 := dsw.AddPodToVolume(util.GetUniquePodName(v.pod2), v.pod2, volumeSpec2, volumeSpec2.Name(), "") + if err1 != nil { + t.Fatalf("test %q: AddPodToVolume failed. Expected: Actual: <%v>", name, err1) + } + if err2 != nil { + t.Fatalf("test %q: AddPodToVolume failed. Expected: Actual: <%v>", name, err2) + } + if v.same { + if generatedVolumeName1 != generatedVolumeName2 { + t.Fatalf("test %q: AddPodToVolume should generate same names, but got %q != %q", name, generatedVolumeName1, generatedVolumeName2) + } + } else { + if generatedVolumeName1 == generatedVolumeName2 { + t.Fatalf("test %q: AddPodToVolume should generate different names, but got %q == %q", name, generatedVolumeName1, generatedVolumeName2) + } + } + } + +} + // Populates data struct with a new volume/pod // Calls DeletePodFromVolume() to removes the pod // Verifies newly added pod/volume are deleted diff --git a/pkg/kubelet/volumemanager/reconciler/reconciler.go b/pkg/kubelet/volumemanager/reconciler/reconciler.go index 1b6bbbfbe77..f57d6bf26e9 100644 --- a/pkg/kubelet/volumemanager/reconciler/reconciler.go +++ b/pkg/kubelet/volumemanager/reconciler/reconciler.go @@ -455,6 +455,10 @@ func (rc *reconciler) reconstructVolume(volume podVolume) (*reconstructedVolume, if err != nil { return nil, err } + deviceMountablePlugin, err := rc.volumePluginMgr.FindDeviceMountablePluginByName(volume.pluginName) + if err != nil { + return nil, err + } // Create pod object pod := &v1.Pod{ @@ -480,13 +484,13 @@ func (rc *reconciler) reconstructVolume(volume podVolume) (*reconstructedVolume, } var uniqueVolumeName v1.UniqueVolumeName - if attachablePlugin != nil { + if attachablePlugin != nil || deviceMountablePlugin != nil { uniqueVolumeName, err = util.GetUniqueVolumeNameFromSpec(plugin, volumeSpec) if err != nil { return nil, err } } else { - uniqueVolumeName = util.GetUniqueVolumeNameForNonAttachableVolume(volume.podName, plugin, volumeSpec) + uniqueVolumeName = util.GetUniqueVolumeNameFromSpecWithPod(volume.podName, plugin, volumeSpec) } // Check existence of mount point for filesystem volume or symbolic link for block volume isExist, checkErr := rc.operationExecutor.CheckVolumeExistenceOperation(volumeSpec, volume.mountPath, volumeSpec.Name(), rc.mounter, uniqueVolumeName, volume.podName, pod.UID, attachablePlugin) diff --git a/pkg/master/BUILD b/pkg/master/BUILD index 6c0ef9e50cf..c99e5056609 100644 --- a/pkg/master/BUILD +++ b/pkg/master/BUILD @@ -83,6 +83,7 @@ go_library( "//staging/src/k8s.io/api/batch/v1beta1:go_default_library", "//staging/src/k8s.io/api/batch/v2alpha1:go_default_library", "//staging/src/k8s.io/api/certificates/v1beta1:go_default_library", + "//staging/src/k8s.io/api/coordination/v1:go_default_library", "//staging/src/k8s.io/api/coordination/v1beta1:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library", "//staging/src/k8s.io/api/events/v1beta1:go_default_library", diff --git a/pkg/master/master.go b/pkg/master/master.go index b2d25a12f70..fcffb2d9447 100644 --- a/pkg/master/master.go +++ b/pkg/master/master.go @@ -41,6 +41,7 @@ import ( batchapiv1beta1 "k8s.io/api/batch/v1beta1" batchapiv2alpha1 "k8s.io/api/batch/v2alpha1" certificatesapiv1beta1 "k8s.io/api/certificates/v1beta1" + coordinationapiv1 "k8s.io/api/coordination/v1" coordinationapiv1beta1 "k8s.io/api/coordination/v1beta1" apiv1 "k8s.io/api/core/v1" eventsv1beta1 "k8s.io/api/events/v1beta1" @@ -444,15 +445,26 @@ func (n nodeAddressProvider) externalAddresses() ([]string, error) { if err != nil { return nil, err } + var matchErr error addrs := []string{} for ix := range nodes.Items { node := &nodes.Items[ix] addr, err := nodeutil.GetPreferredNodeAddress(node, preferredAddressTypes) if err != nil { + if _, ok := err.(*nodeutil.NoMatchError); ok { + matchErr = err + continue + } return nil, err } addrs = append(addrs, addr) } + if len(addrs) == 0 && matchErr != nil { + // We only return an error if we have items. + // Currently we return empty list/no error if Items is empty. + // We do this for backward compatibility reasons. + return nil, matchErr + } return addrs, nil } @@ -462,8 +474,6 @@ func DefaultAPIResourceConfigSource() *serverstorage.ResourceConfig { ret.EnableVersions( admissionregistrationv1beta1.SchemeGroupVersion, apiv1.SchemeGroupVersion, - appsv1beta1.SchemeGroupVersion, - appsv1beta2.SchemeGroupVersion, appsv1.SchemeGroupVersion, authenticationv1.SchemeGroupVersion, authenticationv1beta1.SchemeGroupVersion, @@ -475,6 +485,7 @@ func DefaultAPIResourceConfigSource() *serverstorage.ResourceConfig { batchapiv1.SchemeGroupVersion, batchapiv1beta1.SchemeGroupVersion, certificatesapiv1beta1.SchemeGroupVersion, + coordinationapiv1.SchemeGroupVersion, coordinationapiv1beta1.SchemeGroupVersion, eventsv1beta1.SchemeGroupVersion, extensionsapiv1beta1.SchemeGroupVersion, @@ -486,6 +497,24 @@ func DefaultAPIResourceConfigSource() *serverstorage.ResourceConfig { storageapiv1beta1.SchemeGroupVersion, schedulingapiv1beta1.SchemeGroupVersion, ) + // enable non-deprecated beta resources in extensions/v1beta1 explicitly so we have a full list of what's possible to serve + ret.EnableResources( + extensionsapiv1beta1.SchemeGroupVersion.WithResource("ingresses"), + ) + // enable deprecated beta resources in extensions/v1beta1 explicitly so we have a full list of what's possible to serve + ret.EnableResources( + extensionsapiv1beta1.SchemeGroupVersion.WithResource("daemonsets"), + extensionsapiv1beta1.SchemeGroupVersion.WithResource("deployments"), + extensionsapiv1beta1.SchemeGroupVersion.WithResource("networkpolicies"), + extensionsapiv1beta1.SchemeGroupVersion.WithResource("podsecuritypolicies"), + extensionsapiv1beta1.SchemeGroupVersion.WithResource("replicasets"), + extensionsapiv1beta1.SchemeGroupVersion.WithResource("replicationcontrollers"), + ) + // enable deprecated beta versions explicitly so we have a full list of what's possible to serve + ret.EnableVersions( + appsv1beta1.SchemeGroupVersion, + appsv1beta2.SchemeGroupVersion, + ) // disable alpha versions explicitly so we have a full list of what's possible to serve ret.DisableVersions( auditregistrationv1alpha1.SchemeGroupVersion, diff --git a/pkg/master/master_test.go b/pkg/master/master_test.go index 5be9a014907..5ee2fa4f833 100644 --- a/pkg/master/master_test.go +++ b/pkg/master/master_test.go @@ -278,6 +278,22 @@ func TestGetNodeAddresses(t *testing.T) { assert.Equal([]string{"127.0.0.1", "127.0.0.1"}, addrs) } +func TestGetNodeAddressesWithOnlySomeExternalIP(t *testing.T) { + assert := assert.New(t) + + fakeNodeClient := fake.NewSimpleClientset(makeNodeList([]string{"node1", "node2", "node3"}, apiv1.NodeResources{})).Core().Nodes() + addressProvider := nodeAddressProvider{fakeNodeClient} + + // Pass case with 1 External type IP (index == 1) and nodes (indexes 0 & 2) have no External IP. + nodes, _ := fakeNodeClient.List(metav1.ListOptions{}) + nodes.Items[1].Status.Addresses = []apiv1.NodeAddress{{Type: apiv1.NodeExternalIP, Address: "127.0.0.1"}} + fakeNodeClient.Update(&nodes.Items[1]) + + addrs, err := addressProvider.externalAddresses() + assert.NoError(err, "addresses should not have returned an error.") + assert.Equal([]string{"127.0.0.1"}, addrs) +} + func decodeResponse(resp *http.Response, obj interface{}) error { defer resp.Body.Close() diff --git a/pkg/master/tunneler/BUILD b/pkg/master/tunneler/BUILD index fd4bf629dd9..99648d7f8aa 100644 --- a/pkg/master/tunneler/BUILD +++ b/pkg/master/tunneler/BUILD @@ -25,7 +25,6 @@ go_library( "//pkg/util/file:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/clock:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library", - "//vendor/github.com/prometheus/client_golang/prometheus:go_default_library", "//vendor/k8s.io/klog:go_default_library", ], ) diff --git a/pkg/master/tunneler/ssh.go b/pkg/master/tunneler/ssh.go index 88217d170ed..4bf8307bad0 100644 --- a/pkg/master/tunneler/ssh.go +++ b/pkg/master/tunneler/ssh.go @@ -29,11 +29,9 @@ import ( "k8s.io/apimachinery/pkg/util/clock" "k8s.io/apimachinery/pkg/util/wait" + "k8s.io/klog" "k8s.io/kubernetes/pkg/ssh" utilfile "k8s.io/kubernetes/pkg/util/file" - - "github.com/prometheus/client_golang/prometheus" - "k8s.io/klog" ) type InstallSSHKey func(ctx context.Context, user string, data []byte) error @@ -83,9 +81,8 @@ type SSHTunneler struct { InstallSSHKey InstallSSHKey HealthCheckURL *url.URL - tunnels *ssh.SSHTunnelList - lastSyncMetric prometheus.GaugeFunc - clock clock.Clock + tunnels *ssh.SSHTunnelList + clock clock.Clock getAddresses AddressFunc stopChan chan struct{} diff --git a/pkg/master/tunneler/ssh_test.go b/pkg/master/tunneler/ssh_test.go index f4f58b0f6e8..2fe8f283944 100644 --- a/pkg/master/tunneler/ssh_test.go +++ b/pkg/master/tunneler/ssh_test.go @@ -25,9 +25,9 @@ import ( "testing" "time" - "k8s.io/apimachinery/pkg/util/clock" - "github.com/stretchr/testify/assert" + + "k8s.io/apimachinery/pkg/util/clock" ) // TestSecondsSinceSync verifies that proper results are returned diff --git a/pkg/printers/BUILD b/pkg/printers/BUILD index 4c9f9e647ab..3f1134b1b08 100644 --- a/pkg/printers/BUILD +++ b/pkg/printers/BUILD @@ -23,6 +23,7 @@ go_library( "//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/runtime:go_default_library", + "//vendor/github.com/liggitt/tabwriter:go_default_library", ], ) diff --git a/pkg/printers/humanreadable.go b/pkg/printers/humanreadable.go index bf4a761a4fb..5e51fb335c8 100644 --- a/pkg/printers/humanreadable.go +++ b/pkg/printers/humanreadable.go @@ -22,7 +22,8 @@ import ( "io" "reflect" "strings" - "text/tabwriter" + + "github.com/liggitt/tabwriter" "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" diff --git a/pkg/printers/internalversion/BUILD b/pkg/printers/internalversion/BUILD index 147e1e197b1..1c9b3e7f186 100644 --- a/pkg/printers/internalversion/BUILD +++ b/pkg/printers/internalversion/BUILD @@ -87,7 +87,7 @@ go_library( "//staging/src/k8s.io/api/batch/v1:go_default_library", "//staging/src/k8s.io/api/batch/v1beta1:go_default_library", "//staging/src/k8s.io/api/certificates/v1beta1:go_default_library", - "//staging/src/k8s.io/api/coordination/v1beta1:go_default_library", + "//staging/src/k8s.io/api/coordination/v1:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library", "//staging/src/k8s.io/api/extensions/v1beta1:go_default_library", "//staging/src/k8s.io/api/policy/v1beta1:go_default_library", diff --git a/pkg/printers/internalversion/printers.go b/pkg/printers/internalversion/printers.go index 32722bd0916..a38fba95920 100644 --- a/pkg/printers/internalversion/printers.go +++ b/pkg/printers/internalversion/printers.go @@ -30,7 +30,7 @@ import ( batchv1 "k8s.io/api/batch/v1" batchv1beta1 "k8s.io/api/batch/v1beta1" certificatesv1beta1 "k8s.io/api/certificates/v1beta1" - coordinationv1beta1 "k8s.io/api/coordination/v1beta1" + coordinationv1 "k8s.io/api/coordination/v1" apiv1 "k8s.io/api/core/v1" extensionsv1beta1 "k8s.io/api/extensions/v1beta1" policyv1beta1 "k8s.io/api/policy/v1beta1" @@ -398,7 +398,7 @@ func AddHandlers(h printers.PrintHandler) { leaseColumnDefinitions := []metav1beta1.TableColumnDefinition{ {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]}, - {Name: "Holder", Type: "string", Description: coordinationv1beta1.LeaseSpec{}.SwaggerDoc()["holderIdentity"]}, + {Name: "Holder", Type: "string", Description: coordinationv1.LeaseSpec{}.SwaggerDoc()["holderIdentity"]}, {Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]}, } h.TableHandler(leaseColumnDefinitions, printLease) diff --git a/pkg/printers/tabwriter.go b/pkg/printers/tabwriter.go index d1d4cb53fc5..21d60e1c413 100644 --- a/pkg/printers/tabwriter.go +++ b/pkg/printers/tabwriter.go @@ -18,7 +18,8 @@ package printers import ( "io" - "text/tabwriter" + + "github.com/liggitt/tabwriter" ) const ( @@ -26,7 +27,7 @@ const ( tabwriterWidth = 4 tabwriterPadding = 3 tabwriterPadChar = ' ' - tabwriterFlags = 0 + tabwriterFlags = tabwriter.RememberWidths ) // GetNewTabWriter returns a tabwriter that translates tabbed columns in input into properly aligned text. diff --git a/pkg/probe/http/http.go b/pkg/probe/http/http.go index e9bcc0f3e1b..6c31bed6f23 100644 --- a/pkg/probe/http/http.go +++ b/pkg/probe/http/http.go @@ -39,7 +39,13 @@ func New() Prober { // NewWithTLSConfig takes tls config as parameter. func NewWithTLSConfig(config *tls.Config) Prober { - transport := utilnet.SetTransportDefaults(&http.Transport{TLSClientConfig: config, DisableKeepAlives: true}) + // We do not want the probe use node's local proxy set. + transport := utilnet.SetTransportDefaults( + &http.Transport{ + TLSClientConfig: config, + DisableKeepAlives: true, + Proxy: http.ProxyURL(nil), + }) return httpProber{transport} } diff --git a/pkg/probe/http/http_test.go b/pkg/probe/http/http_test.go index 69ad77064c7..3afa8ff077e 100644 --- a/pkg/probe/http/http_test.go +++ b/pkg/probe/http/http_test.go @@ -22,6 +22,7 @@ import ( "net/http" "net/http/httptest" "net/url" + "os" "strconv" "strings" "testing" @@ -32,6 +33,62 @@ import ( const FailureCode int = -1 +func setEnv(key, value string) func() { + originalValue := os.Getenv(key) + os.Setenv(key, value) + if len(originalValue) > 0 { + return func() { + os.Setenv(key, originalValue) + } + } + return func() {} +} + +func unsetEnv(key string) func() { + originalValue := os.Getenv(key) + os.Unsetenv(key) + if len(originalValue) > 0 { + return func() { + os.Setenv(key, originalValue) + } + } + return func() {} +} + +func TestHTTPProbeProxy(t *testing.T) { + res := "welcome to http probe proxy" + localProxy := "http://127.0.0.1:9098/" + + defer setEnv("http_proxy", localProxy)() + defer setEnv("HTTP_PROXY", localProxy)() + defer unsetEnv("no_proxy")() + defer unsetEnv("NO_PROXY")() + + prober := New() + + go func() { + http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { + fmt.Fprintf(w, res) + }) + err := http.ListenAndServe(":9098", nil) + if err != nil { + t.Errorf("Failed to start foo server: localhost:9098") + } + }() + + // take some time to wait server boot + time.Sleep(2 * time.Second) + url, err := url.Parse("http://example.com") + if err != nil { + t.Errorf("proxy test unexpected error: %v", err) + } + _, response, _ := prober.Probe(url, http.Header{}, time.Second*3) + + if response == res { + t.Errorf("proxy test unexpected error: the probe is using proxy") + } +} + func TestHTTPProbeChecker(t *testing.T) { handleReq := func(s int, body string) func(w http.ResponseWriter, r *http.Request) { return func(w http.ResponseWriter, r *http.Request) { diff --git a/pkg/proxy/iptables/proxier.go b/pkg/proxy/iptables/proxier.go index 1fb994be32f..4734de066d5 100644 --- a/pkg/proxy/iptables/proxier.go +++ b/pkg/proxy/iptables/proxier.go @@ -607,7 +607,13 @@ func (proxier *Proxier) deleteEndpointConnections(connectionMap []proxy.ServiceE for _, epSvcPair := range connectionMap { if svcInfo, ok := proxier.serviceMap[epSvcPair.ServicePortName]; ok && svcInfo.GetProtocol() == v1.ProtocolUDP { endpointIP := utilproxy.IPPart(epSvcPair.Endpoint) - err := conntrack.ClearEntriesForNAT(proxier.exec, svcInfo.ClusterIPString(), endpointIP, v1.ProtocolUDP) + nodePort := svcInfo.GetNodePort() + var err error + if nodePort != 0 { + err = conntrack.ClearEntriesForPortNAT(proxier.exec, endpointIP, nodePort, v1.ProtocolUDP) + } else { + err = conntrack.ClearEntriesForNAT(proxier.exec, svcInfo.ClusterIPString(), endpointIP, v1.ProtocolUDP) + } if err != nil { klog.Errorf("Failed to delete %s endpoint connections, error: %v", epSvcPair.ServicePortName.String(), err) } diff --git a/pkg/proxy/ipvs/graceful_termination.go b/pkg/proxy/ipvs/graceful_termination.go index a705bb9585d..4d53d4ee7b9 100644 --- a/pkg/proxy/ipvs/graceful_termination.go +++ b/pkg/proxy/ipvs/graceful_termination.go @@ -168,6 +168,7 @@ func (m *GracefulTerminationManager) deleteRsFunc(rsToDelete *listItem) (bool, e // For UDP, ActiveConn is always 0 // For TCP, InactiveConn are connections not in ESTABLISHED state if rs.ActiveConn+rs.InactiveConn != 0 { + klog.Infof("Not deleting, RS %v: %v ActiveConn, %v InactiveConn", rsToDelete.String(), rs.ActiveConn, rs.InactiveConn) return false, nil } klog.Infof("Deleting rs: %s", rsToDelete.String()) diff --git a/pkg/proxy/ipvs/netlink_linux.go b/pkg/proxy/ipvs/netlink_linux.go index 0c671200f03..c917c9429c0 100644 --- a/pkg/proxy/ipvs/netlink_linux.go +++ b/pkg/proxy/ipvs/netlink_linux.go @@ -30,11 +30,12 @@ import ( type netlinkHandle struct { netlink.Handle + isIPv6 bool } // NewNetLinkHandle will crate a new NetLinkHandle -func NewNetLinkHandle() NetLinkHandle { - return &netlinkHandle{netlink.Handle{}} +func NewNetLinkHandle(isIPv6 bool) NetLinkHandle { + return &netlinkHandle{netlink.Handle{}, isIPv6} } // EnsureAddressBind checks if address is bound to the interface and, if not, binds it. If the address is already bound, return true. @@ -181,7 +182,11 @@ func (h *netlinkHandle) GetLocalAddresses(dev, filterDev string) (sets.String, e if route.LinkIndex == filterLinkIndex { continue } - if route.Src != nil { + if h.isIPv6 { + if route.Dst.IP.To4() == nil && !route.Dst.IP.IsLinkLocalUnicast() { + res.Insert(route.Dst.IP.String()) + } + } else if route.Src != nil { res.Insert(route.Src.String()) } } diff --git a/pkg/proxy/ipvs/netlink_unsupported.go b/pkg/proxy/ipvs/netlink_unsupported.go index a83081f1fdb..1c709cd2b60 100644 --- a/pkg/proxy/ipvs/netlink_unsupported.go +++ b/pkg/proxy/ipvs/netlink_unsupported.go @@ -28,7 +28,7 @@ type emptyHandle struct { } // NewNetLinkHandle will create an EmptyHandle -func NewNetLinkHandle() NetLinkHandle { +func NewNetLinkHandle(ipv6 bool) NetLinkHandle { return &emptyHandle{} } diff --git a/pkg/proxy/ipvs/proxier.go b/pkg/proxy/ipvs/proxier.go index 20fd8acca5e..a2b358b0068 100644 --- a/pkg/proxy/ipvs/proxier.go +++ b/pkg/proxy/ipvs/proxier.go @@ -162,6 +162,8 @@ const sysctlRouteLocalnet = "net/ipv4/conf/all/route_localnet" const sysctlBridgeCallIPTables = "net/bridge/bridge-nf-call-iptables" const sysctlVSConnTrack = "net/ipv4/vs/conntrack" const sysctlConnReuse = "net/ipv4/vs/conn_reuse_mode" +const sysctlExpireNoDestConn = "net/ipv4/vs/expire_nodest_conn" +const sysctlExpireQuiescentTemplate = "net/ipv4/vs/expire_quiescent_template" const sysctlForward = "net/ipv4/ip_forward" const sysctlArpIgnore = "net/ipv4/conf/all/arp_ignore" const sysctlArpAnnounce = "net/ipv4/conf/all/arp_announce" @@ -321,6 +323,20 @@ func NewProxier(ipt utiliptables.Interface, } } + // Set the expire_nodest_conn sysctl we need for + if val, _ := sysctl.GetSysctl(sysctlExpireNoDestConn); val != 1 { + if err := sysctl.SetSysctl(sysctlExpireNoDestConn, 1); err != nil { + return nil, fmt.Errorf("can't set sysctl %s: %v", sysctlExpireNoDestConn, err) + } + } + + // Set the expire_quiescent_template sysctl we need for + if val, _ := sysctl.GetSysctl(sysctlExpireQuiescentTemplate); val != 1 { + if err := sysctl.SetSysctl(sysctlExpireQuiescentTemplate, 1); err != nil { + return nil, fmt.Errorf("can't set sysctl %s: %v", sysctlExpireQuiescentTemplate, err) + } + } + // Set the ip_forward sysctl we need for if val, _ := sysctl.GetSysctl(sysctlForward); val != 1 { if err := sysctl.SetSysctl(sysctlForward, 1); err != nil { @@ -390,14 +406,14 @@ func NewProxier(ipt utiliptables.Interface, healthzServer: healthzServer, ipvs: ipvs, ipvsScheduler: scheduler, - ipGetter: &realIPGetter{nl: NewNetLinkHandle()}, + ipGetter: &realIPGetter{nl: NewNetLinkHandle(isIPv6)}, iptablesData: bytes.NewBuffer(nil), filterChainsData: bytes.NewBuffer(nil), natChains: bytes.NewBuffer(nil), natRules: bytes.NewBuffer(nil), filterChains: bytes.NewBuffer(nil), filterRules: bytes.NewBuffer(nil), - netlinkHandle: NewNetLinkHandle(), + netlinkHandle: NewNetLinkHandle(isIPv6), ipset: ipset, nodePortAddresses: nodePortAddresses, networkInterfacer: utilproxy.RealNetwork{}, @@ -550,7 +566,7 @@ func cleanupIptablesLeftovers(ipt utiliptables.Interface) (encounteredError bool } } - // Flush and remove all of our chains. + // Flush and remove all of our chains. Flushing all chains before removing them also removes all links between chains first. for _, ch := range iptablesChains { if err := ipt.FlushChain(ch.table, ch.chain); err != nil { if !utiliptables.IsNotFoundError(err) { @@ -558,6 +574,10 @@ func cleanupIptablesLeftovers(ipt utiliptables.Interface) (encounteredError bool encounteredError = true } } + } + + // Remove all of our chains. + for _, ch := range iptablesChains { if err := ipt.DeleteChain(ch.table, ch.chain); err != nil { if !utiliptables.IsNotFoundError(err) { klog.Errorf("Error removing iptables rules in ipvs proxier: %v", err) @@ -584,7 +604,7 @@ func CleanupLeftovers(ipvs utilipvs.Interface, ipt utiliptables.Interface, ipset } } // Delete dummy interface created by ipvs Proxier. - nl := NewNetLinkHandle() + nl := NewNetLinkHandle(false) err := nl.DeleteDummyDevice(DefaultDummyDevice) if err != nil { klog.Errorf("Error deleting dummy device %s created by IPVS proxier: %v", DefaultDummyDevice, err) @@ -1008,11 +1028,9 @@ func (proxier *Proxier) syncProxyRules() { serv.Timeout = uint32(svcInfo.StickyMaxAgeSeconds) } if err := proxier.syncService(svcNameString, serv, true); err == nil { - // check if service need skip endpoints that not in same host as kube-proxy - onlyLocal := svcInfo.SessionAffinityType == v1.ServiceAffinityClientIP && svcInfo.OnlyNodeLocalEndpoints activeIPVSServices[serv.String()] = true activeBindAddrs[serv.Address.String()] = true - if err := proxier.syncEndpoint(svcName, onlyLocal, serv); err != nil { + if err := proxier.syncEndpoint(svcName, svcInfo.OnlyNodeLocalEndpoints, serv); err != nil { klog.Errorf("Failed to sync endpoint for service: %v, err: %v", serv, err) } } else { @@ -1190,7 +1208,15 @@ func (proxier *Proxier) syncProxyRules() { } proxier.portsMap = replacementPortsMap - // Clean up legacy IPVS services + // Get legacy bind address + // currentBindAddrs represents ip addresses bind to DefaultDummyDevice from the system + currentBindAddrs, err := proxier.netlinkHandle.ListBindAddress(DefaultDummyDevice) + if err != nil { + klog.Errorf("Failed to get bind address, err: %v", err) + } + legacyBindAddrs := proxier.getLegacyBindAddr(activeBindAddrs, currentBindAddrs) + + // Clean up legacy IPVS services and unbind addresses appliedSvcs, err := proxier.ipvs.GetVirtualServers() if err == nil { for _, appliedSvc := range appliedSvcs { @@ -1199,15 +1225,7 @@ func (proxier *Proxier) syncProxyRules() { } else { klog.Errorf("Failed to get ipvs service, err: %v", err) } - proxier.cleanLegacyService(activeIPVSServices, currentIPVSServices) - - // Clean up legacy bind address - // currentBindAddrs represents ip addresses bind to DefaultDummyDevice from the system - currentBindAddrs, err := proxier.netlinkHandle.ListBindAddress(DefaultDummyDevice) - if err != nil { - klog.Errorf("Failed to get bind address, err: %v", err) - } - proxier.cleanLegacyBindAddr(activeBindAddrs, currentBindAddrs) + proxier.cleanLegacyService(activeIPVSServices, currentIPVSServices, legacyBindAddrs) // Update healthz timestamp if proxier.healthzServer != nil { @@ -1605,29 +1623,38 @@ func (proxier *Proxier) syncEndpoint(svcPortName proxy.ServicePortName, onlyNode klog.V(5).Infof("Using graceful delete to delete: %v", uniqueRS) err = proxier.gracefuldeleteManager.GracefulDeleteRS(appliedVirtualServer, delDest) if err != nil { - klog.Errorf("Failed to delete destination: %v, error: %v", delDest, err) + klog.Errorf("Failed to delete destination: %v, error: %v", uniqueRS, err) continue } } return nil } -func (proxier *Proxier) cleanLegacyService(activeServices map[string]bool, currentServices map[string]*utilipvs.VirtualServer) { +func (proxier *Proxier) cleanLegacyService(activeServices map[string]bool, currentServices map[string]*utilipvs.VirtualServer, legacyBindAddrs map[string]bool) { for cs := range currentServices { svc := currentServices[cs] if _, ok := activeServices[cs]; !ok { // This service was not processed in the latest sync loop so before deleting it, - // make sure it does not fall within an excluded CIDR range. okayToDelete := true rsList, _ := proxier.ipvs.GetRealServers(svc) + + // If we still have real servers graceful termination is not done + if len(rsList) > 0 { + okayToDelete = false + } + // Applying graceful termination to all real servers for _, rs := range rsList { uniqueRS := GetUniqueRSName(svc, rs) - // if there are in terminating real server in this service, then handle it later + // If RS is already in the graceful termination list, no need to add it again if proxier.gracefuldeleteManager.InTerminationList(uniqueRS) { - okayToDelete = false - break + continue + } + klog.V(5).Infof("Using graceful delete to delete: %v", uniqueRS) + if err := proxier.gracefuldeleteManager.GracefulDeleteRS(svc, rs); err != nil { + klog.Errorf("Failed to delete destination: %v, error: %v", uniqueRS, err) } } + // make sure it does not fall within an excluded CIDR range. for _, excludedCIDR := range proxier.excludeCIDRs { // Any validation of this CIDR already should have occurred. _, n, _ := net.ParseCIDR(excludedCIDR) @@ -1637,26 +1664,38 @@ func (proxier *Proxier) cleanLegacyService(activeServices map[string]bool, curre } } if okayToDelete { + klog.V(4).Infof("Delete service %s", svc.String()) if err := proxier.ipvs.DeleteVirtualServer(svc); err != nil { - klog.Errorf("Failed to delete service, error: %v", err) + klog.Errorf("Failed to delete service %s, error: %v", svc.String(), err) + } + addr := svc.Address.String() + if _, ok := legacyBindAddrs[addr]; ok { + klog.V(4).Infof("Unbinding address %s", addr) + if err := proxier.netlinkHandle.UnbindAddress(addr, DefaultDummyDevice); err != nil { + klog.Errorf("Failed to unbind service addr %s from dummy interface %s: %v", addr, DefaultDummyDevice, err) + } else { + // In case we delete a multi-port service, avoid trying to unbind multiple times + delete(legacyBindAddrs, addr) + } } } } } } -func (proxier *Proxier) cleanLegacyBindAddr(activeBindAddrs map[string]bool, currentBindAddrs []string) { +func (proxier *Proxier) getLegacyBindAddr(activeBindAddrs map[string]bool, currentBindAddrs []string) map[string]bool { + legacyAddrs := make(map[string]bool) + isIpv6 := utilnet.IsIPv6(proxier.nodeIP) for _, addr := range currentBindAddrs { + addrIsIpv6 := utilnet.IsIPv6(net.ParseIP(addr)) + if addrIsIpv6 && !isIpv6 || !addrIsIpv6 && isIpv6 { + continue + } if _, ok := activeBindAddrs[addr]; !ok { - // This address was not processed in the latest sync loop - klog.V(4).Infof("Unbind addr %s", addr) - err := proxier.netlinkHandle.UnbindAddress(addr, DefaultDummyDevice) - // Ignore no such address error when try to unbind address - if err != nil { - klog.Errorf("Failed to unbind service addr %s from dummy interface %s: %v", addr, DefaultDummyDevice, err) - } + legacyAddrs[addr] = true } } + return legacyAddrs } // Join all words with spaces, terminate with newline and write to buff. diff --git a/pkg/proxy/ipvs/proxier_test.go b/pkg/proxy/ipvs/proxier_test.go index 921ff01f0d1..fe0da923592 100644 --- a/pkg/proxy/ipvs/proxier_test.go +++ b/pkg/proxy/ipvs/proxier_test.go @@ -23,7 +23,6 @@ import ( "reflect" "strings" "testing" - "time" "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -126,7 +125,7 @@ func (fakeSysctl *FakeSysctl) SetSysctl(sysctl string, newVal int) error { return nil } -func NewFakeProxier(ipt utiliptables.Interface, ipvs utilipvs.Interface, ipset utilipset.Interface, nodeIPs []net.IP) *Proxier { +func NewFakeProxier(ipt utiliptables.Interface, ipvs utilipvs.Interface, ipset utilipset.Interface, nodeIPs []net.IP, excludeCIDRs []string) *Proxier { fcmd := fakeexec.FakeCmd{ CombinedOutputScript: []fakeexec.FakeCombinedOutputAction{ func() ([]byte, error) { return []byte("dummy device have been created"), nil }, @@ -151,7 +150,7 @@ func NewFakeProxier(ipt utiliptables.Interface, ipvs utilipvs.Interface, ipset u serviceChanges: proxy.NewServiceChangeTracker(newServiceInfo, nil, nil), endpointsMap: make(proxy.EndpointsMap), endpointsChanges: proxy.NewEndpointChangeTracker(testHostname, nil, nil, nil), - excludeCIDRs: make([]string, 0), + excludeCIDRs: excludeCIDRs, iptables: ipt, ipvs: ipvs, ipset: ipset, @@ -228,7 +227,7 @@ func TestCleanupLeftovers(t *testing.T) { ipt := iptablestest.NewFake() ipvs := ipvstest.NewFake() ipset := ipsettest.NewFake(testIPSetVersion) - fp := NewFakeProxier(ipt, ipvs, ipset, nil) + fp := NewFakeProxier(ipt, ipvs, ipset, nil, nil) svcIP := "10.20.30.41" svcPort := 80 svcNodePort := 3001 @@ -418,7 +417,7 @@ func TestNodePortUDP(t *testing.T) { ipt := iptablestest.NewFake() ipvs := ipvstest.NewFake() ipset := ipsettest.NewFake(testIPSetVersion) - fp := NewFakeProxier(ipt, ipvs, ipset, []net.IP{nodeIP}) + fp := NewFakeProxier(ipt, ipvs, ipset, []net.IP{nodeIP}, nil) svcIP := "10.20.30.41" svcPort := 80 @@ -495,7 +494,7 @@ func TestNodePort(t *testing.T) { nodeIPv4 := net.ParseIP("100.101.102.103") nodeIPv6 := net.ParseIP("2001:db8::1:1") nodeIPs := sets.NewString(nodeIPv4.String(), nodeIPv6.String()) - fp := NewFakeProxier(ipt, ipvs, ipset, []net.IP{nodeIPv4, nodeIPv6}) + fp := NewFakeProxier(ipt, ipvs, ipset, []net.IP{nodeIPv4, nodeIPv6}, nil) svcIP := "10.20.30.41" svcPort := 80 svcNodePort := 3001 @@ -573,7 +572,7 @@ func TestNodePortNoEndpoint(t *testing.T) { ipvs := ipvstest.NewFake() ipset := ipsettest.NewFake(testIPSetVersion) nodeIP := net.ParseIP("100.101.102.103") - fp := NewFakeProxier(ipt, ipvs, ipset, []net.IP{nodeIP}) + fp := NewFakeProxier(ipt, ipvs, ipset, []net.IP{nodeIP}, nil) svcIP := "10.20.30.41" svcPort := 80 svcNodePort := 3001 @@ -628,7 +627,7 @@ func TestClusterIPNoEndpoint(t *testing.T) { ipt := iptablestest.NewFake() ipvs := ipvstest.NewFake() ipset := ipsettest.NewFake(testIPSetVersion) - fp := NewFakeProxier(ipt, ipvs, ipset, nil) + fp := NewFakeProxier(ipt, ipvs, ipset, nil, nil) svcIP := "10.20.30.41" svcPort := 80 svcPortName := proxy.ServicePortName{ @@ -672,7 +671,7 @@ func TestClusterIP(t *testing.T) { ipt := iptablestest.NewFake() ipvs := ipvstest.NewFake() ipset := ipsettest.NewFake(testIPSetVersion) - fp := NewFakeProxier(ipt, ipvs, ipset, nil) + fp := NewFakeProxier(ipt, ipvs, ipset, nil, nil) svcIPv4 := "10.20.30.41" svcPortV4 := 80 @@ -779,7 +778,7 @@ func TestExternalIPsNoEndpoint(t *testing.T) { ipt := iptablestest.NewFake() ipvs := ipvstest.NewFake() ipset := ipsettest.NewFake(testIPSetVersion) - fp := NewFakeProxier(ipt, ipvs, ipset, nil) + fp := NewFakeProxier(ipt, ipvs, ipset, nil, nil) svcIP := "10.20.30.41" svcPort := 80 svcExternalIPs := "50.60.70.81" @@ -834,7 +833,7 @@ func TestExternalIPs(t *testing.T) { ipt := iptablestest.NewFake() ipvs := ipvstest.NewFake() ipset := ipsettest.NewFake(testIPSetVersion) - fp := NewFakeProxier(ipt, ipvs, ipset, nil) + fp := NewFakeProxier(ipt, ipvs, ipset, nil, nil) svcIP := "10.20.30.41" svcPort := 80 svcExternalIPs := sets.NewString("50.60.70.81", "2012::51", "127.0.0.1") @@ -1267,18 +1266,32 @@ func TestOnlyLocalLoadBalancing(t *testing.T) { ) epIP := "10.180.0.1" + epIP1 := "10.180.1.1" + thisHostname := testHostname + otherHostname := "other-hostname" + makeEndpointsMap(fp, makeTestEndpoints(svcPortName.Namespace, svcPortName.Name, func(ept *v1.Endpoints) { - ept.Subsets = []v1.EndpointSubset{{ - Addresses: []v1.EndpointAddress{{ - IP: epIP, - NodeName: nil, - }}, - Ports: []v1.EndpointPort{{ - Name: svcPortName.Port, - Port: int32(svcPort), - }}, - }} + ept.Subsets = []v1.EndpointSubset{ + { // **local** endpoint address, should be added as RS + Addresses: []v1.EndpointAddress{{ + IP: epIP, + NodeName: &thisHostname, + }}, + Ports: []v1.EndpointPort{{ + Name: svcPortName.Port, + Port: int32(svcPort), + }}}, + { // **remote** endpoint address, should not be added as RS + Addresses: []v1.EndpointAddress{{ + IP: epIP1, + NodeName: &otherHostname, + }}, + Ports: []v1.EndpointPort{{ + Name: svcPortName.Port, + Port: int32(svcPort), + }}, + }} }), ) @@ -1338,7 +1351,7 @@ func TestBuildServiceMapAddRemove(t *testing.T) { ipt := iptablestest.NewFake() ipvs := ipvstest.NewFake() ipset := ipsettest.NewFake(testIPSetVersion) - fp := NewFakeProxier(ipt, ipvs, ipset, nil) + fp := NewFakeProxier(ipt, ipvs, ipset, nil, nil) services := []*v1.Service{ makeTestService("somewhere-else", "cluster-ip", func(svc *v1.Service) { @@ -1448,7 +1461,7 @@ func TestBuildServiceMapServiceHeadless(t *testing.T) { ipt := iptablestest.NewFake() ipvs := ipvstest.NewFake() ipset := ipsettest.NewFake(testIPSetVersion) - fp := NewFakeProxier(ipt, ipvs, ipset, nil) + fp := NewFakeProxier(ipt, ipvs, ipset, nil, nil) makeServiceMap(fp, makeTestService("somewhere-else", "headless", func(svc *v1.Service) { @@ -1487,7 +1500,7 @@ func TestBuildServiceMapServiceTypeExternalName(t *testing.T) { ipt := iptablestest.NewFake() ipvs := ipvstest.NewFake() ipset := ipsettest.NewFake(testIPSetVersion) - fp := NewFakeProxier(ipt, ipvs, ipset, nil) + fp := NewFakeProxier(ipt, ipvs, ipset, nil, nil) makeServiceMap(fp, makeTestService("somewhere-else", "external-name", func(svc *v1.Service) { @@ -1515,7 +1528,7 @@ func TestBuildServiceMapServiceUpdate(t *testing.T) { ipt := iptablestest.NewFake() ipvs := ipvstest.NewFake() ipset := ipsettest.NewFake(testIPSetVersion) - fp := NewFakeProxier(ipt, ipvs, ipset, nil) + fp := NewFakeProxier(ipt, ipvs, ipset, nil, nil) servicev1 := makeTestService("somewhere", "some-service", func(svc *v1.Service) { svc.Spec.Type = v1.ServiceTypeClusterIP @@ -1599,7 +1612,7 @@ func TestSessionAffinity(t *testing.T) { ipvs := ipvstest.NewFake() ipset := ipsettest.NewFake(testIPSetVersion) nodeIP := net.ParseIP("100.101.102.103") - fp := NewFakeProxier(ipt, ipvs, ipset, []net.IP{nodeIP}) + fp := NewFakeProxier(ipt, ipvs, ipset, []net.IP{nodeIP}, nil) svcIP := "10.20.30.41" svcPort := 80 svcNodePort := 3001 @@ -2462,7 +2475,7 @@ func Test_updateEndpointsMap(t *testing.T) { ipt := iptablestest.NewFake() ipvs := ipvstest.NewFake() ipset := ipsettest.NewFake(testIPSetVersion) - fp := NewFakeProxier(ipt, ipvs, ipset, nil) + fp := NewFakeProxier(ipt, ipvs, ipset, nil, nil) fp.hostname = nodeName // First check that after adding all previous versions of endpoints, @@ -2706,7 +2719,7 @@ func Test_syncService(t *testing.T) { ipt := iptablestest.NewFake() ipvs := ipvstest.NewFake() ipset := ipsettest.NewFake(testIPSetVersion) - proxier := NewFakeProxier(ipt, ipvs, ipset, nil) + proxier := NewFakeProxier(ipt, ipvs, ipset, nil, nil) proxier.netlinkHandle.EnsureDummyDevice(DefaultDummyDevice) if testCases[i].oldVirtualServer != nil { @@ -2736,7 +2749,7 @@ func buildFakeProxier() (*iptablestest.FakeIPTables, *Proxier) { ipt := iptablestest.NewFake() ipvs := ipvstest.NewFake() ipset := ipsettest.NewFake(testIPSetVersion) - return ipt, NewFakeProxier(ipt, ipvs, ipset, nil) + return ipt, NewFakeProxier(ipt, ipvs, ipset, nil, nil) } func hasJump(rules []iptablestest.Rule, destChain, ipSet string) bool { @@ -2806,33 +2819,10 @@ func checkIPVS(t *testing.T, fp *Proxier, vs *netlinktest.ExpectedVirtualServer) } func TestCleanLegacyService(t *testing.T) { - execer := exec.New() ipt := iptablestest.NewFake() ipvs := ipvstest.NewFake() ipset := ipsettest.NewFake(testIPSetVersion) - excludeCIDRs := []string{"3.3.3.0/24", "4.4.4.0/24"} - proxier, err := NewProxier( - ipt, - ipvs, - ipset, - NewFakeSysctl(), - execer, - 250*time.Millisecond, - 100*time.Millisecond, - excludeCIDRs, - false, - 0, - "10.0.0.0/24", - testHostname, - net.ParseIP("127.0.0.1"), - nil, - nil, - DefaultScheduler, - make([]string, 0), - ) - if err != nil { - t.Errorf("Unexpected error: %v", err) - } + fp := NewFakeProxier(ipt, ipvs, ipset, nil, []string{"3.3.3.0/24", "4.4.4.0/24"}) // All ipvs services that were processed in the latest sync loop. activeServices := map[string]bool{"ipvs0": true, "ipvs1": true} @@ -2888,15 +2878,23 @@ func TestCleanLegacyService(t *testing.T) { }, } for v := range currentServices { - proxier.ipvs.AddVirtualServer(currentServices[v]) + fp.ipvs.AddVirtualServer(currentServices[v]) } - proxier.cleanLegacyService(activeServices, currentServices) + + fp.netlinkHandle.EnsureDummyDevice(DefaultDummyDevice) + activeBindAddrs := map[string]bool{"1.1.1.1": true, "2.2.2.2": true, "3.3.3.3": true, "4.4.4.4": true} + // This is ipv4-only so ipv6 addresses should be ignored + currentBindAddrs := []string{"1.1.1.1", "2.2.2.2", "3.3.3.3", "4.4.4.4", "5.5.5.5", "6.6.6.6", "fd80::1:2:3", "fd80::1:2:4"} + for i := range currentBindAddrs { + fp.netlinkHandle.EnsureAddressBind(currentBindAddrs[i], DefaultDummyDevice) + } + + fp.cleanLegacyService(activeServices, currentServices, map[string]bool{"5.5.5.5": true, "6.6.6.6": true}) // ipvs4 and ipvs5 should have been cleaned. - remainingVirtualServers, _ := proxier.ipvs.GetVirtualServers() + remainingVirtualServers, _ := fp.ipvs.GetVirtualServers() if len(remainingVirtualServers) != 4 { t.Errorf("Expected number of remaining IPVS services after cleanup to be %v. Got %v", 4, len(remainingVirtualServers)) } - for _, vs := range remainingVirtualServers { // Checking that ipvs4 and ipvs5 were removed. if vs.Port == 57 { @@ -2906,47 +2904,138 @@ func TestCleanLegacyService(t *testing.T) { t.Errorf("Expected ipvs5 to be removed after cleanup. It still remains") } } -} - -func TestCleanLegacyBindAddr(t *testing.T) { - ipt := iptablestest.NewFake() - ipvs := ipvstest.NewFake() - ipset := ipsettest.NewFake(testIPSetVersion) - fp := NewFakeProxier(ipt, ipvs, ipset, nil) - - // All ipvs service addresses that were bound to ipvs0 in the latest sync loop. - activeBindAddrs := map[string]bool{"1.2.3.4": true, "1002:ab8::2:1": true} - // All service addresses that were bound to ipvs0 in system - currentBindAddrs := []string{"1.2.3.4", "1.2.3.5", "1.2.3.6", "1002:ab8::2:1", "1002:ab8::2:2"} - - fp.netlinkHandle.EnsureDummyDevice(DefaultDummyDevice) - - for i := range currentBindAddrs { - fp.netlinkHandle.EnsureAddressBind(currentBindAddrs[i], DefaultDummyDevice) - } - fp.cleanLegacyBindAddr(activeBindAddrs, currentBindAddrs) + // Addresses 5.5.5.5 and 6.6.6.6 should not be bound any more, but the ipv6 addresses should remain remainingAddrs, _ := fp.netlinkHandle.ListBindAddress(DefaultDummyDevice) - // should only remain "1.2.3.4" and "1002:ab8::2:1" - if len(remainingAddrs) != 2 { - t.Errorf("Expected number of remaining bound addrs after cleanup to be %v. Got %v", 2, len(remainingAddrs)) + if len(remainingAddrs) != 6 { + t.Errorf("Expected number of remaining bound addrs after cleanup to be %v. Got %v", 6, len(remainingAddrs)) } - - // check that address "1.2.3.4" and "1002:ab8::2:1" remain + // check that address "1.1.1.1", "2.2.2.2", "3.3.3.3", "4.4.4.4" are bound, ignore ipv6 addresses remainingAddrsMap := make(map[string]bool) - for i := range remainingAddrs { - remainingAddrsMap[remainingAddrs[i]] = true + for _, a := range remainingAddrs { + if net.ParseIP(a).To4() == nil { + continue + } + remainingAddrsMap[a] = true } if !reflect.DeepEqual(activeBindAddrs, remainingAddrsMap) { t.Errorf("Expected remainingAddrsMap %v, got %v", activeBindAddrs, remainingAddrsMap) } + +} + +func TestCleanLegacyService6(t *testing.T) { + ipt := iptablestest.NewFake() + ipvs := ipvstest.NewFake() + ipset := ipsettest.NewFake(testIPSetVersion) + fp := NewFakeProxier(ipt, ipvs, ipset, nil, []string{"3000::/64", "4000::/64"}) + fp.nodeIP = net.ParseIP("::1") + + // All ipvs services that were processed in the latest sync loop. + activeServices := map[string]bool{"ipvs0": true, "ipvs1": true} + // All ipvs services in the system. + currentServices := map[string]*utilipvs.VirtualServer{ + // Created by kube-proxy. + "ipvs0": { + Address: net.ParseIP("1000::1"), + Protocol: string(v1.ProtocolUDP), + Port: 53, + Scheduler: "rr", + Flags: utilipvs.FlagHashed, + }, + // Created by kube-proxy. + "ipvs1": { + Address: net.ParseIP("1000::2"), + Protocol: string(v1.ProtocolUDP), + Port: 54, + Scheduler: "rr", + Flags: utilipvs.FlagHashed, + }, + // Created by an external party. + "ipvs2": { + Address: net.ParseIP("3000::1"), + Protocol: string(v1.ProtocolUDP), + Port: 55, + Scheduler: "rr", + Flags: utilipvs.FlagHashed, + }, + // Created by an external party. + "ipvs3": { + Address: net.ParseIP("4000::1"), + Protocol: string(v1.ProtocolUDP), + Port: 56, + Scheduler: "rr", + Flags: utilipvs.FlagHashed, + }, + // Created by an external party. + "ipvs4": { + Address: net.ParseIP("5000::1"), + Protocol: string(v1.ProtocolUDP), + Port: 57, + Scheduler: "rr", + Flags: utilipvs.FlagHashed, + }, + // Created by kube-proxy, but now stale. + "ipvs5": { + Address: net.ParseIP("1000::6"), + Protocol: string(v1.ProtocolUDP), + Port: 58, + Scheduler: "rr", + Flags: utilipvs.FlagHashed, + }, + } + for v := range currentServices { + fp.ipvs.AddVirtualServer(currentServices[v]) + } + + fp.netlinkHandle.EnsureDummyDevice(DefaultDummyDevice) + activeBindAddrs := map[string]bool{"1000::1": true, "1000::2": true, "3000::1": true, "4000::1": true} + // This is ipv6-only so ipv4 addresses should be ignored + currentBindAddrs := []string{"1000::1", "1000::2", "3000::1", "4000::1", "5000::1", "1000::6", "1.1.1.1", "2.2.2.2"} + for i := range currentBindAddrs { + fp.netlinkHandle.EnsureAddressBind(currentBindAddrs[i], DefaultDummyDevice) + } + + fp.cleanLegacyService(activeServices, currentServices, map[string]bool{"5000::1": true, "1000::6": true}) + // ipvs4 and ipvs5 should have been cleaned. + remainingVirtualServers, _ := fp.ipvs.GetVirtualServers() + if len(remainingVirtualServers) != 4 { + t.Errorf("Expected number of remaining IPVS services after cleanup to be %v. Got %v", 4, len(remainingVirtualServers)) + } + for _, vs := range remainingVirtualServers { + // Checking that ipvs4 and ipvs5 were removed. + if vs.Port == 57 { + t.Errorf("Expected ipvs4 to be removed after cleanup. It still remains") + } + if vs.Port == 58 { + t.Errorf("Expected ipvs5 to be removed after cleanup. It still remains") + } + } + + // Addresses 5000::1 and 1000::6 should not be bound any more, but the ipv4 addresses should remain + remainingAddrs, _ := fp.netlinkHandle.ListBindAddress(DefaultDummyDevice) + if len(remainingAddrs) != 6 { + t.Errorf("Expected number of remaining bound addrs after cleanup to be %v. Got %v", 6, len(remainingAddrs)) + } + // check that address "1000::1", "1000::2", "3000::1", "4000::1" are still bound, ignore ipv4 addresses + remainingAddrsMap := make(map[string]bool) + for _, a := range remainingAddrs { + if net.ParseIP(a).To4() != nil { + continue + } + remainingAddrsMap[a] = true + } + if !reflect.DeepEqual(activeBindAddrs, remainingAddrsMap) { + t.Errorf("Expected remainingAddrsMap %v, got %v", activeBindAddrs, remainingAddrsMap) + } + } func TestMultiPortServiceBindAddr(t *testing.T) { ipt := iptablestest.NewFake() ipvs := ipvstest.NewFake() ipset := ipsettest.NewFake(testIPSetVersion) - fp := NewFakeProxier(ipt, ipvs, ipset, nil) + fp := NewFakeProxier(ipt, ipvs, ipset, nil, nil) service1 := makeTestService("ns1", "svc1", func(svc *v1.Service) { svc.Spec.Type = v1.ServiceTypeClusterIP diff --git a/pkg/proxy/service.go b/pkg/proxy/service.go index 8386e62c0e2..307c3d1b3bc 100644 --- a/pkg/proxy/service.go +++ b/pkg/proxy/service.go @@ -74,6 +74,11 @@ func (info *BaseServiceInfo) GetHealthCheckNodePort() int { return info.HealthCheckNodePort } +// GetNodePort is part of the ServicePort interface. +func (info *BaseServiceInfo) GetNodePort() int { + return info.NodePort +} + func (sct *ServiceChangeTracker) newBaseServiceInfo(port *v1.ServicePort, service *v1.Service) *BaseServiceInfo { onlyNodeLocalEndpoints := false if apiservice.RequestsOnlyLocalTraffic(service) { diff --git a/pkg/proxy/types.go b/pkg/proxy/types.go index f38937068c8..f77f9ed0f36 100644 --- a/pkg/proxy/types.go +++ b/pkg/proxy/types.go @@ -54,6 +54,8 @@ type ServicePort interface { GetProtocol() v1.Protocol // GetHealthCheckNodePort returns service health check node port if present. If return 0, it means not present. GetHealthCheckNodePort() int + // GetNodePort returns a service Node port if present. If return 0, it means not present. + GetNodePort() int } // Endpoint in an interface which abstracts information about an endpoint. diff --git a/pkg/proxy/util/utils.go b/pkg/proxy/util/utils.go index f1db309a941..2c1408da43b 100644 --- a/pkg/proxy/util/utils.go +++ b/pkg/proxy/util/utils.go @@ -17,6 +17,8 @@ limitations under the License. package util import ( + "context" + "errors" "fmt" "net" @@ -35,6 +37,11 @@ const ( IPv6ZeroCIDR = "::/0" ) +var ( + ErrAddressNotAllowed = errors.New("address not allowed") + ErrNoAddresses = errors.New("No addresses for hostname") +) + func IsZeroCIDR(cidr string) bool { if cidr == IPv4ZeroCIDR || cidr == IPv6ZeroCIDR { return true @@ -42,6 +49,46 @@ func IsZeroCIDR(cidr string) bool { return false } +// IsProxyableIP checks if a given IP address is permitted to be proxied +func IsProxyableIP(ip string) error { + netIP := net.ParseIP(ip) + if netIP == nil { + return ErrAddressNotAllowed + } + return isProxyableIP(netIP) +} + +func isProxyableIP(ip net.IP) error { + if ip.IsLoopback() || ip.IsLinkLocalUnicast() || ip.IsLinkLocalMulticast() || ip.IsInterfaceLocalMulticast() { + return ErrAddressNotAllowed + } + return nil +} + +// Resolver is an interface for net.Resolver +type Resolver interface { + LookupIPAddr(ctx context.Context, host string) ([]net.IPAddr, error) +} + +// IsProxyableHostname checks if the IP addresses for a given hostname are permitted to be proxied +func IsProxyableHostname(ctx context.Context, resolv Resolver, hostname string) error { + resp, err := resolv.LookupIPAddr(ctx, hostname) + if err != nil { + return err + } + + if len(resp) == 0 { + return ErrNoAddresses + } + + for _, host := range resp { + if err := isProxyableIP(host.IP); err != nil { + return err + } + } + return nil +} + func IsLocalIP(ip string) (bool, error) { addrs, err := net.InterfaceAddrs() if err != nil { diff --git a/pkg/proxy/util/utils_test.go b/pkg/proxy/util/utils_test.go index 0f4c19f2e8b..891a3520f1c 100644 --- a/pkg/proxy/util/utils_test.go +++ b/pkg/proxy/util/utils_test.go @@ -17,6 +17,7 @@ limitations under the License. package util import ( + "context" "net" "testing" @@ -27,6 +28,74 @@ import ( fake "k8s.io/kubernetes/pkg/proxy/util/testing" ) +func TestIsProxyableIP(t *testing.T) { + testCases := []struct { + ip string + want error + }{ + {"127.0.0.1", ErrAddressNotAllowed}, + {"127.0.0.2", ErrAddressNotAllowed}, + {"169.254.169.254", ErrAddressNotAllowed}, + {"169.254.1.1", ErrAddressNotAllowed}, + {"224.0.0.0", ErrAddressNotAllowed}, + {"10.0.0.1", nil}, + {"192.168.0.1", nil}, + {"172.16.0.1", nil}, + {"8.8.8.8", nil}, + {"::1", ErrAddressNotAllowed}, + {"fe80::", ErrAddressNotAllowed}, + {"ff02::", ErrAddressNotAllowed}, + {"ff01::", ErrAddressNotAllowed}, + {"2600::", nil}, + {"1", ErrAddressNotAllowed}, + {"", ErrAddressNotAllowed}, + } + + for i := range testCases { + got := IsProxyableIP(testCases[i].ip) + if testCases[i].want != got { + t.Errorf("case %d: expected %v, got %v", i, testCases[i].want, got) + } + } +} + +type dummyResolver struct { + ips []string + err error +} + +func (r *dummyResolver) LookupIPAddr(ctx context.Context, host string) ([]net.IPAddr, error) { + if r.err != nil { + return nil, r.err + } + resp := []net.IPAddr{} + for _, ipString := range r.ips { + resp = append(resp, net.IPAddr{IP: net.ParseIP(ipString)}) + } + return resp, nil +} + +func TestIsProxyableHostname(t *testing.T) { + testCases := []struct { + hostname string + ips []string + want error + }{ + {"k8s.io", []string{}, ErrNoAddresses}, + {"k8s.io", []string{"8.8.8.8"}, nil}, + {"k8s.io", []string{"169.254.169.254"}, ErrAddressNotAllowed}, + {"k8s.io", []string{"127.0.0.1", "8.8.8.8"}, ErrAddressNotAllowed}, + } + + for i := range testCases { + resolv := dummyResolver{ips: testCases[i].ips} + got := IsProxyableHostname(context.Background(), &resolv, testCases[i].hostname) + if testCases[i].want != got { + t.Errorf("case %d: expected %v, got %v", i, testCases[i].want, got) + } + } +} + func TestShouldSkipService(t *testing.T) { testCases := []struct { service *v1.Service diff --git a/pkg/registry/apps/daemonset/strategy.go b/pkg/registry/apps/daemonset/strategy.go index f9b89bb552e..08ffd63f730 100644 --- a/pkg/registry/apps/daemonset/strategy.go +++ b/pkg/registry/apps/daemonset/strategy.go @@ -44,19 +44,20 @@ type daemonSetStrategy struct { // Strategy is the default logic that applies when creating and updating DaemonSet objects. var Strategy = daemonSetStrategy{legacyscheme.Scheme, names.SimpleNameGenerator} -// DefaultGarbageCollectionPolicy returns OrphanDependents by default. For apps/v1, returns DeleteDependents. +// DefaultGarbageCollectionPolicy returns OrphanDependents for extensions/v1beta1 and apps/v1beta2 for backwards compatibility, +// and DeleteDependents for all other versions. func (daemonSetStrategy) DefaultGarbageCollectionPolicy(ctx context.Context) rest.GarbageCollectionPolicy { + var groupVersion schema.GroupVersion if requestInfo, found := genericapirequest.RequestInfoFrom(ctx); found { - groupVersion := schema.GroupVersion{Group: requestInfo.APIGroup, Version: requestInfo.APIVersion} - switch groupVersion { - case extensionsv1beta1.SchemeGroupVersion, appsv1beta2.SchemeGroupVersion: - // for back compatibility - return rest.OrphanDependents - default: - return rest.DeleteDependents - } + groupVersion = schema.GroupVersion{Group: requestInfo.APIGroup, Version: requestInfo.APIVersion} + } + switch groupVersion { + case extensionsv1beta1.SchemeGroupVersion, appsv1beta2.SchemeGroupVersion: + // for back compatibility + return rest.OrphanDependents + default: + return rest.DeleteDependents } - return rest.OrphanDependents } // NamespaceScoped returns true because all DaemonSets need to be within a namespace. @@ -74,7 +75,7 @@ func (daemonSetStrategy) PrepareForCreate(ctx context.Context, obj runtime.Objec daemonSet.Spec.TemplateGeneration = 1 } - pod.DropDisabledAlphaFields(&daemonSet.Spec.Template.Spec) + pod.DropDisabledFields(&daemonSet.Spec.Template.Spec, nil) } // PrepareForUpdate clears fields that are not allowed to be set by end users on update. @@ -82,8 +83,7 @@ func (daemonSetStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime. newDaemonSet := obj.(*apps.DaemonSet) oldDaemonSet := old.(*apps.DaemonSet) - pod.DropDisabledAlphaFields(&newDaemonSet.Spec.Template.Spec) - pod.DropDisabledAlphaFields(&oldDaemonSet.Spec.Template.Spec) + pod.DropDisabledFields(&newDaemonSet.Spec.Template.Spec, &oldDaemonSet.Spec.Template.Spec) // update is not allowed to set status newDaemonSet.Status = oldDaemonSet.Status diff --git a/pkg/registry/apps/daemonset/strategy_test.go b/pkg/registry/apps/daemonset/strategy_test.go index eb932cbf6ff..f48b3fd7e26 100644 --- a/pkg/registry/apps/daemonset/strategy_test.go +++ b/pkg/registry/apps/daemonset/strategy_test.go @@ -72,7 +72,7 @@ func TestDaemonsetDefaultGarbageCollectionPolicy(t *testing.T) { false, }, { - expectedGCPolicy: rest.OrphanDependents, + expectedGCPolicy: rest.DeleteDependents, isNilRequestInfo: true, }, } diff --git a/pkg/registry/apps/deployment/storage/storage.go b/pkg/registry/apps/deployment/storage/storage.go index 5ee1fa2690d..bf456b74ef4 100644 --- a/pkg/registry/apps/deployment/storage/storage.go +++ b/pkg/registry/apps/deployment/storage/storage.go @@ -166,6 +166,12 @@ func (r *RollbackREST) Create(ctx context.Context, obj runtime.Object, createVal return nil, errors.NewBadRequest(fmt.Sprintf("not a DeploymentRollback: %#v", obj)) } + if createValidation != nil { + if err := createValidation(obj.DeepCopyObject()); err != nil { + return nil, err + } + } + if errs := appsvalidation.ValidateDeploymentRollback(rollback); len(errs) != 0 { return nil, errors.NewInvalid(apps.Kind("DeploymentRollback"), rollback.Name, errs) } diff --git a/pkg/registry/apps/deployment/storage/storage_test.go b/pkg/registry/apps/deployment/storage/storage_test.go index 26bcdc0acc6..53f761bc66d 100644 --- a/pkg/registry/apps/deployment/storage/storage_test.go +++ b/pkg/registry/apps/deployment/storage/storage_test.go @@ -17,6 +17,7 @@ limitations under the License. package storage import ( + "fmt" "net/http" "reflect" "testing" @@ -374,6 +375,33 @@ func TestEtcdCreateDeploymentRollback(t *testing.T) { } } +func TestCreateDeploymentRollbackValidation(t *testing.T) { + storage, server := newStorage(t) + rollbackStorage := storage.Rollback + rollback := apps.DeploymentRollback{ + Name: name, + UpdatedAnnotations: map[string]string{}, + RollbackTo: apps.RollbackConfig{Revision: 1}, + } + + ctx := genericapirequest.WithNamespace(genericapirequest.NewContext(), namespace) + + if _, err := storage.Deployment.Create(ctx, validNewDeployment(), rest.ValidateAllObjectFunc, &metav1.CreateOptions{}); err != nil { + t.Fatalf("Unexpected error: %v", err) + } + + validationError := fmt.Errorf("admission deny") + alwaysDenyValidationFunc := func(obj runtime.Object) error { return validationError } + _, err := rollbackStorage.Create(ctx, &rollback, alwaysDenyValidationFunc, &metav1.CreateOptions{}) + + if err == nil || validationError != err { + t.Errorf("expected: %v, got: %v", validationError, err) + } + + storage.Deployment.Store.DestroyFunc() + server.Terminate(t) +} + // Ensure that when a deploymentRollback is created for a deployment that has already been deleted // by the API server, API server returns not-found error. func TestEtcdCreateDeploymentRollbackNoDeployment(t *testing.T) { diff --git a/pkg/registry/apps/deployment/strategy.go b/pkg/registry/apps/deployment/strategy.go index e9d593d838b..cccd62116f3 100644 --- a/pkg/registry/apps/deployment/strategy.go +++ b/pkg/registry/apps/deployment/strategy.go @@ -46,19 +46,20 @@ type deploymentStrategy struct { // objects via the REST API. var Strategy = deploymentStrategy{legacyscheme.Scheme, names.SimpleNameGenerator} -// DefaultGarbageCollectionPolicy returns OrphanDependents by default. For apps/v1, returns DeleteDependents. +// DefaultGarbageCollectionPolicy returns OrphanDependents for extensions/v1beta1, apps/v1beta1, and apps/v1beta2 for backwards compatibility, +// and DeleteDependents for all other versions. func (deploymentStrategy) DefaultGarbageCollectionPolicy(ctx context.Context) rest.GarbageCollectionPolicy { + var groupVersion schema.GroupVersion if requestInfo, found := genericapirequest.RequestInfoFrom(ctx); found { - groupVersion := schema.GroupVersion{Group: requestInfo.APIGroup, Version: requestInfo.APIVersion} - switch groupVersion { - case extensionsv1beta1.SchemeGroupVersion, appsv1beta1.SchemeGroupVersion, appsv1beta2.SchemeGroupVersion: - // for back compatibility - return rest.OrphanDependents - default: - return rest.DeleteDependents - } + groupVersion = schema.GroupVersion{Group: requestInfo.APIGroup, Version: requestInfo.APIVersion} + } + switch groupVersion { + case extensionsv1beta1.SchemeGroupVersion, appsv1beta1.SchemeGroupVersion, appsv1beta2.SchemeGroupVersion: + // for back compatibility + return rest.OrphanDependents + default: + return rest.DeleteDependents } - return rest.OrphanDependents } // NamespaceScoped is true for deployment. @@ -72,7 +73,7 @@ func (deploymentStrategy) PrepareForCreate(ctx context.Context, obj runtime.Obje deployment.Status = apps.DeploymentStatus{} deployment.Generation = 1 - pod.DropDisabledAlphaFields(&deployment.Spec.Template.Spec) + pod.DropDisabledFields(&deployment.Spec.Template.Spec, nil) } // Validate validates a new deployment. @@ -96,8 +97,7 @@ func (deploymentStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime oldDeployment := old.(*apps.Deployment) newDeployment.Status = oldDeployment.Status - pod.DropDisabledAlphaFields(&newDeployment.Spec.Template.Spec) - pod.DropDisabledAlphaFields(&oldDeployment.Spec.Template.Spec) + pod.DropDisabledFields(&newDeployment.Spec.Template.Spec, &oldDeployment.Spec.Template.Spec) // Spec updates bump the generation so that we can distinguish between // scaling events and template changes, annotation updates bump the generation diff --git a/pkg/registry/apps/deployment/strategy_test.go b/pkg/registry/apps/deployment/strategy_test.go index a7a68766b41..3376993605a 100644 --- a/pkg/registry/apps/deployment/strategy_test.go +++ b/pkg/registry/apps/deployment/strategy_test.go @@ -231,7 +231,7 @@ func TestDeploymentDefaultGarbageCollectionPolicy(t *testing.T) { false, }, { - expectedGCPolicy: rest.OrphanDependents, + expectedGCPolicy: rest.DeleteDependents, isNilRequestInfo: true, }, } diff --git a/pkg/registry/apps/replicaset/strategy.go b/pkg/registry/apps/replicaset/strategy.go index 592c6893dea..37bf07eaa3d 100644 --- a/pkg/registry/apps/replicaset/strategy.go +++ b/pkg/registry/apps/replicaset/strategy.go @@ -52,19 +52,20 @@ type rsStrategy struct { // Strategy is the default logic that applies when creating and updating ReplicaSet objects. var Strategy = rsStrategy{legacyscheme.Scheme, names.SimpleNameGenerator} -// DefaultGarbageCollectionPolicy returns OrphanDependents by default. For apps/v1, returns DeleteDependents. +// DefaultGarbageCollectionPolicy returns OrphanDependents for extensions/v1beta1 and apps/v1beta2 for backwards compatibility, +// and DeleteDependents for all other versions. func (rsStrategy) DefaultGarbageCollectionPolicy(ctx context.Context) rest.GarbageCollectionPolicy { + var groupVersion schema.GroupVersion if requestInfo, found := genericapirequest.RequestInfoFrom(ctx); found { - groupVersion := schema.GroupVersion{Group: requestInfo.APIGroup, Version: requestInfo.APIVersion} - switch groupVersion { - case extensionsv1beta1.SchemeGroupVersion, appsv1beta2.SchemeGroupVersion: - // for back compatibility - return rest.OrphanDependents - default: - return rest.DeleteDependents - } + groupVersion = schema.GroupVersion{Group: requestInfo.APIGroup, Version: requestInfo.APIVersion} + } + switch groupVersion { + case extensionsv1beta1.SchemeGroupVersion, appsv1beta2.SchemeGroupVersion: + // for back compatibility + return rest.OrphanDependents + default: + return rest.DeleteDependents } - return rest.OrphanDependents } // NamespaceScoped returns true because all ReplicaSets need to be within a namespace. @@ -79,7 +80,7 @@ func (rsStrategy) PrepareForCreate(ctx context.Context, obj runtime.Object) { rs.Generation = 1 - pod.DropDisabledAlphaFields(&rs.Spec.Template.Spec) + pod.DropDisabledFields(&rs.Spec.Template.Spec, nil) } // PrepareForUpdate clears fields that are not allowed to be set by end users on update. @@ -89,8 +90,7 @@ func (rsStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) // update is not allowed to set status newRS.Status = oldRS.Status - pod.DropDisabledAlphaFields(&newRS.Spec.Template.Spec) - pod.DropDisabledAlphaFields(&oldRS.Spec.Template.Spec) + pod.DropDisabledFields(&newRS.Spec.Template.Spec, &oldRS.Spec.Template.Spec) // Any changes to the spec increment the generation number, any changes to the // status should reflect the generation number of the corresponding object. We push diff --git a/pkg/registry/apps/replicaset/strategy_test.go b/pkg/registry/apps/replicaset/strategy_test.go index 6023fe0aa1c..2c2994af768 100644 --- a/pkg/registry/apps/replicaset/strategy_test.go +++ b/pkg/registry/apps/replicaset/strategy_test.go @@ -266,7 +266,7 @@ func TestReplicasetDefaultGarbageCollectionPolicy(t *testing.T) { false, }, { - expectedGCPolicy: rest.OrphanDependents, + expectedGCPolicy: rest.DeleteDependents, isNilRequestInfo: true, }, } diff --git a/pkg/registry/apps/statefulset/strategy.go b/pkg/registry/apps/statefulset/strategy.go index cbf584933e3..1a8608900bc 100644 --- a/pkg/registry/apps/statefulset/strategy.go +++ b/pkg/registry/apps/statefulset/strategy.go @@ -43,19 +43,20 @@ type statefulSetStrategy struct { // Strategy is the default logic that applies when creating and updating Replication StatefulSet objects. var Strategy = statefulSetStrategy{legacyscheme.Scheme, names.SimpleNameGenerator} -// DefaultGarbageCollectionPolicy returns OrphanDependents by default. For apps/v1, returns DeleteDependents. +// DefaultGarbageCollectionPolicy returns OrphanDependents for apps/v1beta1 and apps/v1beta2 for backwards compatibility, +// and DeleteDependents for all other versions. func (statefulSetStrategy) DefaultGarbageCollectionPolicy(ctx context.Context) rest.GarbageCollectionPolicy { + var groupVersion schema.GroupVersion if requestInfo, found := genericapirequest.RequestInfoFrom(ctx); found { - groupVersion := schema.GroupVersion{Group: requestInfo.APIGroup, Version: requestInfo.APIVersion} - switch groupVersion { - case appsv1beta1.SchemeGroupVersion, appsv1beta2.SchemeGroupVersion: - // for back compatibility - return rest.OrphanDependents - default: - return rest.DeleteDependents - } + groupVersion = schema.GroupVersion{Group: requestInfo.APIGroup, Version: requestInfo.APIVersion} + } + switch groupVersion { + case appsv1beta1.SchemeGroupVersion, appsv1beta2.SchemeGroupVersion: + // for back compatibility + return rest.OrphanDependents + default: + return rest.DeleteDependents } - return rest.OrphanDependents } // NamespaceScoped returns true because all StatefulSet' need to be within a namespace. @@ -71,7 +72,7 @@ func (statefulSetStrategy) PrepareForCreate(ctx context.Context, obj runtime.Obj statefulSet.Generation = 1 - pod.DropDisabledAlphaFields(&statefulSet.Spec.Template.Spec) + pod.DropDisabledFields(&statefulSet.Spec.Template.Spec, nil) } // PrepareForUpdate clears fields that are not allowed to be set by end users on update. @@ -81,8 +82,7 @@ func (statefulSetStrategy) PrepareForUpdate(ctx context.Context, obj, old runtim // Update is not allowed to set status newStatefulSet.Status = oldStatefulSet.Status - pod.DropDisabledAlphaFields(&newStatefulSet.Spec.Template.Spec) - pod.DropDisabledAlphaFields(&oldStatefulSet.Spec.Template.Spec) + pod.DropDisabledFields(&newStatefulSet.Spec.Template.Spec, &oldStatefulSet.Spec.Template.Spec) // Any changes to the spec increment the generation number, any changes to the // status should reflect the generation number of the corresponding object. diff --git a/pkg/registry/apps/statefulset/strategy_test.go b/pkg/registry/apps/statefulset/strategy_test.go index aba7b35bc61..4fdab0e9e62 100644 --- a/pkg/registry/apps/statefulset/strategy_test.go +++ b/pkg/registry/apps/statefulset/strategy_test.go @@ -130,7 +130,7 @@ func TestStatefulsetDefaultGarbageCollectionPolicy(t *testing.T) { false, }, { - expectedGCPolicy: rest.OrphanDependents, + expectedGCPolicy: rest.DeleteDependents, isNilRequestInfo: true, }, } diff --git a/pkg/registry/batch/cronjob/BUILD b/pkg/registry/batch/cronjob/BUILD index e9661e46b18..40cc472645c 100644 --- a/pkg/registry/batch/cronjob/BUILD +++ b/pkg/registry/batch/cronjob/BUILD @@ -18,8 +18,12 @@ go_library( "//pkg/api/pod:go_default_library", "//pkg/apis/batch:go_default_library", "//pkg/apis/batch/validation:go_default_library", + "//staging/src/k8s.io/api/batch/v1beta1:go_default_library", + "//staging/src/k8s.io/api/batch/v2alpha1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library", + "//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/validation/field:go_default_library", + "//staging/src/k8s.io/apiserver/pkg/endpoints/request:go_default_library", "//staging/src/k8s.io/apiserver/pkg/registry/rest:go_default_library", "//staging/src/k8s.io/apiserver/pkg/storage/names:go_default_library", ], diff --git a/pkg/registry/batch/cronjob/strategy.go b/pkg/registry/batch/cronjob/strategy.go index 1e756d6b15f..3ccbee4eb42 100644 --- a/pkg/registry/batch/cronjob/strategy.go +++ b/pkg/registry/batch/cronjob/strategy.go @@ -19,8 +19,12 @@ package cronjob import ( "context" + batchv1beta1 "k8s.io/api/batch/v1beta1" + batchv2alpha1 "k8s.io/api/batch/v2alpha1" "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/util/validation/field" + genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/registry/rest" "k8s.io/apiserver/pkg/storage/names" "k8s.io/kubernetes/pkg/api/legacyscheme" @@ -38,10 +42,20 @@ type cronJobStrategy struct { // Strategy is the default logic that applies when creating and updating CronJob objects. var Strategy = cronJobStrategy{legacyscheme.Scheme, names.SimpleNameGenerator} -// DefaultGarbageCollectionPolicy returns Orphan because that was the default -// behavior before the server-side garbage collection was implemented. +// DefaultGarbageCollectionPolicy returns OrphanDependents for batch/v1beta1 and batch/v2alpha1 for backwards compatibility, +// and DeleteDependents for all other versions. func (cronJobStrategy) DefaultGarbageCollectionPolicy(ctx context.Context) rest.GarbageCollectionPolicy { - return rest.OrphanDependents + var groupVersion schema.GroupVersion + if requestInfo, found := genericapirequest.RequestInfoFrom(ctx); found { + groupVersion = schema.GroupVersion{Group: requestInfo.APIGroup, Version: requestInfo.APIVersion} + } + switch groupVersion { + case batchv1beta1.SchemeGroupVersion, batchv2alpha1.SchemeGroupVersion: + // for back compatibility + return rest.OrphanDependents + default: + return rest.DeleteDependents + } } // NamespaceScoped returns true because all scheduled jobs need to be within a namespace. @@ -54,7 +68,7 @@ func (cronJobStrategy) PrepareForCreate(ctx context.Context, obj runtime.Object) cronJob := obj.(*batch.CronJob) cronJob.Status = batch.CronJobStatus{} - pod.DropDisabledAlphaFields(&cronJob.Spec.JobTemplate.Spec.Template.Spec) + pod.DropDisabledFields(&cronJob.Spec.JobTemplate.Spec.Template.Spec, nil) } // PrepareForUpdate clears fields that are not allowed to be set by end users on update. @@ -63,8 +77,7 @@ func (cronJobStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Ob oldCronJob := old.(*batch.CronJob) newCronJob.Status = oldCronJob.Status - pod.DropDisabledAlphaFields(&newCronJob.Spec.JobTemplate.Spec.Template.Spec) - pod.DropDisabledAlphaFields(&oldCronJob.Spec.JobTemplate.Spec.Template.Spec) + pod.DropDisabledFields(&newCronJob.Spec.JobTemplate.Spec.Template.Spec, &oldCronJob.Spec.JobTemplate.Spec.Template.Spec) } // Validate validates a new scheduled job. diff --git a/pkg/registry/batch/cronjob/strategy_test.go b/pkg/registry/batch/cronjob/strategy_test.go index 0b46ac9f861..be568d1bdcc 100644 --- a/pkg/registry/batch/cronjob/strategy_test.go +++ b/pkg/registry/batch/cronjob/strategy_test.go @@ -90,7 +90,22 @@ func TestCronJobStrategy(t *testing.T) { // Make sure we correctly implement the interface. // Otherwise a typo could silently change the default. var gcds rest.GarbageCollectionDeleteStrategy = Strategy - if got, want := gcds.DefaultGarbageCollectionPolicy(genericapirequest.NewContext()), rest.OrphanDependents; got != want { + if got, want := gcds.DefaultGarbageCollectionPolicy(genericapirequest.NewContext()), rest.DeleteDependents; got != want { + t.Errorf("DefaultGarbageCollectionPolicy() = %#v, want %#v", got, want) + } + + var ( + v1beta1Ctx = genericapirequest.WithRequestInfo(genericapirequest.NewContext(), &genericapirequest.RequestInfo{APIGroup: "batch", APIVersion: "v1beta1", Resource: "cronjobs"}) + v2alpha1Ctx = genericapirequest.WithRequestInfo(genericapirequest.NewContext(), &genericapirequest.RequestInfo{APIGroup: "batch", APIVersion: "v2alpha1", Resource: "cronjobs"}) + otherVersionCtx = genericapirequest.WithRequestInfo(genericapirequest.NewContext(), &genericapirequest.RequestInfo{APIGroup: "batch", APIVersion: "v100", Resource: "cronjobs"}) + ) + if got, want := gcds.DefaultGarbageCollectionPolicy(v1beta1Ctx), rest.OrphanDependents; got != want { + t.Errorf("DefaultGarbageCollectionPolicy() = %#v, want %#v", got, want) + } + if got, want := gcds.DefaultGarbageCollectionPolicy(v2alpha1Ctx), rest.OrphanDependents; got != want { + t.Errorf("DefaultGarbageCollectionPolicy() = %#v, want %#v", got, want) + } + if got, want := gcds.DefaultGarbageCollectionPolicy(otherVersionCtx), rest.DeleteDependents; got != want { t.Errorf("DefaultGarbageCollectionPolicy() = %#v, want %#v", got, want) } } diff --git a/pkg/registry/batch/job/BUILD b/pkg/registry/batch/job/BUILD index 30474db1f3c..d61f5bae717 100644 --- a/pkg/registry/batch/job/BUILD +++ b/pkg/registry/batch/job/BUILD @@ -19,11 +19,14 @@ go_library( "//pkg/apis/batch:go_default_library", "//pkg/apis/batch/validation:go_default_library", "//pkg/features:go_default_library", + "//staging/src/k8s.io/api/batch/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/fields:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/labels:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library", + "//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/validation/field:go_default_library", + "//staging/src/k8s.io/apiserver/pkg/endpoints/request:go_default_library", "//staging/src/k8s.io/apiserver/pkg/registry/generic:go_default_library", "//staging/src/k8s.io/apiserver/pkg/registry/rest:go_default_library", "//staging/src/k8s.io/apiserver/pkg/storage:go_default_library", @@ -47,6 +50,7 @@ go_test( "//staging/src/k8s.io/apiserver/pkg/endpoints/request:go_default_library", "//staging/src/k8s.io/apiserver/pkg/registry/rest:go_default_library", "//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library", + "//staging/src/k8s.io/apiserver/pkg/util/feature/testing:go_default_library", ], ) diff --git a/pkg/registry/batch/job/strategy.go b/pkg/registry/batch/job/strategy.go index 4e46ddc4b37..5ce5e51178b 100644 --- a/pkg/registry/batch/job/strategy.go +++ b/pkg/registry/batch/job/strategy.go @@ -21,11 +21,14 @@ import ( "fmt" "strconv" + batchv1 "k8s.io/api/batch/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/fields" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/util/validation/field" + genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/registry/generic" "k8s.io/apiserver/pkg/registry/rest" "k8s.io/apiserver/pkg/storage" @@ -47,10 +50,20 @@ type jobStrategy struct { // Strategy is the default logic that applies when creating and updating Replication Controller objects. var Strategy = jobStrategy{legacyscheme.Scheme, names.SimpleNameGenerator} -// DefaultGarbageCollectionPolicy returns Orphan because that was the default -// behavior before the server-side garbage collection was implemented. +// DefaultGarbageCollectionPolicy returns OrphanDependents for batch/v1 for backwards compatibility, +// and DeleteDependents for all other versions. func (jobStrategy) DefaultGarbageCollectionPolicy(ctx context.Context) rest.GarbageCollectionPolicy { - return rest.OrphanDependents + var groupVersion schema.GroupVersion + if requestInfo, found := genericapirequest.RequestInfoFrom(ctx); found { + groupVersion = schema.GroupVersion{Group: requestInfo.APIGroup, Version: requestInfo.APIVersion} + } + switch groupVersion { + case batchv1.SchemeGroupVersion: + // for back compatibility + return rest.OrphanDependents + default: + return rest.DeleteDependents + } } // NamespaceScoped returns true because all jobs need to be within a namespace. @@ -67,7 +80,7 @@ func (jobStrategy) PrepareForCreate(ctx context.Context, obj runtime.Object) { job.Spec.TTLSecondsAfterFinished = nil } - pod.DropDisabledAlphaFields(&job.Spec.Template.Spec) + pod.DropDisabledFields(&job.Spec.Template.Spec, nil) } // PrepareForUpdate clears fields that are not allowed to be set by end users on update. @@ -76,13 +89,11 @@ func (jobStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object oldJob := old.(*batch.Job) newJob.Status = oldJob.Status - if !utilfeature.DefaultFeatureGate.Enabled(features.TTLAfterFinished) { + if !utilfeature.DefaultFeatureGate.Enabled(features.TTLAfterFinished) && oldJob.Spec.TTLSecondsAfterFinished == nil { newJob.Spec.TTLSecondsAfterFinished = nil - oldJob.Spec.TTLSecondsAfterFinished = nil } - pod.DropDisabledAlphaFields(&newJob.Spec.Template.Spec) - pod.DropDisabledAlphaFields(&oldJob.Spec.Template.Spec) + pod.DropDisabledFields(&newJob.Spec.Template.Spec, &oldJob.Spec.Template.Spec) } // Validate validates a new job. diff --git a/pkg/registry/batch/job/strategy_test.go b/pkg/registry/batch/job/strategy_test.go index e3b51678c15..ceac03fb675 100644 --- a/pkg/registry/batch/job/strategy_test.go +++ b/pkg/registry/batch/job/strategy_test.go @@ -25,6 +25,7 @@ import ( genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/registry/rest" utilfeature "k8s.io/apiserver/pkg/util/feature" + utilfeaturetesting "k8s.io/apiserver/pkg/util/feature/testing" "k8s.io/kubernetes/pkg/api/testapi" apitesting "k8s.io/kubernetes/pkg/api/testing" "k8s.io/kubernetes/pkg/apis/batch" @@ -121,10 +122,39 @@ func TestJobStrategy(t *testing.T) { t.Errorf("Job should only allow updating .spec.ttlSecondsAfterFinished when %v feature is enabled", features.TTLAfterFinished) } + // set TTLSecondsAfterFinished on both old and new jobs + job.Spec.TTLSecondsAfterFinished = newInt32(1) + updatedJob.Spec.TTLSecondsAfterFinished = newInt32(2) + + // Existing TTLSecondsAfterFinished should be preserved when feature is on + defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.TTLAfterFinished, true)() + Strategy.PrepareForUpdate(ctx, updatedJob, job) + if job.Spec.TTLSecondsAfterFinished == nil || updatedJob.Spec.TTLSecondsAfterFinished == nil { + t.Errorf("existing TTLSecondsAfterFinished should be preserved") + } + + // Existing TTLSecondsAfterFinished should be preserved when feature is off + defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.TTLAfterFinished, false)() + Strategy.PrepareForUpdate(ctx, updatedJob, job) + if job.Spec.TTLSecondsAfterFinished == nil || updatedJob.Spec.TTLSecondsAfterFinished == nil { + t.Errorf("existing TTLSecondsAfterFinished should be preserved") + } + // Make sure we correctly implement the interface. // Otherwise a typo could silently change the default. var gcds rest.GarbageCollectionDeleteStrategy = Strategy - if got, want := gcds.DefaultGarbageCollectionPolicy(genericapirequest.NewContext()), rest.OrphanDependents; got != want { + if got, want := gcds.DefaultGarbageCollectionPolicy(genericapirequest.NewContext()), rest.DeleteDependents; got != want { + t.Errorf("DefaultGarbageCollectionPolicy() = %#v, want %#v", got, want) + } + + var ( + v1Ctx = genericapirequest.WithRequestInfo(genericapirequest.NewContext(), &genericapirequest.RequestInfo{APIGroup: "batch", APIVersion: "v1", Resource: "jobs"}) + otherVersionCtx = genericapirequest.WithRequestInfo(genericapirequest.NewContext(), &genericapirequest.RequestInfo{APIGroup: "batch", APIVersion: "v100", Resource: "jobs"}) + ) + if got, want := gcds.DefaultGarbageCollectionPolicy(v1Ctx), rest.OrphanDependents; got != want { + t.Errorf("DefaultGarbageCollectionPolicy() = %#v, want %#v", got, want) + } + if got, want := gcds.DefaultGarbageCollectionPolicy(otherVersionCtx), rest.DeleteDependents; got != want { t.Errorf("DefaultGarbageCollectionPolicy() = %#v, want %#v", got, want) } } diff --git a/pkg/registry/coordination/rest/BUILD b/pkg/registry/coordination/rest/BUILD index 291fa362875..3be73700ee7 100644 --- a/pkg/registry/coordination/rest/BUILD +++ b/pkg/registry/coordination/rest/BUILD @@ -9,6 +9,7 @@ go_library( "//pkg/api/legacyscheme:go_default_library", "//pkg/apis/coordination:go_default_library", "//pkg/registry/coordination/lease/storage:go_default_library", + "//staging/src/k8s.io/api/coordination/v1:go_default_library", "//staging/src/k8s.io/api/coordination/v1beta1:go_default_library", "//staging/src/k8s.io/apiserver/pkg/registry/generic:go_default_library", "//staging/src/k8s.io/apiserver/pkg/registry/rest:go_default_library", diff --git a/pkg/registry/coordination/rest/storage_coordination.go b/pkg/registry/coordination/rest/storage_coordination.go index 19a88d9c90e..4dae50369de 100644 --- a/pkg/registry/coordination/rest/storage_coordination.go +++ b/pkg/registry/coordination/rest/storage_coordination.go @@ -17,6 +17,7 @@ limitations under the License. package rest import ( + coordinationv1 "k8s.io/api/coordination/v1" coordinationv1beta1 "k8s.io/api/coordination/v1beta1" "k8s.io/apiserver/pkg/registry/generic" "k8s.io/apiserver/pkg/registry/rest" @@ -37,6 +38,9 @@ func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource serverstorag if apiResourceConfigSource.VersionEnabled(coordinationv1beta1.SchemeGroupVersion) { apiGroupInfo.VersionedResourcesStorageMap[coordinationv1beta1.SchemeGroupVersion.Version] = p.v1beta1Storage(apiResourceConfigSource, restOptionsGetter) } + if apiResourceConfigSource.VersionEnabled(coordinationv1.SchemeGroupVersion) { + apiGroupInfo.VersionedResourcesStorageMap[coordinationv1.SchemeGroupVersion.Version] = p.v1Storage(apiResourceConfigSource, restOptionsGetter) + } return apiGroupInfo, true } @@ -49,6 +53,15 @@ func (p RESTStorageProvider) v1beta1Storage(apiResourceConfigSource serverstorag return storage } +func (p RESTStorageProvider) v1Storage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) map[string]rest.Storage { + storage := map[string]rest.Storage{} + // leases + leaseStorage := leasestorage.NewREST(restOptionsGetter) + storage["leases"] = leaseStorage + + return storage +} + func (p RESTStorageProvider) GroupName() string { return coordination.GroupName } diff --git a/pkg/registry/core/node/BUILD b/pkg/registry/core/node/BUILD index e026fe00b6d..0819655b314 100644 --- a/pkg/registry/core/node/BUILD +++ b/pkg/registry/core/node/BUILD @@ -19,6 +19,7 @@ go_library( "//pkg/apis/core/validation:go_default_library", "//pkg/features:go_default_library", "//pkg/kubelet/client:go_default_library", + "//pkg/proxy/util:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/fields:go_default_library", diff --git a/pkg/registry/core/node/strategy.go b/pkg/registry/core/node/strategy.go index 72828b48998..5922b7754a6 100644 --- a/pkg/registry/core/node/strategy.go +++ b/pkg/registry/core/node/strategy.go @@ -40,6 +40,7 @@ import ( "k8s.io/kubernetes/pkg/apis/core/validation" "k8s.io/kubernetes/pkg/features" "k8s.io/kubernetes/pkg/kubelet/client" + proxyutil "k8s.io/kubernetes/pkg/proxy/util" ) // nodeStrategy implements behavior for nodes @@ -66,9 +67,9 @@ func (nodeStrategy) AllowCreateOnUpdate() bool { func (nodeStrategy) PrepareForCreate(ctx context.Context, obj runtime.Object) { node := obj.(*api.Node) // Nodes allow *all* fields, including status, to be set on create. - if !utilfeature.DefaultFeatureGate.Enabled(features.DynamicKubeletConfig) { node.Spec.ConfigSource = nil + node.Status.Config = nil } } @@ -78,12 +79,22 @@ func (nodeStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Objec oldNode := old.(*api.Node) newNode.Status = oldNode.Status - if !utilfeature.DefaultFeatureGate.Enabled(features.DynamicKubeletConfig) { + if !utilfeature.DefaultFeatureGate.Enabled(features.DynamicKubeletConfig) && !nodeConfigSourceInUse(oldNode) { newNode.Spec.ConfigSource = nil - oldNode.Spec.ConfigSource = nil } } +// nodeConfigSourceInUse returns true if node's Spec ConfigSource is set(used) +func nodeConfigSourceInUse(node *api.Node) bool { + if node == nil { + return false + } + if node.Spec.ConfigSource != nil { + return true + } + return false +} + // Validate validates a new node. func (nodeStrategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList { node := obj.(*api.Node) @@ -126,26 +137,27 @@ type nodeStatusStrategy struct { var StatusStrategy = nodeStatusStrategy{Strategy} -func (nodeStatusStrategy) PrepareForCreate(ctx context.Context, obj runtime.Object) { - node := obj.(*api.Node) - // Nodes allow *all* fields, including status, to be set on create. - - if !utilfeature.DefaultFeatureGate.Enabled(features.DynamicKubeletConfig) { - node.Status.Config = nil - } -} - func (nodeStatusStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) { newNode := obj.(*api.Node) oldNode := old.(*api.Node) newNode.Spec = oldNode.Spec - if !utilfeature.DefaultFeatureGate.Enabled(features.DynamicKubeletConfig) { + if !utilfeature.DefaultFeatureGate.Enabled(features.DynamicKubeletConfig) && !nodeStatusConfigInUse(oldNode) { newNode.Status.Config = nil - oldNode.Status.Config = nil } } +// nodeStatusConfigInUse returns true if node's Status Config is set(used) +func nodeStatusConfigInUse(node *api.Node) bool { + if node == nil { + return false + } + if node.Status.Config != nil { + return true + } + return false +} + func (nodeStatusStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList { return validation.ValidateNodeUpdate(obj.(*api.Node), old.(*api.Node)) } @@ -217,6 +229,10 @@ func ResourceLocation(getter ResourceGetter, connection client.ConnectionInfoGet nil } + if err := proxyutil.IsProxyableHostname(ctx, &net.Resolver{}, info.Hostname); err != nil { + return nil, nil, errors.NewBadRequest(err.Error()) + } + // Otherwise, return the requested scheme and port, and the proxy transport return &url.URL{Scheme: schemeReq, Host: net.JoinHostPort(info.Hostname, portReq)}, proxyTransport, nil } diff --git a/pkg/registry/core/persistentvolumeclaim/strategy.go b/pkg/registry/core/persistentvolumeclaim/strategy.go index abefe0de111..16ce8481104 100644 --- a/pkg/registry/core/persistentvolumeclaim/strategy.go +++ b/pkg/registry/core/persistentvolumeclaim/strategy.go @@ -52,7 +52,7 @@ func (persistentvolumeclaimStrategy) PrepareForCreate(ctx context.Context, obj r pvc := obj.(*api.PersistentVolumeClaim) pvc.Status = api.PersistentVolumeClaimStatus{} - pvcutil.DropDisabledAlphaFields(&pvc.Spec) + pvcutil.DropDisabledFields(&pvc.Spec, nil) } func (persistentvolumeclaimStrategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList { @@ -74,8 +74,7 @@ func (persistentvolumeclaimStrategy) PrepareForUpdate(ctx context.Context, obj, oldPvc := old.(*api.PersistentVolumeClaim) newPvc.Status = oldPvc.Status - pvcutil.DropDisabledAlphaFields(&newPvc.Spec) - pvcutil.DropDisabledAlphaFields(&oldPvc.Spec) + pvcutil.DropDisabledFields(&newPvc.Spec, &oldPvc.Spec) } func (persistentvolumeclaimStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList { diff --git a/pkg/registry/core/pod/BUILD b/pkg/registry/core/pod/BUILD index e7386dfa1ac..ddf8fcb5d15 100644 --- a/pkg/registry/core/pod/BUILD +++ b/pkg/registry/core/pod/BUILD @@ -20,6 +20,7 @@ go_library( "//pkg/apis/core/helper/qos:go_default_library", "//pkg/apis/core/validation:go_default_library", "//pkg/kubelet/client:go_default_library", + "//pkg/proxy/util:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/meta:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", diff --git a/pkg/registry/core/pod/strategy.go b/pkg/registry/core/pod/strategy.go index 69e77c5a612..52fb9ec45aa 100644 --- a/pkg/registry/core/pod/strategy.go +++ b/pkg/registry/core/pod/strategy.go @@ -47,6 +47,7 @@ import ( "k8s.io/kubernetes/pkg/apis/core/helper/qos" "k8s.io/kubernetes/pkg/apis/core/validation" "k8s.io/kubernetes/pkg/kubelet/client" + proxyutil "k8s.io/kubernetes/pkg/proxy/util" ) // podStrategy implements behavior for Pods @@ -72,7 +73,7 @@ func (podStrategy) PrepareForCreate(ctx context.Context, obj runtime.Object) { QOSClass: qos.GetPodQOS(pod), } - podutil.DropDisabledAlphaFields(&pod.Spec) + podutil.DropDisabledFields(&pod.Spec, nil) } // PrepareForUpdate clears fields that are not allowed to be set by end users on update. @@ -81,8 +82,7 @@ func (podStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object oldPod := old.(*api.Pod) newPod.Status = oldPod.Status - podutil.DropDisabledAlphaFields(&newPod.Spec) - podutil.DropDisabledAlphaFields(&oldPod.Spec) + podutil.DropDisabledFields(&newPod.Spec, &oldPod.Spec) } // Validate validates a new pod. @@ -290,6 +290,10 @@ func ResourceLocation(getter ResourceGetter, rt http.RoundTripper, ctx context.C } } + if err := proxyutil.IsProxyableIP(pod.Status.PodIP); err != nil { + return nil, nil, errors.NewBadRequest(err.Error()) + } + loc := &url.URL{ Scheme: scheme, } diff --git a/pkg/registry/core/podtemplate/strategy.go b/pkg/registry/core/podtemplate/strategy.go index 83c516fc886..13d841f7829 100644 --- a/pkg/registry/core/podtemplate/strategy.go +++ b/pkg/registry/core/podtemplate/strategy.go @@ -47,7 +47,7 @@ func (podTemplateStrategy) NamespaceScoped() bool { func (podTemplateStrategy) PrepareForCreate(ctx context.Context, obj runtime.Object) { template := obj.(*api.PodTemplate) - pod.DropDisabledAlphaFields(&template.Template.Spec) + pod.DropDisabledFields(&template.Template.Spec, nil) } // Validate validates a new pod template. @@ -70,8 +70,7 @@ func (podTemplateStrategy) PrepareForUpdate(ctx context.Context, obj, old runtim newTemplate := obj.(*api.PodTemplate) oldTemplate := old.(*api.PodTemplate) - pod.DropDisabledAlphaFields(&newTemplate.Template.Spec) - pod.DropDisabledAlphaFields(&oldTemplate.Template.Spec) + pod.DropDisabledFields(&newTemplate.Template.Spec, &oldTemplate.Template.Spec) } // ValidateUpdate is the default update validation for an end user. diff --git a/pkg/registry/core/replicationcontroller/BUILD b/pkg/registry/core/replicationcontroller/BUILD index 2f7a63edf4b..cfc09d1b4d9 100644 --- a/pkg/registry/core/replicationcontroller/BUILD +++ b/pkg/registry/core/replicationcontroller/BUILD @@ -19,11 +19,14 @@ go_library( "//pkg/apis/core:go_default_library", "//pkg/apis/core/helper:go_default_library", "//pkg/apis/core/validation:go_default_library", + "//staging/src/k8s.io/api/core/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/equality:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/fields:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/labels:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library", + "//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/validation/field:go_default_library", + "//staging/src/k8s.io/apiserver/pkg/endpoints/request:go_default_library", "//staging/src/k8s.io/apiserver/pkg/registry/generic:go_default_library", "//staging/src/k8s.io/apiserver/pkg/registry/rest:go_default_library", "//staging/src/k8s.io/apiserver/pkg/storage:go_default_library", diff --git a/pkg/registry/core/replicationcontroller/strategy.go b/pkg/registry/core/replicationcontroller/strategy.go index 0cc784bc9fd..2c0cc34a402 100644 --- a/pkg/registry/core/replicationcontroller/strategy.go +++ b/pkg/registry/core/replicationcontroller/strategy.go @@ -24,11 +24,14 @@ import ( "strconv" "strings" + corev1 "k8s.io/api/core/v1" apiequality "k8s.io/apimachinery/pkg/api/equality" "k8s.io/apimachinery/pkg/fields" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/util/validation/field" + genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/registry/generic" "k8s.io/apiserver/pkg/registry/rest" apistorage "k8s.io/apiserver/pkg/storage" @@ -49,10 +52,20 @@ type rcStrategy struct { // Strategy is the default logic that applies when creating and updating Replication Controller objects. var Strategy = rcStrategy{legacyscheme.Scheme, names.SimpleNameGenerator} -// DefaultGarbageCollectionPolicy returns Orphan because that was the default -// behavior before the server-side garbage collection was implemented. +// DefaultGarbageCollectionPolicy returns OrphanDependents for v1 for backwards compatibility, +// and DeleteDependents for all other versions. func (rcStrategy) DefaultGarbageCollectionPolicy(ctx context.Context) rest.GarbageCollectionPolicy { - return rest.OrphanDependents + var groupVersion schema.GroupVersion + if requestInfo, found := genericapirequest.RequestInfoFrom(ctx); found { + groupVersion = schema.GroupVersion{Group: requestInfo.APIGroup, Version: requestInfo.APIVersion} + } + switch groupVersion { + case corev1.SchemeGroupVersion: + // for back compatibility + return rest.OrphanDependents + default: + return rest.DeleteDependents + } } // NamespaceScoped returns true because all Replication Controllers need to be within a namespace. @@ -68,7 +81,7 @@ func (rcStrategy) PrepareForCreate(ctx context.Context, obj runtime.Object) { controller.Generation = 1 if controller.Spec.Template != nil { - pod.DropDisabledAlphaFields(&controller.Spec.Template.Spec) + pod.DropDisabledFields(&controller.Spec.Template.Spec, nil) } } @@ -79,12 +92,16 @@ func (rcStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) // update is not allowed to set status newController.Status = oldController.Status + var newSpec, oldSpec *api.PodSpec if oldController.Spec.Template != nil { - pod.DropDisabledAlphaFields(&oldController.Spec.Template.Spec) + oldSpec = &oldController.Spec.Template.Spec } if newController.Spec.Template != nil { - pod.DropDisabledAlphaFields(&newController.Spec.Template.Spec) + newSpec = &newController.Spec.Template.Spec + } else { + newSpec = &api.PodSpec{} } + pod.DropDisabledFields(newSpec, oldSpec) // Any changes to the spec increment the generation number, any changes to the // status should reflect the generation number of the corresponding object. We push diff --git a/pkg/registry/core/serviceaccount/storage/token.go b/pkg/registry/core/serviceaccount/storage/token.go index f1018b7eb0c..881b5f26e40 100644 --- a/pkg/registry/core/serviceaccount/storage/token.go +++ b/pkg/registry/core/serviceaccount/storage/token.go @@ -58,8 +58,10 @@ var gvk = schema.GroupVersionKind{ } func (r *TokenREST) Create(ctx context.Context, name string, obj runtime.Object, createValidation rest.ValidateObjectFunc, options *metav1.CreateOptions) (runtime.Object, error) { - if err := createValidation(obj); err != nil { - return nil, err + if createValidation != nil { + if err := createValidation(obj.DeepCopyObject()); err != nil { + return nil, err + } } out := obj.(*authenticationapi.TokenRequest) diff --git a/pkg/registry/extensions/rest/storage_extensions.go b/pkg/registry/extensions/rest/storage_extensions.go index 2b21e502f07..83bdce27c31 100644 --- a/pkg/registry/extensions/rest/storage_extensions.go +++ b/pkg/registry/extensions/rest/storage_extensions.go @@ -52,39 +52,53 @@ func (p RESTStorageProvider) v1beta1Storage(apiResourceConfigSource serverstorag // This is a dummy replication controller for scale subresource purposes. // TODO: figure out how to enable this only if needed as a part of scale subresource GA. - controllerStorage := expcontrollerstore.NewStorage(restOptionsGetter) - storage["replicationcontrollers"] = controllerStorage.ReplicationController - storage["replicationcontrollers/scale"] = controllerStorage.Scale + if apiResourceConfigSource.ResourceEnabled(extensionsapiv1beta1.SchemeGroupVersion.WithResource("replicationcontrollers")) { + controllerStorage := expcontrollerstore.NewStorage(restOptionsGetter) + storage["replicationcontrollers"] = controllerStorage.ReplicationController + storage["replicationcontrollers/scale"] = controllerStorage.Scale + } // daemonsets - daemonSetStorage, daemonSetStatusStorage := daemonstore.NewREST(restOptionsGetter) - storage["daemonsets"] = daemonSetStorage.WithCategories(nil) - storage["daemonsets/status"] = daemonSetStatusStorage + if apiResourceConfigSource.ResourceEnabled(extensionsapiv1beta1.SchemeGroupVersion.WithResource("daemonsets")) { + daemonSetStorage, daemonSetStatusStorage := daemonstore.NewREST(restOptionsGetter) + storage["daemonsets"] = daemonSetStorage.WithCategories(nil) + storage["daemonsets/status"] = daemonSetStatusStorage + } //deployments - deploymentStorage := deploymentstore.NewStorage(restOptionsGetter) - storage["deployments"] = deploymentStorage.Deployment.WithCategories(nil) - storage["deployments/status"] = deploymentStorage.Status - storage["deployments/rollback"] = deploymentStorage.Rollback - storage["deployments/scale"] = deploymentStorage.Scale + if apiResourceConfigSource.ResourceEnabled(extensionsapiv1beta1.SchemeGroupVersion.WithResource("deployments")) { + deploymentStorage := deploymentstore.NewStorage(restOptionsGetter) + storage["deployments"] = deploymentStorage.Deployment.WithCategories(nil) + storage["deployments/status"] = deploymentStorage.Status + storage["deployments/rollback"] = deploymentStorage.Rollback + storage["deployments/scale"] = deploymentStorage.Scale + } // ingresses - ingressStorage, ingressStatusStorage := ingressstore.NewREST(restOptionsGetter) - storage["ingresses"] = ingressStorage - storage["ingresses/status"] = ingressStatusStorage + if apiResourceConfigSource.ResourceEnabled(extensionsapiv1beta1.SchemeGroupVersion.WithResource("ingresses")) { + ingressStorage, ingressStatusStorage := ingressstore.NewREST(restOptionsGetter) + storage["ingresses"] = ingressStorage + storage["ingresses/status"] = ingressStatusStorage + } // podsecuritypolicy - podSecurityPolicyStorage := pspstore.NewREST(restOptionsGetter) - storage["podSecurityPolicies"] = podSecurityPolicyStorage + if apiResourceConfigSource.ResourceEnabled(extensionsapiv1beta1.SchemeGroupVersion.WithResource("podsecuritypolicies")) { + podSecurityPolicyStorage := pspstore.NewREST(restOptionsGetter) + storage["podSecurityPolicies"] = podSecurityPolicyStorage + } // replicasets - replicaSetStorage := replicasetstore.NewStorage(restOptionsGetter) - storage["replicasets"] = replicaSetStorage.ReplicaSet.WithCategories(nil) - storage["replicasets/status"] = replicaSetStorage.Status - storage["replicasets/scale"] = replicaSetStorage.Scale + if apiResourceConfigSource.ResourceEnabled(extensionsapiv1beta1.SchemeGroupVersion.WithResource("replicasets")) { + replicaSetStorage := replicasetstore.NewStorage(restOptionsGetter) + storage["replicasets"] = replicaSetStorage.ReplicaSet.WithCategories(nil) + storage["replicasets/status"] = replicaSetStorage.Status + storage["replicasets/scale"] = replicaSetStorage.Scale + } // networkpolicies - networkExtensionsStorage := networkpolicystore.NewREST(restOptionsGetter) - storage["networkpolicies"] = networkExtensionsStorage + if apiResourceConfigSource.ResourceEnabled(extensionsapiv1beta1.SchemeGroupVersion.WithResource("networkpolicies")) { + networkExtensionsStorage := networkpolicystore.NewREST(restOptionsGetter) + storage["networkpolicies"] = networkExtensionsStorage + } return storage } diff --git a/pkg/registry/policy/podsecuritypolicy/strategy.go b/pkg/registry/policy/podsecuritypolicy/strategy.go index c9940fe2d83..e09d76239e3 100644 --- a/pkg/registry/policy/podsecuritypolicy/strategy.go +++ b/pkg/registry/policy/podsecuritypolicy/strategy.go @@ -58,15 +58,14 @@ func (strategy) AllowUnconditionalUpdate() bool { func (strategy) PrepareForCreate(ctx context.Context, obj runtime.Object) { psp := obj.(*policy.PodSecurityPolicy) - psputil.DropDisabledAlphaFields(&psp.Spec) + psputil.DropDisabledFields(&psp.Spec, nil) } func (strategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) { newPsp := obj.(*policy.PodSecurityPolicy) oldPsp := old.(*policy.PodSecurityPolicy) - psputil.DropDisabledAlphaFields(&newPsp.Spec) - psputil.DropDisabledAlphaFields(&oldPsp.Spec) + psputil.DropDisabledFields(&newPsp.Spec, &oldPsp.Spec) } func (strategy) Canonicalize(obj runtime.Object) { diff --git a/pkg/registry/scheduling/rest/storage_scheduling.go b/pkg/registry/scheduling/rest/storage_scheduling.go index ed291b32c65..cdbfb9e2be9 100644 --- a/pkg/registry/scheduling/rest/storage_scheduling.go +++ b/pkg/registry/scheduling/rest/storage_scheduling.go @@ -93,7 +93,7 @@ func AddSystemPriorityClasses() genericapiserver.PostStartHookFunc { } else { // Unable to get the priority class for reasons other than "not found". klog.Warningf("unable to get PriorityClass %v: %v. Retrying...", pc.Name, err) - return false, err + return false, nil } } } diff --git a/pkg/registry/storage/storageclass/BUILD b/pkg/registry/storage/storageclass/BUILD index 31ab232a746..6dc98c39d42 100644 --- a/pkg/registry/storage/storageclass/BUILD +++ b/pkg/registry/storage/storageclass/BUILD @@ -18,11 +18,9 @@ go_library( "//pkg/apis/storage:go_default_library", "//pkg/apis/storage/util:go_default_library", "//pkg/apis/storage/validation:go_default_library", - "//pkg/features:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/validation/field:go_default_library", "//staging/src/k8s.io/apiserver/pkg/storage/names:go_default_library", - "//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library", ], ) diff --git a/pkg/registry/storage/storageclass/strategy.go b/pkg/registry/storage/storageclass/strategy.go index b570d39e239..58744efeb43 100644 --- a/pkg/registry/storage/storageclass/strategy.go +++ b/pkg/registry/storage/storageclass/strategy.go @@ -22,12 +22,10 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/validation/field" "k8s.io/apiserver/pkg/storage/names" - utilfeature "k8s.io/apiserver/pkg/util/feature" "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/apis/storage" storageutil "k8s.io/kubernetes/pkg/apis/storage/util" "k8s.io/kubernetes/pkg/apis/storage/validation" - "k8s.io/kubernetes/pkg/features" ) // storageClassStrategy implements behavior for StorageClass objects @@ -48,11 +46,7 @@ func (storageClassStrategy) NamespaceScoped() bool { func (storageClassStrategy) PrepareForCreate(ctx context.Context, obj runtime.Object) { class := obj.(*storage.StorageClass) - if !utilfeature.DefaultFeatureGate.Enabled(features.ExpandPersistentVolumes) { - class.AllowVolumeExpansion = nil - } - - storageutil.DropDisabledAlphaFields(class) + storageutil.DropDisabledFields(class, nil) } func (storageClassStrategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList { @@ -73,12 +67,7 @@ func (storageClassStrategy) PrepareForUpdate(ctx context.Context, obj, old runti newClass := obj.(*storage.StorageClass) oldClass := old.(*storage.StorageClass) - if !utilfeature.DefaultFeatureGate.Enabled(features.ExpandPersistentVolumes) { - newClass.AllowVolumeExpansion = nil - oldClass.AllowVolumeExpansion = nil - } - storageutil.DropDisabledAlphaFields(oldClass) - storageutil.DropDisabledAlphaFields(newClass) + storageutil.DropDisabledFields(oldClass, newClass) } func (storageClassStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList { diff --git a/pkg/scheduler/BUILD b/pkg/scheduler/BUILD index 98e4bbc140d..b781d2178e6 100644 --- a/pkg/scheduler/BUILD +++ b/pkg/scheduler/BUILD @@ -9,7 +9,6 @@ go_library( importpath = "k8s.io/kubernetes/pkg/scheduler", visibility = ["//visibility:public"], deps = [ - "//pkg/features:go_default_library", "//pkg/scheduler/algorithm:go_default_library", "//pkg/scheduler/algorithm/predicates:go_default_library", "//pkg/scheduler/api:go_default_library", @@ -20,13 +19,13 @@ go_library( "//pkg/scheduler/internal/cache:go_default_library", "//pkg/scheduler/internal/queue:go_default_library", "//pkg/scheduler/metrics:go_default_library", + "//pkg/scheduler/plugins/v1alpha1:go_default_library", "//pkg/scheduler/util:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library", - "//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library", "//staging/src/k8s.io/client-go/informers/apps/v1:go_default_library", "//staging/src/k8s.io/client-go/informers/core/v1:go_default_library", "//staging/src/k8s.io/client-go/informers/policy/v1beta1:go_default_library", @@ -45,16 +44,15 @@ go_test( deps = [ "//pkg/api/legacyscheme:go_default_library", "//pkg/controller/volume/persistentvolume:go_default_library", - "//pkg/features:go_default_library", "//pkg/scheduler/algorithm:go_default_library", "//pkg/scheduler/algorithm/predicates:go_default_library", "//pkg/scheduler/api:go_default_library", "//pkg/scheduler/apis/config:go_default_library", - "//pkg/scheduler/cache:go_default_library", "//pkg/scheduler/core:go_default_library", "//pkg/scheduler/factory:go_default_library", "//pkg/scheduler/internal/cache:go_default_library", "//pkg/scheduler/internal/cache/fake:go_default_library", + "//pkg/scheduler/nodeinfo:go_default_library", "//pkg/scheduler/volumebinder:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/resource:go_default_library", @@ -65,8 +63,6 @@ go_test( "//staging/src/k8s.io/apimachinery/pkg/util/diff:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library", - "//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library", - "//staging/src/k8s.io/apiserver/pkg/util/feature/testing:go_default_library", "//staging/src/k8s.io/client-go/informers:go_default_library", "//staging/src/k8s.io/client-go/kubernetes/fake:go_default_library", "//staging/src/k8s.io/client-go/listers/core/v1:go_default_library", @@ -90,12 +86,13 @@ filegroup( "//pkg/scheduler/algorithmprovider:all-srcs", "//pkg/scheduler/api:all-srcs", "//pkg/scheduler/apis/config:all-srcs", - "//pkg/scheduler/cache:all-srcs", "//pkg/scheduler/core:all-srcs", "//pkg/scheduler/factory:all-srcs", "//pkg/scheduler/internal/cache:all-srcs", "//pkg/scheduler/internal/queue:all-srcs", "//pkg/scheduler/metrics:all-srcs", + "//pkg/scheduler/nodeinfo:all-srcs", + "//pkg/scheduler/plugins:all-srcs", "//pkg/scheduler/testing:all-srcs", "//pkg/scheduler/util:all-srcs", "//pkg/scheduler/volumebinder:all-srcs", diff --git a/pkg/scheduler/algorithm/BUILD b/pkg/scheduler/algorithm/BUILD index 0b19967bafa..6dfd534bf8c 100644 --- a/pkg/scheduler/algorithm/BUILD +++ b/pkg/scheduler/algorithm/BUILD @@ -16,8 +16,7 @@ go_library( importpath = "k8s.io/kubernetes/pkg/scheduler/algorithm", deps = [ "//pkg/scheduler/api:go_default_library", - "//pkg/scheduler/cache:go_default_library", - "//pkg/scheduler/internal/cache:go_default_library", + "//pkg/scheduler/nodeinfo:go_default_library", "//staging/src/k8s.io/api/apps/v1:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library", "//staging/src/k8s.io/api/policy/v1beta1:go_default_library", @@ -30,7 +29,7 @@ go_test( srcs = ["types_test.go"], embed = [":go_default_library"], deps = [ - "//pkg/scheduler/cache:go_default_library", + "//pkg/scheduler/nodeinfo:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/labels:go_default_library", ], diff --git a/pkg/scheduler/algorithm/predicates/BUILD b/pkg/scheduler/algorithm/predicates/BUILD index 0653a92a7af..4f979a11c77 100644 --- a/pkg/scheduler/algorithm/predicates/BUILD +++ b/pkg/scheduler/algorithm/predicates/BUILD @@ -25,7 +25,7 @@ go_library( "//pkg/scheduler/algorithm:go_default_library", "//pkg/scheduler/algorithm/priorities/util:go_default_library", "//pkg/scheduler/api:go_default_library", - "//pkg/scheduler/cache:go_default_library", + "//pkg/scheduler/nodeinfo:go_default_library", "//pkg/scheduler/util:go_default_library", "//pkg/scheduler/volumebinder:go_default_library", "//pkg/volume/util:go_default_library", @@ -59,9 +59,8 @@ go_test( "//pkg/apis/core/v1/helper:go_default_library", "//pkg/features:go_default_library", "//pkg/kubelet/apis:go_default_library", - "//pkg/scheduler/algorithm:go_default_library", "//pkg/scheduler/api:go_default_library", - "//pkg/scheduler/cache:go_default_library", + "//pkg/scheduler/nodeinfo:go_default_library", "//pkg/scheduler/testing:go_default_library", "//pkg/volume/util:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library", diff --git a/pkg/scheduler/algorithm/predicates/csi_volume_predicate.go b/pkg/scheduler/algorithm/predicates/csi_volume_predicate.go index ff2215eb28d..e0f070e610a 100644 --- a/pkg/scheduler/algorithm/predicates/csi_volume_predicate.go +++ b/pkg/scheduler/algorithm/predicates/csi_volume_predicate.go @@ -23,8 +23,7 @@ import ( utilfeature "k8s.io/apiserver/pkg/util/feature" "k8s.io/klog" "k8s.io/kubernetes/pkg/features" - "k8s.io/kubernetes/pkg/scheduler/algorithm" - schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" + schedulernodeinfo "k8s.io/kubernetes/pkg/scheduler/nodeinfo" volumeutil "k8s.io/kubernetes/pkg/volume/util" ) @@ -36,7 +35,7 @@ type CSIMaxVolumeLimitChecker struct { // NewCSIMaxVolumeLimitPredicate returns a predicate for counting CSI volumes func NewCSIMaxVolumeLimitPredicate( - pvInfo PersistentVolumeInfo, pvcInfo PersistentVolumeClaimInfo) algorithm.FitPredicate { + pvInfo PersistentVolumeInfo, pvcInfo PersistentVolumeClaimInfo) FitPredicate { c := &CSIMaxVolumeLimitChecker{ pvInfo: pvInfo, pvcInfo: pvcInfo, @@ -45,7 +44,7 @@ func NewCSIMaxVolumeLimitPredicate( } func (c *CSIMaxVolumeLimitChecker) attachableLimitPredicate( - pod *v1.Pod, meta algorithm.PredicateMetadata, nodeInfo *schedulercache.NodeInfo) (bool, []algorithm.PredicateFailureReason, error) { + pod *v1.Pod, meta PredicateMetadata, nodeInfo *schedulernodeinfo.NodeInfo) (bool, []PredicateFailureReason, error) { // if feature gate is disable we return if !utilfeature.DefaultFeatureGate.Enabled(features.AttachVolumeLimit) { @@ -101,7 +100,7 @@ func (c *CSIMaxVolumeLimitChecker) attachableLimitPredicate( if ok { currentVolumeCount := attachedVolumeCount[volumeLimitKey] if currentVolumeCount+count > int(maxVolumeLimit) { - return false, []algorithm.PredicateFailureReason{ErrMaxVolumeCountExceeded}, nil + return false, []PredicateFailureReason{ErrMaxVolumeCountExceeded}, nil } } } diff --git a/pkg/scheduler/algorithm/predicates/csi_volume_predicate_test.go b/pkg/scheduler/algorithm/predicates/csi_volume_predicate_test.go index 5e34088f4d9..d89da381557 100644 --- a/pkg/scheduler/algorithm/predicates/csi_volume_predicate_test.go +++ b/pkg/scheduler/algorithm/predicates/csi_volume_predicate_test.go @@ -25,7 +25,6 @@ import ( utilfeature "k8s.io/apiserver/pkg/util/feature" utilfeaturetesting "k8s.io/apiserver/pkg/util/feature/testing" "k8s.io/kubernetes/pkg/features" - "k8s.io/kubernetes/pkg/scheduler/algorithm" ) func TestCSIVolumeCountPredicate(t *testing.T) { @@ -105,12 +104,12 @@ func TestCSIVolumeCountPredicate(t *testing.T) { } defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.AttachVolumeLimit, true)() - expectedFailureReasons := []algorithm.PredicateFailureReason{ErrMaxVolumeCountExceeded} + expectedFailureReasons := []PredicateFailureReason{ErrMaxVolumeCountExceeded} // running attachable predicate tests with feature gate and limit present on nodes for _, test := range tests { node := getNodeWithPodAndVolumeLimits(test.existingPods, int64(test.maxVols), test.filterName) pred := NewCSIMaxVolumeLimitPredicate(getFakeCSIPVInfo("csi-ebs", "csi-ebs"), getFakeCSIPVCInfo("csi-ebs")) - fits, reasons, err := pred(test.newPod, PredicateMetadata(test.newPod, nil), node) + fits, reasons, err := pred(test.newPod, GetPredicateMetadata(test.newPod, nil), node) if err != nil { t.Errorf("Using allocatable [%s]%s: unexpected error: %v", test.filterName, test.test, err) } diff --git a/pkg/scheduler/algorithm/predicates/error.go b/pkg/scheduler/algorithm/predicates/error.go index 1e1cbcaa9fa..7f35c84f93e 100644 --- a/pkg/scheduler/algorithm/predicates/error.go +++ b/pkg/scheduler/algorithm/predicates/error.go @@ -63,8 +63,6 @@ var ( ErrNodeUnderDiskPressure = newPredicateFailureError("NodeUnderDiskPressure", "node(s) had disk pressure") // ErrNodeUnderPIDPressure is used for NodeUnderPIDPressure predicate error. ErrNodeUnderPIDPressure = newPredicateFailureError("NodeUnderPIDPressure", "node(s) had pid pressure") - // ErrNodeOutOfDisk is used for NodeOutOfDisk predicate error. - ErrNodeOutOfDisk = newPredicateFailureError("NodeOutOfDisk", "node(s) were out of disk space") // ErrNodeNotReady is used for NodeNotReady predicate error. ErrNodeNotReady = newPredicateFailureError("NodeNotReady", "node(s) were not ready") // ErrNodeNetworkUnavailable is used for NodeNetworkUnavailable predicate error. @@ -136,6 +134,11 @@ func (e *PredicateFailureError) GetReason() string { return e.PredicateDesc } +// PredicateFailureReason interface represents the failure reason of a predicate. +type PredicateFailureReason interface { + GetReason() string +} + // FailureReason describes a failure reason. type FailureReason struct { reason string diff --git a/pkg/scheduler/algorithm/predicates/max_attachable_volume_predicate_test.go b/pkg/scheduler/algorithm/predicates/max_attachable_volume_predicate_test.go index 11434273aa7..24d2f0a70ce 100644 --- a/pkg/scheduler/algorithm/predicates/max_attachable_volume_predicate_test.go +++ b/pkg/scheduler/algorithm/predicates/max_attachable_volume_predicate_test.go @@ -30,8 +30,7 @@ import ( utilfeaturetesting "k8s.io/apiserver/pkg/util/feature/testing" "k8s.io/kubernetes/pkg/features" kubeletapis "k8s.io/kubernetes/pkg/kubelet/apis" - "k8s.io/kubernetes/pkg/scheduler/algorithm" - schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" + schedulernodeinfo "k8s.io/kubernetes/pkg/scheduler/nodeinfo" volumeutil "k8s.io/kubernetes/pkg/volume/util" ) @@ -742,13 +741,13 @@ func TestVolumeCountConflicts(t *testing.T) { }, } - expectedFailureReasons := []algorithm.PredicateFailureReason{ErrMaxVolumeCountExceeded} + expectedFailureReasons := []PredicateFailureReason{ErrMaxVolumeCountExceeded} // running attachable predicate tests without feature gate and no limit present on nodes for _, test := range tests { os.Setenv(KubeMaxPDVols, strconv.Itoa(test.maxVols)) pred := NewMaxPDVolumeCountPredicate(test.filterName, getFakePVInfo(test.filterName), getFakePVCInfo(test.filterName)) - fits, reasons, err := pred(test.newPod, PredicateMetadata(test.newPod, nil), schedulercache.NewNodeInfo(test.existingPods...)) + fits, reasons, err := pred(test.newPod, GetPredicateMetadata(test.newPod, nil), schedulernodeinfo.NewNodeInfo(test.existingPods...)) if err != nil { t.Errorf("[%s]%s: unexpected error: %v", test.filterName, test.test, err) } @@ -766,7 +765,7 @@ func TestVolumeCountConflicts(t *testing.T) { for _, test := range tests { node := getNodeWithPodAndVolumeLimits(test.existingPods, int64(test.maxVols), test.filterName) pred := NewMaxPDVolumeCountPredicate(test.filterName, getFakePVInfo(test.filterName), getFakePVCInfo(test.filterName)) - fits, reasons, err := pred(test.newPod, PredicateMetadata(test.newPod, nil), node) + fits, reasons, err := pred(test.newPod, GetPredicateMetadata(test.newPod, nil), node) if err != nil { t.Errorf("Using allocatable [%s]%s: unexpected error: %v", test.filterName, test.test, err) } @@ -895,8 +894,8 @@ func TestMaxVolumeFuncM4(t *testing.T) { } } -func getNodeWithPodAndVolumeLimits(pods []*v1.Pod, limit int64, filter string) *schedulercache.NodeInfo { - nodeInfo := schedulercache.NewNodeInfo(pods...) +func getNodeWithPodAndVolumeLimits(pods []*v1.Pod, limit int64, filter string) *schedulernodeinfo.NodeInfo { + nodeInfo := schedulernodeinfo.NewNodeInfo(pods...) node := &v1.Node{ ObjectMeta: metav1.ObjectMeta{Name: "node-for-max-pd-test-1"}, Status: v1.NodeStatus{ diff --git a/pkg/scheduler/algorithm/predicates/metadata.go b/pkg/scheduler/algorithm/predicates/metadata.go index 9284cda2381..99baed71ab5 100644 --- a/pkg/scheduler/algorithm/predicates/metadata.go +++ b/pkg/scheduler/algorithm/predicates/metadata.go @@ -30,10 +30,20 @@ import ( "k8s.io/client-go/util/workqueue" "k8s.io/kubernetes/pkg/scheduler/algorithm" priorityutil "k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/util" - schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" + schedulernodeinfo "k8s.io/kubernetes/pkg/scheduler/nodeinfo" schedutil "k8s.io/kubernetes/pkg/scheduler/util" ) +// PredicateMetadata interface represents anything that can access a predicate metadata. +type PredicateMetadata interface { + ShallowCopy() PredicateMetadata + AddPod(addedPod *v1.Pod, nodeInfo *schedulernodeinfo.NodeInfo) error + RemovePod(deletedPod *v1.Pod) error +} + +// PredicateMetadataProducer is a function that computes predicate metadata for a given pod. +type PredicateMetadataProducer func(pod *v1.Pod, nodeNameToInfo map[string]*schedulernodeinfo.NodeInfo) PredicateMetadata + // PredicateMetadataFactory defines a factory of predicate metadata. type PredicateMetadataFactory struct { podLister algorithm.PodLister @@ -68,7 +78,7 @@ type topologyPairsMaps struct { type predicateMetadata struct { pod *v1.Pod podBestEffort bool - podRequest *schedulercache.Resource + podRequest *schedulernodeinfo.Resource podPorts []*v1.ContainerPort topologyPairsAntiAffinityPodsMap *topologyPairsMaps @@ -91,21 +101,27 @@ type predicateMetadata struct { } // Ensure that predicateMetadata implements algorithm.PredicateMetadata. -var _ algorithm.PredicateMetadata = &predicateMetadata{} +var _ PredicateMetadata = &predicateMetadata{} -// PredicateMetadataProducer function produces predicate metadata. -type PredicateMetadataProducer func(pm *predicateMetadata) +// predicateMetadataProducer function produces predicate metadata. It is stored in a global variable below +// and used to modify the return values of PredicateMetadataProducer +type predicateMetadataProducer func(pm *predicateMetadata) var predicateMetaProducerRegisterLock sync.Mutex -var predicateMetadataProducers = make(map[string]PredicateMetadataProducer) +var predicateMetadataProducers = make(map[string]predicateMetadataProducer) // RegisterPredicateMetadataProducer registers a PredicateMetadataProducer. -func RegisterPredicateMetadataProducer(predicateName string, precomp PredicateMetadataProducer) { +func RegisterPredicateMetadataProducer(predicateName string, precomp predicateMetadataProducer) { predicateMetaProducerRegisterLock.Lock() defer predicateMetaProducerRegisterLock.Unlock() predicateMetadataProducers[predicateName] = precomp } +// EmptyPredicateMetadataProducer returns a no-op MetadataProducer type. +func EmptyPredicateMetadataProducer(pod *v1.Pod, nodeNameToInfo map[string]*schedulernodeinfo.NodeInfo) PredicateMetadata { + return nil +} + // RegisterPredicateMetadataProducerWithExtendedResourceOptions registers a // PredicateMetadataProducer that creates predicate metadata with the provided // options for extended resources. @@ -118,7 +134,7 @@ func RegisterPredicateMetadataProducerWithExtendedResourceOptions(ignoredExtende } // NewPredicateMetadataFactory creates a PredicateMetadataFactory. -func NewPredicateMetadataFactory(podLister algorithm.PodLister) algorithm.PredicateMetadataProducer { +func NewPredicateMetadataFactory(podLister algorithm.PodLister) PredicateMetadataProducer { factory := &PredicateMetadataFactory{ podLister, } @@ -126,7 +142,7 @@ func NewPredicateMetadataFactory(podLister algorithm.PodLister) algorithm.Predic } // GetMetadata returns the predicateMetadata used which will be used by various predicates. -func (pfactory *PredicateMetadataFactory) GetMetadata(pod *v1.Pod, nodeNameToInfoMap map[string]*schedulercache.NodeInfo) algorithm.PredicateMetadata { +func (pfactory *PredicateMetadataFactory) GetMetadata(pod *v1.Pod, nodeNameToInfoMap map[string]*schedulernodeinfo.NodeInfo) PredicateMetadata { // If we cannot compute metadata, just return nil if pod == nil { return nil @@ -230,7 +246,7 @@ func (meta *predicateMetadata) RemovePod(deletedPod *v1.Pod) error { // AddPod changes predicateMetadata assuming that `newPod` is added to the // system. -func (meta *predicateMetadata) AddPod(addedPod *v1.Pod, nodeInfo *schedulercache.NodeInfo) error { +func (meta *predicateMetadata) AddPod(addedPod *v1.Pod, nodeInfo *schedulernodeinfo.NodeInfo) error { addedPodFullName := schedutil.GetPodFullName(addedPod) if addedPodFullName == schedutil.GetPodFullName(meta.pod) { return fmt.Errorf("addedPod and meta.pod must not be the same") @@ -285,7 +301,7 @@ func (meta *predicateMetadata) AddPod(addedPod *v1.Pod, nodeInfo *schedulercache // ShallowCopy copies a metadata struct into a new struct and creates a copy of // its maps and slices, but it does not copy the contents of pointer values. -func (meta *predicateMetadata) ShallowCopy() algorithm.PredicateMetadata { +func (meta *predicateMetadata) ShallowCopy() PredicateMetadata { newPredMeta := &predicateMetadata{ pod: meta.pod, podBestEffort: meta.podBestEffort, @@ -304,7 +320,7 @@ func (meta *predicateMetadata) ShallowCopy() algorithm.PredicateMetadata { meta.serviceAffinityMatchingPodServices...) newPredMeta.serviceAffinityMatchingPodList = append([]*v1.Pod(nil), meta.serviceAffinityMatchingPodList...) - return (algorithm.PredicateMetadata)(newPredMeta) + return (PredicateMetadata)(newPredMeta) } type affinityTermProperties struct { @@ -359,7 +375,7 @@ func podMatchesAnyAffinityTermProperties(pod *v1.Pod, properties []*affinityTerm // getTPMapMatchingExistingAntiAffinity calculates the following for each existing pod on each node: // (1) Whether it has PodAntiAffinity // (2) Whether any AffinityTerm matches the incoming pod -func getTPMapMatchingExistingAntiAffinity(pod *v1.Pod, nodeInfoMap map[string]*schedulercache.NodeInfo) (*topologyPairsMaps, error) { +func getTPMapMatchingExistingAntiAffinity(pod *v1.Pod, nodeInfoMap map[string]*schedulernodeinfo.NodeInfo) (*topologyPairsMaps, error) { allNodeNames := make([]string, 0, len(nodeInfoMap)) for name := range nodeInfoMap { allNodeNames = append(allNodeNames, name) @@ -407,7 +423,7 @@ func getTPMapMatchingExistingAntiAffinity(pod *v1.Pod, nodeInfoMap map[string]*s // It returns a topologyPairsMaps that are checked later by the affinity // predicate. With this topologyPairsMaps available, the affinity predicate does not // need to check all the pods in the cluster. -func getTPMapMatchingIncomingAffinityAntiAffinity(pod *v1.Pod, nodeInfoMap map[string]*schedulercache.NodeInfo) (topologyPairsAffinityPodsMaps *topologyPairsMaps, topologyPairsAntiAffinityPodsMaps *topologyPairsMaps, err error) { +func getTPMapMatchingIncomingAffinityAntiAffinity(pod *v1.Pod, nodeInfoMap map[string]*schedulernodeinfo.NodeInfo) (topologyPairsAffinityPodsMaps *topologyPairsMaps, topologyPairsAntiAffinityPodsMaps *topologyPairsMaps, err error) { affinity := pod.Spec.Affinity if affinity == nil || (affinity.PodAffinity == nil && affinity.PodAntiAffinity == nil) { return newTopologyPairsMaps(), newTopologyPairsMaps(), nil diff --git a/pkg/scheduler/algorithm/predicates/metadata_test.go b/pkg/scheduler/algorithm/predicates/metadata_test.go index 7fb1e1f3115..3ab656dc30a 100644 --- a/pkg/scheduler/algorithm/predicates/metadata_test.go +++ b/pkg/scheduler/algorithm/predicates/metadata_test.go @@ -24,7 +24,7 @@ import ( "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" + schedulernodeinfo "k8s.io/kubernetes/pkg/scheduler/nodeinfo" schedulertesting "k8s.io/kubernetes/pkg/scheduler/testing" ) @@ -354,8 +354,8 @@ func TestPredicateMetadata_AddRemovePod(t *testing.T) { t.Run(test.name, func(t *testing.T) { allPodLister := schedulertesting.FakePodLister(append(test.existingPods, test.addedPod)) // getMeta creates predicate meta data given the list of pods. - getMeta := func(lister schedulertesting.FakePodLister) (*predicateMetadata, map[string]*schedulercache.NodeInfo) { - nodeInfoMap := schedulercache.CreateNodeNameToInfoMap(lister, test.nodes) + getMeta := func(lister schedulertesting.FakePodLister) (*predicateMetadata, map[string]*schedulernodeinfo.NodeInfo) { + nodeInfoMap := schedulernodeinfo.CreateNodeNameToInfoMap(lister, test.nodes) // nodeList is a list of non-pointer nodes to feed to FakeNodeListInfo. nodeList := []v1.Node{} for _, n := range test.nodes { @@ -407,7 +407,7 @@ func TestPredicateMetadata_ShallowCopy(t *testing.T) { }, }, podBestEffort: true, - podRequest: &schedulercache.Resource{ + podRequest: &schedulernodeinfo.Resource{ MilliCPU: 1000, Memory: 300, AllowedPodNumber: 4, @@ -775,7 +775,7 @@ func TestGetTPMapMatchingIncomingAffinityAntiAffinity(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - nodeInfoMap := schedulercache.CreateNodeNameToInfoMap(tt.existingPods, tt.nodes) + nodeInfoMap := schedulernodeinfo.CreateNodeNameToInfoMap(tt.existingPods, tt.nodes) gotAffinityPodsMaps, gotAntiAffinityPodsMaps, err := getTPMapMatchingIncomingAffinityAntiAffinity(tt.pod, nodeInfoMap) if (err != nil) != tt.wantErr { diff --git a/pkg/scheduler/algorithm/predicates/predicates.go b/pkg/scheduler/algorithm/predicates/predicates.go index 7594c76405d..3fcc02b0ca9 100644 --- a/pkg/scheduler/algorithm/predicates/predicates.go +++ b/pkg/scheduler/algorithm/predicates/predicates.go @@ -43,7 +43,7 @@ import ( "k8s.io/kubernetes/pkg/scheduler/algorithm" priorityutil "k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/util" schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" - schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" + schedulernodeinfo "k8s.io/kubernetes/pkg/scheduler/nodeinfo" schedutil "k8s.io/kubernetes/pkg/scheduler/util" "k8s.io/kubernetes/pkg/scheduler/volumebinder" volumeutil "k8s.io/kubernetes/pkg/volume/util" @@ -137,6 +137,10 @@ var ( CheckNodeMemoryPressurePred, CheckNodePIDPressurePred, CheckNodeDiskPressurePred, MatchInterPodAffinityPred} ) +// FitPredicate is a function that indicates if a pod fits into an existing node. +// The failure information is given by the error. +type FitPredicate func(pod *v1.Pod, meta PredicateMetadata, nodeInfo *schedulernodeinfo.NodeInfo) (bool, []PredicateFailureReason, error) + // NodeInfo interface represents anything that can get node object from node ID. type NodeInfo interface { GetNodeInfo(nodeID string) (*v1.Node, error) @@ -274,11 +278,11 @@ func isVolumeConflict(volume v1.Volume, pod *v1.Pod) bool { // - Ceph RBD forbids if any two pods share at least same monitor, and match pool and image. // - ISCSI forbids if any two pods share at least same IQN, LUN and Target // TODO: migrate this into some per-volume specific code? -func NoDiskConflict(pod *v1.Pod, meta algorithm.PredicateMetadata, nodeInfo *schedulercache.NodeInfo) (bool, []algorithm.PredicateFailureReason, error) { +func NoDiskConflict(pod *v1.Pod, meta PredicateMetadata, nodeInfo *schedulernodeinfo.NodeInfo) (bool, []PredicateFailureReason, error) { for _, v := range pod.Spec.Volumes { for _, ev := range nodeInfo.Pods() { if isVolumeConflict(v, ev) { - return false, []algorithm.PredicateFailureReason{ErrDiskConflict}, nil + return false, []PredicateFailureReason{ErrDiskConflict}, nil } } } @@ -313,7 +317,7 @@ type VolumeFilter struct { // types, counts the number of unique volumes, and rejects the new pod if it would place the total count over // the maximum. func NewMaxPDVolumeCountPredicate( - filterName string, pvInfo PersistentVolumeInfo, pvcInfo PersistentVolumeClaimInfo) algorithm.FitPredicate { + filterName string, pvInfo PersistentVolumeInfo, pvcInfo PersistentVolumeClaimInfo) FitPredicate { var filter VolumeFilter var volumeLimitKey v1.ResourceName @@ -447,7 +451,7 @@ func (c *MaxPDVolumeCountChecker) filterVolumes(volumes []v1.Volume, namespace s return nil } -func (c *MaxPDVolumeCountChecker) predicate(pod *v1.Pod, meta algorithm.PredicateMetadata, nodeInfo *schedulercache.NodeInfo) (bool, []algorithm.PredicateFailureReason, error) { +func (c *MaxPDVolumeCountChecker) predicate(pod *v1.Pod, meta PredicateMetadata, nodeInfo *schedulernodeinfo.NodeInfo) (bool, []PredicateFailureReason, error) { // If a pod doesn't have any volume attached to it, the predicate will always be true. // Thus we make a fast path for it, to avoid unnecessary computations in this case. if len(pod.Spec.Volumes) == 0 { @@ -492,7 +496,7 @@ func (c *MaxPDVolumeCountChecker) predicate(pod *v1.Pod, meta algorithm.Predicat if numExistingVolumes+numNewVolumes > maxAttachLimit { // violates MaxEBSVolumeCount or MaxGCEPDVolumeCount - return false, []algorithm.PredicateFailureReason{ErrMaxVolumeCountExceeded}, nil + return false, []PredicateFailureReason{ErrMaxVolumeCountExceeded}, nil } if nodeInfo != nil && nodeInfo.TransientInfo != nil && utilfeature.DefaultFeatureGate.Enabled(features.BalanceAttachedNodeVolumes) { nodeInfo.TransientInfo.TransientLock.Lock() @@ -575,7 +579,7 @@ type VolumeZoneChecker struct { // determining the zone of a volume during scheduling, and that is likely to // require calling out to the cloud provider. It seems that we are moving away // from inline volume declarations anyway. -func NewVolumeZonePredicate(pvInfo PersistentVolumeInfo, pvcInfo PersistentVolumeClaimInfo, classInfo StorageClassInfo) algorithm.FitPredicate { +func NewVolumeZonePredicate(pvInfo PersistentVolumeInfo, pvcInfo PersistentVolumeClaimInfo, classInfo StorageClassInfo) FitPredicate { c := &VolumeZoneChecker{ pvInfo: pvInfo, pvcInfo: pvcInfo, @@ -584,7 +588,7 @@ func NewVolumeZonePredicate(pvInfo PersistentVolumeInfo, pvcInfo PersistentVolum return c.predicate } -func (c *VolumeZoneChecker) predicate(pod *v1.Pod, meta algorithm.PredicateMetadata, nodeInfo *schedulercache.NodeInfo) (bool, []algorithm.PredicateFailureReason, error) { +func (c *VolumeZoneChecker) predicate(pod *v1.Pod, meta PredicateMetadata, nodeInfo *schedulernodeinfo.NodeInfo) (bool, []PredicateFailureReason, error) { // If a pod doesn't have any volume attached to it, the predicate will always be true. // Thus we make a fast path for it, to avoid unnecessary computations in this case. if len(pod.Spec.Volumes) == 0 { @@ -631,18 +635,16 @@ func (c *VolumeZoneChecker) predicate(pod *v1.Pod, meta algorithm.PredicateMetad pvName := pvc.Spec.VolumeName if pvName == "" { - if utilfeature.DefaultFeatureGate.Enabled(features.VolumeScheduling) { - scName := v1helper.GetPersistentVolumeClaimClass(pvc) - if len(scName) > 0 { - class, _ := c.classInfo.GetStorageClassInfo(scName) - if class != nil { - if class.VolumeBindingMode == nil { - return false, nil, fmt.Errorf("VolumeBindingMode not set for StorageClass %q", scName) - } - if *class.VolumeBindingMode == storagev1.VolumeBindingWaitForFirstConsumer { - // Skip unbound volumes - continue - } + scName := v1helper.GetPersistentVolumeClaimClass(pvc) + if len(scName) > 0 { + class, _ := c.classInfo.GetStorageClassInfo(scName) + if class != nil { + if class.VolumeBindingMode == nil { + return false, nil, fmt.Errorf("VolumeBindingMode not set for StorageClass %q", scName) + } + if *class.VolumeBindingMode == storagev1.VolumeBindingWaitForFirstConsumer { + // Skip unbound volumes + continue } } } @@ -671,7 +673,7 @@ func (c *VolumeZoneChecker) predicate(pod *v1.Pod, meta algorithm.PredicateMetad if !volumeVSet.Has(nodeV) { klog.V(10).Infof("Won't schedule pod %q onto node %q due to volume %q (mismatch on %q)", pod.Name, node.Name, pvName, k) - return false, []algorithm.PredicateFailureReason{ErrVolumeZoneConflict}, nil + return false, []PredicateFailureReason{ErrVolumeZoneConflict}, nil } } } @@ -680,7 +682,7 @@ func (c *VolumeZoneChecker) predicate(pod *v1.Pod, meta algorithm.PredicateMetad return true, nil, nil } -// GetResourceRequest returns a *schedulercache.Resource that covers the largest +// GetResourceRequest returns a *schedulernodeinfo.Resource that covers the largest // width in each resource dimension. Because init-containers run sequentially, we collect // the max in each dimension iteratively. In contrast, we sum the resource vectors for // regular containers since they run simultaneously. @@ -704,8 +706,8 @@ func (c *VolumeZoneChecker) predicate(pod *v1.Pod, meta algorithm.PredicateMetad // Memory: 1G // // Result: CPU: 3, Memory: 3G -func GetResourceRequest(pod *v1.Pod) *schedulercache.Resource { - result := &schedulercache.Resource{} +func GetResourceRequest(pod *v1.Pod) *schedulernodeinfo.Resource { + result := &schedulernodeinfo.Resource{} for _, container := range pod.Spec.Containers { result.Add(container.Resources.Requests) } @@ -725,13 +727,13 @@ func podName(pod *v1.Pod) string { // PodFitsResources checks if a node has sufficient resources, such as cpu, memory, gpu, opaque int resources etc to run a pod. // First return value indicates whether a node has sufficient resources to run a pod while the second return value indicates the // predicate failure reasons if the node has insufficient resources to run the pod. -func PodFitsResources(pod *v1.Pod, meta algorithm.PredicateMetadata, nodeInfo *schedulercache.NodeInfo) (bool, []algorithm.PredicateFailureReason, error) { +func PodFitsResources(pod *v1.Pod, meta PredicateMetadata, nodeInfo *schedulernodeinfo.NodeInfo) (bool, []PredicateFailureReason, error) { node := nodeInfo.Node() if node == nil { return false, nil, fmt.Errorf("node not found") } - var predicateFails []algorithm.PredicateFailureReason + var predicateFails []PredicateFailureReason allowedPodNumber := nodeInfo.AllowedPodNumber() if len(nodeInfo.Pods())+1 > allowedPodNumber { predicateFails = append(predicateFails, NewInsufficientResourceError(v1.ResourcePods, 1, int64(len(nodeInfo.Pods())), int64(allowedPodNumber))) @@ -740,7 +742,7 @@ func PodFitsResources(pod *v1.Pod, meta algorithm.PredicateMetadata, nodeInfo *s // No extended resources should be ignored by default. ignoredExtendedResources := sets.NewString() - var podRequest *schedulercache.Resource + var podRequest *schedulernodeinfo.Resource if predicateMeta, ok := meta.(*predicateMetadata); ok { podRequest = predicateMeta.podRequest if predicateMeta.ignoredExtendedResources != nil { @@ -850,7 +852,7 @@ func podMatchesNodeSelectorAndAffinityTerms(pod *v1.Pod, node *v1.Node) bool { } // PodMatchNodeSelector checks if a pod node selector matches the node label. -func PodMatchNodeSelector(pod *v1.Pod, meta algorithm.PredicateMetadata, nodeInfo *schedulercache.NodeInfo) (bool, []algorithm.PredicateFailureReason, error) { +func PodMatchNodeSelector(pod *v1.Pod, meta PredicateMetadata, nodeInfo *schedulernodeinfo.NodeInfo) (bool, []PredicateFailureReason, error) { node := nodeInfo.Node() if node == nil { return false, nil, fmt.Errorf("node not found") @@ -858,11 +860,11 @@ func PodMatchNodeSelector(pod *v1.Pod, meta algorithm.PredicateMetadata, nodeInf if podMatchesNodeSelectorAndAffinityTerms(pod, node) { return true, nil, nil } - return false, []algorithm.PredicateFailureReason{ErrNodeSelectorNotMatch}, nil + return false, []PredicateFailureReason{ErrNodeSelectorNotMatch}, nil } // PodFitsHost checks if a pod spec node name matches the current node. -func PodFitsHost(pod *v1.Pod, meta algorithm.PredicateMetadata, nodeInfo *schedulercache.NodeInfo) (bool, []algorithm.PredicateFailureReason, error) { +func PodFitsHost(pod *v1.Pod, meta PredicateMetadata, nodeInfo *schedulernodeinfo.NodeInfo) (bool, []PredicateFailureReason, error) { if len(pod.Spec.NodeName) == 0 { return true, nil, nil } @@ -873,7 +875,7 @@ func PodFitsHost(pod *v1.Pod, meta algorithm.PredicateMetadata, nodeInfo *schedu if pod.Spec.NodeName == node.Name { return true, nil, nil } - return false, []algorithm.PredicateFailureReason{ErrPodNotMatchHostName}, nil + return false, []PredicateFailureReason{ErrPodNotMatchHostName}, nil } // NodeLabelChecker contains information to check node labels for a predicate. @@ -884,7 +886,7 @@ type NodeLabelChecker struct { // NewNodeLabelPredicate creates a predicate which evaluates whether a pod can fit based on the // node labels which match a filter that it requests. -func NewNodeLabelPredicate(labels []string, presence bool) algorithm.FitPredicate { +func NewNodeLabelPredicate(labels []string, presence bool) FitPredicate { labelChecker := &NodeLabelChecker{ labels: labels, presence: presence, @@ -904,7 +906,7 @@ func NewNodeLabelPredicate(labels []string, presence bool) algorithm.FitPredicat // Alternately, eliminating nodes that have a certain label, regardless of value, is also useful // A node may have a label with "retiring" as key and the date as the value // and it may be desirable to avoid scheduling new pods on this node -func (n *NodeLabelChecker) CheckNodeLabelPresence(pod *v1.Pod, meta algorithm.PredicateMetadata, nodeInfo *schedulercache.NodeInfo) (bool, []algorithm.PredicateFailureReason, error) { +func (n *NodeLabelChecker) CheckNodeLabelPresence(pod *v1.Pod, meta PredicateMetadata, nodeInfo *schedulernodeinfo.NodeInfo) (bool, []PredicateFailureReason, error) { node := nodeInfo.Node() if node == nil { return false, nil, fmt.Errorf("node not found") @@ -915,7 +917,7 @@ func (n *NodeLabelChecker) CheckNodeLabelPresence(pod *v1.Pod, meta algorithm.Pr for _, label := range n.labels { exists = nodeLabels.Has(label) if (exists && !n.presence) || (!exists && n.presence) { - return false, []algorithm.PredicateFailureReason{ErrNodeLabelPresenceViolated}, nil + return false, []PredicateFailureReason{ErrNodeLabelPresenceViolated}, nil } } return true, nil, nil @@ -952,7 +954,7 @@ func (s *ServiceAffinity) serviceAffinityMetadataProducer(pm *predicateMetadata) } // NewServiceAffinityPredicate creates a ServiceAffinity. -func NewServiceAffinityPredicate(podLister algorithm.PodLister, serviceLister algorithm.ServiceLister, nodeInfo NodeInfo, labels []string) (algorithm.FitPredicate, PredicateMetadataProducer) { +func NewServiceAffinityPredicate(podLister algorithm.PodLister, serviceLister algorithm.ServiceLister, nodeInfo NodeInfo, labels []string) (FitPredicate, predicateMetadataProducer) { affinity := &ServiceAffinity{ podLister: podLister, serviceLister: serviceLister, @@ -989,7 +991,7 @@ func NewServiceAffinityPredicate(podLister algorithm.PodLister, serviceLister al // // WARNING: This Predicate is NOT guaranteed to work if some of the predicateMetadata data isn't precomputed... // For that reason it is not exported, i.e. it is highly coupled to the implementation of the FitPredicate construction. -func (s *ServiceAffinity) checkServiceAffinity(pod *v1.Pod, meta algorithm.PredicateMetadata, nodeInfo *schedulercache.NodeInfo) (bool, []algorithm.PredicateFailureReason, error) { +func (s *ServiceAffinity) checkServiceAffinity(pod *v1.Pod, meta PredicateMetadata, nodeInfo *schedulernodeinfo.NodeInfo) (bool, []PredicateFailureReason, error) { var services []*v1.Service var pods []*v1.Pod if pm, ok := meta.(*predicateMetadata); ok && (pm.serviceAffinityMatchingPodList != nil || pm.serviceAffinityMatchingPodServices != nil) { @@ -1024,11 +1026,11 @@ func (s *ServiceAffinity) checkServiceAffinity(pod *v1.Pod, meta algorithm.Predi if CreateSelectorFromLabels(affinityLabels).Matches(labels.Set(node.Labels)) { return true, nil, nil } - return false, []algorithm.PredicateFailureReason{ErrServiceAffinityViolated}, nil + return false, []PredicateFailureReason{ErrServiceAffinityViolated}, nil } // PodFitsHostPorts checks if a node has free ports for the requested pod ports. -func PodFitsHostPorts(pod *v1.Pod, meta algorithm.PredicateMetadata, nodeInfo *schedulercache.NodeInfo) (bool, []algorithm.PredicateFailureReason, error) { +func PodFitsHostPorts(pod *v1.Pod, meta PredicateMetadata, nodeInfo *schedulernodeinfo.NodeInfo) (bool, []PredicateFailureReason, error) { var wantPorts []*v1.ContainerPort if predicateMeta, ok := meta.(*predicateMetadata); ok { wantPorts = predicateMeta.podPorts @@ -1044,7 +1046,7 @@ func PodFitsHostPorts(pod *v1.Pod, meta algorithm.PredicateMetadata, nodeInfo *s // try to see whether existingPorts and wantPorts will conflict or not if portsConflict(existingPorts, wantPorts) { - return false, []algorithm.PredicateFailureReason{ErrPodNotFitsHostPorts}, nil + return false, []PredicateFailureReason{ErrPodNotFitsHostPorts}, nil } return true, nil, nil @@ -1068,8 +1070,8 @@ func haveOverlap(a1, a2 []string) bool { // GeneralPredicates checks whether noncriticalPredicates and EssentialPredicates pass. noncriticalPredicates are the predicates // that only non-critical pods need and EssentialPredicates are the predicates that all pods, including critical pods, need -func GeneralPredicates(pod *v1.Pod, meta algorithm.PredicateMetadata, nodeInfo *schedulercache.NodeInfo) (bool, []algorithm.PredicateFailureReason, error) { - var predicateFails []algorithm.PredicateFailureReason +func GeneralPredicates(pod *v1.Pod, meta PredicateMetadata, nodeInfo *schedulernodeinfo.NodeInfo) (bool, []PredicateFailureReason, error) { + var predicateFails []PredicateFailureReason fit, reasons, err := noncriticalPredicates(pod, meta, nodeInfo) if err != nil { return false, predicateFails, err @@ -1090,8 +1092,8 @@ func GeneralPredicates(pod *v1.Pod, meta algorithm.PredicateMetadata, nodeInfo * } // noncriticalPredicates are the predicates that only non-critical pods need -func noncriticalPredicates(pod *v1.Pod, meta algorithm.PredicateMetadata, nodeInfo *schedulercache.NodeInfo) (bool, []algorithm.PredicateFailureReason, error) { - var predicateFails []algorithm.PredicateFailureReason +func noncriticalPredicates(pod *v1.Pod, meta PredicateMetadata, nodeInfo *schedulernodeinfo.NodeInfo) (bool, []PredicateFailureReason, error) { + var predicateFails []PredicateFailureReason fit, reasons, err := PodFitsResources(pod, meta, nodeInfo) if err != nil { return false, predicateFails, err @@ -1104,8 +1106,8 @@ func noncriticalPredicates(pod *v1.Pod, meta algorithm.PredicateMetadata, nodeIn } // EssentialPredicates are the predicates that all pods, including critical pods, need -func EssentialPredicates(pod *v1.Pod, meta algorithm.PredicateMetadata, nodeInfo *schedulercache.NodeInfo) (bool, []algorithm.PredicateFailureReason, error) { - var predicateFails []algorithm.PredicateFailureReason +func EssentialPredicates(pod *v1.Pod, meta PredicateMetadata, nodeInfo *schedulernodeinfo.NodeInfo) (bool, []PredicateFailureReason, error) { + var predicateFails []PredicateFailureReason fit, reasons, err := PodFitsHost(pod, meta, nodeInfo) if err != nil { return false, predicateFails, err @@ -1141,7 +1143,7 @@ type PodAffinityChecker struct { } // NewPodAffinityPredicate creates a PodAffinityChecker. -func NewPodAffinityPredicate(info NodeInfo, podLister algorithm.PodLister) algorithm.FitPredicate { +func NewPodAffinityPredicate(info NodeInfo, podLister algorithm.PodLister) FitPredicate { checker := &PodAffinityChecker{ info: info, podLister: podLister, @@ -1152,13 +1154,13 @@ func NewPodAffinityPredicate(info NodeInfo, podLister algorithm.PodLister) algor // InterPodAffinityMatches checks if a pod can be scheduled on the specified node with pod affinity/anti-affinity configuration. // First return value indicates whether a pod can be scheduled on the specified node while the second return value indicates the // predicate failure reasons if the pod cannot be scheduled on the specified node. -func (c *PodAffinityChecker) InterPodAffinityMatches(pod *v1.Pod, meta algorithm.PredicateMetadata, nodeInfo *schedulercache.NodeInfo) (bool, []algorithm.PredicateFailureReason, error) { +func (c *PodAffinityChecker) InterPodAffinityMatches(pod *v1.Pod, meta PredicateMetadata, nodeInfo *schedulernodeinfo.NodeInfo) (bool, []PredicateFailureReason, error) { node := nodeInfo.Node() if node == nil { return false, nil, fmt.Errorf("node not found") } if failedPredicates, error := c.satisfiesExistingPodsAntiAffinity(pod, meta, nodeInfo); failedPredicates != nil { - failedPredicates := append([]algorithm.PredicateFailureReason{ErrPodAffinityNotMatch}, failedPredicates) + failedPredicates := append([]PredicateFailureReason{ErrPodAffinityNotMatch}, failedPredicates) return false, failedPredicates, error } @@ -1168,7 +1170,7 @@ func (c *PodAffinityChecker) InterPodAffinityMatches(pod *v1.Pod, meta algorithm return true, nil, nil } if failedPredicates, error := c.satisfiesPodsAffinityAntiAffinity(pod, meta, nodeInfo, affinity); failedPredicates != nil { - failedPredicates := append([]algorithm.PredicateFailureReason{ErrPodAffinityNotMatch}, failedPredicates) + failedPredicates := append([]PredicateFailureReason{ErrPodAffinityNotMatch}, failedPredicates) return false, failedPredicates, error } @@ -1186,7 +1188,7 @@ func (c *PodAffinityChecker) InterPodAffinityMatches(pod *v1.Pod, meta algorithm // targetPod matches all the terms and their topologies, 2) whether targetPod // matches all the terms label selector and namespaces (AKA term properties), // 3) any error. -func (c *PodAffinityChecker) podMatchesPodAffinityTerms(pod, targetPod *v1.Pod, nodeInfo *schedulercache.NodeInfo, terms []v1.PodAffinityTerm) (bool, bool, error) { +func (c *PodAffinityChecker) podMatchesPodAffinityTerms(pod, targetPod *v1.Pod, nodeInfo *schedulernodeinfo.NodeInfo, terms []v1.PodAffinityTerm) (bool, bool, error) { if len(terms) == 0 { return false, false, fmt.Errorf("terms array is empty") } @@ -1290,7 +1292,7 @@ func (c *PodAffinityChecker) getMatchingAntiAffinityTopologyPairsOfPods(pod *v1. // Checks if scheduling the pod onto this node would break any anti-affinity // terms indicated by the existing pods. -func (c *PodAffinityChecker) satisfiesExistingPodsAntiAffinity(pod *v1.Pod, meta algorithm.PredicateMetadata, nodeInfo *schedulercache.NodeInfo) (algorithm.PredicateFailureReason, error) { +func (c *PodAffinityChecker) satisfiesExistingPodsAntiAffinity(pod *v1.Pod, meta PredicateMetadata, nodeInfo *schedulernodeinfo.NodeInfo) (PredicateFailureReason, error) { node := nodeInfo.Node() if node == nil { return ErrExistingPodsAntiAffinityRulesNotMatch, fmt.Errorf("Node is nil") @@ -1333,7 +1335,7 @@ func (c *PodAffinityChecker) satisfiesExistingPodsAntiAffinity(pod *v1.Pod, meta // nodeMatchesAllTopologyTerms checks whether "nodeInfo" matches // topology of all the "terms" for the given "pod". -func (c *PodAffinityChecker) nodeMatchesAllTopologyTerms(pod *v1.Pod, topologyPairs *topologyPairsMaps, nodeInfo *schedulercache.NodeInfo, terms []v1.PodAffinityTerm) bool { +func (c *PodAffinityChecker) nodeMatchesAllTopologyTerms(pod *v1.Pod, topologyPairs *topologyPairsMaps, nodeInfo *schedulernodeinfo.NodeInfo, terms []v1.PodAffinityTerm) bool { node := nodeInfo.Node() for _, term := range terms { if topologyValue, ok := node.Labels[term.TopologyKey]; ok { @@ -1350,7 +1352,7 @@ func (c *PodAffinityChecker) nodeMatchesAllTopologyTerms(pod *v1.Pod, topologyPa // nodeMatchesAnyTopologyTerm checks whether "nodeInfo" matches // topology of any "term" for the given "pod". -func (c *PodAffinityChecker) nodeMatchesAnyTopologyTerm(pod *v1.Pod, topologyPairs *topologyPairsMaps, nodeInfo *schedulercache.NodeInfo, terms []v1.PodAffinityTerm) bool { +func (c *PodAffinityChecker) nodeMatchesAnyTopologyTerm(pod *v1.Pod, topologyPairs *topologyPairsMaps, nodeInfo *schedulernodeinfo.NodeInfo, terms []v1.PodAffinityTerm) bool { node := nodeInfo.Node() for _, term := range terms { if topologyValue, ok := node.Labels[term.TopologyKey]; ok { @@ -1365,8 +1367,8 @@ func (c *PodAffinityChecker) nodeMatchesAnyTopologyTerm(pod *v1.Pod, topologyPai // Checks if scheduling the pod onto this node would break any term of this pod. func (c *PodAffinityChecker) satisfiesPodsAffinityAntiAffinity(pod *v1.Pod, - meta algorithm.PredicateMetadata, nodeInfo *schedulercache.NodeInfo, - affinity *v1.Affinity) (algorithm.PredicateFailureReason, error) { + meta PredicateMetadata, nodeInfo *schedulernodeinfo.NodeInfo, + affinity *v1.Affinity) (PredicateFailureReason, error) { node := nodeInfo.Node() if node == nil { return ErrPodAffinityRulesNotMatch, fmt.Errorf("Node is nil") @@ -1466,9 +1468,9 @@ func (c *PodAffinityChecker) satisfiesPodsAffinityAntiAffinity(pod *v1.Pod, } // CheckNodeUnschedulablePredicate checks if a pod can be scheduled on a node with Unschedulable spec. -func CheckNodeUnschedulablePredicate(pod *v1.Pod, meta algorithm.PredicateMetadata, nodeInfo *schedulercache.NodeInfo) (bool, []algorithm.PredicateFailureReason, error) { +func CheckNodeUnschedulablePredicate(pod *v1.Pod, meta PredicateMetadata, nodeInfo *schedulernodeinfo.NodeInfo) (bool, []PredicateFailureReason, error) { if nodeInfo == nil || nodeInfo.Node() == nil { - return false, []algorithm.PredicateFailureReason{ErrNodeUnknownCondition}, nil + return false, []PredicateFailureReason{ErrNodeUnknownCondition}, nil } // If pod tolerate unschedulable taint, it's also tolerate `node.Spec.Unschedulable`. @@ -1479,16 +1481,16 @@ func CheckNodeUnschedulablePredicate(pod *v1.Pod, meta algorithm.PredicateMetada // TODO (k82cn): deprecates `node.Spec.Unschedulable` in 1.13. if nodeInfo.Node().Spec.Unschedulable && !podToleratesUnschedulable { - return false, []algorithm.PredicateFailureReason{ErrNodeUnschedulable}, nil + return false, []PredicateFailureReason{ErrNodeUnschedulable}, nil } return true, nil, nil } // PodToleratesNodeTaints checks if a pod tolerations can tolerate the node taints -func PodToleratesNodeTaints(pod *v1.Pod, meta algorithm.PredicateMetadata, nodeInfo *schedulercache.NodeInfo) (bool, []algorithm.PredicateFailureReason, error) { +func PodToleratesNodeTaints(pod *v1.Pod, meta PredicateMetadata, nodeInfo *schedulernodeinfo.NodeInfo) (bool, []PredicateFailureReason, error) { if nodeInfo == nil || nodeInfo.Node() == nil { - return false, []algorithm.PredicateFailureReason{ErrNodeUnknownCondition}, nil + return false, []PredicateFailureReason{ErrNodeUnknownCondition}, nil } return podToleratesNodeTaints(pod, nodeInfo, func(t *v1.Taint) bool { @@ -1498,13 +1500,13 @@ func PodToleratesNodeTaints(pod *v1.Pod, meta algorithm.PredicateMetadata, nodeI } // PodToleratesNodeNoExecuteTaints checks if a pod tolerations can tolerate the node's NoExecute taints -func PodToleratesNodeNoExecuteTaints(pod *v1.Pod, meta algorithm.PredicateMetadata, nodeInfo *schedulercache.NodeInfo) (bool, []algorithm.PredicateFailureReason, error) { +func PodToleratesNodeNoExecuteTaints(pod *v1.Pod, meta PredicateMetadata, nodeInfo *schedulernodeinfo.NodeInfo) (bool, []PredicateFailureReason, error) { return podToleratesNodeTaints(pod, nodeInfo, func(t *v1.Taint) bool { return t.Effect == v1.TaintEffectNoExecute }) } -func podToleratesNodeTaints(pod *v1.Pod, nodeInfo *schedulercache.NodeInfo, filter func(t *v1.Taint) bool) (bool, []algorithm.PredicateFailureReason, error) { +func podToleratesNodeTaints(pod *v1.Pod, nodeInfo *schedulernodeinfo.NodeInfo, filter func(t *v1.Taint) bool) (bool, []PredicateFailureReason, error) { taints, err := nodeInfo.Taints() if err != nil { return false, nil, err @@ -1513,7 +1515,7 @@ func podToleratesNodeTaints(pod *v1.Pod, nodeInfo *schedulercache.NodeInfo, filt if v1helper.TolerationsTolerateTaintsWithFilter(pod.Spec.Tolerations, taints, filter) { return true, nil, nil } - return false, []algorithm.PredicateFailureReason{ErrTaintsTolerationsNotMatch}, nil + return false, []PredicateFailureReason{ErrTaintsTolerationsNotMatch}, nil } // isPodBestEffort checks if pod is scheduled with best-effort QoS @@ -1523,7 +1525,7 @@ func isPodBestEffort(pod *v1.Pod) bool { // CheckNodeMemoryPressurePredicate checks if a pod can be scheduled on a node // reporting memory pressure condition. -func CheckNodeMemoryPressurePredicate(pod *v1.Pod, meta algorithm.PredicateMetadata, nodeInfo *schedulercache.NodeInfo) (bool, []algorithm.PredicateFailureReason, error) { +func CheckNodeMemoryPressurePredicate(pod *v1.Pod, meta PredicateMetadata, nodeInfo *schedulernodeinfo.NodeInfo) (bool, []PredicateFailureReason, error) { var podBestEffort bool if predicateMeta, ok := meta.(*predicateMetadata); ok { podBestEffort = predicateMeta.podBestEffort @@ -1538,50 +1540,46 @@ func CheckNodeMemoryPressurePredicate(pod *v1.Pod, meta algorithm.PredicateMetad // check if node is under memory pressure if nodeInfo.MemoryPressureCondition() == v1.ConditionTrue { - return false, []algorithm.PredicateFailureReason{ErrNodeUnderMemoryPressure}, nil + return false, []PredicateFailureReason{ErrNodeUnderMemoryPressure}, nil } return true, nil, nil } // CheckNodeDiskPressurePredicate checks if a pod can be scheduled on a node // reporting disk pressure condition. -func CheckNodeDiskPressurePredicate(pod *v1.Pod, meta algorithm.PredicateMetadata, nodeInfo *schedulercache.NodeInfo) (bool, []algorithm.PredicateFailureReason, error) { +func CheckNodeDiskPressurePredicate(pod *v1.Pod, meta PredicateMetadata, nodeInfo *schedulernodeinfo.NodeInfo) (bool, []PredicateFailureReason, error) { // check if node is under disk pressure if nodeInfo.DiskPressureCondition() == v1.ConditionTrue { - return false, []algorithm.PredicateFailureReason{ErrNodeUnderDiskPressure}, nil + return false, []PredicateFailureReason{ErrNodeUnderDiskPressure}, nil } return true, nil, nil } // CheckNodePIDPressurePredicate checks if a pod can be scheduled on a node // reporting pid pressure condition. -func CheckNodePIDPressurePredicate(pod *v1.Pod, meta algorithm.PredicateMetadata, nodeInfo *schedulercache.NodeInfo) (bool, []algorithm.PredicateFailureReason, error) { +func CheckNodePIDPressurePredicate(pod *v1.Pod, meta PredicateMetadata, nodeInfo *schedulernodeinfo.NodeInfo) (bool, []PredicateFailureReason, error) { // check if node is under pid pressure if nodeInfo.PIDPressureCondition() == v1.ConditionTrue { - return false, []algorithm.PredicateFailureReason{ErrNodeUnderPIDPressure}, nil + return false, []PredicateFailureReason{ErrNodeUnderPIDPressure}, nil } return true, nil, nil } -// CheckNodeConditionPredicate checks if a pod can be scheduled on a node reporting out of disk, +// CheckNodeConditionPredicate checks if a pod can be scheduled on a node reporting // network unavailable and not ready condition. Only node conditions are accounted in this predicate. -func CheckNodeConditionPredicate(pod *v1.Pod, meta algorithm.PredicateMetadata, nodeInfo *schedulercache.NodeInfo) (bool, []algorithm.PredicateFailureReason, error) { - reasons := []algorithm.PredicateFailureReason{} - +func CheckNodeConditionPredicate(pod *v1.Pod, meta PredicateMetadata, nodeInfo *schedulernodeinfo.NodeInfo) (bool, []PredicateFailureReason, error) { + reasons := []PredicateFailureReason{} if nodeInfo == nil || nodeInfo.Node() == nil { - return false, []algorithm.PredicateFailureReason{ErrNodeUnknownCondition}, nil + return false, []PredicateFailureReason{ErrNodeUnknownCondition}, nil } node := nodeInfo.Node() for _, cond := range node.Status.Conditions { // We consider the node for scheduling only when its: // - NodeReady condition status is ConditionTrue, - // - NodeOutOfDisk condition status is ConditionFalse, // - NodeNetworkUnavailable condition status is ConditionFalse. if cond.Type == v1.NodeReady && cond.Status != v1.ConditionTrue { reasons = append(reasons, ErrNodeNotReady) - } else if cond.Type == v1.NodeOutOfDisk && cond.Status != v1.ConditionFalse { - reasons = append(reasons, ErrNodeOutOfDisk) } else if cond.Type == v1.NodeNetworkUnavailable && cond.Status != v1.ConditionFalse { reasons = append(reasons, ErrNodeNetworkUnavailable) } @@ -1610,18 +1608,14 @@ type VolumeBindingChecker struct { // // The predicate returns true if all bound PVCs have compatible PVs with the node, and if all unbound // PVCs can be matched with an available and node-compatible PV. -func NewVolumeBindingPredicate(binder *volumebinder.VolumeBinder) algorithm.FitPredicate { +func NewVolumeBindingPredicate(binder *volumebinder.VolumeBinder) FitPredicate { c := &VolumeBindingChecker{ binder: binder, } return c.predicate } -func (c *VolumeBindingChecker) predicate(pod *v1.Pod, meta algorithm.PredicateMetadata, nodeInfo *schedulercache.NodeInfo) (bool, []algorithm.PredicateFailureReason, error) { - if !utilfeature.DefaultFeatureGate.Enabled(features.VolumeScheduling) { - return true, nil, nil - } - +func (c *VolumeBindingChecker) predicate(pod *v1.Pod, meta PredicateMetadata, nodeInfo *schedulernodeinfo.NodeInfo) (bool, []PredicateFailureReason, error) { node := nodeInfo.Node() if node == nil { return false, nil, fmt.Errorf("node not found") @@ -1632,7 +1626,7 @@ func (c *VolumeBindingChecker) predicate(pod *v1.Pod, meta algorithm.PredicateMe return false, nil, err } - failReasons := []algorithm.PredicateFailureReason{} + failReasons := []PredicateFailureReason{} if !boundSatisfied { klog.V(5).Infof("Bound PVs not satisfied for pod %v/%v, node %q", pod.Namespace, pod.Name, node.Name) failReasons = append(failReasons, ErrVolumeNodeConflict) diff --git a/pkg/scheduler/algorithm/predicates/predicates_test.go b/pkg/scheduler/algorithm/predicates/predicates_test.go index 5a752901060..0a9305aa8e1 100644 --- a/pkg/scheduler/algorithm/predicates/predicates_test.go +++ b/pkg/scheduler/algorithm/predicates/predicates_test.go @@ -29,14 +29,10 @@ import ( "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/sets" - utilfeature "k8s.io/apiserver/pkg/util/feature" - utilfeaturetesting "k8s.io/apiserver/pkg/util/feature/testing" v1helper "k8s.io/kubernetes/pkg/apis/core/v1/helper" - "k8s.io/kubernetes/pkg/features" kubeletapis "k8s.io/kubernetes/pkg/kubelet/apis" - "k8s.io/kubernetes/pkg/scheduler/algorithm" schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" - schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" + schedulernodeinfo "k8s.io/kubernetes/pkg/scheduler/nodeinfo" schedulertesting "k8s.io/kubernetes/pkg/scheduler/testing" ) @@ -72,7 +68,7 @@ func makeAllocatableResources(milliCPU, memory, pods, extendedA, storage, hugePa } } -func newResourcePod(usage ...schedulercache.Resource) *v1.Pod { +func newResourcePod(usage ...schedulernodeinfo.Resource) *v1.Pod { containers := []v1.Container{} for _, req := range usage { containers = append(containers, v1.Container{ @@ -86,12 +82,12 @@ func newResourcePod(usage ...schedulercache.Resource) *v1.Pod { } } -func newResourceInitPod(pod *v1.Pod, usage ...schedulercache.Resource) *v1.Pod { +func newResourceInitPod(pod *v1.Pod, usage ...schedulernodeinfo.Resource) *v1.Pod { pod.Spec.InitContainers = newResourcePod(usage...).Spec.Containers return pod } -func PredicateMetadata(p *v1.Pod, nodeInfo map[string]*schedulercache.NodeInfo) algorithm.PredicateMetadata { +func GetPredicateMetadata(p *v1.Pod, nodeInfo map[string]*schedulernodeinfo.NodeInfo) PredicateMetadata { pm := PredicateMetadataFactory{schedulertesting.FakePodLister{p}} return pm.GetMetadata(p, nodeInfo) } @@ -99,259 +95,259 @@ func PredicateMetadata(p *v1.Pod, nodeInfo map[string]*schedulercache.NodeInfo) func TestPodFitsResources(t *testing.T) { enoughPodsTests := []struct { pod *v1.Pod - nodeInfo *schedulercache.NodeInfo + nodeInfo *schedulernodeinfo.NodeInfo fits bool name string - reasons []algorithm.PredicateFailureReason + reasons []PredicateFailureReason ignoredExtendedResources sets.String }{ { pod: &v1.Pod{}, - nodeInfo: schedulercache.NewNodeInfo( - newResourcePod(schedulercache.Resource{MilliCPU: 10, Memory: 20})), + nodeInfo: schedulernodeinfo.NewNodeInfo( + newResourcePod(schedulernodeinfo.Resource{MilliCPU: 10, Memory: 20})), fits: true, name: "no resources requested always fits", }, { - pod: newResourcePod(schedulercache.Resource{MilliCPU: 1, Memory: 1}), - nodeInfo: schedulercache.NewNodeInfo( - newResourcePod(schedulercache.Resource{MilliCPU: 10, Memory: 20})), + pod: newResourcePod(schedulernodeinfo.Resource{MilliCPU: 1, Memory: 1}), + nodeInfo: schedulernodeinfo.NewNodeInfo( + newResourcePod(schedulernodeinfo.Resource{MilliCPU: 10, Memory: 20})), fits: false, name: "too many resources fails", - reasons: []algorithm.PredicateFailureReason{ + reasons: []PredicateFailureReason{ NewInsufficientResourceError(v1.ResourceCPU, 1, 10, 10), NewInsufficientResourceError(v1.ResourceMemory, 1, 20, 20), }, }, { - pod: newResourceInitPod(newResourcePod(schedulercache.Resource{MilliCPU: 1, Memory: 1}), schedulercache.Resource{MilliCPU: 3, Memory: 1}), - nodeInfo: schedulercache.NewNodeInfo( - newResourcePod(schedulercache.Resource{MilliCPU: 8, Memory: 19})), + pod: newResourceInitPod(newResourcePod(schedulernodeinfo.Resource{MilliCPU: 1, Memory: 1}), schedulernodeinfo.Resource{MilliCPU: 3, Memory: 1}), + nodeInfo: schedulernodeinfo.NewNodeInfo( + newResourcePod(schedulernodeinfo.Resource{MilliCPU: 8, Memory: 19})), fits: false, name: "too many resources fails due to init container cpu", - reasons: []algorithm.PredicateFailureReason{NewInsufficientResourceError(v1.ResourceCPU, 3, 8, 10)}, + reasons: []PredicateFailureReason{NewInsufficientResourceError(v1.ResourceCPU, 3, 8, 10)}, }, { - pod: newResourceInitPod(newResourcePod(schedulercache.Resource{MilliCPU: 1, Memory: 1}), schedulercache.Resource{MilliCPU: 3, Memory: 1}, schedulercache.Resource{MilliCPU: 2, Memory: 1}), - nodeInfo: schedulercache.NewNodeInfo( - newResourcePod(schedulercache.Resource{MilliCPU: 8, Memory: 19})), + pod: newResourceInitPod(newResourcePod(schedulernodeinfo.Resource{MilliCPU: 1, Memory: 1}), schedulernodeinfo.Resource{MilliCPU: 3, Memory: 1}, schedulernodeinfo.Resource{MilliCPU: 2, Memory: 1}), + nodeInfo: schedulernodeinfo.NewNodeInfo( + newResourcePod(schedulernodeinfo.Resource{MilliCPU: 8, Memory: 19})), fits: false, name: "too many resources fails due to highest init container cpu", - reasons: []algorithm.PredicateFailureReason{NewInsufficientResourceError(v1.ResourceCPU, 3, 8, 10)}, + reasons: []PredicateFailureReason{NewInsufficientResourceError(v1.ResourceCPU, 3, 8, 10)}, }, { - pod: newResourceInitPod(newResourcePod(schedulercache.Resource{MilliCPU: 1, Memory: 1}), schedulercache.Resource{MilliCPU: 1, Memory: 3}), - nodeInfo: schedulercache.NewNodeInfo( - newResourcePod(schedulercache.Resource{MilliCPU: 9, Memory: 19})), + pod: newResourceInitPod(newResourcePod(schedulernodeinfo.Resource{MilliCPU: 1, Memory: 1}), schedulernodeinfo.Resource{MilliCPU: 1, Memory: 3}), + nodeInfo: schedulernodeinfo.NewNodeInfo( + newResourcePod(schedulernodeinfo.Resource{MilliCPU: 9, Memory: 19})), fits: false, name: "too many resources fails due to init container memory", - reasons: []algorithm.PredicateFailureReason{NewInsufficientResourceError(v1.ResourceMemory, 3, 19, 20)}, + reasons: []PredicateFailureReason{NewInsufficientResourceError(v1.ResourceMemory, 3, 19, 20)}, }, { - pod: newResourceInitPod(newResourcePod(schedulercache.Resource{MilliCPU: 1, Memory: 1}), schedulercache.Resource{MilliCPU: 1, Memory: 3}, schedulercache.Resource{MilliCPU: 1, Memory: 2}), - nodeInfo: schedulercache.NewNodeInfo( - newResourcePod(schedulercache.Resource{MilliCPU: 9, Memory: 19})), + pod: newResourceInitPod(newResourcePod(schedulernodeinfo.Resource{MilliCPU: 1, Memory: 1}), schedulernodeinfo.Resource{MilliCPU: 1, Memory: 3}, schedulernodeinfo.Resource{MilliCPU: 1, Memory: 2}), + nodeInfo: schedulernodeinfo.NewNodeInfo( + newResourcePod(schedulernodeinfo.Resource{MilliCPU: 9, Memory: 19})), fits: false, name: "too many resources fails due to highest init container memory", - reasons: []algorithm.PredicateFailureReason{NewInsufficientResourceError(v1.ResourceMemory, 3, 19, 20)}, + reasons: []PredicateFailureReason{NewInsufficientResourceError(v1.ResourceMemory, 3, 19, 20)}, }, { - pod: newResourceInitPod(newResourcePod(schedulercache.Resource{MilliCPU: 1, Memory: 1}), schedulercache.Resource{MilliCPU: 1, Memory: 1}), - nodeInfo: schedulercache.NewNodeInfo( - newResourcePod(schedulercache.Resource{MilliCPU: 9, Memory: 19})), + pod: newResourceInitPod(newResourcePod(schedulernodeinfo.Resource{MilliCPU: 1, Memory: 1}), schedulernodeinfo.Resource{MilliCPU: 1, Memory: 1}), + nodeInfo: schedulernodeinfo.NewNodeInfo( + newResourcePod(schedulernodeinfo.Resource{MilliCPU: 9, Memory: 19})), fits: true, name: "init container fits because it's the max, not sum, of containers and init containers", }, { - pod: newResourceInitPod(newResourcePod(schedulercache.Resource{MilliCPU: 1, Memory: 1}), schedulercache.Resource{MilliCPU: 1, Memory: 1}, schedulercache.Resource{MilliCPU: 1, Memory: 1}), - nodeInfo: schedulercache.NewNodeInfo( - newResourcePod(schedulercache.Resource{MilliCPU: 9, Memory: 19})), + pod: newResourceInitPod(newResourcePod(schedulernodeinfo.Resource{MilliCPU: 1, Memory: 1}), schedulernodeinfo.Resource{MilliCPU: 1, Memory: 1}, schedulernodeinfo.Resource{MilliCPU: 1, Memory: 1}), + nodeInfo: schedulernodeinfo.NewNodeInfo( + newResourcePod(schedulernodeinfo.Resource{MilliCPU: 9, Memory: 19})), fits: true, name: "multiple init containers fit because it's the max, not sum, of containers and init containers", }, { - pod: newResourcePod(schedulercache.Resource{MilliCPU: 1, Memory: 1}), - nodeInfo: schedulercache.NewNodeInfo( - newResourcePod(schedulercache.Resource{MilliCPU: 5, Memory: 5})), + pod: newResourcePod(schedulernodeinfo.Resource{MilliCPU: 1, Memory: 1}), + nodeInfo: schedulernodeinfo.NewNodeInfo( + newResourcePod(schedulernodeinfo.Resource{MilliCPU: 5, Memory: 5})), fits: true, name: "both resources fit", }, { - pod: newResourcePod(schedulercache.Resource{MilliCPU: 2, Memory: 1}), - nodeInfo: schedulercache.NewNodeInfo( - newResourcePod(schedulercache.Resource{MilliCPU: 9, Memory: 5})), + pod: newResourcePod(schedulernodeinfo.Resource{MilliCPU: 2, Memory: 1}), + nodeInfo: schedulernodeinfo.NewNodeInfo( + newResourcePod(schedulernodeinfo.Resource{MilliCPU: 9, Memory: 5})), fits: false, name: "one resource memory fits", - reasons: []algorithm.PredicateFailureReason{NewInsufficientResourceError(v1.ResourceCPU, 2, 9, 10)}, + reasons: []PredicateFailureReason{NewInsufficientResourceError(v1.ResourceCPU, 2, 9, 10)}, }, { - pod: newResourcePod(schedulercache.Resource{MilliCPU: 1, Memory: 2}), - nodeInfo: schedulercache.NewNodeInfo( - newResourcePod(schedulercache.Resource{MilliCPU: 5, Memory: 19})), + pod: newResourcePod(schedulernodeinfo.Resource{MilliCPU: 1, Memory: 2}), + nodeInfo: schedulernodeinfo.NewNodeInfo( + newResourcePod(schedulernodeinfo.Resource{MilliCPU: 5, Memory: 19})), fits: false, name: "one resource cpu fits", - reasons: []algorithm.PredicateFailureReason{NewInsufficientResourceError(v1.ResourceMemory, 2, 19, 20)}, + reasons: []PredicateFailureReason{NewInsufficientResourceError(v1.ResourceMemory, 2, 19, 20)}, }, { - pod: newResourcePod(schedulercache.Resource{MilliCPU: 5, Memory: 1}), - nodeInfo: schedulercache.NewNodeInfo( - newResourcePod(schedulercache.Resource{MilliCPU: 5, Memory: 19})), + pod: newResourcePod(schedulernodeinfo.Resource{MilliCPU: 5, Memory: 1}), + nodeInfo: schedulernodeinfo.NewNodeInfo( + newResourcePod(schedulernodeinfo.Resource{MilliCPU: 5, Memory: 19})), fits: true, name: "equal edge case", }, { - pod: newResourceInitPod(newResourcePod(schedulercache.Resource{MilliCPU: 4, Memory: 1}), schedulercache.Resource{MilliCPU: 5, Memory: 1}), - nodeInfo: schedulercache.NewNodeInfo( - newResourcePod(schedulercache.Resource{MilliCPU: 5, Memory: 19})), + pod: newResourceInitPod(newResourcePod(schedulernodeinfo.Resource{MilliCPU: 4, Memory: 1}), schedulernodeinfo.Resource{MilliCPU: 5, Memory: 1}), + nodeInfo: schedulernodeinfo.NewNodeInfo( + newResourcePod(schedulernodeinfo.Resource{MilliCPU: 5, Memory: 19})), fits: true, name: "equal edge case for init container", }, { - pod: newResourcePod(schedulercache.Resource{ScalarResources: map[v1.ResourceName]int64{extendedResourceA: 1}}), - nodeInfo: schedulercache.NewNodeInfo(newResourcePod(schedulercache.Resource{})), + pod: newResourcePod(schedulernodeinfo.Resource{ScalarResources: map[v1.ResourceName]int64{extendedResourceA: 1}}), + nodeInfo: schedulernodeinfo.NewNodeInfo(newResourcePod(schedulernodeinfo.Resource{})), fits: true, name: "extended resource fits", }, { - pod: newResourceInitPod(newResourcePod(schedulercache.Resource{}), schedulercache.Resource{ScalarResources: map[v1.ResourceName]int64{extendedResourceA: 1}}), - nodeInfo: schedulercache.NewNodeInfo(newResourcePod(schedulercache.Resource{})), + pod: newResourceInitPod(newResourcePod(schedulernodeinfo.Resource{}), schedulernodeinfo.Resource{ScalarResources: map[v1.ResourceName]int64{extendedResourceA: 1}}), + nodeInfo: schedulernodeinfo.NewNodeInfo(newResourcePod(schedulernodeinfo.Resource{})), fits: true, name: "extended resource fits for init container", }, { pod: newResourcePod( - schedulercache.Resource{MilliCPU: 1, Memory: 1, ScalarResources: map[v1.ResourceName]int64{extendedResourceA: 10}}), - nodeInfo: schedulercache.NewNodeInfo( - newResourcePod(schedulercache.Resource{MilliCPU: 0, Memory: 0, ScalarResources: map[v1.ResourceName]int64{extendedResourceA: 0}})), + schedulernodeinfo.Resource{MilliCPU: 1, Memory: 1, ScalarResources: map[v1.ResourceName]int64{extendedResourceA: 10}}), + nodeInfo: schedulernodeinfo.NewNodeInfo( + newResourcePod(schedulernodeinfo.Resource{MilliCPU: 0, Memory: 0, ScalarResources: map[v1.ResourceName]int64{extendedResourceA: 0}})), fits: false, name: "extended resource capacity enforced", - reasons: []algorithm.PredicateFailureReason{NewInsufficientResourceError(extendedResourceA, 10, 0, 5)}, + reasons: []PredicateFailureReason{NewInsufficientResourceError(extendedResourceA, 10, 0, 5)}, }, { - pod: newResourceInitPod(newResourcePod(schedulercache.Resource{}), - schedulercache.Resource{MilliCPU: 1, Memory: 1, ScalarResources: map[v1.ResourceName]int64{extendedResourceA: 10}}), - nodeInfo: schedulercache.NewNodeInfo( - newResourcePod(schedulercache.Resource{MilliCPU: 0, Memory: 0, ScalarResources: map[v1.ResourceName]int64{extendedResourceA: 0}})), + pod: newResourceInitPod(newResourcePod(schedulernodeinfo.Resource{}), + schedulernodeinfo.Resource{MilliCPU: 1, Memory: 1, ScalarResources: map[v1.ResourceName]int64{extendedResourceA: 10}}), + nodeInfo: schedulernodeinfo.NewNodeInfo( + newResourcePod(schedulernodeinfo.Resource{MilliCPU: 0, Memory: 0, ScalarResources: map[v1.ResourceName]int64{extendedResourceA: 0}})), fits: false, name: "extended resource capacity enforced for init container", - reasons: []algorithm.PredicateFailureReason{NewInsufficientResourceError(extendedResourceA, 10, 0, 5)}, + reasons: []PredicateFailureReason{NewInsufficientResourceError(extendedResourceA, 10, 0, 5)}, }, { pod: newResourcePod( - schedulercache.Resource{MilliCPU: 1, Memory: 1, ScalarResources: map[v1.ResourceName]int64{extendedResourceA: 1}}), - nodeInfo: schedulercache.NewNodeInfo( - newResourcePod(schedulercache.Resource{MilliCPU: 0, Memory: 0, ScalarResources: map[v1.ResourceName]int64{extendedResourceA: 5}})), + schedulernodeinfo.Resource{MilliCPU: 1, Memory: 1, ScalarResources: map[v1.ResourceName]int64{extendedResourceA: 1}}), + nodeInfo: schedulernodeinfo.NewNodeInfo( + newResourcePod(schedulernodeinfo.Resource{MilliCPU: 0, Memory: 0, ScalarResources: map[v1.ResourceName]int64{extendedResourceA: 5}})), fits: false, name: "extended resource allocatable enforced", - reasons: []algorithm.PredicateFailureReason{NewInsufficientResourceError(extendedResourceA, 1, 5, 5)}, + reasons: []PredicateFailureReason{NewInsufficientResourceError(extendedResourceA, 1, 5, 5)}, }, { - pod: newResourceInitPod(newResourcePod(schedulercache.Resource{}), - schedulercache.Resource{MilliCPU: 1, Memory: 1, ScalarResources: map[v1.ResourceName]int64{extendedResourceA: 1}}), - nodeInfo: schedulercache.NewNodeInfo( - newResourcePod(schedulercache.Resource{MilliCPU: 0, Memory: 0, ScalarResources: map[v1.ResourceName]int64{extendedResourceA: 5}})), + pod: newResourceInitPod(newResourcePod(schedulernodeinfo.Resource{}), + schedulernodeinfo.Resource{MilliCPU: 1, Memory: 1, ScalarResources: map[v1.ResourceName]int64{extendedResourceA: 1}}), + nodeInfo: schedulernodeinfo.NewNodeInfo( + newResourcePod(schedulernodeinfo.Resource{MilliCPU: 0, Memory: 0, ScalarResources: map[v1.ResourceName]int64{extendedResourceA: 5}})), fits: false, name: "extended resource allocatable enforced for init container", - reasons: []algorithm.PredicateFailureReason{NewInsufficientResourceError(extendedResourceA, 1, 5, 5)}, + reasons: []PredicateFailureReason{NewInsufficientResourceError(extendedResourceA, 1, 5, 5)}, }, { pod: newResourcePod( - schedulercache.Resource{MilliCPU: 1, Memory: 1, ScalarResources: map[v1.ResourceName]int64{extendedResourceA: 3}}, - schedulercache.Resource{MilliCPU: 1, Memory: 1, ScalarResources: map[v1.ResourceName]int64{extendedResourceA: 3}}), - nodeInfo: schedulercache.NewNodeInfo( - newResourcePod(schedulercache.Resource{MilliCPU: 0, Memory: 0, ScalarResources: map[v1.ResourceName]int64{extendedResourceA: 2}})), + schedulernodeinfo.Resource{MilliCPU: 1, Memory: 1, ScalarResources: map[v1.ResourceName]int64{extendedResourceA: 3}}, + schedulernodeinfo.Resource{MilliCPU: 1, Memory: 1, ScalarResources: map[v1.ResourceName]int64{extendedResourceA: 3}}), + nodeInfo: schedulernodeinfo.NewNodeInfo( + newResourcePod(schedulernodeinfo.Resource{MilliCPU: 0, Memory: 0, ScalarResources: map[v1.ResourceName]int64{extendedResourceA: 2}})), fits: false, name: "extended resource allocatable enforced for multiple containers", - reasons: []algorithm.PredicateFailureReason{NewInsufficientResourceError(extendedResourceA, 6, 2, 5)}, + reasons: []PredicateFailureReason{NewInsufficientResourceError(extendedResourceA, 6, 2, 5)}, }, { - pod: newResourceInitPod(newResourcePod(schedulercache.Resource{}), - schedulercache.Resource{MilliCPU: 1, Memory: 1, ScalarResources: map[v1.ResourceName]int64{extendedResourceA: 3}}, - schedulercache.Resource{MilliCPU: 1, Memory: 1, ScalarResources: map[v1.ResourceName]int64{extendedResourceA: 3}}), - nodeInfo: schedulercache.NewNodeInfo( - newResourcePod(schedulercache.Resource{MilliCPU: 0, Memory: 0, ScalarResources: map[v1.ResourceName]int64{extendedResourceA: 2}})), + pod: newResourceInitPod(newResourcePod(schedulernodeinfo.Resource{}), + schedulernodeinfo.Resource{MilliCPU: 1, Memory: 1, ScalarResources: map[v1.ResourceName]int64{extendedResourceA: 3}}, + schedulernodeinfo.Resource{MilliCPU: 1, Memory: 1, ScalarResources: map[v1.ResourceName]int64{extendedResourceA: 3}}), + nodeInfo: schedulernodeinfo.NewNodeInfo( + newResourcePod(schedulernodeinfo.Resource{MilliCPU: 0, Memory: 0, ScalarResources: map[v1.ResourceName]int64{extendedResourceA: 2}})), fits: true, name: "extended resource allocatable admits multiple init containers", }, { - pod: newResourceInitPod(newResourcePod(schedulercache.Resource{}), - schedulercache.Resource{MilliCPU: 1, Memory: 1, ScalarResources: map[v1.ResourceName]int64{extendedResourceA: 6}}, - schedulercache.Resource{MilliCPU: 1, Memory: 1, ScalarResources: map[v1.ResourceName]int64{extendedResourceA: 3}}), - nodeInfo: schedulercache.NewNodeInfo( - newResourcePod(schedulercache.Resource{MilliCPU: 0, Memory: 0, ScalarResources: map[v1.ResourceName]int64{extendedResourceA: 2}})), + pod: newResourceInitPod(newResourcePod(schedulernodeinfo.Resource{}), + schedulernodeinfo.Resource{MilliCPU: 1, Memory: 1, ScalarResources: map[v1.ResourceName]int64{extendedResourceA: 6}}, + schedulernodeinfo.Resource{MilliCPU: 1, Memory: 1, ScalarResources: map[v1.ResourceName]int64{extendedResourceA: 3}}), + nodeInfo: schedulernodeinfo.NewNodeInfo( + newResourcePod(schedulernodeinfo.Resource{MilliCPU: 0, Memory: 0, ScalarResources: map[v1.ResourceName]int64{extendedResourceA: 2}})), fits: false, name: "extended resource allocatable enforced for multiple init containers", - reasons: []algorithm.PredicateFailureReason{NewInsufficientResourceError(extendedResourceA, 6, 2, 5)}, + reasons: []PredicateFailureReason{NewInsufficientResourceError(extendedResourceA, 6, 2, 5)}, }, { pod: newResourcePod( - schedulercache.Resource{MilliCPU: 1, Memory: 1, ScalarResources: map[v1.ResourceName]int64{extendedResourceB: 1}}), - nodeInfo: schedulercache.NewNodeInfo( - newResourcePod(schedulercache.Resource{MilliCPU: 0, Memory: 0})), + schedulernodeinfo.Resource{MilliCPU: 1, Memory: 1, ScalarResources: map[v1.ResourceName]int64{extendedResourceB: 1}}), + nodeInfo: schedulernodeinfo.NewNodeInfo( + newResourcePod(schedulernodeinfo.Resource{MilliCPU: 0, Memory: 0})), fits: false, name: "extended resource allocatable enforced for unknown resource", - reasons: []algorithm.PredicateFailureReason{NewInsufficientResourceError(extendedResourceB, 1, 0, 0)}, + reasons: []PredicateFailureReason{NewInsufficientResourceError(extendedResourceB, 1, 0, 0)}, }, { - pod: newResourceInitPod(newResourcePod(schedulercache.Resource{}), - schedulercache.Resource{MilliCPU: 1, Memory: 1, ScalarResources: map[v1.ResourceName]int64{extendedResourceB: 1}}), - nodeInfo: schedulercache.NewNodeInfo( - newResourcePod(schedulercache.Resource{MilliCPU: 0, Memory: 0})), + pod: newResourceInitPod(newResourcePod(schedulernodeinfo.Resource{}), + schedulernodeinfo.Resource{MilliCPU: 1, Memory: 1, ScalarResources: map[v1.ResourceName]int64{extendedResourceB: 1}}), + nodeInfo: schedulernodeinfo.NewNodeInfo( + newResourcePod(schedulernodeinfo.Resource{MilliCPU: 0, Memory: 0})), fits: false, name: "extended resource allocatable enforced for unknown resource for init container", - reasons: []algorithm.PredicateFailureReason{NewInsufficientResourceError(extendedResourceB, 1, 0, 0)}, + reasons: []PredicateFailureReason{NewInsufficientResourceError(extendedResourceB, 1, 0, 0)}, }, { pod: newResourcePod( - schedulercache.Resource{MilliCPU: 1, Memory: 1, ScalarResources: map[v1.ResourceName]int64{kubernetesIOResourceA: 10}}), - nodeInfo: schedulercache.NewNodeInfo( - newResourcePod(schedulercache.Resource{MilliCPU: 0, Memory: 0})), + schedulernodeinfo.Resource{MilliCPU: 1, Memory: 1, ScalarResources: map[v1.ResourceName]int64{kubernetesIOResourceA: 10}}), + nodeInfo: schedulernodeinfo.NewNodeInfo( + newResourcePod(schedulernodeinfo.Resource{MilliCPU: 0, Memory: 0})), fits: false, name: "kubernetes.io resource capacity enforced", - reasons: []algorithm.PredicateFailureReason{NewInsufficientResourceError(kubernetesIOResourceA, 10, 0, 0)}, + reasons: []PredicateFailureReason{NewInsufficientResourceError(kubernetesIOResourceA, 10, 0, 0)}, }, { - pod: newResourceInitPod(newResourcePod(schedulercache.Resource{}), - schedulercache.Resource{MilliCPU: 1, Memory: 1, ScalarResources: map[v1.ResourceName]int64{kubernetesIOResourceB: 10}}), - nodeInfo: schedulercache.NewNodeInfo( - newResourcePod(schedulercache.Resource{MilliCPU: 0, Memory: 0})), + pod: newResourceInitPod(newResourcePod(schedulernodeinfo.Resource{}), + schedulernodeinfo.Resource{MilliCPU: 1, Memory: 1, ScalarResources: map[v1.ResourceName]int64{kubernetesIOResourceB: 10}}), + nodeInfo: schedulernodeinfo.NewNodeInfo( + newResourcePod(schedulernodeinfo.Resource{MilliCPU: 0, Memory: 0})), fits: false, name: "kubernetes.io resource capacity enforced for init container", - reasons: []algorithm.PredicateFailureReason{NewInsufficientResourceError(kubernetesIOResourceB, 10, 0, 0)}, + reasons: []PredicateFailureReason{NewInsufficientResourceError(kubernetesIOResourceB, 10, 0, 0)}, }, { pod: newResourcePod( - schedulercache.Resource{MilliCPU: 1, Memory: 1, ScalarResources: map[v1.ResourceName]int64{hugePageResourceA: 10}}), - nodeInfo: schedulercache.NewNodeInfo( - newResourcePod(schedulercache.Resource{MilliCPU: 0, Memory: 0, ScalarResources: map[v1.ResourceName]int64{hugePageResourceA: 0}})), + schedulernodeinfo.Resource{MilliCPU: 1, Memory: 1, ScalarResources: map[v1.ResourceName]int64{hugePageResourceA: 10}}), + nodeInfo: schedulernodeinfo.NewNodeInfo( + newResourcePod(schedulernodeinfo.Resource{MilliCPU: 0, Memory: 0, ScalarResources: map[v1.ResourceName]int64{hugePageResourceA: 0}})), fits: false, name: "hugepages resource capacity enforced", - reasons: []algorithm.PredicateFailureReason{NewInsufficientResourceError(hugePageResourceA, 10, 0, 5)}, + reasons: []PredicateFailureReason{NewInsufficientResourceError(hugePageResourceA, 10, 0, 5)}, }, { - pod: newResourceInitPod(newResourcePod(schedulercache.Resource{}), - schedulercache.Resource{MilliCPU: 1, Memory: 1, ScalarResources: map[v1.ResourceName]int64{hugePageResourceA: 10}}), - nodeInfo: schedulercache.NewNodeInfo( - newResourcePod(schedulercache.Resource{MilliCPU: 0, Memory: 0, ScalarResources: map[v1.ResourceName]int64{hugePageResourceA: 0}})), + pod: newResourceInitPod(newResourcePod(schedulernodeinfo.Resource{}), + schedulernodeinfo.Resource{MilliCPU: 1, Memory: 1, ScalarResources: map[v1.ResourceName]int64{hugePageResourceA: 10}}), + nodeInfo: schedulernodeinfo.NewNodeInfo( + newResourcePod(schedulernodeinfo.Resource{MilliCPU: 0, Memory: 0, ScalarResources: map[v1.ResourceName]int64{hugePageResourceA: 0}})), fits: false, name: "hugepages resource capacity enforced for init container", - reasons: []algorithm.PredicateFailureReason{NewInsufficientResourceError(hugePageResourceA, 10, 0, 5)}, + reasons: []PredicateFailureReason{NewInsufficientResourceError(hugePageResourceA, 10, 0, 5)}, }, { pod: newResourcePod( - schedulercache.Resource{MilliCPU: 1, Memory: 1, ScalarResources: map[v1.ResourceName]int64{hugePageResourceA: 3}}, - schedulercache.Resource{MilliCPU: 1, Memory: 1, ScalarResources: map[v1.ResourceName]int64{hugePageResourceA: 3}}), - nodeInfo: schedulercache.NewNodeInfo( - newResourcePod(schedulercache.Resource{MilliCPU: 0, Memory: 0, ScalarResources: map[v1.ResourceName]int64{hugePageResourceA: 2}})), + schedulernodeinfo.Resource{MilliCPU: 1, Memory: 1, ScalarResources: map[v1.ResourceName]int64{hugePageResourceA: 3}}, + schedulernodeinfo.Resource{MilliCPU: 1, Memory: 1, ScalarResources: map[v1.ResourceName]int64{hugePageResourceA: 3}}), + nodeInfo: schedulernodeinfo.NewNodeInfo( + newResourcePod(schedulernodeinfo.Resource{MilliCPU: 0, Memory: 0, ScalarResources: map[v1.ResourceName]int64{hugePageResourceA: 2}})), fits: false, name: "hugepages resource allocatable enforced for multiple containers", - reasons: []algorithm.PredicateFailureReason{NewInsufficientResourceError(hugePageResourceA, 6, 2, 5)}, + reasons: []PredicateFailureReason{NewInsufficientResourceError(hugePageResourceA, 6, 2, 5)}, }, { pod: newResourcePod( - schedulercache.Resource{MilliCPU: 1, Memory: 1, ScalarResources: map[v1.ResourceName]int64{extendedResourceB: 1}}), - nodeInfo: schedulercache.NewNodeInfo( - newResourcePod(schedulercache.Resource{MilliCPU: 0, Memory: 0})), + schedulernodeinfo.Resource{MilliCPU: 1, Memory: 1, ScalarResources: map[v1.ResourceName]int64{extendedResourceB: 1}}), + nodeInfo: schedulernodeinfo.NewNodeInfo( + newResourcePod(schedulernodeinfo.Resource{MilliCPU: 0, Memory: 0})), fits: true, ignoredExtendedResources: sets.NewString(string(extendedResourceB)), name: "skip checking ignored extended resource", @@ -363,7 +359,7 @@ func TestPodFitsResources(t *testing.T) { node := v1.Node{Status: v1.NodeStatus{Capacity: makeResources(10, 20, 32, 5, 20, 5).Capacity, Allocatable: makeAllocatableResources(10, 20, 32, 5, 20, 5)}} test.nodeInfo.SetNode(&node) RegisterPredicateMetadataProducerWithExtendedResourceOptions(test.ignoredExtendedResources) - meta := PredicateMetadata(test.pod, nil) + meta := GetPredicateMetadata(test.pod, nil) fits, reasons, err := PodFitsResources(test.pod, meta, test.nodeInfo) if err != nil { t.Errorf("unexpected error: %v", err) @@ -379,49 +375,49 @@ func TestPodFitsResources(t *testing.T) { notEnoughPodsTests := []struct { pod *v1.Pod - nodeInfo *schedulercache.NodeInfo + nodeInfo *schedulernodeinfo.NodeInfo fits bool name string - reasons []algorithm.PredicateFailureReason + reasons []PredicateFailureReason }{ { pod: &v1.Pod{}, - nodeInfo: schedulercache.NewNodeInfo( - newResourcePod(schedulercache.Resource{MilliCPU: 10, Memory: 20})), + nodeInfo: schedulernodeinfo.NewNodeInfo( + newResourcePod(schedulernodeinfo.Resource{MilliCPU: 10, Memory: 20})), fits: false, name: "even without specified resources predicate fails when there's no space for additional pod", - reasons: []algorithm.PredicateFailureReason{NewInsufficientResourceError(v1.ResourcePods, 1, 1, 1)}, + reasons: []PredicateFailureReason{NewInsufficientResourceError(v1.ResourcePods, 1, 1, 1)}, }, { - pod: newResourcePod(schedulercache.Resource{MilliCPU: 1, Memory: 1}), - nodeInfo: schedulercache.NewNodeInfo( - newResourcePod(schedulercache.Resource{MilliCPU: 5, Memory: 5})), + pod: newResourcePod(schedulernodeinfo.Resource{MilliCPU: 1, Memory: 1}), + nodeInfo: schedulernodeinfo.NewNodeInfo( + newResourcePod(schedulernodeinfo.Resource{MilliCPU: 5, Memory: 5})), fits: false, name: "even if both resources fit predicate fails when there's no space for additional pod", - reasons: []algorithm.PredicateFailureReason{NewInsufficientResourceError(v1.ResourcePods, 1, 1, 1)}, + reasons: []PredicateFailureReason{NewInsufficientResourceError(v1.ResourcePods, 1, 1, 1)}, }, { - pod: newResourcePod(schedulercache.Resource{MilliCPU: 5, Memory: 1}), - nodeInfo: schedulercache.NewNodeInfo( - newResourcePod(schedulercache.Resource{MilliCPU: 5, Memory: 19})), + pod: newResourcePod(schedulernodeinfo.Resource{MilliCPU: 5, Memory: 1}), + nodeInfo: schedulernodeinfo.NewNodeInfo( + newResourcePod(schedulernodeinfo.Resource{MilliCPU: 5, Memory: 19})), fits: false, name: "even for equal edge case predicate fails when there's no space for additional pod", - reasons: []algorithm.PredicateFailureReason{NewInsufficientResourceError(v1.ResourcePods, 1, 1, 1)}, + reasons: []PredicateFailureReason{NewInsufficientResourceError(v1.ResourcePods, 1, 1, 1)}, }, { - pod: newResourceInitPod(newResourcePod(schedulercache.Resource{MilliCPU: 5, Memory: 1}), schedulercache.Resource{MilliCPU: 5, Memory: 1}), - nodeInfo: schedulercache.NewNodeInfo( - newResourcePod(schedulercache.Resource{MilliCPU: 5, Memory: 19})), + pod: newResourceInitPod(newResourcePod(schedulernodeinfo.Resource{MilliCPU: 5, Memory: 1}), schedulernodeinfo.Resource{MilliCPU: 5, Memory: 1}), + nodeInfo: schedulernodeinfo.NewNodeInfo( + newResourcePod(schedulernodeinfo.Resource{MilliCPU: 5, Memory: 19})), fits: false, name: "even for equal edge case predicate fails when there's no space for additional pod due to init container", - reasons: []algorithm.PredicateFailureReason{NewInsufficientResourceError(v1.ResourcePods, 1, 1, 1)}, + reasons: []PredicateFailureReason{NewInsufficientResourceError(v1.ResourcePods, 1, 1, 1)}, }, } for _, test := range notEnoughPodsTests { t.Run(test.name, func(t *testing.T) { node := v1.Node{Status: v1.NodeStatus{Capacity: v1.ResourceList{}, Allocatable: makeAllocatableResources(10, 20, 1, 0, 0, 0)}} test.nodeInfo.SetNode(&node) - fits, reasons, err := PodFitsResources(test.pod, PredicateMetadata(test.pod, nil), test.nodeInfo) + fits, reasons, err := PodFitsResources(test.pod, GetPredicateMetadata(test.pod, nil), test.nodeInfo) if err != nil { t.Errorf("unexpected error: %v", err) } @@ -436,42 +432,42 @@ func TestPodFitsResources(t *testing.T) { storagePodsTests := []struct { pod *v1.Pod - nodeInfo *schedulercache.NodeInfo + nodeInfo *schedulernodeinfo.NodeInfo fits bool name string - reasons []algorithm.PredicateFailureReason + reasons []PredicateFailureReason }{ { - pod: newResourcePod(schedulercache.Resource{MilliCPU: 1, Memory: 1}), - nodeInfo: schedulercache.NewNodeInfo( - newResourcePod(schedulercache.Resource{MilliCPU: 10, Memory: 10})), + pod: newResourcePod(schedulernodeinfo.Resource{MilliCPU: 1, Memory: 1}), + nodeInfo: schedulernodeinfo.NewNodeInfo( + newResourcePod(schedulernodeinfo.Resource{MilliCPU: 10, Memory: 10})), fits: false, name: "due to container scratch disk", - reasons: []algorithm.PredicateFailureReason{ + reasons: []PredicateFailureReason{ NewInsufficientResourceError(v1.ResourceCPU, 1, 10, 10), }, }, { - pod: newResourcePod(schedulercache.Resource{MilliCPU: 1, Memory: 1}), - nodeInfo: schedulercache.NewNodeInfo( - newResourcePod(schedulercache.Resource{MilliCPU: 2, Memory: 10})), + pod: newResourcePod(schedulernodeinfo.Resource{MilliCPU: 1, Memory: 1}), + nodeInfo: schedulernodeinfo.NewNodeInfo( + newResourcePod(schedulernodeinfo.Resource{MilliCPU: 2, Memory: 10})), fits: true, name: "pod fit", }, { - pod: newResourcePod(schedulercache.Resource{EphemeralStorage: 25}), - nodeInfo: schedulercache.NewNodeInfo( - newResourcePod(schedulercache.Resource{MilliCPU: 2, Memory: 2})), + pod: newResourcePod(schedulernodeinfo.Resource{EphemeralStorage: 25}), + nodeInfo: schedulernodeinfo.NewNodeInfo( + newResourcePod(schedulernodeinfo.Resource{MilliCPU: 2, Memory: 2})), fits: false, name: "storage ephemeral local storage request exceeds allocatable", - reasons: []algorithm.PredicateFailureReason{ + reasons: []PredicateFailureReason{ NewInsufficientResourceError(v1.ResourceEphemeralStorage, 25, 0, 20), }, }, { - pod: newResourcePod(schedulercache.Resource{EphemeralStorage: 10}), - nodeInfo: schedulercache.NewNodeInfo( - newResourcePod(schedulercache.Resource{MilliCPU: 2, Memory: 2})), + pod: newResourcePod(schedulernodeinfo.Resource{EphemeralStorage: 10}), + nodeInfo: schedulernodeinfo.NewNodeInfo( + newResourcePod(schedulernodeinfo.Resource{MilliCPU: 2, Memory: 2})), fits: true, name: "pod fits", }, @@ -481,7 +477,7 @@ func TestPodFitsResources(t *testing.T) { t.Run(test.name, func(t *testing.T) { node := v1.Node{Status: v1.NodeStatus{Capacity: makeResources(10, 20, 32, 5, 20, 5).Capacity, Allocatable: makeAllocatableResources(10, 20, 32, 5, 20, 5)}} test.nodeInfo.SetNode(&node) - fits, reasons, err := PodFitsResources(test.pod, PredicateMetadata(test.pod, nil), test.nodeInfo) + fits, reasons, err := PodFitsResources(test.pod, GetPredicateMetadata(test.pod, nil), test.nodeInfo) if err != nil { t.Errorf("unexpected error: %v", err) } @@ -538,13 +534,13 @@ func TestPodFitsHost(t *testing.T) { name: "host doesn't match", }, } - expectedFailureReasons := []algorithm.PredicateFailureReason{ErrPodNotMatchHostName} + expectedFailureReasons := []PredicateFailureReason{ErrPodNotMatchHostName} for _, test := range tests { t.Run(test.name, func(t *testing.T) { - nodeInfo := schedulercache.NewNodeInfo() + nodeInfo := schedulernodeinfo.NewNodeInfo() nodeInfo.SetNode(test.node) - fits, reasons, err := PodFitsHost(test.pod, PredicateMetadata(test.pod, nil), nodeInfo) + fits, reasons, err := PodFitsHost(test.pod, GetPredicateMetadata(test.pod, nil), nodeInfo) if err != nil { t.Errorf("unexpected error: %v", err) } @@ -585,106 +581,106 @@ func newPod(host string, hostPortInfos ...string) *v1.Pod { func TestPodFitsHostPorts(t *testing.T) { tests := []struct { pod *v1.Pod - nodeInfo *schedulercache.NodeInfo + nodeInfo *schedulernodeinfo.NodeInfo fits bool name string }{ { pod: &v1.Pod{}, - nodeInfo: schedulercache.NewNodeInfo(), + nodeInfo: schedulernodeinfo.NewNodeInfo(), fits: true, name: "nothing running", }, { pod: newPod("m1", "UDP/127.0.0.1/8080"), - nodeInfo: schedulercache.NewNodeInfo( + nodeInfo: schedulernodeinfo.NewNodeInfo( newPod("m1", "UDP/127.0.0.1/9090")), fits: true, name: "other port", }, { pod: newPod("m1", "UDP/127.0.0.1/8080"), - nodeInfo: schedulercache.NewNodeInfo( + nodeInfo: schedulernodeinfo.NewNodeInfo( newPod("m1", "UDP/127.0.0.1/8080")), fits: false, name: "same udp port", }, { pod: newPod("m1", "TCP/127.0.0.1/8080"), - nodeInfo: schedulercache.NewNodeInfo( + nodeInfo: schedulernodeinfo.NewNodeInfo( newPod("m1", "TCP/127.0.0.1/8080")), fits: false, name: "same tcp port", }, { pod: newPod("m1", "TCP/127.0.0.1/8080"), - nodeInfo: schedulercache.NewNodeInfo( + nodeInfo: schedulernodeinfo.NewNodeInfo( newPod("m1", "TCP/127.0.0.2/8080")), fits: true, name: "different host ip", }, { pod: newPod("m1", "UDP/127.0.0.1/8080"), - nodeInfo: schedulercache.NewNodeInfo( + nodeInfo: schedulernodeinfo.NewNodeInfo( newPod("m1", "TCP/127.0.0.1/8080")), fits: true, name: "different protocol", }, { pod: newPod("m1", "UDP/127.0.0.1/8000", "UDP/127.0.0.1/8080"), - nodeInfo: schedulercache.NewNodeInfo( + nodeInfo: schedulernodeinfo.NewNodeInfo( newPod("m1", "UDP/127.0.0.1/8080")), fits: false, name: "second udp port conflict", }, { pod: newPod("m1", "TCP/127.0.0.1/8001", "UDP/127.0.0.1/8080"), - nodeInfo: schedulercache.NewNodeInfo( + nodeInfo: schedulernodeinfo.NewNodeInfo( newPod("m1", "TCP/127.0.0.1/8001", "UDP/127.0.0.1/8081")), fits: false, name: "first tcp port conflict", }, { pod: newPod("m1", "TCP/0.0.0.0/8001"), - nodeInfo: schedulercache.NewNodeInfo( + nodeInfo: schedulernodeinfo.NewNodeInfo( newPod("m1", "TCP/127.0.0.1/8001")), fits: false, name: "first tcp port conflict due to 0.0.0.0 hostIP", }, { pod: newPod("m1", "TCP/10.0.10.10/8001", "TCP/0.0.0.0/8001"), - nodeInfo: schedulercache.NewNodeInfo( + nodeInfo: schedulernodeinfo.NewNodeInfo( newPod("m1", "TCP/127.0.0.1/8001")), fits: false, name: "TCP hostPort conflict due to 0.0.0.0 hostIP", }, { pod: newPod("m1", "TCP/127.0.0.1/8001"), - nodeInfo: schedulercache.NewNodeInfo( + nodeInfo: schedulernodeinfo.NewNodeInfo( newPod("m1", "TCP/0.0.0.0/8001")), fits: false, name: "second tcp port conflict to 0.0.0.0 hostIP", }, { pod: newPod("m1", "UDP/127.0.0.1/8001"), - nodeInfo: schedulercache.NewNodeInfo( + nodeInfo: schedulernodeinfo.NewNodeInfo( newPod("m1", "TCP/0.0.0.0/8001")), fits: true, name: "second different protocol", }, { pod: newPod("m1", "UDP/127.0.0.1/8001"), - nodeInfo: schedulercache.NewNodeInfo( + nodeInfo: schedulernodeinfo.NewNodeInfo( newPod("m1", "TCP/0.0.0.0/8001", "UDP/0.0.0.0/8001")), fits: false, name: "UDP hostPort conflict due to 0.0.0.0 hostIP", }, } - expectedFailureReasons := []algorithm.PredicateFailureReason{ErrPodNotFitsHostPorts} + expectedFailureReasons := []PredicateFailureReason{ErrPodNotFitsHostPorts} for _, test := range tests { t.Run(test.name, func(t *testing.T) { - fits, reasons, err := PodFitsHostPorts(test.pod, PredicateMetadata(test.pod, nil), test.nodeInfo) + fits, reasons, err := PodFitsHostPorts(test.pod, GetPredicateMetadata(test.pod, nil), test.nodeInfo) if err != nil { t.Errorf("unexpected error: %v", err) } @@ -723,20 +719,20 @@ func TestGCEDiskConflicts(t *testing.T) { } tests := []struct { pod *v1.Pod - nodeInfo *schedulercache.NodeInfo + nodeInfo *schedulernodeinfo.NodeInfo isOk bool name string }{ - {&v1.Pod{}, schedulercache.NewNodeInfo(), true, "nothing"}, - {&v1.Pod{}, schedulercache.NewNodeInfo(&v1.Pod{Spec: volState}), true, "one state"}, - {&v1.Pod{Spec: volState}, schedulercache.NewNodeInfo(&v1.Pod{Spec: volState}), false, "same state"}, - {&v1.Pod{Spec: volState2}, schedulercache.NewNodeInfo(&v1.Pod{Spec: volState}), true, "different state"}, + {&v1.Pod{}, schedulernodeinfo.NewNodeInfo(), true, "nothing"}, + {&v1.Pod{}, schedulernodeinfo.NewNodeInfo(&v1.Pod{Spec: volState}), true, "one state"}, + {&v1.Pod{Spec: volState}, schedulernodeinfo.NewNodeInfo(&v1.Pod{Spec: volState}), false, "same state"}, + {&v1.Pod{Spec: volState2}, schedulernodeinfo.NewNodeInfo(&v1.Pod{Spec: volState}), true, "different state"}, } - expectedFailureReasons := []algorithm.PredicateFailureReason{ErrDiskConflict} + expectedFailureReasons := []PredicateFailureReason{ErrDiskConflict} for _, test := range tests { t.Run(test.name, func(t *testing.T) { - ok, reasons, err := NoDiskConflict(test.pod, PredicateMetadata(test.pod, nil), test.nodeInfo) + ok, reasons, err := NoDiskConflict(test.pod, GetPredicateMetadata(test.pod, nil), test.nodeInfo) if err != nil { t.Errorf("unexpected error: %v", err) } @@ -778,20 +774,20 @@ func TestAWSDiskConflicts(t *testing.T) { } tests := []struct { pod *v1.Pod - nodeInfo *schedulercache.NodeInfo + nodeInfo *schedulernodeinfo.NodeInfo isOk bool name string }{ - {&v1.Pod{}, schedulercache.NewNodeInfo(), true, "nothing"}, - {&v1.Pod{}, schedulercache.NewNodeInfo(&v1.Pod{Spec: volState}), true, "one state"}, - {&v1.Pod{Spec: volState}, schedulercache.NewNodeInfo(&v1.Pod{Spec: volState}), false, "same state"}, - {&v1.Pod{Spec: volState2}, schedulercache.NewNodeInfo(&v1.Pod{Spec: volState}), true, "different state"}, + {&v1.Pod{}, schedulernodeinfo.NewNodeInfo(), true, "nothing"}, + {&v1.Pod{}, schedulernodeinfo.NewNodeInfo(&v1.Pod{Spec: volState}), true, "one state"}, + {&v1.Pod{Spec: volState}, schedulernodeinfo.NewNodeInfo(&v1.Pod{Spec: volState}), false, "same state"}, + {&v1.Pod{Spec: volState2}, schedulernodeinfo.NewNodeInfo(&v1.Pod{Spec: volState}), true, "different state"}, } - expectedFailureReasons := []algorithm.PredicateFailureReason{ErrDiskConflict} + expectedFailureReasons := []PredicateFailureReason{ErrDiskConflict} for _, test := range tests { t.Run(test.name, func(t *testing.T) { - ok, reasons, err := NoDiskConflict(test.pod, PredicateMetadata(test.pod, nil), test.nodeInfo) + ok, reasons, err := NoDiskConflict(test.pod, GetPredicateMetadata(test.pod, nil), test.nodeInfo) if err != nil { t.Errorf("unexpected error: %v", err) } @@ -839,20 +835,20 @@ func TestRBDDiskConflicts(t *testing.T) { } tests := []struct { pod *v1.Pod - nodeInfo *schedulercache.NodeInfo + nodeInfo *schedulernodeinfo.NodeInfo isOk bool name string }{ - {&v1.Pod{}, schedulercache.NewNodeInfo(), true, "nothing"}, - {&v1.Pod{}, schedulercache.NewNodeInfo(&v1.Pod{Spec: volState}), true, "one state"}, - {&v1.Pod{Spec: volState}, schedulercache.NewNodeInfo(&v1.Pod{Spec: volState}), false, "same state"}, - {&v1.Pod{Spec: volState2}, schedulercache.NewNodeInfo(&v1.Pod{Spec: volState}), true, "different state"}, + {&v1.Pod{}, schedulernodeinfo.NewNodeInfo(), true, "nothing"}, + {&v1.Pod{}, schedulernodeinfo.NewNodeInfo(&v1.Pod{Spec: volState}), true, "one state"}, + {&v1.Pod{Spec: volState}, schedulernodeinfo.NewNodeInfo(&v1.Pod{Spec: volState}), false, "same state"}, + {&v1.Pod{Spec: volState2}, schedulernodeinfo.NewNodeInfo(&v1.Pod{Spec: volState}), true, "different state"}, } - expectedFailureReasons := []algorithm.PredicateFailureReason{ErrDiskConflict} + expectedFailureReasons := []PredicateFailureReason{ErrDiskConflict} for _, test := range tests { t.Run(test.name, func(t *testing.T) { - ok, reasons, err := NoDiskConflict(test.pod, PredicateMetadata(test.pod, nil), test.nodeInfo) + ok, reasons, err := NoDiskConflict(test.pod, GetPredicateMetadata(test.pod, nil), test.nodeInfo) if err != nil { t.Errorf("unexpected error: %v", err) } @@ -900,20 +896,20 @@ func TestISCSIDiskConflicts(t *testing.T) { } tests := []struct { pod *v1.Pod - nodeInfo *schedulercache.NodeInfo + nodeInfo *schedulernodeinfo.NodeInfo isOk bool name string }{ - {&v1.Pod{}, schedulercache.NewNodeInfo(), true, "nothing"}, - {&v1.Pod{}, schedulercache.NewNodeInfo(&v1.Pod{Spec: volState}), true, "one state"}, - {&v1.Pod{Spec: volState}, schedulercache.NewNodeInfo(&v1.Pod{Spec: volState}), false, "same state"}, - {&v1.Pod{Spec: volState2}, schedulercache.NewNodeInfo(&v1.Pod{Spec: volState}), true, "different state"}, + {&v1.Pod{}, schedulernodeinfo.NewNodeInfo(), true, "nothing"}, + {&v1.Pod{}, schedulernodeinfo.NewNodeInfo(&v1.Pod{Spec: volState}), true, "one state"}, + {&v1.Pod{Spec: volState}, schedulernodeinfo.NewNodeInfo(&v1.Pod{Spec: volState}), false, "same state"}, + {&v1.Pod{Spec: volState2}, schedulernodeinfo.NewNodeInfo(&v1.Pod{Spec: volState}), true, "different state"}, } - expectedFailureReasons := []algorithm.PredicateFailureReason{ErrDiskConflict} + expectedFailureReasons := []PredicateFailureReason{ErrDiskConflict} for _, test := range tests { t.Run(test.name, func(t *testing.T) { - ok, reasons, err := NoDiskConflict(test.pod, PredicateMetadata(test.pod, nil), test.nodeInfo) + ok, reasons, err := NoDiskConflict(test.pod, GetPredicateMetadata(test.pod, nil), test.nodeInfo) if err != nil { t.Errorf("unexpected error: %v", err) } @@ -1603,7 +1599,7 @@ func TestPodFitsSelector(t *testing.T) { name: "Pod with two terms: both matchFields and matchExpressions do not match", }, } - expectedFailureReasons := []algorithm.PredicateFailureReason{ErrNodeSelectorNotMatch} + expectedFailureReasons := []PredicateFailureReason{ErrNodeSelectorNotMatch} for _, test := range tests { t.Run(test.name, func(t *testing.T) { @@ -1611,10 +1607,10 @@ func TestPodFitsSelector(t *testing.T) { Name: test.nodeName, Labels: test.labels, }} - nodeInfo := schedulercache.NewNodeInfo() + nodeInfo := schedulernodeinfo.NewNodeInfo() nodeInfo.SetNode(&node) - fits, reasons, err := PodMatchNodeSelector(test.pod, PredicateMetadata(test.pod, nil), nodeInfo) + fits, reasons, err := PodMatchNodeSelector(test.pod, GetPredicateMetadata(test.pod, nil), nodeInfo) if err != nil { t.Errorf("unexpected error: %v", err) } @@ -1674,16 +1670,16 @@ func TestNodeLabelPresence(t *testing.T) { name: "all labels match, presence false", }, } - expectedFailureReasons := []algorithm.PredicateFailureReason{ErrNodeLabelPresenceViolated} + expectedFailureReasons := []PredicateFailureReason{ErrNodeLabelPresenceViolated} for _, test := range tests { t.Run(test.name, func(t *testing.T) { node := v1.Node{ObjectMeta: metav1.ObjectMeta{Labels: label}} - nodeInfo := schedulercache.NewNodeInfo() + nodeInfo := schedulernodeinfo.NewNodeInfo() nodeInfo.SetNode(&node) labelChecker := NodeLabelChecker{test.labels, test.presence} - fits, reasons, err := labelChecker.CheckNodeLabelPresence(test.pod, PredicateMetadata(test.pod, nil), nodeInfo) + fits, reasons, err := labelChecker.CheckNodeLabelPresence(test.pod, GetPredicateMetadata(test.pod, nil), nodeInfo) if err != nil { t.Errorf("unexpected error: %v", err) } @@ -1823,14 +1819,14 @@ func TestServiceAffinity(t *testing.T) { name: "service pod on different node, multiple labels, all match", }, } - expectedFailureReasons := []algorithm.PredicateFailureReason{ErrServiceAffinityViolated} + expectedFailureReasons := []PredicateFailureReason{ErrServiceAffinityViolated} for _, test := range tests { testIt := func(skipPrecompute bool) { t.Run(fmt.Sprintf("%v/skipPrecompute/%v", test.name, skipPrecompute), func(t *testing.T) { nodes := []v1.Node{node1, node2, node3, node4, node5} - nodeInfo := schedulercache.NewNodeInfo() + nodeInfo := schedulernodeinfo.NewNodeInfo() nodeInfo.SetNode(test.node) - nodeInfoMap := map[string]*schedulercache.NodeInfo{test.node.Name: nodeInfo} + nodeInfoMap := map[string]*schedulernodeinfo.NodeInfo{test.node.Name: nodeInfo} // Reimplementing the logic that the scheduler implements: Any time it makes a predicate, it registers any precomputations. predicate, precompute := NewServiceAffinityPredicate(schedulertesting.FakePodLister(test.pods), schedulertesting.FakeServiceLister(test.services), FakeNodeListInfo(nodes), test.labels) // Register a precomputation or Rewrite the precomputation to a no-op, depending on the state we want to test. @@ -1839,7 +1835,7 @@ func TestServiceAffinity(t *testing.T) { precompute(pm) } }) - if pmeta, ok := (PredicateMetadata(test.pod, nodeInfoMap)).(*predicateMetadata); ok { + if pmeta, ok := (GetPredicateMetadata(test.pod, nodeInfoMap)).(*predicateMetadata); ok { fits, reasons, err := predicate(test.pod, pmeta, nodeInfo) if err != nil { t.Errorf("unexpected error: %v", err) @@ -1880,17 +1876,17 @@ func newPodWithPort(hostPorts ...int) *v1.Pod { func TestRunGeneralPredicates(t *testing.T) { resourceTests := []struct { pod *v1.Pod - nodeInfo *schedulercache.NodeInfo + nodeInfo *schedulernodeinfo.NodeInfo node *v1.Node fits bool name string wErr error - reasons []algorithm.PredicateFailureReason + reasons []PredicateFailureReason }{ { pod: &v1.Pod{}, - nodeInfo: schedulercache.NewNodeInfo( - newResourcePod(schedulercache.Resource{MilliCPU: 9, Memory: 19})), + nodeInfo: schedulernodeinfo.NewNodeInfo( + newResourcePod(schedulernodeinfo.Resource{MilliCPU: 9, Memory: 19})), node: &v1.Node{ ObjectMeta: metav1.ObjectMeta{Name: "machine1"}, Status: v1.NodeStatus{Capacity: makeResources(10, 20, 32, 0, 0, 0).Capacity, Allocatable: makeAllocatableResources(10, 20, 32, 0, 0, 0)}, @@ -1900,16 +1896,16 @@ func TestRunGeneralPredicates(t *testing.T) { name: "no resources/port/host requested always fits", }, { - pod: newResourcePod(schedulercache.Resource{MilliCPU: 8, Memory: 10}), - nodeInfo: schedulercache.NewNodeInfo( - newResourcePod(schedulercache.Resource{MilliCPU: 5, Memory: 19})), + pod: newResourcePod(schedulernodeinfo.Resource{MilliCPU: 8, Memory: 10}), + nodeInfo: schedulernodeinfo.NewNodeInfo( + newResourcePod(schedulernodeinfo.Resource{MilliCPU: 5, Memory: 19})), node: &v1.Node{ ObjectMeta: metav1.ObjectMeta{Name: "machine1"}, Status: v1.NodeStatus{Capacity: makeResources(10, 20, 32, 0, 0, 0).Capacity, Allocatable: makeAllocatableResources(10, 20, 32, 0, 0, 0)}, }, fits: false, wErr: nil, - reasons: []algorithm.PredicateFailureReason{ + reasons: []PredicateFailureReason{ NewInsufficientResourceError(v1.ResourceCPU, 8, 5, 10), NewInsufficientResourceError(v1.ResourceMemory, 10, 19, 20), }, @@ -1921,33 +1917,33 @@ func TestRunGeneralPredicates(t *testing.T) { NodeName: "machine2", }, }, - nodeInfo: schedulercache.NewNodeInfo(), + nodeInfo: schedulernodeinfo.NewNodeInfo(), node: &v1.Node{ ObjectMeta: metav1.ObjectMeta{Name: "machine1"}, Status: v1.NodeStatus{Capacity: makeResources(10, 20, 32, 0, 0, 0).Capacity, Allocatable: makeAllocatableResources(10, 20, 32, 0, 0, 0)}, }, fits: false, wErr: nil, - reasons: []algorithm.PredicateFailureReason{ErrPodNotMatchHostName}, + reasons: []PredicateFailureReason{ErrPodNotMatchHostName}, name: "host not match", }, { pod: newPodWithPort(123), - nodeInfo: schedulercache.NewNodeInfo(newPodWithPort(123)), + nodeInfo: schedulernodeinfo.NewNodeInfo(newPodWithPort(123)), node: &v1.Node{ ObjectMeta: metav1.ObjectMeta{Name: "machine1"}, Status: v1.NodeStatus{Capacity: makeResources(10, 20, 32, 0, 0, 0).Capacity, Allocatable: makeAllocatableResources(10, 20, 32, 0, 0, 0)}, }, fits: false, wErr: nil, - reasons: []algorithm.PredicateFailureReason{ErrPodNotFitsHostPorts}, + reasons: []PredicateFailureReason{ErrPodNotFitsHostPorts}, name: "hostport conflict", }, } for _, test := range resourceTests { t.Run(test.name, func(t *testing.T) { test.nodeInfo.SetNode(test.node) - fits, reasons, err := GeneralPredicates(test.pod, PredicateMetadata(test.pod, nil), test.nodeInfo) + fits, reasons, err := GeneralPredicates(test.pod, GetPredicateMetadata(test.pod, nil), test.nodeInfo) if err != nil { t.Errorf("unexpected error: %v", err) } @@ -1976,7 +1972,7 @@ func TestInterPodAffinity(t *testing.T) { node *v1.Node fits bool name string - expectFailureReasons []algorithm.PredicateFailureReason + expectFailureReasons []PredicateFailureReason }{ { pod: new(v1.Pod), @@ -2076,7 +2072,7 @@ func TestInterPodAffinity(t *testing.T) { node: &node1, fits: false, name: "Does not satisfy the PodAffinity with labelSelector because of diff Namespace", - expectFailureReasons: []algorithm.PredicateFailureReason{ErrPodAffinityNotMatch, ErrPodAffinityRulesNotMatch}, + expectFailureReasons: []PredicateFailureReason{ErrPodAffinityNotMatch, ErrPodAffinityRulesNotMatch}, }, { pod: &v1.Pod{ @@ -2107,7 +2103,7 @@ func TestInterPodAffinity(t *testing.T) { node: &node1, fits: false, name: "Doesn't satisfy the PodAffinity because of unmatching labelSelector with the existing pod", - expectFailureReasons: []algorithm.PredicateFailureReason{ErrPodAffinityNotMatch, ErrPodAffinityRulesNotMatch}, + expectFailureReasons: []PredicateFailureReason{ErrPodAffinityNotMatch, ErrPodAffinityRulesNotMatch}, }, { pod: &v1.Pod{ @@ -2204,7 +2200,7 @@ func TestInterPodAffinity(t *testing.T) { node: &node1, fits: false, name: "The labelSelector requirements(items of matchExpressions) are ANDed, the pod cannot schedule onto the node because one of the matchExpression item don't match.", - expectFailureReasons: []algorithm.PredicateFailureReason{ErrPodAffinityNotMatch, ErrPodAffinityRulesNotMatch}, + expectFailureReasons: []PredicateFailureReason{ErrPodAffinityNotMatch, ErrPodAffinityRulesNotMatch}, }, { pod: &v1.Pod{ @@ -2371,7 +2367,7 @@ func TestInterPodAffinity(t *testing.T) { node: &node1, fits: false, name: "satisfies the PodAffinity but doesn't satisfy the PodAntiAffinity with the existing pod", - expectFailureReasons: []algorithm.PredicateFailureReason{ErrPodAffinityNotMatch, ErrPodAntiAffinityRulesNotMatch}, + expectFailureReasons: []PredicateFailureReason{ErrPodAffinityNotMatch, ErrPodAntiAffinityRulesNotMatch}, }, { pod: &v1.Pod{ @@ -2444,7 +2440,7 @@ func TestInterPodAffinity(t *testing.T) { node: &node1, fits: false, name: "satisfies the PodAffinity and PodAntiAffinity but doesn't satisfy PodAntiAffinity symmetry with the existing pod", - expectFailureReasons: []algorithm.PredicateFailureReason{ErrPodAffinityNotMatch, ErrExistingPodsAntiAffinityRulesNotMatch}, + expectFailureReasons: []PredicateFailureReason{ErrPodAffinityNotMatch, ErrExistingPodsAntiAffinityRulesNotMatch}, }, { pod: &v1.Pod{ @@ -2476,7 +2472,7 @@ func TestInterPodAffinity(t *testing.T) { node: &node1, fits: false, name: "pod matches its own Label in PodAffinity and that matches the existing pod Labels", - expectFailureReasons: []algorithm.PredicateFailureReason{ErrPodAffinityNotMatch, ErrPodAffinityRulesNotMatch}, + expectFailureReasons: []PredicateFailureReason{ErrPodAffinityNotMatch, ErrPodAffinityRulesNotMatch}, }, { pod: &v1.Pod{ @@ -2512,7 +2508,7 @@ func TestInterPodAffinity(t *testing.T) { node: &node1, fits: false, name: "verify that PodAntiAffinity from existing pod is respected when pod has no AntiAffinity constraints. doesn't satisfy PodAntiAffinity symmetry with the existing pod", - expectFailureReasons: []algorithm.PredicateFailureReason{ErrPodAffinityNotMatch, ErrExistingPodsAntiAffinityRulesNotMatch}, + expectFailureReasons: []PredicateFailureReason{ErrPodAffinityNotMatch, ErrExistingPodsAntiAffinityRulesNotMatch}, }, { pod: &v1.Pod{ @@ -2612,7 +2608,7 @@ func TestInterPodAffinity(t *testing.T) { node: &node1, fits: false, name: "satisfies the PodAntiAffinity with existing pod but doesn't satisfy PodAntiAffinity symmetry with incoming pod", - expectFailureReasons: []algorithm.PredicateFailureReason{ErrPodAffinityNotMatch, ErrPodAntiAffinityRulesNotMatch}, + expectFailureReasons: []PredicateFailureReason{ErrPodAffinityNotMatch, ErrPodAntiAffinityRulesNotMatch}, }, { pod: &v1.Pod{ @@ -2675,7 +2671,7 @@ func TestInterPodAffinity(t *testing.T) { }, node: &node1, fits: false, - expectFailureReasons: []algorithm.PredicateFailureReason{ErrPodAffinityNotMatch, ErrPodAntiAffinityRulesNotMatch}, + expectFailureReasons: []PredicateFailureReason{ErrPodAffinityNotMatch, ErrPodAntiAffinityRulesNotMatch}, name: "PodAntiAffinity symmetry check a1: incoming pod and existing pod partially match each other on AffinityTerms", }, { @@ -2739,7 +2735,7 @@ func TestInterPodAffinity(t *testing.T) { }, node: &node1, fits: false, - expectFailureReasons: []algorithm.PredicateFailureReason{ErrPodAffinityNotMatch, ErrExistingPodsAntiAffinityRulesNotMatch}, + expectFailureReasons: []PredicateFailureReason{ErrPodAffinityNotMatch, ErrExistingPodsAntiAffinityRulesNotMatch}, name: "PodAntiAffinity symmetry check a2: incoming pod and existing pod partially match each other on AffinityTerms", }, { @@ -2814,7 +2810,7 @@ func TestInterPodAffinity(t *testing.T) { }, node: &node1, fits: false, - expectFailureReasons: []algorithm.PredicateFailureReason{ErrPodAffinityNotMatch, ErrExistingPodsAntiAffinityRulesNotMatch}, + expectFailureReasons: []PredicateFailureReason{ErrPodAffinityNotMatch, ErrExistingPodsAntiAffinityRulesNotMatch}, name: "PodAntiAffinity symmetry check b1: incoming pod and existing pod partially match each other on AffinityTerms", }, { @@ -2889,7 +2885,7 @@ func TestInterPodAffinity(t *testing.T) { }, node: &node1, fits: false, - expectFailureReasons: []algorithm.PredicateFailureReason{ErrPodAffinityNotMatch, ErrExistingPodsAntiAffinityRulesNotMatch}, + expectFailureReasons: []PredicateFailureReason{ErrPodAffinityNotMatch, ErrExistingPodsAntiAffinityRulesNotMatch}, name: "PodAntiAffinity symmetry check b2: incoming pod and existing pod partially match each other on AffinityTerms", }, } @@ -2908,10 +2904,10 @@ func TestInterPodAffinity(t *testing.T) { info: FakeNodeInfo(*node), podLister: schedulertesting.FakePodLister(test.pods), } - nodeInfo := schedulercache.NewNodeInfo(podsOnNode...) + nodeInfo := schedulernodeinfo.NewNodeInfo(podsOnNode...) nodeInfo.SetNode(test.node) - nodeInfoMap := map[string]*schedulercache.NodeInfo{test.node.Name: nodeInfo} - fits, reasons, _ := fit.InterPodAffinityMatches(test.pod, PredicateMetadata(test.pod, nodeInfoMap), nodeInfo) + nodeInfoMap := map[string]*schedulernodeinfo.NodeInfo{test.node.Name: nodeInfo} + fits, reasons, _ := fit.InterPodAffinityMatches(test.pod, GetPredicateMetadata(test.pod, nodeInfoMap), nodeInfo) if !fits && !reflect.DeepEqual(reasons, test.expectFailureReasons) { t.Errorf("unexpected failure reasons: %v, want: %v", reasons, test.expectFailureReasons) } @@ -2944,7 +2940,7 @@ func TestInterPodAffinityWithMultipleNodes(t *testing.T) { pod *v1.Pod pods []*v1.Pod nodes []v1.Node - nodesExpectAffinityFailureReasons [][]algorithm.PredicateFailureReason + nodesExpectAffinityFailureReasons [][]PredicateFailureReason fits map[string]bool name string nometa bool @@ -2985,7 +2981,7 @@ func TestInterPodAffinityWithMultipleNodes(t *testing.T) { "machine2": true, "machine3": false, }, - nodesExpectAffinityFailureReasons: [][]algorithm.PredicateFailureReason{nil, nil, {ErrPodAffinityNotMatch, ErrPodAffinityRulesNotMatch}}, + nodesExpectAffinityFailureReasons: [][]PredicateFailureReason{nil, nil, {ErrPodAffinityNotMatch, ErrPodAffinityRulesNotMatch}}, name: "A pod can be scheduled onto all the nodes that have the same topology key & label value with one of them has an existing pod that matches the affinity rules", }, { @@ -3034,7 +3030,7 @@ func TestInterPodAffinityWithMultipleNodes(t *testing.T) { {ObjectMeta: metav1.ObjectMeta{Name: "nodeA", Labels: map[string]string{"region": "r1", "hostname": "h1"}}}, {ObjectMeta: metav1.ObjectMeta{Name: "nodeB", Labels: map[string]string{"region": "r1", "hostname": "h2"}}}, }, - nodesExpectAffinityFailureReasons: [][]algorithm.PredicateFailureReason{nil, nil}, + nodesExpectAffinityFailureReasons: [][]PredicateFailureReason{nil, nil}, fits: map[string]bool{ "nodeA": false, "nodeB": true, @@ -3087,7 +3083,7 @@ func TestInterPodAffinityWithMultipleNodes(t *testing.T) { {ObjectMeta: metav1.ObjectMeta{Name: "nodeA", Labels: map[string]string{"zone": "az1", "hostname": "h1"}}}, {ObjectMeta: metav1.ObjectMeta{Name: "nodeB", Labels: map[string]string{"zone": "az2", "hostname": "h2"}}}, }, - nodesExpectAffinityFailureReasons: [][]algorithm.PredicateFailureReason{nil, nil}, + nodesExpectAffinityFailureReasons: [][]PredicateFailureReason{nil, nil}, fits: map[string]bool{ "nodeA": true, "nodeB": true, @@ -3125,7 +3121,7 @@ func TestInterPodAffinityWithMultipleNodes(t *testing.T) { {ObjectMeta: metav1.ObjectMeta{Name: "nodeA", Labels: map[string]string{"region": "r1", "hostname": "nodeA"}}}, {ObjectMeta: metav1.ObjectMeta{Name: "nodeB", Labels: map[string]string{"region": "r1", "hostname": "nodeB"}}}, }, - nodesExpectAffinityFailureReasons: [][]algorithm.PredicateFailureReason{{ErrPodAffinityNotMatch, ErrPodAntiAffinityRulesNotMatch}, {ErrPodAffinityNotMatch, ErrPodAntiAffinityRulesNotMatch}}, + nodesExpectAffinityFailureReasons: [][]PredicateFailureReason{{ErrPodAffinityNotMatch, ErrPodAntiAffinityRulesNotMatch}, {ErrPodAffinityNotMatch, ErrPodAntiAffinityRulesNotMatch}}, fits: map[string]bool{ "nodeA": false, "nodeB": false, @@ -3174,7 +3170,7 @@ func TestInterPodAffinityWithMultipleNodes(t *testing.T) { {ObjectMeta: metav1.ObjectMeta{Name: "nodeA", Labels: map[string]string{"region": "r1", "zone": "z1", "hostname": "nodeA"}}}, {ObjectMeta: metav1.ObjectMeta{Name: "nodeB", Labels: map[string]string{"region": "r1", "zone": "z2", "hostname": "nodeB"}}}, }, - nodesExpectAffinityFailureReasons: [][]algorithm.PredicateFailureReason{ + nodesExpectAffinityFailureReasons: [][]PredicateFailureReason{ {ErrPodAffinityNotMatch, ErrPodAntiAffinityRulesNotMatch}, {ErrPodAffinityNotMatch, ErrPodAntiAffinityRulesNotMatch}, }, @@ -3215,7 +3211,7 @@ func TestInterPodAffinityWithMultipleNodes(t *testing.T) { {ObjectMeta: metav1.ObjectMeta{Name: "nodeB", Labels: labelRgChinaAzAz1}}, {ObjectMeta: metav1.ObjectMeta{Name: "nodeC", Labels: labelRgIndia}}, }, - nodesExpectAffinityFailureReasons: [][]algorithm.PredicateFailureReason{{ErrPodAffinityNotMatch, ErrPodAntiAffinityRulesNotMatch}, {ErrPodAffinityNotMatch, ErrPodAntiAffinityRulesNotMatch}, nil}, + nodesExpectAffinityFailureReasons: [][]PredicateFailureReason{{ErrPodAffinityNotMatch, ErrPodAntiAffinityRulesNotMatch}, {ErrPodAffinityNotMatch, ErrPodAntiAffinityRulesNotMatch}, nil}, fits: map[string]bool{ "nodeA": false, "nodeB": false, @@ -3279,7 +3275,7 @@ func TestInterPodAffinityWithMultipleNodes(t *testing.T) { {ObjectMeta: metav1.ObjectMeta{Name: "nodeC", Labels: labelRgIndia}}, {ObjectMeta: metav1.ObjectMeta{Name: "nodeD", Labels: labelRgUS}}, }, - nodesExpectAffinityFailureReasons: [][]algorithm.PredicateFailureReason{ + nodesExpectAffinityFailureReasons: [][]PredicateFailureReason{ {ErrPodAffinityNotMatch, ErrPodAntiAffinityRulesNotMatch}, {ErrPodAffinityNotMatch, ErrPodAntiAffinityRulesNotMatch}, {ErrPodAffinityNotMatch, ErrExistingPodsAntiAffinityRulesNotMatch}, @@ -3359,7 +3355,7 @@ func TestInterPodAffinityWithMultipleNodes(t *testing.T) { {ObjectMeta: metav1.ObjectMeta{Name: "nodeB", Labels: labelRgChinaAzAz1}}, {ObjectMeta: metav1.ObjectMeta{Name: "nodeC", Labels: labelRgIndia}}, }, - nodesExpectAffinityFailureReasons: [][]algorithm.PredicateFailureReason{ + nodesExpectAffinityFailureReasons: [][]PredicateFailureReason{ {ErrPodAffinityNotMatch, ErrPodAntiAffinityRulesNotMatch}, {ErrPodAffinityNotMatch, ErrPodAntiAffinityRulesNotMatch}, nil, @@ -3403,7 +3399,7 @@ func TestInterPodAffinityWithMultipleNodes(t *testing.T) { {ObjectMeta: metav1.ObjectMeta{Name: "nodeA", Labels: map[string]string{"region": "r1", "zone": "z1", "hostname": "nodeA"}}}, {ObjectMeta: metav1.ObjectMeta{Name: "nodeB", Labels: map[string]string{"region": "r1", "zone": "z1", "hostname": "nodeB"}}}, }, - nodesExpectAffinityFailureReasons: [][]algorithm.PredicateFailureReason{}, + nodesExpectAffinityFailureReasons: [][]PredicateFailureReason{}, fits: map[string]bool{ "nodeA": true, "nodeB": true, @@ -3444,7 +3440,7 @@ func TestInterPodAffinityWithMultipleNodes(t *testing.T) { {ObjectMeta: metav1.ObjectMeta{Name: "nodeA", Labels: map[string]string{"region": "r1", "zone": "z1", "hostname": "nodeA"}}}, {ObjectMeta: metav1.ObjectMeta{Name: "nodeB", Labels: map[string]string{"region": "r1", "zone": "z1", "hostname": "nodeB"}}}, }, - nodesExpectAffinityFailureReasons: [][]algorithm.PredicateFailureReason{}, + nodesExpectAffinityFailureReasons: [][]PredicateFailureReason{}, fits: map[string]bool{ "nodeA": true, "nodeB": true, @@ -3507,7 +3503,7 @@ func TestInterPodAffinityWithMultipleNodes(t *testing.T) { {ObjectMeta: metav1.ObjectMeta{Name: "nodeA", Labels: map[string]string{"region": "r1", "zone": "z1", "hostname": "nodeA"}}}, {ObjectMeta: metav1.ObjectMeta{Name: "nodeB", Labels: map[string]string{"region": "r1", "zone": "z2", "hostname": "nodeB"}}}, }, - nodesExpectAffinityFailureReasons: [][]algorithm.PredicateFailureReason{ + nodesExpectAffinityFailureReasons: [][]PredicateFailureReason{ {ErrPodAffinityNotMatch, ErrExistingPodsAntiAffinityRulesNotMatch}, {ErrPodAffinityNotMatch, ErrExistingPodsAntiAffinityRulesNotMatch}, }, @@ -3568,7 +3564,7 @@ func TestInterPodAffinityWithMultipleNodes(t *testing.T) { {ObjectMeta: metav1.ObjectMeta{Name: "nodeA", Labels: map[string]string{"region": "r1", "zone": "z1", "hostname": "nodeA"}}}, {ObjectMeta: metav1.ObjectMeta{Name: "nodeB", Labels: map[string]string{"region": "r1", "zone": "z2", "hostname": "nodeB"}}}, }, - nodesExpectAffinityFailureReasons: [][]algorithm.PredicateFailureReason{ + nodesExpectAffinityFailureReasons: [][]PredicateFailureReason{ {ErrPodAffinityNotMatch, ErrPodAntiAffinityRulesNotMatch}, {ErrPodAffinityNotMatch, ErrPodAntiAffinityRulesNotMatch}, }, @@ -3621,7 +3617,7 @@ func TestInterPodAffinityWithMultipleNodes(t *testing.T) { {ObjectMeta: metav1.ObjectMeta{Name: "nodeA", Labels: map[string]string{"region": "r1", "zone": "z1", "hostname": "nodeA"}}}, {ObjectMeta: metav1.ObjectMeta{Name: "nodeB", Labels: map[string]string{"region": "r1", "zone": "z2", "hostname": "nodeB"}}}, }, - nodesExpectAffinityFailureReasons: [][]algorithm.PredicateFailureReason{ + nodesExpectAffinityFailureReasons: [][]PredicateFailureReason{ {ErrPodAffinityNotMatch, ErrExistingPodsAntiAffinityRulesNotMatch}, }, fits: map[string]bool{ @@ -3675,7 +3671,7 @@ func TestInterPodAffinityWithMultipleNodes(t *testing.T) { {ObjectMeta: metav1.ObjectMeta{Name: "nodeA", Labels: map[string]string{"region": "r1", "zone": "z1", "hostname": "nodeA"}}}, {ObjectMeta: metav1.ObjectMeta{Name: "nodeB", Labels: map[string]string{"region": "r1", "zone": "z2", "hostname": "nodeB"}}}, }, - nodesExpectAffinityFailureReasons: [][]algorithm.PredicateFailureReason{ + nodesExpectAffinityFailureReasons: [][]PredicateFailureReason{ {ErrPodAffinityNotMatch, ErrPodAntiAffinityRulesNotMatch}, }, fits: map[string]bool{ @@ -3727,7 +3723,7 @@ func TestInterPodAffinityWithMultipleNodes(t *testing.T) { {ObjectMeta: metav1.ObjectMeta{Name: "nodeA", Labels: map[string]string{"region": "r1", "zone": "z1", "hostname": "nodeA"}}}, {ObjectMeta: metav1.ObjectMeta{Name: "nodeB", Labels: map[string]string{"region": "r1", "zone": "z2", "hostname": "nodeB"}}}, }, - nodesExpectAffinityFailureReasons: [][]algorithm.PredicateFailureReason{ + nodesExpectAffinityFailureReasons: [][]PredicateFailureReason{ {ErrPodAffinityNotMatch, ErrExistingPodsAntiAffinityRulesNotMatch}, {ErrPodAffinityNotMatch, ErrExistingPodsAntiAffinityRulesNotMatch}, }, @@ -3782,7 +3778,7 @@ func TestInterPodAffinityWithMultipleNodes(t *testing.T) { {ObjectMeta: metav1.ObjectMeta{Name: "nodeA", Labels: map[string]string{"region": "r1", "zone": "z1", "hostname": "nodeA"}}}, {ObjectMeta: metav1.ObjectMeta{Name: "nodeB", Labels: map[string]string{"region": "r1", "zone": "z2", "hostname": "nodeB"}}}, }, - nodesExpectAffinityFailureReasons: [][]algorithm.PredicateFailureReason{ + nodesExpectAffinityFailureReasons: [][]PredicateFailureReason{ {ErrPodAffinityNotMatch, ErrPodAntiAffinityRulesNotMatch}, {ErrPodAffinityNotMatch, ErrPodAntiAffinityRulesNotMatch}, }, @@ -3869,7 +3865,7 @@ func TestInterPodAffinityWithMultipleNodes(t *testing.T) { {ObjectMeta: metav1.ObjectMeta{Name: "nodeB", Labels: map[string]string{"region": "r1", "zone": "z2", "hostname": "nodeB"}}}, {ObjectMeta: metav1.ObjectMeta{Name: "nodeC", Labels: map[string]string{"region": "r1", "zone": "z3", "hostname": "nodeC"}}}, }, - nodesExpectAffinityFailureReasons: [][]algorithm.PredicateFailureReason{ + nodesExpectAffinityFailureReasons: [][]PredicateFailureReason{ {ErrPodAffinityNotMatch, ErrExistingPodsAntiAffinityRulesNotMatch}, {ErrPodAffinityNotMatch, ErrExistingPodsAntiAffinityRulesNotMatch}, }, @@ -3925,7 +3921,7 @@ func TestInterPodAffinityWithMultipleNodes(t *testing.T) { {ObjectMeta: metav1.ObjectMeta{Name: "nodeA", Labels: map[string]string{"region": "r1", "zone": "z1", "hostname": "nodeA"}}}, {ObjectMeta: metav1.ObjectMeta{Name: "nodeB", Labels: map[string]string{"region": "r1", "zone": "z1", "hostname": "nodeB"}}}, }, - nodesExpectAffinityFailureReasons: [][]algorithm.PredicateFailureReason{ + nodesExpectAffinityFailureReasons: [][]PredicateFailureReason{ {}, {ErrPodAffinityNotMatch, ErrPodAffinityRulesNotMatch}, }, @@ -3986,7 +3982,7 @@ func TestInterPodAffinityWithMultipleNodes(t *testing.T) { {ObjectMeta: metav1.ObjectMeta{Name: "nodeA", Labels: map[string]string{"region": "r1", "zone": "z1", "hostname": "nodeA"}}}, {ObjectMeta: metav1.ObjectMeta{Name: "nodeB", Labels: map[string]string{"region": "r1", "zone": "z2", "hostname": "nodeB"}}}, }, - nodesExpectAffinityFailureReasons: [][]algorithm.PredicateFailureReason{ + nodesExpectAffinityFailureReasons: [][]PredicateFailureReason{ {ErrPodAffinityNotMatch, ErrPodAffinityRulesNotMatch}, {ErrPodAffinityNotMatch, ErrPodAffinityRulesNotMatch}, }, @@ -3998,12 +3994,12 @@ func TestInterPodAffinityWithMultipleNodes(t *testing.T) { }, } - selectorExpectedFailureReasons := []algorithm.PredicateFailureReason{ErrNodeSelectorNotMatch} + selectorExpectedFailureReasons := []PredicateFailureReason{ErrNodeSelectorNotMatch} for indexTest, test := range tests { t.Run(test.name, func(t *testing.T) { nodeListInfo := FakeNodeListInfo(test.nodes) - nodeInfoMap := make(map[string]*schedulercache.NodeInfo) + nodeInfoMap := make(map[string]*schedulernodeinfo.NodeInfo) for i, node := range test.nodes { var podsOnNode []*v1.Pod for _, pod := range test.pods { @@ -4012,7 +4008,7 @@ func TestInterPodAffinityWithMultipleNodes(t *testing.T) { } } - nodeInfo := schedulercache.NewNodeInfo(podsOnNode...) + nodeInfo := schedulernodeinfo.NewNodeInfo(podsOnNode...) nodeInfo.SetNode(&test.nodes[i]) nodeInfoMap[node.Name] = nodeInfo } @@ -4023,9 +4019,9 @@ func TestInterPodAffinityWithMultipleNodes(t *testing.T) { podLister: schedulertesting.FakePodLister(test.pods), } - var meta algorithm.PredicateMetadata + var meta PredicateMetadata if !test.nometa { - meta = PredicateMetadata(test.pod, nodeInfoMap) + meta = GetPredicateMetadata(test.pod, nodeInfoMap) } fits, reasons, _ := testFit.InterPodAffinityMatches(test.pod, meta, nodeInfoMap[node.Name]) @@ -4034,10 +4030,10 @@ func TestInterPodAffinityWithMultipleNodes(t *testing.T) { } affinity := test.pod.Spec.Affinity if affinity != nil && affinity.NodeAffinity != nil { - nodeInfo := schedulercache.NewNodeInfo() + nodeInfo := schedulernodeinfo.NewNodeInfo() nodeInfo.SetNode(&node) - nodeInfoMap := map[string]*schedulercache.NodeInfo{node.Name: nodeInfo} - fits2, reasons, err := PodMatchNodeSelector(test.pod, PredicateMetadata(test.pod, nodeInfoMap), nodeInfo) + nodeInfoMap := map[string]*schedulernodeinfo.NodeInfo{node.Name: nodeInfo} + fits2, reasons, err := PodMatchNodeSelector(test.pod, GetPredicateMetadata(test.pod, nodeInfoMap), nodeInfo) if err != nil { t.Errorf("unexpected error: %v", err) } @@ -4238,13 +4234,13 @@ func TestPodToleratesTaints(t *testing.T) { "but the effect of taint on node is PreferNochedule. Pod can be scheduled onto the node", }, } - expectedFailureReasons := []algorithm.PredicateFailureReason{ErrTaintsTolerationsNotMatch} + expectedFailureReasons := []PredicateFailureReason{ErrTaintsTolerationsNotMatch} for _, test := range podTolerateTaintsTests { t.Run(test.name, func(t *testing.T) { - nodeInfo := schedulercache.NewNodeInfo() + nodeInfo := schedulernodeinfo.NewNodeInfo() nodeInfo.SetNode(&test.node) - fits, reasons, err := PodToleratesNodeTaints(test.pod, PredicateMetadata(test.pod, nil), nodeInfo) + fits, reasons, err := PodToleratesNodeTaints(test.pod, GetPredicateMetadata(test.pod, nil), nodeInfo) if err != nil { t.Errorf("unexpected error: %v", err) } @@ -4258,8 +4254,8 @@ func TestPodToleratesTaints(t *testing.T) { } } -func makeEmptyNodeInfo(node *v1.Node) *schedulercache.NodeInfo { - nodeInfo := schedulercache.NewNodeInfo() +func makeEmptyNodeInfo(node *v1.Node) *schedulernodeinfo.NodeInfo { + nodeInfo := schedulernodeinfo.NewNodeInfo() nodeInfo.SetNode(node) return nodeInfo } @@ -4323,7 +4319,7 @@ func TestPodSchedulesOnNodeWithMemoryPressureCondition(t *testing.T) { tests := []struct { pod *v1.Pod - nodeInfo *schedulercache.NodeInfo + nodeInfo *schedulernodeinfo.NodeInfo fits bool name string }{ @@ -4352,11 +4348,11 @@ func TestPodSchedulesOnNodeWithMemoryPressureCondition(t *testing.T) { name: "non best-effort pod schedulable on node without memory pressure condition on", }, } - expectedFailureReasons := []algorithm.PredicateFailureReason{ErrNodeUnderMemoryPressure} + expectedFailureReasons := []PredicateFailureReason{ErrNodeUnderMemoryPressure} for _, test := range tests { t.Run(test.name, func(t *testing.T) { - fits, reasons, err := CheckNodeMemoryPressurePredicate(test.pod, PredicateMetadata(test.pod, nil), test.nodeInfo) + fits, reasons, err := CheckNodeMemoryPressurePredicate(test.pod, GetPredicateMetadata(test.pod, nil), test.nodeInfo) if err != nil { t.Errorf("unexpected error: %v", err) } @@ -4409,7 +4405,7 @@ func TestPodSchedulesOnNodeWithDiskPressureCondition(t *testing.T) { tests := []struct { pod *v1.Pod - nodeInfo *schedulercache.NodeInfo + nodeInfo *schedulernodeinfo.NodeInfo fits bool name string }{ @@ -4426,11 +4422,11 @@ func TestPodSchedulesOnNodeWithDiskPressureCondition(t *testing.T) { name: "pod not schedulable on node with pressure condition on", }, } - expectedFailureReasons := []algorithm.PredicateFailureReason{ErrNodeUnderDiskPressure} + expectedFailureReasons := []PredicateFailureReason{ErrNodeUnderDiskPressure} for _, test := range tests { t.Run(test.name, func(t *testing.T) { - fits, reasons, err := CheckNodeDiskPressurePredicate(test.pod, PredicateMetadata(test.pod, nil), test.nodeInfo) + fits, reasons, err := CheckNodeDiskPressurePredicate(test.pod, GetPredicateMetadata(test.pod, nil), test.nodeInfo) if err != nil { t.Errorf("unexpected error: %v", err) } @@ -4471,7 +4467,7 @@ func TestPodSchedulesOnNodeWithPIDPressureCondition(t *testing.T) { } tests := []struct { - nodeInfo *schedulercache.NodeInfo + nodeInfo *schedulernodeinfo.NodeInfo fits bool name string }{ @@ -4486,11 +4482,11 @@ func TestPodSchedulesOnNodeWithPIDPressureCondition(t *testing.T) { name: "pod not schedulable on node with pressure condition on", }, } - expectedFailureReasons := []algorithm.PredicateFailureReason{ErrNodeUnderPIDPressure} + expectedFailureReasons := []PredicateFailureReason{ErrNodeUnderPIDPressure} for _, test := range tests { t.Run(test.name, func(t *testing.T) { - fits, reasons, err := CheckNodePIDPressurePredicate(&v1.Pod{}, PredicateMetadata(&v1.Pod{}, nil), test.nodeInfo) + fits, reasons, err := CheckNodePIDPressurePredicate(&v1.Pod{}, GetPredicateMetadata(&v1.Pod{}, nil), test.nodeInfo) if err != nil { t.Fatalf("unexpected error: %v", err) } @@ -4521,47 +4517,17 @@ func TestNodeConditionPredicate(t *testing.T) { schedulable: false, }, { - name: "node3 ignored - node out of disk", - node: &v1.Node{ObjectMeta: metav1.ObjectMeta{Name: "node3"}, Status: v1.NodeStatus{Conditions: []v1.NodeCondition{{Type: v1.NodeOutOfDisk, Status: v1.ConditionTrue}}}}, - schedulable: false, - }, - { - name: "node4 considered", - node: &v1.Node{ObjectMeta: metav1.ObjectMeta{Name: "node4"}, Status: v1.NodeStatus{Conditions: []v1.NodeCondition{{Type: v1.NodeOutOfDisk, Status: v1.ConditionFalse}}}}, - schedulable: true, - }, - { - name: "node5 ignored - node out of disk", - node: &v1.Node{ObjectMeta: metav1.ObjectMeta{Name: "node5"}, Status: v1.NodeStatus{Conditions: []v1.NodeCondition{{Type: v1.NodeReady, Status: v1.ConditionTrue}, {Type: v1.NodeOutOfDisk, Status: v1.ConditionTrue}}}}, - schedulable: false, - }, - { - name: "node6 considered", - node: &v1.Node{ObjectMeta: metav1.ObjectMeta{Name: "node6"}, Status: v1.NodeStatus{Conditions: []v1.NodeCondition{{Type: v1.NodeReady, Status: v1.ConditionTrue}, {Type: v1.NodeOutOfDisk, Status: v1.ConditionFalse}}}}, - schedulable: true, - }, - { - name: "node7 ignored - node out of disk, node not Ready", - node: &v1.Node{ObjectMeta: metav1.ObjectMeta{Name: "node7"}, Status: v1.NodeStatus{Conditions: []v1.NodeCondition{{Type: v1.NodeReady, Status: v1.ConditionFalse}, {Type: v1.NodeOutOfDisk, Status: v1.ConditionTrue}}}}, - schedulable: false, - }, - { - name: "node8 ignored - node not Ready", - node: &v1.Node{ObjectMeta: metav1.ObjectMeta{Name: "node8"}, Status: v1.NodeStatus{Conditions: []v1.NodeCondition{{Type: v1.NodeReady, Status: v1.ConditionFalse}, {Type: v1.NodeOutOfDisk, Status: v1.ConditionFalse}}}}, - schedulable: false, - }, - { - name: "node9 ignored - node unschedulable", + name: "node3 ignored - node unschedulable", node: &v1.Node{ObjectMeta: metav1.ObjectMeta{Name: "node9"}, Spec: v1.NodeSpec{Unschedulable: true}}, schedulable: false, }, { - name: "node10 considered", + name: "node4 considered", node: &v1.Node{ObjectMeta: metav1.ObjectMeta{Name: "node10"}, Spec: v1.NodeSpec{Unschedulable: false}}, schedulable: true, }, { - name: "node11 considered", + name: "node5 considered", node: &v1.Node{ObjectMeta: metav1.ObjectMeta{Name: "node11"}}, schedulable: true, }, @@ -4703,12 +4669,12 @@ func TestVolumeZonePredicate(t *testing.T) { }, } - expectedFailureReasons := []algorithm.PredicateFailureReason{ErrVolumeZoneConflict} + expectedFailureReasons := []PredicateFailureReason{ErrVolumeZoneConflict} for _, test := range tests { t.Run(test.name, func(t *testing.T) { fit := NewVolumeZonePredicate(pvInfo, pvcInfo, nil) - node := &schedulercache.NodeInfo{} + node := &schedulernodeinfo.NodeInfo{} node.SetNode(test.Node) fits, reasons, err := fit(test.Pod, nil, node) @@ -4797,12 +4763,12 @@ func TestVolumeZonePredicateMultiZone(t *testing.T) { }, } - expectedFailureReasons := []algorithm.PredicateFailureReason{ErrVolumeZoneConflict} + expectedFailureReasons := []PredicateFailureReason{ErrVolumeZoneConflict} for _, test := range tests { t.Run(test.name, func(t *testing.T) { fit := NewVolumeZonePredicate(pvInfo, pvcInfo, nil) - node := &schedulercache.NodeInfo{} + node := &schedulernodeinfo.NodeInfo{} node.SetNode(test.Node) fits, reasons, err := fit(test.Pod, nil, node) @@ -4915,12 +4881,10 @@ func TestVolumeZonePredicateWithVolumeBinding(t *testing.T) { }, } - defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.VolumeScheduling, true)() - for _, test := range tests { t.Run(test.name, func(t *testing.T) { fit := NewVolumeZonePredicate(pvInfo, pvcInfo, classInfo) - node := &schedulercache.NodeInfo{} + node := &schedulernodeinfo.NodeInfo{} node.SetNode(test.Node) fits, _, err := fit(test.Pod, nil, node) @@ -5028,7 +4992,7 @@ func TestCheckNodeUnschedulablePredicate(t *testing.T) { } for _, test := range testCases { - nodeInfo := schedulercache.NewNodeInfo() + nodeInfo := schedulernodeinfo.NewNodeInfo() nodeInfo.SetNode(test.node) fit, _, err := CheckNodeUnschedulablePredicate(test.pod, nil, nodeInfo) if err != nil { diff --git a/pkg/scheduler/algorithm/predicates/utils.go b/pkg/scheduler/algorithm/predicates/utils.go index de2826a4df4..4080baf91ee 100644 --- a/pkg/scheduler/algorithm/predicates/utils.go +++ b/pkg/scheduler/algorithm/predicates/utils.go @@ -19,7 +19,7 @@ package predicates import ( "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/labels" - schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" + schedulernodeinfo "k8s.io/kubernetes/pkg/scheduler/nodeinfo" ) // FindLabelsInSet gets as many key/value pairs as possible out of a label set. @@ -68,7 +68,7 @@ func CreateSelectorFromLabels(aL map[string]string) labels.Selector { // portsConflict check whether existingPorts and wantPorts conflict with each other // return true if we have a conflict -func portsConflict(existingPorts schedulercache.HostPortInfo, wantPorts []*v1.ContainerPort) bool { +func portsConflict(existingPorts schedulernodeinfo.HostPortInfo, wantPorts []*v1.ContainerPort) bool { for _, cp := range wantPorts { if existingPorts.CheckConflict(cp.HostIP, string(cp.Protocol), cp.HostPort) { return true diff --git a/pkg/scheduler/algorithm/priorities/BUILD b/pkg/scheduler/algorithm/priorities/BUILD index 7f287117f5e..98df72999dc 100644 --- a/pkg/scheduler/algorithm/priorities/BUILD +++ b/pkg/scheduler/algorithm/priorities/BUILD @@ -18,6 +18,7 @@ go_library( "node_affinity.go", "node_label.go", "node_prefer_avoid_pods.go", + "priorities.go", "reduce.go", "requested_to_capacity_ratio.go", "resource_allocation.go", @@ -34,7 +35,7 @@ go_library( "//pkg/scheduler/algorithm/predicates:go_default_library", "//pkg/scheduler/algorithm/priorities/util:go_default_library", "//pkg/scheduler/api:go_default_library", - "//pkg/scheduler/cache:go_default_library", + "//pkg/scheduler/nodeinfo:go_default_library", "//pkg/util/node:go_default_library", "//pkg/util/parsers:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library", @@ -71,7 +72,7 @@ go_test( "//pkg/kubelet/apis:go_default_library", "//pkg/scheduler/algorithm/priorities/util:go_default_library", "//pkg/scheduler/api:go_default_library", - "//pkg/scheduler/cache:go_default_library", + "//pkg/scheduler/nodeinfo:go_default_library", "//pkg/scheduler/testing:go_default_library", "//pkg/util/parsers:go_default_library", "//staging/src/k8s.io/api/apps/v1:go_default_library", diff --git a/pkg/scheduler/algorithm/priorities/balanced_resource_allocation.go b/pkg/scheduler/algorithm/priorities/balanced_resource_allocation.go index c77dd399d5a..97635cddddc 100644 --- a/pkg/scheduler/algorithm/priorities/balanced_resource_allocation.go +++ b/pkg/scheduler/algorithm/priorities/balanced_resource_allocation.go @@ -22,7 +22,7 @@ import ( utilfeature "k8s.io/apiserver/pkg/util/feature" "k8s.io/kubernetes/pkg/features" schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" - schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" + schedulernodeinfo "k8s.io/kubernetes/pkg/scheduler/nodeinfo" ) var ( @@ -38,7 +38,7 @@ var ( BalancedResourceAllocationMap = balancedResourcePriority.PriorityMap ) -func balancedResourceScorer(requested, allocable *schedulercache.Resource, includeVolumes bool, requestedVolumes int, allocatableVolumes int) int64 { +func balancedResourceScorer(requested, allocable *schedulernodeinfo.Resource, includeVolumes bool, requestedVolumes int, allocatableVolumes int) int64 { cpuFraction := fractionOfCapacity(requested.MilliCPU, allocable.MilliCPU) memoryFraction := fractionOfCapacity(requested.Memory, allocable.Memory) // This to find a node which has most balanced CPU, memory and volume usage. diff --git a/pkg/scheduler/algorithm/priorities/balanced_resource_allocation_test.go b/pkg/scheduler/algorithm/priorities/balanced_resource_allocation_test.go index ccbfe45959b..07dcd733179 100644 --- a/pkg/scheduler/algorithm/priorities/balanced_resource_allocation_test.go +++ b/pkg/scheduler/algorithm/priorities/balanced_resource_allocation_test.go @@ -27,7 +27,7 @@ import ( utilfeaturetesting "k8s.io/apiserver/pkg/util/feature/testing" "k8s.io/kubernetes/pkg/features" schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" - schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" + schedulernodeinfo "k8s.io/kubernetes/pkg/scheduler/nodeinfo" ) // getExistingVolumeCountForNode gets the current number of volumes on node. @@ -401,7 +401,7 @@ func TestBalancedResourceAllocation(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { - nodeNameToInfo := schedulercache.CreateNodeNameToInfoMap(test.pods, test.nodes) + nodeNameToInfo := schedulernodeinfo.CreateNodeNameToInfoMap(test.pods, test.nodes) if len(test.pod.Spec.Volumes) > 0 { maxVolumes := 5 for _, info := range nodeNameToInfo { diff --git a/pkg/scheduler/algorithm/priorities/image_locality.go b/pkg/scheduler/algorithm/priorities/image_locality.go index 041e52d4fce..cc1db725ad9 100644 --- a/pkg/scheduler/algorithm/priorities/image_locality.go +++ b/pkg/scheduler/algorithm/priorities/image_locality.go @@ -22,7 +22,7 @@ import ( "k8s.io/api/core/v1" schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" - schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" + schedulernodeinfo "k8s.io/kubernetes/pkg/scheduler/nodeinfo" "k8s.io/kubernetes/pkg/util/parsers" ) @@ -39,7 +39,7 @@ const ( // based on the total size of those images. // - If none of the images are present, this node will be given the lowest priority. // - If some of the images are present on a node, the larger their sizes' sum, the higher the node's priority. -func ImageLocalityPriorityMap(pod *v1.Pod, meta interface{}, nodeInfo *schedulercache.NodeInfo) (schedulerapi.HostPriority, error) { +func ImageLocalityPriorityMap(pod *v1.Pod, meta interface{}, nodeInfo *schedulernodeinfo.NodeInfo) (schedulerapi.HostPriority, error) { node := nodeInfo.Node() if node == nil { return schedulerapi.HostPriority{}, fmt.Errorf("node not found") @@ -74,7 +74,7 @@ func calculatePriority(sumScores int64) int { // sumImageScores returns the sum of image scores of all the containers that are already on the node. // Each image receives a raw score of its size, scaled by scaledImageScore. The raw scores are later used to calculate // the final score. Note that the init containers are not considered for it's rare for users to deploy huge init containers. -func sumImageScores(nodeInfo *schedulercache.NodeInfo, containers []v1.Container, totalNumNodes int) int64 { +func sumImageScores(nodeInfo *schedulernodeinfo.NodeInfo, containers []v1.Container, totalNumNodes int) int64 { var sum int64 imageStates := nodeInfo.ImageStates() @@ -91,7 +91,7 @@ func sumImageScores(nodeInfo *schedulercache.NodeInfo, containers []v1.Container // The size of the image is used as the base score, scaled by a factor which considers how much nodes the image has "spread" to. // This heuristic aims to mitigate the undesirable "node heating problem", i.e., pods get assigned to the same or // a few nodes due to image locality. -func scaledImageScore(imageState *schedulercache.ImageStateSummary, totalNumNodes int) int64 { +func scaledImageScore(imageState *schedulernodeinfo.ImageStateSummary, totalNumNodes int) int64 { spread := float64(imageState.NumNodes) / float64(totalNumNodes) return int64(float64(imageState.Size) * spread) } diff --git a/pkg/scheduler/algorithm/priorities/image_locality_test.go b/pkg/scheduler/algorithm/priorities/image_locality_test.go index 58dc02a2335..55c0aa546a8 100644 --- a/pkg/scheduler/algorithm/priorities/image_locality_test.go +++ b/pkg/scheduler/algorithm/priorities/image_locality_test.go @@ -26,7 +26,7 @@ import ( "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" - schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" + schedulernodeinfo "k8s.io/kubernetes/pkg/scheduler/nodeinfo" "k8s.io/kubernetes/pkg/util/parsers" ) @@ -164,7 +164,7 @@ func TestImageLocalityPriority(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { - nodeNameToInfo := schedulercache.CreateNodeNameToInfoMap(test.pods, test.nodes) + nodeNameToInfo := schedulernodeinfo.CreateNodeNameToInfoMap(test.pods, test.nodes) list, err := priorityFunction(ImageLocalityPriorityMap, nil, &priorityMetadata{totalNumNodes: len(test.nodes)})(test.pod, nodeNameToInfo, test.nodes) if err != nil { t.Errorf("unexpected error: %v", err) diff --git a/pkg/scheduler/algorithm/priorities/interpod_affinity.go b/pkg/scheduler/algorithm/priorities/interpod_affinity.go index 32cf27c83bf..d18397446a5 100644 --- a/pkg/scheduler/algorithm/priorities/interpod_affinity.go +++ b/pkg/scheduler/algorithm/priorities/interpod_affinity.go @@ -28,7 +28,7 @@ import ( "k8s.io/kubernetes/pkg/scheduler/algorithm/predicates" priorityutil "k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/util" schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" - schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" + schedulernodeinfo "k8s.io/kubernetes/pkg/scheduler/nodeinfo" "k8s.io/klog" ) @@ -116,7 +116,7 @@ func (p *podAffinityPriorityMap) processTerms(terms []v1.WeightedPodAffinityTerm // that node; the node(s) with the highest sum are the most preferred. // Symmetry need to be considered for preferredDuringSchedulingIgnoredDuringExecution from podAffinity & podAntiAffinity, // symmetry need to be considered for hard requirements from podAffinity -func (ipa *InterPodAffinity) CalculateInterPodAffinityPriority(pod *v1.Pod, nodeNameToInfo map[string]*schedulercache.NodeInfo, nodes []*v1.Node) (schedulerapi.HostPriorityList, error) { +func (ipa *InterPodAffinity) CalculateInterPodAffinityPriority(pod *v1.Pod, nodeNameToInfo map[string]*schedulernodeinfo.NodeInfo, nodes []*v1.Node) (schedulerapi.HostPriorityList, error) { affinity := pod.Spec.Affinity hasAffinityConstraints := affinity != nil && affinity.PodAffinity != nil hasAntiAffinityConstraints := affinity != nil && affinity.PodAntiAffinity != nil diff --git a/pkg/scheduler/algorithm/priorities/interpod_affinity_test.go b/pkg/scheduler/algorithm/priorities/interpod_affinity_test.go index 7f86006d56a..582e73d9c24 100644 --- a/pkg/scheduler/algorithm/priorities/interpod_affinity_test.go +++ b/pkg/scheduler/algorithm/priorities/interpod_affinity_test.go @@ -24,7 +24,7 @@ import ( "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" - schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" + schedulernodeinfo "k8s.io/kubernetes/pkg/scheduler/nodeinfo" schedulertesting "k8s.io/kubernetes/pkg/scheduler/testing" ) @@ -510,7 +510,7 @@ func TestInterPodAffinityPriority(t *testing.T) { } for _, test := range tests { t.Run(test.name, func(t *testing.T) { - nodeNameToInfo := schedulercache.CreateNodeNameToInfoMap(test.pods, test.nodes) + nodeNameToInfo := schedulernodeinfo.CreateNodeNameToInfoMap(test.pods, test.nodes) interPodAffinity := InterPodAffinity{ info: FakeNodeListInfo(test.nodes), nodeLister: schedulertesting.FakeNodeLister(test.nodes), @@ -600,7 +600,7 @@ func TestHardPodAffinitySymmetricWeight(t *testing.T) { } for _, test := range tests { t.Run(test.name, func(t *testing.T) { - nodeNameToInfo := schedulercache.CreateNodeNameToInfoMap(test.pods, test.nodes) + nodeNameToInfo := schedulernodeinfo.CreateNodeNameToInfoMap(test.pods, test.nodes) ipa := InterPodAffinity{ info: FakeNodeListInfo(test.nodes), nodeLister: schedulertesting.FakeNodeLister(test.nodes), diff --git a/pkg/scheduler/algorithm/priorities/least_requested.go b/pkg/scheduler/algorithm/priorities/least_requested.go index d691810896d..e469ee50356 100644 --- a/pkg/scheduler/algorithm/priorities/least_requested.go +++ b/pkg/scheduler/algorithm/priorities/least_requested.go @@ -18,7 +18,7 @@ package priorities import ( schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" - schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" + schedulernodeinfo "k8s.io/kubernetes/pkg/scheduler/nodeinfo" ) var ( @@ -33,7 +33,7 @@ var ( LeastRequestedPriorityMap = leastResourcePriority.PriorityMap ) -func leastResourceScorer(requested, allocable *schedulercache.Resource, includeVolumes bool, requestedVolumes int, allocatableVolumes int) int64 { +func leastResourceScorer(requested, allocable *schedulernodeinfo.Resource, includeVolumes bool, requestedVolumes int, allocatableVolumes int) int64 { return (leastRequestedScore(requested.MilliCPU, allocable.MilliCPU) + leastRequestedScore(requested.Memory, allocable.Memory)) / 2 } diff --git a/pkg/scheduler/algorithm/priorities/least_requested_test.go b/pkg/scheduler/algorithm/priorities/least_requested_test.go index ca9d569bfc9..08a3e3be09e 100644 --- a/pkg/scheduler/algorithm/priorities/least_requested_test.go +++ b/pkg/scheduler/algorithm/priorities/least_requested_test.go @@ -24,7 +24,7 @@ import ( "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" - schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" + schedulernodeinfo "k8s.io/kubernetes/pkg/scheduler/nodeinfo" ) func TestLeastRequested(t *testing.T) { @@ -253,7 +253,7 @@ func TestLeastRequested(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { - nodeNameToInfo := schedulercache.CreateNodeNameToInfoMap(test.pods, test.nodes) + nodeNameToInfo := schedulernodeinfo.CreateNodeNameToInfoMap(test.pods, test.nodes) list, err := priorityFunction(LeastRequestedPriorityMap, nil, nil)(test.pod, nodeNameToInfo, test.nodes) if err != nil { t.Errorf("unexpected error: %v", err) diff --git a/pkg/scheduler/algorithm/priorities/metadata.go b/pkg/scheduler/algorithm/priorities/metadata.go index 0771cdca83d..b860c496959 100644 --- a/pkg/scheduler/algorithm/priorities/metadata.go +++ b/pkg/scheduler/algorithm/priorities/metadata.go @@ -21,7 +21,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" "k8s.io/kubernetes/pkg/scheduler/algorithm" - schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" + schedulernodeinfo "k8s.io/kubernetes/pkg/scheduler/nodeinfo" ) // PriorityMetadataFactory is a factory to produce PriorityMetadata. @@ -45,7 +45,7 @@ func NewPriorityMetadataFactory(serviceLister algorithm.ServiceLister, controlle // priorityMetadata is a type that is passed as metadata for priority functions type priorityMetadata struct { - nonZeroRequest *schedulercache.Resource + nonZeroRequest *schedulernodeinfo.Resource podTolerations []v1.Toleration affinity *v1.Affinity podSelectors []labels.Selector @@ -55,7 +55,7 @@ type priorityMetadata struct { } // PriorityMetadata is a PriorityMetadataProducer. Node info can be nil. -func (pmf *PriorityMetadataFactory) PriorityMetadata(pod *v1.Pod, nodeNameToInfo map[string]*schedulercache.NodeInfo) interface{} { +func (pmf *PriorityMetadataFactory) PriorityMetadata(pod *v1.Pod, nodeNameToInfo map[string]*schedulernodeinfo.NodeInfo) interface{} { // If we cannot compute metadata, just return nil if pod == nil { return nil diff --git a/pkg/scheduler/algorithm/priorities/metadata_test.go b/pkg/scheduler/algorithm/priorities/metadata_test.go index a778df6f649..9a992b5797f 100644 --- a/pkg/scheduler/algorithm/priorities/metadata_test.go +++ b/pkg/scheduler/algorithm/priorities/metadata_test.go @@ -25,16 +25,16 @@ import ( "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" priorityutil "k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/util" - schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" + schedulernodeinfo "k8s.io/kubernetes/pkg/scheduler/nodeinfo" schedulertesting "k8s.io/kubernetes/pkg/scheduler/testing" ) func TestPriorityMetadata(t *testing.T) { - nonZeroReqs := &schedulercache.Resource{} + nonZeroReqs := &schedulernodeinfo.Resource{} nonZeroReqs.MilliCPU = priorityutil.DefaultMilliCPURequest nonZeroReqs.Memory = priorityutil.DefaultMemoryRequest - specifiedReqs := &schedulercache.Resource{} + specifiedReqs := &schedulernodeinfo.Resource{} specifiedReqs.MilliCPU = 200 specifiedReqs.Memory = 2000 diff --git a/pkg/scheduler/algorithm/priorities/most_requested.go b/pkg/scheduler/algorithm/priorities/most_requested.go index f1cc7c6ad5c..ef9dd3a7283 100644 --- a/pkg/scheduler/algorithm/priorities/most_requested.go +++ b/pkg/scheduler/algorithm/priorities/most_requested.go @@ -18,7 +18,7 @@ package priorities import ( schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" - schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" + schedulernodeinfo "k8s.io/kubernetes/pkg/scheduler/nodeinfo" ) var ( @@ -31,7 +31,7 @@ var ( MostRequestedPriorityMap = mostResourcePriority.PriorityMap ) -func mostResourceScorer(requested, allocable *schedulercache.Resource, includeVolumes bool, requestedVolumes int, allocatableVolumes int) int64 { +func mostResourceScorer(requested, allocable *schedulernodeinfo.Resource, includeVolumes bool, requestedVolumes int, allocatableVolumes int) int64 { return (mostRequestedScore(requested.MilliCPU, allocable.MilliCPU) + mostRequestedScore(requested.Memory, allocable.Memory)) / 2 } diff --git a/pkg/scheduler/algorithm/priorities/most_requested_test.go b/pkg/scheduler/algorithm/priorities/most_requested_test.go index 94262d32cbc..af53ef47424 100644 --- a/pkg/scheduler/algorithm/priorities/most_requested_test.go +++ b/pkg/scheduler/algorithm/priorities/most_requested_test.go @@ -24,7 +24,7 @@ import ( "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" - schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" + schedulernodeinfo "k8s.io/kubernetes/pkg/scheduler/nodeinfo" ) func TestMostRequested(t *testing.T) { @@ -210,7 +210,7 @@ func TestMostRequested(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { - nodeNameToInfo := schedulercache.CreateNodeNameToInfoMap(test.pods, test.nodes) + nodeNameToInfo := schedulernodeinfo.CreateNodeNameToInfoMap(test.pods, test.nodes) list, err := priorityFunction(MostRequestedPriorityMap, nil, nil)(test.pod, nodeNameToInfo, test.nodes) if err != nil { t.Errorf("unexpected error: %v", err) diff --git a/pkg/scheduler/algorithm/priorities/node_affinity.go b/pkg/scheduler/algorithm/priorities/node_affinity.go index e274e170921..f9db3fec117 100644 --- a/pkg/scheduler/algorithm/priorities/node_affinity.go +++ b/pkg/scheduler/algorithm/priorities/node_affinity.go @@ -23,7 +23,7 @@ import ( "k8s.io/apimachinery/pkg/labels" v1helper "k8s.io/kubernetes/pkg/apis/core/v1/helper" schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" - schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" + schedulernodeinfo "k8s.io/kubernetes/pkg/scheduler/nodeinfo" ) // CalculateNodeAffinityPriorityMap prioritizes nodes according to node affinity scheduling preferences @@ -31,7 +31,7 @@ import ( // it will a get an add of preferredSchedulingTerm.Weight. Thus, the more preferredSchedulingTerms // the node satisfies and the more the preferredSchedulingTerm that is satisfied weights, the higher // score the node gets. -func CalculateNodeAffinityPriorityMap(pod *v1.Pod, meta interface{}, nodeInfo *schedulercache.NodeInfo) (schedulerapi.HostPriority, error) { +func CalculateNodeAffinityPriorityMap(pod *v1.Pod, meta interface{}, nodeInfo *schedulernodeinfo.NodeInfo) (schedulerapi.HostPriority, error) { node := nodeInfo.Node() if node == nil { return schedulerapi.HostPriority{}, fmt.Errorf("node not found") diff --git a/pkg/scheduler/algorithm/priorities/node_affinity_test.go b/pkg/scheduler/algorithm/priorities/node_affinity_test.go index 8ba1cb1e8c0..6425047df46 100644 --- a/pkg/scheduler/algorithm/priorities/node_affinity_test.go +++ b/pkg/scheduler/algorithm/priorities/node_affinity_test.go @@ -23,7 +23,7 @@ import ( "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" - schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" + schedulernodeinfo "k8s.io/kubernetes/pkg/scheduler/nodeinfo" ) func TestNodeAffinityPriority(t *testing.T) { @@ -167,7 +167,7 @@ func TestNodeAffinityPriority(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { - nodeNameToInfo := schedulercache.CreateNodeNameToInfoMap(nil, test.nodes) + nodeNameToInfo := schedulernodeinfo.CreateNodeNameToInfoMap(nil, test.nodes) nap := priorityFunction(CalculateNodeAffinityPriorityMap, CalculateNodeAffinityPriorityReduce, nil) list, err := nap(test.pod, nodeNameToInfo, test.nodes) if err != nil { diff --git a/pkg/scheduler/algorithm/priorities/node_label.go b/pkg/scheduler/algorithm/priorities/node_label.go index 82505f788ac..c3ddb1af51a 100644 --- a/pkg/scheduler/algorithm/priorities/node_label.go +++ b/pkg/scheduler/algorithm/priorities/node_label.go @@ -23,7 +23,7 @@ import ( "k8s.io/apimachinery/pkg/labels" "k8s.io/kubernetes/pkg/scheduler/algorithm" schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" - schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" + schedulernodeinfo "k8s.io/kubernetes/pkg/scheduler/nodeinfo" ) // NodeLabelPrioritizer contains information to calculate node label priority. @@ -44,7 +44,7 @@ func NewNodeLabelPriority(label string, presence bool) (algorithm.PriorityMapFun // CalculateNodeLabelPriorityMap checks whether a particular label exists on a node or not, regardless of its value. // If presence is true, prioritizes nodes that have the specified label, regardless of value. // If presence is false, prioritizes nodes that do not have the specified label. -func (n *NodeLabelPrioritizer) CalculateNodeLabelPriorityMap(pod *v1.Pod, meta interface{}, nodeInfo *schedulercache.NodeInfo) (schedulerapi.HostPriority, error) { +func (n *NodeLabelPrioritizer) CalculateNodeLabelPriorityMap(pod *v1.Pod, meta interface{}, nodeInfo *schedulernodeinfo.NodeInfo) (schedulerapi.HostPriority, error) { node := nodeInfo.Node() if node == nil { return schedulerapi.HostPriority{}, fmt.Errorf("node not found") diff --git a/pkg/scheduler/algorithm/priorities/node_label_test.go b/pkg/scheduler/algorithm/priorities/node_label_test.go index f713d02f34a..0bde8e100a9 100644 --- a/pkg/scheduler/algorithm/priorities/node_label_test.go +++ b/pkg/scheduler/algorithm/priorities/node_label_test.go @@ -24,7 +24,7 @@ import ( "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" - schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" + schedulernodeinfo "k8s.io/kubernetes/pkg/scheduler/nodeinfo" ) func TestNewNodeLabelPriority(t *testing.T) { @@ -108,7 +108,7 @@ func TestNewNodeLabelPriority(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { - nodeNameToInfo := schedulercache.CreateNodeNameToInfoMap(nil, test.nodes) + nodeNameToInfo := schedulernodeinfo.CreateNodeNameToInfoMap(nil, test.nodes) labelPrioritizer := &NodeLabelPrioritizer{ label: test.label, presence: test.presence, diff --git a/pkg/scheduler/algorithm/priorities/node_prefer_avoid_pods.go b/pkg/scheduler/algorithm/priorities/node_prefer_avoid_pods.go index 810face510b..8af4ce15c04 100644 --- a/pkg/scheduler/algorithm/priorities/node_prefer_avoid_pods.go +++ b/pkg/scheduler/algorithm/priorities/node_prefer_avoid_pods.go @@ -23,12 +23,12 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" v1helper "k8s.io/kubernetes/pkg/apis/core/v1/helper" schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" - schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" + schedulernodeinfo "k8s.io/kubernetes/pkg/scheduler/nodeinfo" ) // CalculateNodePreferAvoidPodsPriorityMap priorities nodes according to the node annotation // "scheduler.alpha.kubernetes.io/preferAvoidPods". -func CalculateNodePreferAvoidPodsPriorityMap(pod *v1.Pod, meta interface{}, nodeInfo *schedulercache.NodeInfo) (schedulerapi.HostPriority, error) { +func CalculateNodePreferAvoidPodsPriorityMap(pod *v1.Pod, meta interface{}, nodeInfo *schedulernodeinfo.NodeInfo) (schedulerapi.HostPriority, error) { node := nodeInfo.Node() if node == nil { return schedulerapi.HostPriority{}, fmt.Errorf("node not found") diff --git a/pkg/scheduler/algorithm/priorities/node_prefer_avoid_pods_test.go b/pkg/scheduler/algorithm/priorities/node_prefer_avoid_pods_test.go index c9b8c9365e6..b7a2059309e 100644 --- a/pkg/scheduler/algorithm/priorities/node_prefer_avoid_pods_test.go +++ b/pkg/scheduler/algorithm/priorities/node_prefer_avoid_pods_test.go @@ -24,7 +24,7 @@ import ( "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" - schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" + schedulernodeinfo "k8s.io/kubernetes/pkg/scheduler/nodeinfo" ) func TestNodePreferAvoidPriority(t *testing.T) { @@ -142,7 +142,7 @@ func TestNodePreferAvoidPriority(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { - nodeNameToInfo := schedulercache.CreateNodeNameToInfoMap(nil, test.nodes) + nodeNameToInfo := schedulernodeinfo.CreateNodeNameToInfoMap(nil, test.nodes) list, err := priorityFunction(CalculateNodePreferAvoidPodsPriorityMap, nil, nil)(test.pod, nodeNameToInfo, test.nodes) if err != nil { t.Errorf("unexpected error: %v", err) diff --git a/pkg/scheduler/algorithm/priorities/priorities.go b/pkg/scheduler/algorithm/priorities/priorities.go new file mode 100644 index 00000000000..605fdd143e3 --- /dev/null +++ b/pkg/scheduler/algorithm/priorities/priorities.go @@ -0,0 +1,54 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package priorities + +const ( + // EqualPriority defines the name of prioritizer function that gives an equal weight of one to all nodes. + EqualPriority = "EqualPriority" + // MostRequestedPriority defines the name of prioritizer function that gives used nodes higher priority. + MostRequestedPriority = "MostRequestedPriority" + // RequestedToCapacityRatioPriority defines the name of RequestedToCapacityRatioPriority. + RequestedToCapacityRatioPriority = "RequestedToCapacityRatioPriority" + // SelectorSpreadPriority defines the name of prioritizer function that spreads pods by minimizing + // the number of pods (belonging to the same service or replication controller) on the same node. + SelectorSpreadPriority = "SelectorSpreadPriority" + // ServiceSpreadingPriority is largely replaced by "SelectorSpreadPriority". + ServiceSpreadingPriority = "ServiceSpreadingPriority" + // InterPodAffinityPriority defines the name of prioritizer function that decides which pods should or + // should not be placed in the same topological domain as some other pods. + InterPodAffinityPriority = "InterPodAffinityPriority" + // LeastRequestedPriority defines the name of prioritizer function that prioritize nodes by least + // requested utilization. + LeastRequestedPriority = "LeastRequestedPriority" + // BalancedResourceAllocation defines the name of prioritizer function that prioritizes nodes + // to help achieve balanced resource usage. + BalancedResourceAllocation = "BalancedResourceAllocation" + // NodePreferAvoidPodsPriority defines the name of prioritizer function that priorities nodes according to + // the node annotation "scheduler.alpha.kubernetes.io/preferAvoidPods". + NodePreferAvoidPodsPriority = "NodePreferAvoidPodsPriority" + // NodeAffinityPriority defines the name of prioritizer function that prioritizes nodes which have labels + // matching NodeAffinity. + NodeAffinityPriority = "NodeAffinityPriority" + // TaintTolerationPriority defines the name of prioritizer function that prioritizes nodes that marked + // with taint which pod can tolerate. + TaintTolerationPriority = "TaintTolerationPriority" + // ImageLocalityPriority defines the name of prioritizer function that prioritizes nodes that have images + // requested by the pod present. + ImageLocalityPriority = "ImageLocalityPriority" + // ResourceLimitsPriority defines the nodes of prioritizer function ResourceLimitsPriority. + ResourceLimitsPriority = "ResourceLimitsPriority" +) diff --git a/pkg/scheduler/algorithm/priorities/reduce.go b/pkg/scheduler/algorithm/priorities/reduce.go index 6a6a7427f1d..aaeb9add87b 100644 --- a/pkg/scheduler/algorithm/priorities/reduce.go +++ b/pkg/scheduler/algorithm/priorities/reduce.go @@ -20,7 +20,7 @@ import ( "k8s.io/api/core/v1" "k8s.io/kubernetes/pkg/scheduler/algorithm" schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" - schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" + schedulernodeinfo "k8s.io/kubernetes/pkg/scheduler/nodeinfo" ) // NormalizeReduce generates a PriorityReduceFunction that can normalize the result @@ -30,7 +30,7 @@ func NormalizeReduce(maxPriority int, reverse bool) algorithm.PriorityReduceFunc return func( _ *v1.Pod, _ interface{}, - _ map[string]*schedulercache.NodeInfo, + _ map[string]*schedulernodeinfo.NodeInfo, result schedulerapi.HostPriorityList) error { var maxCount int diff --git a/pkg/scheduler/algorithm/priorities/requested_to_capacity_ratio.go b/pkg/scheduler/algorithm/priorities/requested_to_capacity_ratio.go index a6ac7a837e8..9337404dd75 100644 --- a/pkg/scheduler/algorithm/priorities/requested_to_capacity_ratio.go +++ b/pkg/scheduler/algorithm/priorities/requested_to_capacity_ratio.go @@ -20,7 +20,7 @@ import ( "fmt" schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" - schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" + schedulernodeinfo "k8s.io/kubernetes/pkg/scheduler/nodeinfo" ) // FunctionShape represents shape of scoring function. @@ -98,7 +98,7 @@ func RequestedToCapacityRatioResourceAllocationPriority(scoringFunctionShape Fun return &ResourceAllocationPriority{"RequestedToCapacityRatioResourceAllocationPriority", buildRequestedToCapacityRatioScorerFunction(scoringFunctionShape)} } -func buildRequestedToCapacityRatioScorerFunction(scoringFunctionShape FunctionShape) func(*schedulercache.Resource, *schedulercache.Resource, bool, int, int) int64 { +func buildRequestedToCapacityRatioScorerFunction(scoringFunctionShape FunctionShape) func(*schedulernodeinfo.Resource, *schedulernodeinfo.Resource, bool, int, int) int64 { rawScoringFunction := buildBrokenLinearFunction(scoringFunctionShape) resourceScoringFunction := func(requested, capacity int64) int64 { @@ -109,7 +109,7 @@ func buildRequestedToCapacityRatioScorerFunction(scoringFunctionShape FunctionSh return rawScoringFunction(maxUtilization - (capacity-requested)*maxUtilization/capacity) } - return func(requested, allocable *schedulercache.Resource, includeVolumes bool, requestedVolumes int, allocatableVolumes int) int64 { + return func(requested, allocable *schedulernodeinfo.Resource, includeVolumes bool, requestedVolumes int, allocatableVolumes int) int64 { cpuScore := resourceScoringFunction(requested.MilliCPU, allocable.MilliCPU) memoryScore := resourceScoringFunction(requested.Memory, allocable.Memory) return (cpuScore + memoryScore) / 2 diff --git a/pkg/scheduler/algorithm/priorities/requested_to_capacity_ratio_test.go b/pkg/scheduler/algorithm/priorities/requested_to_capacity_ratio_test.go index 0d360c8d444..9e520d61e5f 100644 --- a/pkg/scheduler/algorithm/priorities/requested_to_capacity_ratio_test.go +++ b/pkg/scheduler/algorithm/priorities/requested_to_capacity_ratio_test.go @@ -25,7 +25,7 @@ import ( "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" - schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" + schedulernodeinfo "k8s.io/kubernetes/pkg/scheduler/nodeinfo" ) func TestCreatingFunctionShapeErrorsIfEmptyPoints(t *testing.T) { @@ -229,7 +229,7 @@ func TestRequestedToCapacityRatio(t *testing.T) { newPod := buildResourcesPod("", test.requested) - nodeNameToInfo := schedulercache.CreateNodeNameToInfoMap(scheduledPods, nodes) + nodeNameToInfo := schedulernodeinfo.CreateNodeNameToInfoMap(scheduledPods, nodes) list, err := priorityFunction(RequestedToCapacityRatioResourceAllocationPriorityDefault().PriorityMap, nil, nil)(newPod, nodeNameToInfo, nodes) if err != nil { t.Errorf("unexpected error: %v", err) diff --git a/pkg/scheduler/algorithm/priorities/resource_allocation.go b/pkg/scheduler/algorithm/priorities/resource_allocation.go index 027eabae5ff..fea2e680697 100644 --- a/pkg/scheduler/algorithm/priorities/resource_allocation.go +++ b/pkg/scheduler/algorithm/priorities/resource_allocation.go @@ -25,13 +25,13 @@ import ( "k8s.io/kubernetes/pkg/features" priorityutil "k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/util" schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" - schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" + schedulernodeinfo "k8s.io/kubernetes/pkg/scheduler/nodeinfo" ) // ResourceAllocationPriority contains information to calculate resource allocation priority. type ResourceAllocationPriority struct { Name string - scorer func(requested, allocable *schedulercache.Resource, includeVolumes bool, requestedVolumes int, allocatableVolumes int) int64 + scorer func(requested, allocable *schedulernodeinfo.Resource, includeVolumes bool, requestedVolumes int, allocatableVolumes int) int64 } // PriorityMap priorities nodes according to the resource allocations on the node. @@ -39,14 +39,14 @@ type ResourceAllocationPriority struct { func (r *ResourceAllocationPriority) PriorityMap( pod *v1.Pod, meta interface{}, - nodeInfo *schedulercache.NodeInfo) (schedulerapi.HostPriority, error) { + nodeInfo *schedulernodeinfo.NodeInfo) (schedulerapi.HostPriority, error) { node := nodeInfo.Node() if node == nil { return schedulerapi.HostPriority{}, fmt.Errorf("node not found") } allocatable := nodeInfo.AllocatableResource() - var requested schedulercache.Resource + var requested schedulernodeinfo.Resource if priorityMeta, ok := meta.(*priorityMetadata); ok { requested = *priorityMeta.nonZeroRequest } else { @@ -91,8 +91,8 @@ func (r *ResourceAllocationPriority) PriorityMap( }, nil } -func getNonZeroRequests(pod *v1.Pod) *schedulercache.Resource { - result := &schedulercache.Resource{} +func getNonZeroRequests(pod *v1.Pod) *schedulernodeinfo.Resource { + result := &schedulernodeinfo.Resource{} for i := range pod.Spec.Containers { container := &pod.Spec.Containers[i] cpu, memory := priorityutil.GetNonzeroRequests(&container.Resources.Requests) diff --git a/pkg/scheduler/algorithm/priorities/resource_limits.go b/pkg/scheduler/algorithm/priorities/resource_limits.go index 82b803cbf72..1344dc1eec4 100644 --- a/pkg/scheduler/algorithm/priorities/resource_limits.go +++ b/pkg/scheduler/algorithm/priorities/resource_limits.go @@ -21,7 +21,7 @@ import ( "k8s.io/api/core/v1" schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" - schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" + schedulernodeinfo "k8s.io/kubernetes/pkg/scheduler/nodeinfo" "k8s.io/klog" ) @@ -33,7 +33,7 @@ import ( // of the pod are satisfied, the node is assigned a score of 1. // Rationale of choosing the lowest score of 1 is that this is mainly selected to break ties between nodes that have // same scores assigned by one of least and most requested priority functions. -func ResourceLimitsPriorityMap(pod *v1.Pod, meta interface{}, nodeInfo *schedulercache.NodeInfo) (schedulerapi.HostPriority, error) { +func ResourceLimitsPriorityMap(pod *v1.Pod, meta interface{}, nodeInfo *schedulernodeinfo.NodeInfo) (schedulerapi.HostPriority, error) { node := nodeInfo.Node() if node == nil { return schedulerapi.HostPriority{}, fmt.Errorf("node not found") @@ -82,10 +82,10 @@ func computeScore(limit, allocatable int64) int64 { // getResourceLimits computes resource limits for input pod. // The reason to create this new function is to be consistent with other // priority functions because most or perhaps all priority functions work -// with schedulercache.Resource. +// with schedulernodeinfo.Resource. // TODO: cache it as part of metadata passed to priority functions. -func getResourceLimits(pod *v1.Pod) *schedulercache.Resource { - result := &schedulercache.Resource{} +func getResourceLimits(pod *v1.Pod) *schedulernodeinfo.Resource { + result := &schedulernodeinfo.Resource{} for _, container := range pod.Spec.Containers { result.Add(container.Resources.Limits) } diff --git a/pkg/scheduler/algorithm/priorities/resource_limits_test.go b/pkg/scheduler/algorithm/priorities/resource_limits_test.go index 86ecd8cca95..1e3782b014c 100644 --- a/pkg/scheduler/algorithm/priorities/resource_limits_test.go +++ b/pkg/scheduler/algorithm/priorities/resource_limits_test.go @@ -24,7 +24,7 @@ import ( "k8s.io/apimachinery/pkg/api/resource" //metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" - schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" + schedulernodeinfo "k8s.io/kubernetes/pkg/scheduler/nodeinfo" ) func TestResourceLimistPriority(t *testing.T) { @@ -139,7 +139,7 @@ func TestResourceLimistPriority(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { - nodeNameToInfo := schedulercache.CreateNodeNameToInfoMap(nil, test.nodes) + nodeNameToInfo := schedulernodeinfo.CreateNodeNameToInfoMap(nil, test.nodes) list, err := priorityFunction(ResourceLimitsPriorityMap, nil, nil)(test.pod, nodeNameToInfo, test.nodes) if err != nil { t.Errorf("unexpected error: %v", err) diff --git a/pkg/scheduler/algorithm/priorities/selector_spreading.go b/pkg/scheduler/algorithm/priorities/selector_spreading.go index 1371d765a53..06cdc6edbbf 100644 --- a/pkg/scheduler/algorithm/priorities/selector_spreading.go +++ b/pkg/scheduler/algorithm/priorities/selector_spreading.go @@ -23,7 +23,7 @@ import ( "k8s.io/apimachinery/pkg/labels" "k8s.io/kubernetes/pkg/scheduler/algorithm" schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" - schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" + schedulernodeinfo "k8s.io/kubernetes/pkg/scheduler/nodeinfo" utilnode "k8s.io/kubernetes/pkg/util/node" "k8s.io/klog" @@ -63,7 +63,7 @@ func NewSelectorSpreadPriority( // It favors nodes that have fewer existing matching pods. // i.e. it pushes the scheduler towards a node where there's the smallest number of // pods which match the same service, RC,RSs or StatefulSets selectors as the pod being scheduled. -func (s *SelectorSpread) CalculateSpreadPriorityMap(pod *v1.Pod, meta interface{}, nodeInfo *schedulercache.NodeInfo) (schedulerapi.HostPriority, error) { +func (s *SelectorSpread) CalculateSpreadPriorityMap(pod *v1.Pod, meta interface{}, nodeInfo *schedulernodeinfo.NodeInfo) (schedulerapi.HostPriority, error) { var selectors []labels.Selector node := nodeInfo.Node() if node == nil { @@ -114,7 +114,7 @@ func (s *SelectorSpread) CalculateSpreadPriorityMap(pod *v1.Pod, meta interface{ // based on the number of existing matching pods on the node // where zone information is included on the nodes, it favors nodes // in zones with fewer existing matching pods. -func (s *SelectorSpread) CalculateSpreadPriorityReduce(pod *v1.Pod, meta interface{}, nodeNameToInfo map[string]*schedulercache.NodeInfo, result schedulerapi.HostPriorityList) error { +func (s *SelectorSpread) CalculateSpreadPriorityReduce(pod *v1.Pod, meta interface{}, nodeNameToInfo map[string]*schedulernodeinfo.NodeInfo, result schedulerapi.HostPriorityList) error { countsByZone := make(map[string]int, 10) maxCountByZone := int(0) maxCountByNodeName := int(0) @@ -202,7 +202,7 @@ func (s *ServiceAntiAffinity) getNodeClassificationByLabels(nodes []*v1.Node) (m } // filteredPod get pods based on namespace and selector -func filteredPod(namespace string, selector labels.Selector, nodeInfo *schedulercache.NodeInfo) (pods []*v1.Pod) { +func filteredPod(namespace string, selector labels.Selector, nodeInfo *schedulernodeinfo.NodeInfo) (pods []*v1.Pod) { if nodeInfo.Pods() == nil || len(nodeInfo.Pods()) == 0 || selector == nil { return []*v1.Pod{} } @@ -218,7 +218,7 @@ func filteredPod(namespace string, selector labels.Selector, nodeInfo *scheduler // CalculateAntiAffinityPriorityMap spreads pods by minimizing the number of pods belonging to the same service // on given machine -func (s *ServiceAntiAffinity) CalculateAntiAffinityPriorityMap(pod *v1.Pod, meta interface{}, nodeInfo *schedulercache.NodeInfo) (schedulerapi.HostPriority, error) { +func (s *ServiceAntiAffinity) CalculateAntiAffinityPriorityMap(pod *v1.Pod, meta interface{}, nodeInfo *schedulernodeinfo.NodeInfo) (schedulerapi.HostPriority, error) { var firstServiceSelector labels.Selector node := nodeInfo.Node() @@ -242,7 +242,7 @@ func (s *ServiceAntiAffinity) CalculateAntiAffinityPriorityMap(pod *v1.Pod, meta // CalculateAntiAffinityPriorityReduce computes each node score with the same value for a particular label. // The label to be considered is provided to the struct (ServiceAntiAffinity). -func (s *ServiceAntiAffinity) CalculateAntiAffinityPriorityReduce(pod *v1.Pod, meta interface{}, nodeNameToInfo map[string]*schedulercache.NodeInfo, result schedulerapi.HostPriorityList) error { +func (s *ServiceAntiAffinity) CalculateAntiAffinityPriorityReduce(pod *v1.Pod, meta interface{}, nodeNameToInfo map[string]*schedulernodeinfo.NodeInfo, result schedulerapi.HostPriorityList) error { var numServicePods int var label string podCounts := map[string]int{} diff --git a/pkg/scheduler/algorithm/priorities/selector_spreading_test.go b/pkg/scheduler/algorithm/priorities/selector_spreading_test.go index 954f7900683..e76d879aef9 100644 --- a/pkg/scheduler/algorithm/priorities/selector_spreading_test.go +++ b/pkg/scheduler/algorithm/priorities/selector_spreading_test.go @@ -26,7 +26,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" kubeletapis "k8s.io/kubernetes/pkg/kubelet/apis" schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" - schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" + schedulernodeinfo "k8s.io/kubernetes/pkg/scheduler/nodeinfo" schedulertesting "k8s.io/kubernetes/pkg/scheduler/testing" ) @@ -339,7 +339,7 @@ func TestSelectorSpreadPriority(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { - nodeNameToInfo := schedulercache.CreateNodeNameToInfoMap(test.pods, makeNodeList(test.nodes)) + nodeNameToInfo := schedulernodeinfo.CreateNodeNameToInfoMap(test.pods, makeNodeList(test.nodes)) selectorSpread := SelectorSpread{ serviceLister: schedulertesting.FakeServiceLister(test.services), controllerLister: schedulertesting.FakeControllerLister(test.rcs), @@ -575,7 +575,7 @@ func TestZoneSelectorSpreadPriority(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { - nodeNameToInfo := schedulercache.CreateNodeNameToInfoMap(test.pods, makeLabeledNodeList(labeledNodes)) + nodeNameToInfo := schedulernodeinfo.CreateNodeNameToInfoMap(test.pods, makeLabeledNodeList(labeledNodes)) selectorSpread := SelectorSpread{ serviceLister: schedulertesting.FakeServiceLister(test.services), controllerLister: schedulertesting.FakeControllerLister(test.rcs), @@ -767,7 +767,7 @@ func TestZoneSpreadPriority(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { - nodeNameToInfo := schedulercache.CreateNodeNameToInfoMap(test.pods, makeLabeledNodeList(test.nodes)) + nodeNameToInfo := schedulernodeinfo.CreateNodeNameToInfoMap(test.pods, makeLabeledNodeList(test.nodes)) zoneSpread := ServiceAntiAffinity{podLister: schedulertesting.FakePodLister(test.pods), serviceLister: schedulertesting.FakeServiceLister(test.services), label: "zone"} metaDataProducer := NewPriorityMetadataFactory( diff --git a/pkg/scheduler/algorithm/priorities/taint_toleration.go b/pkg/scheduler/algorithm/priorities/taint_toleration.go index 5790a4b091a..85be011cabe 100644 --- a/pkg/scheduler/algorithm/priorities/taint_toleration.go +++ b/pkg/scheduler/algorithm/priorities/taint_toleration.go @@ -22,7 +22,7 @@ import ( "k8s.io/api/core/v1" v1helper "k8s.io/kubernetes/pkg/apis/core/v1/helper" schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" - schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" + schedulernodeinfo "k8s.io/kubernetes/pkg/scheduler/nodeinfo" ) // CountIntolerableTaintsPreferNoSchedule gives the count of intolerable taints of a pod with effect PreferNoSchedule @@ -52,7 +52,7 @@ func getAllTolerationPreferNoSchedule(tolerations []v1.Toleration) (tolerationLi } // ComputeTaintTolerationPriorityMap prepares the priority list for all the nodes based on the number of intolerable taints on the node -func ComputeTaintTolerationPriorityMap(pod *v1.Pod, meta interface{}, nodeInfo *schedulercache.NodeInfo) (schedulerapi.HostPriority, error) { +func ComputeTaintTolerationPriorityMap(pod *v1.Pod, meta interface{}, nodeInfo *schedulernodeinfo.NodeInfo) (schedulerapi.HostPriority, error) { node := nodeInfo.Node() if node == nil { return schedulerapi.HostPriority{}, fmt.Errorf("node not found") diff --git a/pkg/scheduler/algorithm/priorities/taint_toleration_test.go b/pkg/scheduler/algorithm/priorities/taint_toleration_test.go index 70b69aed6de..e093692eb0b 100644 --- a/pkg/scheduler/algorithm/priorities/taint_toleration_test.go +++ b/pkg/scheduler/algorithm/priorities/taint_toleration_test.go @@ -23,7 +23,7 @@ import ( "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" - schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" + schedulernodeinfo "k8s.io/kubernetes/pkg/scheduler/nodeinfo" ) func nodeWithTaints(nodeName string, taints []v1.Taint) *v1.Node { @@ -227,7 +227,7 @@ func TestTaintAndToleration(t *testing.T) { } for _, test := range tests { t.Run(test.name, func(t *testing.T) { - nodeNameToInfo := schedulercache.CreateNodeNameToInfoMap(nil, test.nodes) + nodeNameToInfo := schedulernodeinfo.CreateNodeNameToInfoMap(nil, test.nodes) ttp := priorityFunction(ComputeTaintTolerationPriorityMap, ComputeTaintTolerationPriorityReduce, nil) list, err := ttp(test.pod, nodeNameToInfo, test.nodes) if err != nil { diff --git a/pkg/scheduler/algorithm/priorities/test_util.go b/pkg/scheduler/algorithm/priorities/test_util.go index da85c6b391b..d154fca7526 100644 --- a/pkg/scheduler/algorithm/priorities/test_util.go +++ b/pkg/scheduler/algorithm/priorities/test_util.go @@ -22,7 +22,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/kubernetes/pkg/scheduler/algorithm" schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" - schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" + schedulernodeinfo "k8s.io/kubernetes/pkg/scheduler/nodeinfo" ) func makeNode(node string, milliCPU, memory int64) *v1.Node { @@ -42,7 +42,7 @@ func makeNode(node string, milliCPU, memory int64) *v1.Node { } func priorityFunction(mapFn algorithm.PriorityMapFunction, reduceFn algorithm.PriorityReduceFunction, metaData interface{}) algorithm.PriorityFunction { - return func(pod *v1.Pod, nodeNameToInfo map[string]*schedulercache.NodeInfo, nodes []*v1.Node) (schedulerapi.HostPriorityList, error) { + return func(pod *v1.Pod, nodeNameToInfo map[string]*schedulernodeinfo.NodeInfo, nodes []*v1.Node) (schedulerapi.HostPriorityList, error) { result := make(schedulerapi.HostPriorityList, 0, len(nodes)) for i := range nodes { hostResult, err := mapFn(pod, metaData, nodeNameToInfo[nodes[i].Name]) diff --git a/pkg/scheduler/algorithm/scheduler_interface.go b/pkg/scheduler/algorithm/scheduler_interface.go index d74af089d35..81dedd42928 100644 --- a/pkg/scheduler/algorithm/scheduler_interface.go +++ b/pkg/scheduler/algorithm/scheduler_interface.go @@ -19,7 +19,7 @@ package algorithm import ( "k8s.io/api/core/v1" schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" - schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" + schedulernodeinfo "k8s.io/kubernetes/pkg/scheduler/nodeinfo" ) // SchedulerExtender is an interface for external processes to influence scheduling @@ -33,7 +33,7 @@ type SchedulerExtender interface { // expected to be a subset of the supplied list. failedNodesMap optionally contains // the list of failed nodes and failure reasons. Filter(pod *v1.Pod, - nodes []*v1.Node, nodeNameToInfo map[string]*schedulercache.NodeInfo, + nodes []*v1.Node, nodeNameToInfo map[string]*schedulernodeinfo.NodeInfo, ) (filteredNodes []*v1.Node, failedNodesMap schedulerapi.FailedNodesMap, err error) // Prioritize based on extender-implemented priority functions. The returned scores & weight @@ -62,7 +62,7 @@ type SchedulerExtender interface { ProcessPreemption( pod *v1.Pod, nodeToVictims map[*v1.Node]*schedulerapi.Victims, - nodeNameToInfo map[string]*schedulercache.NodeInfo, + nodeNameToInfo map[string]*schedulernodeinfo.NodeInfo, ) (map[*v1.Node]*schedulerapi.Victims, error) // SupportsPreemption returns if the scheduler extender support preemption or not. @@ -72,20 +72,3 @@ type SchedulerExtender interface { // is unavailable. This gives scheduler ability to fail fast and tolerate non-critical extenders as well. IsIgnorable() bool } - -// ScheduleAlgorithm is an interface implemented by things that know how to schedule pods -// onto machines. -type ScheduleAlgorithm interface { - Schedule(*v1.Pod, NodeLister) (selectedMachine string, err error) - // Preempt receives scheduling errors for a pod and tries to create room for - // the pod by preempting lower priority pods if possible. - // It returns the node where preemption happened, a list of preempted pods, a - // list of pods whose nominated node name should be removed, and error if any. - Preempt(*v1.Pod, NodeLister, error) (selectedNode *v1.Node, preemptedPods []*v1.Pod, cleanupNominatedPods []*v1.Pod, err error) - // Predicates() returns a pointer to a map of predicate functions. This is - // exposed for testing. - Predicates() map[string]FitPredicate - // Prioritizers returns a slice of priority config. This is exposed for - // testing. - Prioritizers() []PriorityConfig -} diff --git a/pkg/scheduler/algorithm/types.go b/pkg/scheduler/algorithm/types.go index 835a5a0bfb8..d00951f500e 100644 --- a/pkg/scheduler/algorithm/types.go +++ b/pkg/scheduler/algorithm/types.go @@ -22,8 +22,7 @@ import ( policyv1beta1 "k8s.io/api/policy/v1beta1" "k8s.io/apimachinery/pkg/labels" schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" - schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" - schedulerinternalcache "k8s.io/kubernetes/pkg/scheduler/internal/cache" + schedulernodeinfo "k8s.io/kubernetes/pkg/scheduler/nodeinfo" ) // NodeFieldSelectorKeys is a map that: the key are node field selector keys; the values are @@ -32,32 +31,25 @@ var NodeFieldSelectorKeys = map[string]func(*v1.Node) string{ schedulerapi.NodeFieldSelectorKeyNodeName: func(n *v1.Node) string { return n.Name }, } -// FitPredicate is a function that indicates if a pod fits into an existing node. -// The failure information is given by the error. -type FitPredicate func(pod *v1.Pod, meta PredicateMetadata, nodeInfo *schedulercache.NodeInfo) (bool, []PredicateFailureReason, error) - // PriorityMapFunction is a function that computes per-node results for a given node. // TODO: Figure out the exact API of this method. // TODO: Change interface{} to a specific type. -type PriorityMapFunction func(pod *v1.Pod, meta interface{}, nodeInfo *schedulercache.NodeInfo) (schedulerapi.HostPriority, error) +type PriorityMapFunction func(pod *v1.Pod, meta interface{}, nodeInfo *schedulernodeinfo.NodeInfo) (schedulerapi.HostPriority, error) // PriorityReduceFunction is a function that aggregated per-node results and computes // final scores for all nodes. // TODO: Figure out the exact API of this method. // TODO: Change interface{} to a specific type. -type PriorityReduceFunction func(pod *v1.Pod, meta interface{}, nodeNameToInfo map[string]*schedulercache.NodeInfo, result schedulerapi.HostPriorityList) error - -// PredicateMetadataProducer is a function that computes predicate metadata for a given pod. -type PredicateMetadataProducer func(pod *v1.Pod, nodeNameToInfo map[string]*schedulercache.NodeInfo) PredicateMetadata +type PriorityReduceFunction func(pod *v1.Pod, meta interface{}, nodeNameToInfo map[string]*schedulernodeinfo.NodeInfo, result schedulerapi.HostPriorityList) error // PriorityMetadataProducer is a function that computes metadata for a given pod. This // is now used for only for priority functions. For predicates please use PredicateMetadataProducer. -type PriorityMetadataProducer func(pod *v1.Pod, nodeNameToInfo map[string]*schedulercache.NodeInfo) interface{} +type PriorityMetadataProducer func(pod *v1.Pod, nodeNameToInfo map[string]*schedulernodeinfo.NodeInfo) interface{} // PriorityFunction is a function that computes scores for all nodes. // DEPRECATED // Use Map-Reduce pattern for priority functions. -type PriorityFunction func(pod *v1.Pod, nodeNameToInfo map[string]*schedulercache.NodeInfo, nodes []*v1.Node) (schedulerapi.HostPriorityList, error) +type PriorityFunction func(pod *v1.Pod, nodeNameToInfo map[string]*schedulernodeinfo.NodeInfo, nodes []*v1.Node) (schedulerapi.HostPriorityList, error) // PriorityConfig is a config used for a priority function. type PriorityConfig struct { @@ -70,21 +62,11 @@ type PriorityConfig struct { Weight int } -// EmptyPredicateMetadataProducer returns a no-op MetadataProducer type. -func EmptyPredicateMetadataProducer(pod *v1.Pod, nodeNameToInfo map[string]*schedulercache.NodeInfo) PredicateMetadata { - return nil -} - // EmptyPriorityMetadataProducer returns a no-op PriorityMetadataProducer type. -func EmptyPriorityMetadataProducer(pod *v1.Pod, nodeNameToInfo map[string]*schedulercache.NodeInfo) interface{} { +func EmptyPriorityMetadataProducer(pod *v1.Pod, nodeNameToInfo map[string]*schedulernodeinfo.NodeInfo) interface{} { return nil } -// PredicateFailureReason interface represents the failure reason of a predicate. -type PredicateFailureReason interface { - GetReason() string -} - // NodeLister interface represents anything that can list nodes for a scheduler. type NodeLister interface { // We explicitly return []*v1.Node, instead of v1.NodeList, to avoid @@ -92,6 +74,9 @@ type NodeLister interface { List() ([]*v1.Node, error) } +// PodFilter is a function to filter a pod. If pod passed return true else return false. +type PodFilter func(*v1.Pod) bool + // PodLister interface represents anything that can list pods for a scheduler. type PodLister interface { // We explicitly return []*v1.Pod, instead of v1.PodList, to avoid @@ -99,7 +84,7 @@ type PodLister interface { List(labels.Selector) ([]*v1.Pod, error) // This is similar to "List()", but the returned slice does not // contain pods that don't pass `podFilter`. - FilteredList(podFilter schedulerinternalcache.PodFilter, selector labels.Selector) ([]*v1.Pod, error) + FilteredList(podFilter PodFilter, selector labels.Selector) ([]*v1.Pod, error) } // ServiceLister interface represents anything that can produce a list of services; the list is consumed by a scheduler. @@ -170,10 +155,3 @@ type EmptyStatefulSetLister struct{} func (f EmptyStatefulSetLister) GetPodStatefulSets(pod *v1.Pod) (sss []*apps.StatefulSet, err error) { return nil, nil } - -// PredicateMetadata interface represents anything that can access a predicate metadata. -type PredicateMetadata interface { - ShallowCopy() PredicateMetadata - AddPod(addedPod *v1.Pod, nodeInfo *schedulercache.NodeInfo) error - RemovePod(deletedPod *v1.Pod) error -} diff --git a/pkg/scheduler/algorithm/types_test.go b/pkg/scheduler/algorithm/types_test.go index e613c8c5028..9f117240d3f 100644 --- a/pkg/scheduler/algorithm/types_test.go +++ b/pkg/scheduler/algorithm/types_test.go @@ -21,7 +21,7 @@ import ( "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/labels" - schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" + schedulernodeinfo "k8s.io/kubernetes/pkg/scheduler/nodeinfo" ) // EmptyPriorityMetadataProducer should returns a no-op PriorityMetadataProducer type. @@ -29,9 +29,9 @@ func TestEmptyPriorityMetadataProducer(t *testing.T) { fakePod := new(v1.Pod) fakeLabelSelector := labels.SelectorFromSet(labels.Set{"foo": "bar"}) - nodeNameToInfo := map[string]*schedulercache.NodeInfo{ - "2": schedulercache.NewNodeInfo(fakePod), - "1": schedulercache.NewNodeInfo(), + nodeNameToInfo := map[string]*schedulernodeinfo.NodeInfo{ + "2": schedulernodeinfo.NewNodeInfo(fakePod), + "1": schedulernodeinfo.NewNodeInfo(), } // Test EmptyPriorityMetadataProducer metadata := EmptyPriorityMetadataProducer(fakePod, nodeNameToInfo) diff --git a/pkg/scheduler/algorithmprovider/defaults/BUILD b/pkg/scheduler/algorithmprovider/defaults/BUILD index ae77ea8609c..a13259cdd43 100644 --- a/pkg/scheduler/algorithmprovider/defaults/BUILD +++ b/pkg/scheduler/algorithmprovider/defaults/BUILD @@ -8,7 +8,11 @@ load( go_library( name = "go_default_library", - srcs = ["defaults.go"], + srcs = [ + "defaults.go", + "register_predicates.go", + "register_priorities.go", + ], importpath = "k8s.io/kubernetes/pkg/scheduler/algorithmprovider/defaults", deps = [ "//pkg/features:go_default_library", @@ -25,25 +29,12 @@ go_library( go_test( name = "go_default_test", - srcs = [ - "compatibility_test.go", - "defaults_test.go", - ], + srcs = ["defaults_test.go"], embed = [":go_default_library"], deps = [ - "//pkg/apis/core/install:go_default_library", "//pkg/scheduler/algorithm/predicates:go_default_library", - "//pkg/scheduler/api:go_default_library", - "//pkg/scheduler/api/latest:go_default_library", - "//pkg/scheduler/factory:go_default_library", - "//staging/src/k8s.io/api/core/v1:go_default_library", - "//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library", - "//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", + "//pkg/scheduler/algorithm/priorities:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library", - "//staging/src/k8s.io/client-go/informers:go_default_library", - "//staging/src/k8s.io/client-go/kubernetes:go_default_library", - "//staging/src/k8s.io/client-go/rest:go_default_library", - "//staging/src/k8s.io/client-go/util/testing:go_default_library", ], ) diff --git a/pkg/scheduler/algorithmprovider/defaults/defaults.go b/pkg/scheduler/algorithmprovider/defaults/defaults.go index 74467fe17a5..fbc8cb87b83 100644 --- a/pkg/scheduler/algorithmprovider/defaults/defaults.go +++ b/pkg/scheduler/algorithmprovider/defaults/defaults.go @@ -23,10 +23,8 @@ import ( utilfeature "k8s.io/apiserver/pkg/util/feature" "k8s.io/kubernetes/pkg/features" - "k8s.io/kubernetes/pkg/scheduler/algorithm" "k8s.io/kubernetes/pkg/scheduler/algorithm/predicates" "k8s.io/kubernetes/pkg/scheduler/algorithm/priorities" - "k8s.io/kubernetes/pkg/scheduler/core" "k8s.io/kubernetes/pkg/scheduler/factory" ) @@ -36,146 +34,25 @@ const ( ) func init() { - // Register functions that extract metadata used by predicates and priorities computations. - factory.RegisterPredicateMetadataProducerFactory( - func(args factory.PluginFactoryArgs) algorithm.PredicateMetadataProducer { - return predicates.NewPredicateMetadataFactory(args.PodLister) - }) - factory.RegisterPriorityMetadataProducerFactory( - func(args factory.PluginFactoryArgs) algorithm.PriorityMetadataProducer { - return priorities.NewPriorityMetadataFactory(args.ServiceLister, args.ControllerLister, args.ReplicaSetLister, args.StatefulSetLister) - }) - registerAlgorithmProvider(defaultPredicates(), defaultPriorities()) - - // IMPORTANT NOTES for predicate developers: - // We are using cached predicate result for pods belonging to the same equivalence class. - // So when implementing a new predicate, you are expected to check whether the result - // of your predicate function can be affected by related API object change (ADD/DELETE/UPDATE). - // If yes, you are expected to invalidate the cached predicate result for related API object change. - // For example: - // https://github.com/kubernetes/kubernetes/blob/36a218e/plugin/pkg/scheduler/factory/factory.go#L422 - - // Registers predicates and priorities that are not enabled by default, but user can pick when creating their - // own set of priorities/predicates. - - // PodFitsPorts has been replaced by PodFitsHostPorts for better user understanding. - // For backwards compatibility with 1.0, PodFitsPorts is registered as well. - factory.RegisterFitPredicate("PodFitsPorts", predicates.PodFitsHostPorts) - // Fit is defined based on the absence of port conflicts. - // This predicate is actually a default predicate, because it is invoked from - // predicates.GeneralPredicates() - factory.RegisterFitPredicate(predicates.PodFitsHostPortsPred, predicates.PodFitsHostPorts) - // Fit is determined by resource availability. - // This predicate is actually a default predicate, because it is invoked from - // predicates.GeneralPredicates() - factory.RegisterFitPredicate(predicates.PodFitsResourcesPred, predicates.PodFitsResources) - // Fit is determined by the presence of the Host parameter and a string match - // This predicate is actually a default predicate, because it is invoked from - // predicates.GeneralPredicates() - factory.RegisterFitPredicate(predicates.HostNamePred, predicates.PodFitsHost) - // Fit is determined by node selector query. - factory.RegisterFitPredicate(predicates.MatchNodeSelectorPred, predicates.PodMatchNodeSelector) - - // ServiceSpreadingPriority is a priority config factory that spreads pods by minimizing - // the number of pods (belonging to the same service) on the same node. - // Register the factory so that it's available, but do not include it as part of the default priorities - // Largely replaced by "SelectorSpreadPriority", but registered for backward compatibility with 1.0 - factory.RegisterPriorityConfigFactory( - "ServiceSpreadingPriority", - factory.PriorityConfigFactory{ - MapReduceFunction: func(args factory.PluginFactoryArgs) (algorithm.PriorityMapFunction, algorithm.PriorityReduceFunction) { - return priorities.NewSelectorSpreadPriority(args.ServiceLister, algorithm.EmptyControllerLister{}, algorithm.EmptyReplicaSetLister{}, algorithm.EmptyStatefulSetLister{}) - }, - Weight: 1, - }, - ) - // EqualPriority is a prioritizer function that gives an equal weight of one to all nodes - // Register the priority function so that its available - // but do not include it as part of the default priorities - factory.RegisterPriorityFunction2("EqualPriority", core.EqualPriorityMap, nil, 1) - // Optional, cluster-autoscaler friendly priority function - give used nodes higher priority. - factory.RegisterPriorityFunction2("MostRequestedPriority", priorities.MostRequestedPriorityMap, nil, 1) - factory.RegisterPriorityFunction2( - "RequestedToCapacityRatioPriority", - priorities.RequestedToCapacityRatioResourceAllocationPriorityDefault().PriorityMap, - nil, - 1) } func defaultPredicates() sets.String { return sets.NewString( - // Fit is determined by volume zone requirements. - factory.RegisterFitPredicateFactory( - predicates.NoVolumeZoneConflictPred, - func(args factory.PluginFactoryArgs) algorithm.FitPredicate { - return predicates.NewVolumeZonePredicate(args.PVInfo, args.PVCInfo, args.StorageClassInfo) - }, - ), - // Fit is determined by whether or not there would be too many AWS EBS volumes attached to the node - factory.RegisterFitPredicateFactory( - predicates.MaxEBSVolumeCountPred, - func(args factory.PluginFactoryArgs) algorithm.FitPredicate { - return predicates.NewMaxPDVolumeCountPredicate(predicates.EBSVolumeFilterType, args.PVInfo, args.PVCInfo) - }, - ), - // Fit is determined by whether or not there would be too many GCE PD volumes attached to the node - factory.RegisterFitPredicateFactory( - predicates.MaxGCEPDVolumeCountPred, - func(args factory.PluginFactoryArgs) algorithm.FitPredicate { - return predicates.NewMaxPDVolumeCountPredicate(predicates.GCEPDVolumeFilterType, args.PVInfo, args.PVCInfo) - }, - ), - // Fit is determined by whether or not there would be too many Azure Disk volumes attached to the node - factory.RegisterFitPredicateFactory( - predicates.MaxAzureDiskVolumeCountPred, - func(args factory.PluginFactoryArgs) algorithm.FitPredicate { - return predicates.NewMaxPDVolumeCountPredicate(predicates.AzureDiskVolumeFilterType, args.PVInfo, args.PVCInfo) - }, - ), - factory.RegisterFitPredicateFactory( - predicates.MaxCSIVolumeCountPred, - func(args factory.PluginFactoryArgs) algorithm.FitPredicate { - return predicates.NewCSIMaxVolumeLimitPredicate(args.PVInfo, args.PVCInfo) - }, - ), - // Fit is determined by inter-pod affinity. - factory.RegisterFitPredicateFactory( - predicates.MatchInterPodAffinityPred, - func(args factory.PluginFactoryArgs) algorithm.FitPredicate { - return predicates.NewPodAffinityPredicate(args.NodeInfo, args.PodLister) - }, - ), - - // Fit is determined by non-conflicting disk volumes. - factory.RegisterFitPredicate(predicates.NoDiskConflictPred, predicates.NoDiskConflict), - - // GeneralPredicates are the predicates that are enforced by all Kubernetes components - // (e.g. kubelet and all schedulers) - factory.RegisterFitPredicate(predicates.GeneralPred, predicates.GeneralPredicates), - - // Fit is determined by node memory pressure condition. - factory.RegisterFitPredicate(predicates.CheckNodeMemoryPressurePred, predicates.CheckNodeMemoryPressurePredicate), - - // Fit is determined by node disk pressure condition. - factory.RegisterFitPredicate(predicates.CheckNodeDiskPressurePred, predicates.CheckNodeDiskPressurePredicate), - - // Fit is determined by node pid pressure condition. - factory.RegisterFitPredicate(predicates.CheckNodePIDPressurePred, predicates.CheckNodePIDPressurePredicate), - - // Fit is determined by node conditions: not ready, network unavailable or out of disk. - factory.RegisterMandatoryFitPredicate(predicates.CheckNodeConditionPred, predicates.CheckNodeConditionPredicate), - - // Fit is determined based on whether a pod can tolerate all of the node's taints - factory.RegisterFitPredicate(predicates.PodToleratesNodeTaintsPred, predicates.PodToleratesNodeTaints), - - // Fit is determined by volume topology requirements. - factory.RegisterFitPredicateFactory( - predicates.CheckVolumeBindingPred, - func(args factory.PluginFactoryArgs) algorithm.FitPredicate { - return predicates.NewVolumeBindingPredicate(args.VolumeBinder) - }, - ), + predicates.NoVolumeZoneConflictPred, + predicates.MaxEBSVolumeCountPred, + predicates.MaxGCEPDVolumeCountPred, + predicates.MaxAzureDiskVolumeCountPred, + predicates.MaxCSIVolumeCountPred, + predicates.MatchInterPodAffinityPred, + predicates.NoDiskConflictPred, + predicates.GeneralPred, + predicates.CheckNodeMemoryPressurePred, + predicates.CheckNodeDiskPressurePred, + predicates.CheckNodePIDPressurePred, + predicates.CheckNodeConditionPred, + predicates.PodToleratesNodeTaintsPred, + predicates.CheckVolumeBindingPred, ) } @@ -213,9 +90,9 @@ func ApplyFeatureGates() { // Prioritizes nodes that satisfy pod's resource limits if utilfeature.DefaultFeatureGate.Enabled(features.ResourceLimitsPriorityFunction) { klog.Infof("Registering resourcelimits priority function") - factory.RegisterPriorityFunction2("ResourceLimitsPriority", priorities.ResourceLimitsPriorityMap, nil, 1) + factory.RegisterPriorityFunction2(priorities.ResourceLimitsPriority, priorities.ResourceLimitsPriorityMap, nil, 1) // Register the priority function to specific provider too. - factory.InsertPriorityKeyToAlgorithmProviderMap(factory.RegisterPriorityFunction2("ResourceLimitsPriority", priorities.ResourceLimitsPriorityMap, nil, 1)) + factory.InsertPriorityKeyToAlgorithmProviderMap(factory.RegisterPriorityFunction2(priorities.ResourceLimitsPriority, priorities.ResourceLimitsPriorityMap, nil, 1)) } } @@ -225,51 +102,19 @@ func registerAlgorithmProvider(predSet, priSet sets.String) { factory.RegisterAlgorithmProvider(factory.DefaultProvider, predSet, priSet) // Cluster autoscaler friendly scheduling algorithm. factory.RegisterAlgorithmProvider(ClusterAutoscalerProvider, predSet, - copyAndReplace(priSet, "LeastRequestedPriority", "MostRequestedPriority")) + copyAndReplace(priSet, priorities.LeastRequestedPriority, priorities.MostRequestedPriority)) } func defaultPriorities() sets.String { return sets.NewString( - // spreads pods by minimizing the number of pods (belonging to the same service or replication controller) on the same node. - factory.RegisterPriorityConfigFactory( - "SelectorSpreadPriority", - factory.PriorityConfigFactory{ - MapReduceFunction: func(args factory.PluginFactoryArgs) (algorithm.PriorityMapFunction, algorithm.PriorityReduceFunction) { - return priorities.NewSelectorSpreadPriority(args.ServiceLister, args.ControllerLister, args.ReplicaSetLister, args.StatefulSetLister) - }, - Weight: 1, - }, - ), - // pods should be placed in the same topological domain (e.g. same node, same rack, same zone, same power domain, etc.) - // as some other pods, or, conversely, should not be placed in the same topological domain as some other pods. - factory.RegisterPriorityConfigFactory( - "InterPodAffinityPriority", - factory.PriorityConfigFactory{ - Function: func(args factory.PluginFactoryArgs) algorithm.PriorityFunction { - return priorities.NewInterPodAffinityPriority(args.NodeInfo, args.NodeLister, args.PodLister, args.HardPodAffinitySymmetricWeight) - }, - Weight: 1, - }, - ), - - // Prioritize nodes by least requested utilization. - factory.RegisterPriorityFunction2("LeastRequestedPriority", priorities.LeastRequestedPriorityMap, nil, 1), - - // Prioritizes nodes to help achieve balanced resource usage - factory.RegisterPriorityFunction2("BalancedResourceAllocation", priorities.BalancedResourceAllocationMap, nil, 1), - - // Set this weight large enough to override all other priority functions. - // TODO: Figure out a better way to do this, maybe at same time as fixing #24720. - factory.RegisterPriorityFunction2("NodePreferAvoidPodsPriority", priorities.CalculateNodePreferAvoidPodsPriorityMap, nil, 10000), - - // Prioritizes nodes that have labels matching NodeAffinity - factory.RegisterPriorityFunction2("NodeAffinityPriority", priorities.CalculateNodeAffinityPriorityMap, priorities.CalculateNodeAffinityPriorityReduce, 1), - - // Prioritizes nodes that marked with taint which pod can tolerate. - factory.RegisterPriorityFunction2("TaintTolerationPriority", priorities.ComputeTaintTolerationPriorityMap, priorities.ComputeTaintTolerationPriorityReduce, 1), - - // ImageLocalityPriority prioritizes nodes that have images requested by the pod present. - factory.RegisterPriorityFunction2("ImageLocalityPriority", priorities.ImageLocalityPriorityMap, nil, 1), + priorities.SelectorSpreadPriority, + priorities.InterPodAffinityPriority, + priorities.LeastRequestedPriority, + priorities.BalancedResourceAllocation, + priorities.NodePreferAvoidPodsPriority, + priorities.NodeAffinityPriority, + priorities.TaintTolerationPriority, + priorities.ImageLocalityPriority, ) } diff --git a/pkg/scheduler/algorithmprovider/defaults/defaults_test.go b/pkg/scheduler/algorithmprovider/defaults/defaults_test.go index afe04cfacc2..48696ba0264 100644 --- a/pkg/scheduler/algorithmprovider/defaults/defaults_test.go +++ b/pkg/scheduler/algorithmprovider/defaults/defaults_test.go @@ -21,6 +21,7 @@ import ( "k8s.io/apimachinery/pkg/util/sets" "k8s.io/kubernetes/pkg/scheduler/algorithm/predicates" + "k8s.io/kubernetes/pkg/scheduler/algorithm/priorities" ) func TestCopyAndReplace(t *testing.T) { @@ -53,14 +54,15 @@ func TestCopyAndReplace(t *testing.T) { func TestDefaultPriorities(t *testing.T) { result := sets.NewString( - "SelectorSpreadPriority", - "InterPodAffinityPriority", - "LeastRequestedPriority", - "BalancedResourceAllocation", - "NodePreferAvoidPodsPriority", - "NodeAffinityPriority", - "TaintTolerationPriority", - "ImageLocalityPriority") + priorities.SelectorSpreadPriority, + priorities.InterPodAffinityPriority, + priorities.LeastRequestedPriority, + priorities.BalancedResourceAllocation, + priorities.NodePreferAvoidPodsPriority, + priorities.NodeAffinityPriority, + priorities.TaintTolerationPriority, + priorities.ImageLocalityPriority, + ) if expected := defaultPriorities(); !result.Equal(expected) { t.Errorf("expected %v got %v", expected, result) } diff --git a/pkg/scheduler/algorithmprovider/defaults/register_predicates.go b/pkg/scheduler/algorithmprovider/defaults/register_predicates.go new file mode 100644 index 00000000000..4f93f83da22 --- /dev/null +++ b/pkg/scheduler/algorithmprovider/defaults/register_predicates.go @@ -0,0 +1,124 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package defaults + +import ( + "k8s.io/kubernetes/pkg/scheduler/algorithm/predicates" + "k8s.io/kubernetes/pkg/scheduler/factory" +) + +func init() { + // Register functions that extract metadata used by predicates computations. + factory.RegisterPredicateMetadataProducerFactory( + func(args factory.PluginFactoryArgs) predicates.PredicateMetadataProducer { + return predicates.NewPredicateMetadataFactory(args.PodLister) + }) + + // IMPORTANT NOTES for predicate developers: + // Registers predicates and priorities that are not enabled by default, but user can pick when creating their + // own set of priorities/predicates. + + // PodFitsPorts has been replaced by PodFitsHostPorts for better user understanding. + // For backwards compatibility with 1.0, PodFitsPorts is registered as well. + factory.RegisterFitPredicate("PodFitsPorts", predicates.PodFitsHostPorts) + // Fit is defined based on the absence of port conflicts. + // This predicate is actually a default predicate, because it is invoked from + // predicates.GeneralPredicates() + factory.RegisterFitPredicate(predicates.PodFitsHostPortsPred, predicates.PodFitsHostPorts) + // Fit is determined by resource availability. + // This predicate is actually a default predicate, because it is invoked from + // predicates.GeneralPredicates() + factory.RegisterFitPredicate(predicates.PodFitsResourcesPred, predicates.PodFitsResources) + // Fit is determined by the presence of the Host parameter and a string match + // This predicate is actually a default predicate, because it is invoked from + // predicates.GeneralPredicates() + factory.RegisterFitPredicate(predicates.HostNamePred, predicates.PodFitsHost) + // Fit is determined by node selector query. + factory.RegisterFitPredicate(predicates.MatchNodeSelectorPred, predicates.PodMatchNodeSelector) + + // Fit is determined by volume zone requirements. + factory.RegisterFitPredicateFactory( + predicates.NoVolumeZoneConflictPred, + func(args factory.PluginFactoryArgs) predicates.FitPredicate { + return predicates.NewVolumeZonePredicate(args.PVInfo, args.PVCInfo, args.StorageClassInfo) + }, + ) + // Fit is determined by whether or not there would be too many AWS EBS volumes attached to the node + factory.RegisterFitPredicateFactory( + predicates.MaxEBSVolumeCountPred, + func(args factory.PluginFactoryArgs) predicates.FitPredicate { + return predicates.NewMaxPDVolumeCountPredicate(predicates.EBSVolumeFilterType, args.PVInfo, args.PVCInfo) + }, + ) + // Fit is determined by whether or not there would be too many GCE PD volumes attached to the node + factory.RegisterFitPredicateFactory( + predicates.MaxGCEPDVolumeCountPred, + func(args factory.PluginFactoryArgs) predicates.FitPredicate { + return predicates.NewMaxPDVolumeCountPredicate(predicates.GCEPDVolumeFilterType, args.PVInfo, args.PVCInfo) + }, + ) + // Fit is determined by whether or not there would be too many Azure Disk volumes attached to the node + factory.RegisterFitPredicateFactory( + predicates.MaxAzureDiskVolumeCountPred, + func(args factory.PluginFactoryArgs) predicates.FitPredicate { + return predicates.NewMaxPDVolumeCountPredicate(predicates.AzureDiskVolumeFilterType, args.PVInfo, args.PVCInfo) + }, + ) + factory.RegisterFitPredicateFactory( + predicates.MaxCSIVolumeCountPred, + func(args factory.PluginFactoryArgs) predicates.FitPredicate { + return predicates.NewCSIMaxVolumeLimitPredicate(args.PVInfo, args.PVCInfo) + }, + ) + // Fit is determined by inter-pod affinity. + factory.RegisterFitPredicateFactory( + predicates.MatchInterPodAffinityPred, + func(args factory.PluginFactoryArgs) predicates.FitPredicate { + return predicates.NewPodAffinityPredicate(args.NodeInfo, args.PodLister) + }, + ) + + // Fit is determined by non-conflicting disk volumes. + factory.RegisterFitPredicate(predicates.NoDiskConflictPred, predicates.NoDiskConflict) + + // GeneralPredicates are the predicates that are enforced by all Kubernetes components + // (e.g. kubelet and all schedulers) + factory.RegisterFitPredicate(predicates.GeneralPred, predicates.GeneralPredicates) + + // Fit is determined by node memory pressure condition. + factory.RegisterFitPredicate(predicates.CheckNodeMemoryPressurePred, predicates.CheckNodeMemoryPressurePredicate) + + // Fit is determined by node disk pressure condition. + factory.RegisterFitPredicate(predicates.CheckNodeDiskPressurePred, predicates.CheckNodeDiskPressurePredicate) + + // Fit is determined by node pid pressure condition. + factory.RegisterFitPredicate(predicates.CheckNodePIDPressurePred, predicates.CheckNodePIDPressurePredicate) + + // Fit is determined by node conditions: not ready, network unavailable or out of disk. + factory.RegisterMandatoryFitPredicate(predicates.CheckNodeConditionPred, predicates.CheckNodeConditionPredicate) + + // Fit is determined based on whether a pod can tolerate all of the node's taints + factory.RegisterFitPredicate(predicates.PodToleratesNodeTaintsPred, predicates.PodToleratesNodeTaints) + + // Fit is determined by volume topology requirements. + factory.RegisterFitPredicateFactory( + predicates.CheckVolumeBindingPred, + func(args factory.PluginFactoryArgs) predicates.FitPredicate { + return predicates.NewVolumeBindingPredicate(args.VolumeBinder) + }, + ) +} diff --git a/pkg/scheduler/algorithmprovider/defaults/register_priorities.go b/pkg/scheduler/algorithmprovider/defaults/register_priorities.go new file mode 100644 index 00000000000..eeb649787f2 --- /dev/null +++ b/pkg/scheduler/algorithmprovider/defaults/register_priorities.go @@ -0,0 +1,97 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package defaults + +import ( + "k8s.io/kubernetes/pkg/scheduler/algorithm" + "k8s.io/kubernetes/pkg/scheduler/algorithm/priorities" + "k8s.io/kubernetes/pkg/scheduler/core" + "k8s.io/kubernetes/pkg/scheduler/factory" +) + +func init() { + // Register functions that extract metadata used by priorities computations. + factory.RegisterPriorityMetadataProducerFactory( + func(args factory.PluginFactoryArgs) algorithm.PriorityMetadataProducer { + return priorities.NewPriorityMetadataFactory(args.ServiceLister, args.ControllerLister, args.ReplicaSetLister, args.StatefulSetLister) + }) + + // ServiceSpreadingPriority is a priority config factory that spreads pods by minimizing + // the number of pods (belonging to the same service) on the same node. + // Register the factory so that it's available, but do not include it as part of the default priorities + // Largely replaced by "SelectorSpreadPriority", but registered for backward compatibility with 1.0 + factory.RegisterPriorityConfigFactory( + priorities.ServiceSpreadingPriority, + factory.PriorityConfigFactory{ + MapReduceFunction: func(args factory.PluginFactoryArgs) (algorithm.PriorityMapFunction, algorithm.PriorityReduceFunction) { + return priorities.NewSelectorSpreadPriority(args.ServiceLister, algorithm.EmptyControllerLister{}, algorithm.EmptyReplicaSetLister{}, algorithm.EmptyStatefulSetLister{}) + }, + Weight: 1, + }, + ) + // EqualPriority is a prioritizer function that gives an equal weight of one to all nodes + // Register the priority function so that its available + // but do not include it as part of the default priorities + factory.RegisterPriorityFunction2(priorities.EqualPriority, core.EqualPriorityMap, nil, 1) + // Optional, cluster-autoscaler friendly priority function - give used nodes higher priority. + factory.RegisterPriorityFunction2(priorities.MostRequestedPriority, priorities.MostRequestedPriorityMap, nil, 1) + factory.RegisterPriorityFunction2( + priorities.RequestedToCapacityRatioPriority, + priorities.RequestedToCapacityRatioResourceAllocationPriorityDefault().PriorityMap, + nil, + 1) + // spreads pods by minimizing the number of pods (belonging to the same service or replication controller) on the same node. + factory.RegisterPriorityConfigFactory( + priorities.SelectorSpreadPriority, + factory.PriorityConfigFactory{ + MapReduceFunction: func(args factory.PluginFactoryArgs) (algorithm.PriorityMapFunction, algorithm.PriorityReduceFunction) { + return priorities.NewSelectorSpreadPriority(args.ServiceLister, args.ControllerLister, args.ReplicaSetLister, args.StatefulSetLister) + }, + Weight: 1, + }, + ) + // pods should be placed in the same topological domain (e.g. same node, same rack, same zone, same power domain, etc.) + // as some other pods, or, conversely, should not be placed in the same topological domain as some other pods. + factory.RegisterPriorityConfigFactory( + priorities.InterPodAffinityPriority, + factory.PriorityConfigFactory{ + Function: func(args factory.PluginFactoryArgs) algorithm.PriorityFunction { + return priorities.NewInterPodAffinityPriority(args.NodeInfo, args.NodeLister, args.PodLister, args.HardPodAffinitySymmetricWeight) + }, + Weight: 1, + }, + ) + + // Prioritize nodes by least requested utilization. + factory.RegisterPriorityFunction2(priorities.LeastRequestedPriority, priorities.LeastRequestedPriorityMap, nil, 1) + + // Prioritizes nodes to help achieve balanced resource usage + factory.RegisterPriorityFunction2(priorities.BalancedResourceAllocation, priorities.BalancedResourceAllocationMap, nil, 1) + + // Set this weight large enough to override all other priority functions. + // TODO: Figure out a better way to do this, maybe at same time as fixing #24720. + factory.RegisterPriorityFunction2(priorities.NodePreferAvoidPodsPriority, priorities.CalculateNodePreferAvoidPodsPriorityMap, nil, 10000) + + // Prioritizes nodes that have labels matching NodeAffinity + factory.RegisterPriorityFunction2(priorities.NodeAffinityPriority, priorities.CalculateNodeAffinityPriorityMap, priorities.CalculateNodeAffinityPriorityReduce, 1) + + // Prioritizes nodes that marked with taint which pod can tolerate. + factory.RegisterPriorityFunction2(priorities.TaintTolerationPriority, priorities.ComputeTaintTolerationPriorityMap, priorities.ComputeTaintTolerationPriorityReduce, 1) + + // ImageLocalityPriority prioritizes nodes that have images requested by the pod present. + factory.RegisterPriorityFunction2(priorities.ImageLocalityPriority, priorities.ImageLocalityPriorityMap, nil, 1) +} diff --git a/pkg/scheduler/api/BUILD b/pkg/scheduler/api/BUILD index 0f6361b6a62..da8f819eea2 100644 --- a/pkg/scheduler/api/BUILD +++ b/pkg/scheduler/api/BUILD @@ -22,7 +22,6 @@ go_library( "//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/types:go_default_library", - "//staging/src/k8s.io/client-go/rest:go_default_library", ], ) @@ -37,6 +36,7 @@ filegroup( name = "all-srcs", srcs = [ ":package-srcs", + "//pkg/scheduler/api/compatibility:all-srcs", "//pkg/scheduler/api/latest:all-srcs", "//pkg/scheduler/api/v1:all-srcs", "//pkg/scheduler/api/validation:all-srcs", diff --git a/pkg/scheduler/api/compatibility/BUILD b/pkg/scheduler/api/compatibility/BUILD new file mode 100644 index 00000000000..810e0b3115f --- /dev/null +++ b/pkg/scheduler/api/compatibility/BUILD @@ -0,0 +1,35 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_test") + +go_test( + name = "go_default_test", + srcs = ["compatibility_test.go"], + deps = [ + "//pkg/apis/core/install:go_default_library", + "//pkg/scheduler/algorithmprovider/defaults:go_default_library", + "//pkg/scheduler/api:go_default_library", + "//pkg/scheduler/api/latest:go_default_library", + "//pkg/scheduler/factory:go_default_library", + "//staging/src/k8s.io/api/core/v1:go_default_library", + "//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library", + "//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", + "//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library", + "//staging/src/k8s.io/client-go/informers:go_default_library", + "//staging/src/k8s.io/client-go/kubernetes:go_default_library", + "//staging/src/k8s.io/client-go/rest:go_default_library", + "//staging/src/k8s.io/client-go/util/testing:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/pkg/scheduler/algorithmprovider/defaults/compatibility_test.go b/pkg/scheduler/api/compatibility/compatibility_test.go similarity index 98% rename from pkg/scheduler/algorithmprovider/defaults/compatibility_test.go rename to pkg/scheduler/api/compatibility/compatibility_test.go index 9e2262ee306..9a04f199354 100644 --- a/pkg/scheduler/algorithmprovider/defaults/compatibility_test.go +++ b/pkg/scheduler/api/compatibility/compatibility_test.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package defaults +package compatibility import ( "fmt" @@ -31,13 +31,12 @@ import ( restclient "k8s.io/client-go/rest" utiltesting "k8s.io/client-go/util/testing" _ "k8s.io/kubernetes/pkg/apis/core/install" + _ "k8s.io/kubernetes/pkg/scheduler/algorithmprovider/defaults" schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" latestschedulerapi "k8s.io/kubernetes/pkg/scheduler/api/latest" "k8s.io/kubernetes/pkg/scheduler/factory" ) -const enableEquivalenceCache = true - func TestCompatibility_v1_Scheduler(t *testing.T) { // Add serialized versions of scheduler config that exercise available options to ensure compatibility between releases schedulerFiles := map[string]struct { @@ -399,7 +398,7 @@ func TestCompatibility_v1_Scheduler(t *testing.T) { Weight: 1, BindVerb: "bind", // 1.7 was missing json tags on the BindVerb field and required "BindVerb" EnableHTTPS: true, - TLSConfig: &restclient.TLSClientConfig{Insecure: true}, + TLSConfig: &schedulerapi.ExtenderTLSConfig{Insecure: true}, HTTPTimeout: 1, NodeCacheCapable: true, }}, @@ -491,7 +490,7 @@ func TestCompatibility_v1_Scheduler(t *testing.T) { Weight: 1, BindVerb: "bind", // 1.8 became case-insensitive and tolerated "bindVerb" EnableHTTPS: true, - TLSConfig: &restclient.TLSClientConfig{Insecure: true}, + TLSConfig: &schedulerapi.ExtenderTLSConfig{Insecure: true}, HTTPTimeout: 1, NodeCacheCapable: true, }}, @@ -585,7 +584,7 @@ func TestCompatibility_v1_Scheduler(t *testing.T) { Weight: 1, BindVerb: "bind", // 1.9 was case-insensitive and tolerated "bindVerb" EnableHTTPS: true, - TLSConfig: &restclient.TLSClientConfig{Insecure: true}, + TLSConfig: &schedulerapi.ExtenderTLSConfig{Insecure: true}, HTTPTimeout: 1, NodeCacheCapable: true, }}, @@ -684,7 +683,7 @@ func TestCompatibility_v1_Scheduler(t *testing.T) { Weight: 1, BindVerb: "bind", // 1.10 was case-insensitive and tolerated "bindVerb" EnableHTTPS: true, - TLSConfig: &restclient.TLSClientConfig{Insecure: true}, + TLSConfig: &schedulerapi.ExtenderTLSConfig{Insecure: true}, HTTPTimeout: 1, NodeCacheCapable: true, ManagedResources: []schedulerapi.ExtenderManagedResource{{Name: v1.ResourceName("example.com/foo"), IgnoredByScheduler: true}}, @@ -806,7 +805,7 @@ func TestCompatibility_v1_Scheduler(t *testing.T) { Weight: 1, BindVerb: "bind", // 1.11 restored case-sensitivity, but allowed either "BindVerb" or "bindVerb" EnableHTTPS: true, - TLSConfig: &restclient.TLSClientConfig{Insecure: true}, + TLSConfig: &schedulerapi.ExtenderTLSConfig{Insecure: true}, HTTPTimeout: 1, NodeCacheCapable: true, ManagedResources: []schedulerapi.ExtenderManagedResource{{Name: v1.ResourceName("example.com/foo"), IgnoredByScheduler: true}}, @@ -930,7 +929,7 @@ func TestCompatibility_v1_Scheduler(t *testing.T) { Weight: 1, BindVerb: "bind", // 1.11 restored case-sensitivity, but allowed either "BindVerb" or "bindVerb" EnableHTTPS: true, - TLSConfig: &restclient.TLSClientConfig{Insecure: true}, + TLSConfig: &schedulerapi.ExtenderTLSConfig{Insecure: true}, HTTPTimeout: 1, NodeCacheCapable: true, ManagedResources: []schedulerapi.ExtenderManagedResource{{Name: v1.ResourceName("example.com/foo"), IgnoredByScheduler: true}}, @@ -987,7 +986,6 @@ func TestCompatibility_v1_Scheduler(t *testing.T) { PdbInformer: informerFactory.Policy().V1beta1().PodDisruptionBudgets(), StorageClassInformer: informerFactory.Storage().V1().StorageClasses(), HardPodAffinitySymmetricWeight: v1.DefaultHardPodAffinitySymmetricWeight, - EnableEquivalenceClassCache: enableEquivalenceCache, DisablePreemption: false, PercentageOfNodesToScore: schedulerapi.DefaultPercentageOfNodesToScore, }).CreateFromConfig(policy); err != nil { diff --git a/pkg/scheduler/api/types.go b/pkg/scheduler/api/types.go index 3bffc216376..fcc490820e6 100644 --- a/pkg/scheduler/api/types.go +++ b/pkg/scheduler/api/types.go @@ -22,7 +22,6 @@ import ( "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" - restclient "k8s.io/client-go/rest" ) const ( @@ -172,6 +171,33 @@ type ExtenderManagedResource struct { IgnoredByScheduler bool } +// ExtenderTLSConfig contains settings to enable TLS with extender +type ExtenderTLSConfig struct { + // Server should be accessed without verifying the TLS certificate. For testing only. + Insecure bool + // ServerName is passed to the server for SNI and is used in the client to check server + // ceritificates against. If ServerName is empty, the hostname used to contact the + // server is used. + ServerName string + + // Server requires TLS client certificate authentication + CertFile string + // Server requires TLS client certificate authentication + KeyFile string + // Trusted root certificates for server + CAFile string + + // CertData holds PEM-encoded bytes (typically read from a client certificate file). + // CertData takes precedence over CertFile + CertData []byte + // KeyData holds PEM-encoded bytes (typically read from a client certificate key file). + // KeyData takes precedence over KeyFile + KeyData []byte + // CAData holds PEM-encoded bytes (typically read from a root certificates bundle). + // CAData takes precedence over CAFile + CAData []byte +} + // ExtenderConfig holds the parameters used to communicate with the extender. If a verb is unspecified/empty, // it is assumed that the extender chose not to provide that extension. type ExtenderConfig struct { @@ -193,7 +219,7 @@ type ExtenderConfig struct { // EnableHTTPS specifies whether https should be used to communicate with the extender EnableHTTPS bool // TLSConfig specifies the transport layer security config - TLSConfig *restclient.TLSClientConfig + TLSConfig *ExtenderTLSConfig // HTTPTimeout specifies the timeout duration for a call to the extender. Filter timeout fails the scheduling of the pod. Prioritize // timeout is ignored, k8s/other extenders priorities are used to select the node. HTTPTimeout time.Duration diff --git a/pkg/scheduler/api/v1/BUILD b/pkg/scheduler/api/v1/BUILD index 7c911c9ece5..85d53c672ae 100644 --- a/pkg/scheduler/api/v1/BUILD +++ b/pkg/scheduler/api/v1/BUILD @@ -21,7 +21,6 @@ go_library( "//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/types:go_default_library", - "//staging/src/k8s.io/client-go/rest:go_default_library", ], ) diff --git a/pkg/scheduler/api/v1/types.go b/pkg/scheduler/api/v1/types.go index 10ea29bb322..b8d49429861 100644 --- a/pkg/scheduler/api/v1/types.go +++ b/pkg/scheduler/api/v1/types.go @@ -23,7 +23,6 @@ import ( apiv1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" - restclient "k8s.io/client-go/rest" ) // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object @@ -152,6 +151,33 @@ type ExtenderManagedResource struct { IgnoredByScheduler bool `json:"ignoredByScheduler,omitempty"` } +// ExtenderTLSConfig contains settings to enable TLS with extender +type ExtenderTLSConfig struct { + // Server should be accessed without verifying the TLS certificate. For testing only. + Insecure bool `json:"insecure,omitempty"` + // ServerName is passed to the server for SNI and is used in the client to check server + // ceritificates against. If ServerName is empty, the hostname used to contact the + // server is used. + ServerName string `json:"serverName,omitempty"` + + // Server requires TLS client certificate authentication + CertFile string `json:"certFile,omitempty"` + // Server requires TLS client certificate authentication + KeyFile string `json:"keyFile,omitempty"` + // Trusted root certificates for server + CAFile string `json:"caFile,omitempty"` + + // CertData holds PEM-encoded bytes (typically read from a client certificate file). + // CertData takes precedence over CertFile + CertData []byte `json:"certData,omitempty"` + // KeyData holds PEM-encoded bytes (typically read from a client certificate key file). + // KeyData takes precedence over KeyFile + KeyData []byte `json:"keyData,omitempty"` + // CAData holds PEM-encoded bytes (typically read from a root certificates bundle). + // CAData takes precedence over CAFile + CAData []byte `json:"caData,omitempty"` +} + // ExtenderConfig holds the parameters used to communicate with the extender. If a verb is unspecified/empty, // it is assumed that the extender chose not to provide that extension. type ExtenderConfig struct { @@ -169,11 +195,11 @@ type ExtenderConfig struct { // Verb for the bind call, empty if not supported. This verb is appended to the URLPrefix when issuing the bind call to extender. // If this method is implemented by the extender, it is the extender's responsibility to bind the pod to apiserver. Only one extender // can implement this function. - BindVerb string + BindVerb string `json:"bindVerb,omitempty"` // EnableHTTPS specifies whether https should be used to communicate with the extender EnableHTTPS bool `json:"enableHttps,omitempty"` // TLSConfig specifies the transport layer security config - TLSConfig *restclient.TLSClientConfig `json:"tlsConfig,omitempty"` + TLSConfig *ExtenderTLSConfig `json:"tlsConfig,omitempty"` // HTTPTimeout specifies the timeout duration for a call to the extender. Filter timeout fails the scheduling of the pod. Prioritize // timeout is ignored, k8s/other extenders priorities are used to select the node. HTTPTimeout time.Duration `json:"httpTimeout,omitempty"` diff --git a/pkg/scheduler/api/v1/zz_generated.deepcopy.go b/pkg/scheduler/api/v1/zz_generated.deepcopy.go index 7fc885f9460..b201de16a0c 100644 --- a/pkg/scheduler/api/v1/zz_generated.deepcopy.go +++ b/pkg/scheduler/api/v1/zz_generated.deepcopy.go @@ -23,7 +23,6 @@ package v1 import ( corev1 "k8s.io/api/core/v1" runtime "k8s.io/apimachinery/pkg/runtime" - rest "k8s.io/client-go/rest" ) // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. @@ -98,7 +97,7 @@ func (in *ExtenderConfig) DeepCopyInto(out *ExtenderConfig) { *out = *in if in.TLSConfig != nil { in, out := &in.TLSConfig, &out.TLSConfig - *out = new(rest.TLSClientConfig) + *out = new(ExtenderTLSConfig) (*in).DeepCopyInto(*out) } if in.ManagedResources != nil { @@ -254,6 +253,37 @@ func (in *ExtenderPreemptionResult) DeepCopy() *ExtenderPreemptionResult { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ExtenderTLSConfig) DeepCopyInto(out *ExtenderTLSConfig) { + *out = *in + if in.CertData != nil { + in, out := &in.CertData, &out.CertData + *out = make([]byte, len(*in)) + copy(*out, *in) + } + if in.KeyData != nil { + in, out := &in.KeyData, &out.KeyData + *out = make([]byte, len(*in)) + copy(*out, *in) + } + if in.CAData != nil { + in, out := &in.CAData, &out.CAData + *out = make([]byte, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExtenderTLSConfig. +func (in *ExtenderTLSConfig) DeepCopy() *ExtenderTLSConfig { + if in == nil { + return nil + } + out := new(ExtenderTLSConfig) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in FailedNodesMap) DeepCopyInto(out *FailedNodesMap) { { diff --git a/pkg/scheduler/api/well_known_labels.go b/pkg/scheduler/api/well_known_labels.go index afe64dd50f7..7c1d7078309 100644 --- a/pkg/scheduler/api/well_known_labels.go +++ b/pkg/scheduler/api/well_known_labels.go @@ -45,11 +45,6 @@ const ( // and removed when node becomes scheduable. TaintNodeUnschedulable = "node.kubernetes.io/unschedulable" - // TaintNodeOutOfDisk will be added when node becomes out of disk - // and feature-gate for TaintNodesByCondition flag is enabled, - // and removed when node has enough disk. - TaintNodeOutOfDisk = "node.kubernetes.io/out-of-disk" - // TaintNodeMemoryPressure will be added when node has memory pressure // and feature-gate for TaintNodesByCondition flag is enabled, // and removed when node has enough memory. diff --git a/pkg/scheduler/api/zz_generated.deepcopy.go b/pkg/scheduler/api/zz_generated.deepcopy.go index 418c78cd1e1..30c10135151 100644 --- a/pkg/scheduler/api/zz_generated.deepcopy.go +++ b/pkg/scheduler/api/zz_generated.deepcopy.go @@ -23,7 +23,6 @@ package api import ( v1 "k8s.io/api/core/v1" runtime "k8s.io/apimachinery/pkg/runtime" - rest "k8s.io/client-go/rest" ) // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. @@ -98,7 +97,7 @@ func (in *ExtenderConfig) DeepCopyInto(out *ExtenderConfig) { *out = *in if in.TLSConfig != nil { in, out := &in.TLSConfig, &out.TLSConfig - *out = new(rest.TLSClientConfig) + *out = new(ExtenderTLSConfig) (*in).DeepCopyInto(*out) } if in.ManagedResources != nil { @@ -254,6 +253,37 @@ func (in *ExtenderPreemptionResult) DeepCopy() *ExtenderPreemptionResult { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ExtenderTLSConfig) DeepCopyInto(out *ExtenderTLSConfig) { + *out = *in + if in.CertData != nil { + in, out := &in.CertData, &out.CertData + *out = make([]byte, len(*in)) + copy(*out, *in) + } + if in.KeyData != nil { + in, out := &in.KeyData, &out.KeyData + *out = make([]byte, len(*in)) + copy(*out, *in) + } + if in.CAData != nil { + in, out := &in.CAData, &out.CAData + *out = make([]byte, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExtenderTLSConfig. +func (in *ExtenderTLSConfig) DeepCopy() *ExtenderTLSConfig { + if in == nil { + return nil + } + out := new(ExtenderTLSConfig) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in FailedNodesMap) DeepCopyInto(out *FailedNodesMap) { { diff --git a/pkg/scheduler/apis/config/types.go b/pkg/scheduler/apis/config/types.go index 1c5fee16b8b..b0d36cd31b2 100644 --- a/pkg/scheduler/apis/config/types.go +++ b/pkg/scheduler/apis/config/types.go @@ -79,7 +79,8 @@ type KubeSchedulerConfiguration struct { // at least "minFeasibleNodesToFind" feasible nodes no matter what the value of this flag is. // Example: if the cluster size is 500 nodes and the value of this flag is 30, // then scheduler stops finding further feasible nodes once it finds 150 feasible ones. - // When the value is 0, default percentage (50%) of the nodes will be scored. + // When the value is 0, default percentage (5%--50% based on the size of the cluster) of the + // nodes will be scored. PercentageOfNodesToScore int32 // DEPRECATED. diff --git a/pkg/scheduler/apis/config/v1alpha1/defaults.go b/pkg/scheduler/apis/config/v1alpha1/defaults.go index e212dcf4370..5768d2334b7 100644 --- a/pkg/scheduler/apis/config/v1alpha1/defaults.go +++ b/pkg/scheduler/apis/config/v1alpha1/defaults.go @@ -81,11 +81,6 @@ func SetDefaults_KubeSchedulerConfiguration(obj *kubescedulerconfigv1alpha1.Kube obj.LeaderElection.LockObjectName = kubescedulerconfigv1alpha1.SchedulerDefaultLockObjectName } - if obj.PercentageOfNodesToScore == 0 { - // by default, stop finding feasible nodes once the number of feasible nodes is 50% of the cluster. - obj.PercentageOfNodesToScore = 50 - } - if len(obj.FailureDomains) == 0 { obj.FailureDomains = kubeletapis.DefaultFailureDomains } diff --git a/pkg/scheduler/core/BUILD b/pkg/scheduler/core/BUILD index 7df943d3f7e..00c00804cef 100644 --- a/pkg/scheduler/core/BUILD +++ b/pkg/scheduler/core/BUILD @@ -12,11 +12,11 @@ go_library( "//pkg/scheduler/algorithm:go_default_library", "//pkg/scheduler/algorithm/predicates:go_default_library", "//pkg/scheduler/api:go_default_library", - "//pkg/scheduler/cache:go_default_library", - "//pkg/scheduler/core/equivalence:go_default_library", "//pkg/scheduler/internal/cache:go_default_library", "//pkg/scheduler/internal/queue:go_default_library", "//pkg/scheduler/metrics:go_default_library", + "//pkg/scheduler/nodeinfo:go_default_library", + "//pkg/scheduler/plugins/v1alpha1:go_default_library", "//pkg/scheduler/util:go_default_library", "//pkg/scheduler/volumebinder:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library", @@ -47,10 +47,10 @@ go_test( "//pkg/scheduler/algorithm/priorities:go_default_library", "//pkg/scheduler/algorithm/priorities/util:go_default_library", "//pkg/scheduler/api:go_default_library", - "//pkg/scheduler/cache:go_default_library", - "//pkg/scheduler/core/equivalence:go_default_library", "//pkg/scheduler/internal/cache:go_default_library", "//pkg/scheduler/internal/queue:go_default_library", + "//pkg/scheduler/nodeinfo:go_default_library", + "//pkg/scheduler/plugins/v1alpha1:go_default_library", "//pkg/scheduler/testing:go_default_library", "//pkg/scheduler/util:go_default_library", "//staging/src/k8s.io/api/apps/v1:go_default_library", @@ -73,10 +73,7 @@ filegroup( filegroup( name = "all-srcs", - srcs = [ - ":package-srcs", - "//pkg/scheduler/core/equivalence:all-srcs", - ], + srcs = [":package-srcs"], tags = ["automanaged"], visibility = ["//visibility:public"], ) diff --git a/pkg/scheduler/core/equivalence/BUILD b/pkg/scheduler/core/equivalence/BUILD deleted file mode 100644 index a6ad12ff724..00000000000 --- a/pkg/scheduler/core/equivalence/BUILD +++ /dev/null @@ -1,49 +0,0 @@ -load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") - -go_library( - name = "go_default_library", - srcs = ["eqivalence.go"], - importpath = "k8s.io/kubernetes/pkg/scheduler/core/equivalence", - visibility = ["//visibility:public"], - deps = [ - "//pkg/features:go_default_library", - "//pkg/scheduler/algorithm:go_default_library", - "//pkg/scheduler/algorithm/predicates:go_default_library", - "//pkg/scheduler/cache:go_default_library", - "//pkg/scheduler/metrics:go_default_library", - "//pkg/util/hash:go_default_library", - "//staging/src/k8s.io/api/core/v1:go_default_library", - "//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library", - "//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library", - "//vendor/k8s.io/klog:go_default_library", - ], -) - -go_test( - name = "go_default_test", - srcs = ["eqivalence_test.go"], - embed = [":go_default_library"], - deps = [ - "//pkg/scheduler/algorithm:go_default_library", - "//pkg/scheduler/algorithm/predicates:go_default_library", - "//pkg/scheduler/cache:go_default_library", - "//staging/src/k8s.io/api/core/v1:go_default_library", - "//staging/src/k8s.io/apimachinery/pkg/api/resource:go_default_library", - "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], - visibility = ["//visibility:public"], -) diff --git a/pkg/scheduler/core/equivalence/eqivalence.go b/pkg/scheduler/core/equivalence/eqivalence.go deleted file mode 100644 index d776981999b..00000000000 --- a/pkg/scheduler/core/equivalence/eqivalence.go +++ /dev/null @@ -1,443 +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 equivalence defines Pod equivalence classes and the equivalence class -// cache. -package equivalence - -import ( - "fmt" - "hash/fnv" - "sync" - - "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/util/sets" - utilfeature "k8s.io/apiserver/pkg/util/feature" - "k8s.io/klog" - "k8s.io/kubernetes/pkg/features" - "k8s.io/kubernetes/pkg/scheduler/algorithm" - "k8s.io/kubernetes/pkg/scheduler/algorithm/predicates" - schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" - "k8s.io/kubernetes/pkg/scheduler/metrics" - hashutil "k8s.io/kubernetes/pkg/util/hash" -) - -// nodeMap stores a *NodeCache for each node. -type nodeMap map[string]*NodeCache - -// Cache is a thread safe map saves and reuses the output of predicate functions, -// it uses node name as key to access those cached results. -// -// Internally, results are keyed by predicate name, and "equivalence -// class". (Equivalence class is defined in the `Class` type.) Saved results -// will be reused until an appropriate invalidation function is called. -type Cache struct { - // NOTE(harry): Theoretically sync.Map has better performance in machine with 8+ CPUs, while - // the reality is lock contention in first level cache is rare. - mu sync.RWMutex - nodeToCache nodeMap - predicateIDMap map[string]int -} - -// NewCache create an empty equiv class cache. -func NewCache(predicates []string) *Cache { - predicateIDMap := make(map[string]int, len(predicates)) - for id, predicate := range predicates { - predicateIDMap[predicate] = id - } - return &Cache{ - nodeToCache: make(nodeMap), - predicateIDMap: predicateIDMap, - } -} - -// NodeCache saves and reuses the output of predicate functions. Use RunPredicate to -// get or update the cached results. An appropriate Invalidate* function should -// be called when some predicate results are no longer valid. -// -// Internally, results are keyed by predicate name, and "equivalence -// class". (Equivalence class is defined in the `Class` type.) Saved results -// will be reused until an appropriate invalidation function is called. -// -// NodeCache objects are thread safe within the context of NodeCache, -type NodeCache struct { - mu sync.RWMutex - cache predicateMap - // generation is current generation of node cache, incremented on node - // invalidation. - generation uint64 - // snapshotGeneration saves snapshot of generation of node cache. - snapshotGeneration uint64 - // predicateGenerations stores generation numbers for predicates, incremented on - // predicate invalidation. Created on first update. Use 0 if does not - // exist. - predicateGenerations []uint64 - // snapshotPredicateGenerations saves snapshot of generation numbers for predicates. - snapshotPredicateGenerations []uint64 -} - -// newNodeCache returns an empty NodeCache. -func newNodeCache(n int) *NodeCache { - return &NodeCache{ - cache: make(predicateMap, n), - predicateGenerations: make([]uint64, n), - snapshotPredicateGenerations: make([]uint64, n), - } -} - -// Snapshot snapshots current generations of cache. -// NOTE: We snapshot generations of all node caches before using it and these -// operations are serialized, we can save snapshot as member of node cache -// itself. -func (c *Cache) Snapshot() { - c.mu.RLock() - defer c.mu.RUnlock() - for _, n := range c.nodeToCache { - n.mu.Lock() - // snapshot predicate generations - copy(n.snapshotPredicateGenerations, n.predicateGenerations) - // snapshot node generation - n.snapshotGeneration = n.generation - n.mu.Unlock() - } - return -} - -// GetNodeCache returns the existing NodeCache for given node if present. Otherwise, -// it creates the NodeCache and returns it. -// The boolean flag is true if the value was loaded, false if created. -func (c *Cache) GetNodeCache(name string) (nodeCache *NodeCache, exists bool) { - c.mu.Lock() - defer c.mu.Unlock() - if nodeCache, exists = c.nodeToCache[name]; !exists { - nodeCache = newNodeCache(len(c.predicateIDMap)) - c.nodeToCache[name] = nodeCache - } - return -} - -// LoadNodeCache returns the existing NodeCache for given node, nil if not -// present. -func (c *Cache) LoadNodeCache(node string) *NodeCache { - c.mu.RLock() - defer c.mu.RUnlock() - return c.nodeToCache[node] -} - -func (c *Cache) predicateKeysToIDs(predicateKeys sets.String) []int { - predicateIDs := make([]int, 0, len(predicateKeys)) - for predicateKey := range predicateKeys { - if id, ok := c.predicateIDMap[predicateKey]; ok { - predicateIDs = append(predicateIDs, id) - } else { - klog.Errorf("predicate key %q not found", predicateKey) - } - } - return predicateIDs -} - -// InvalidatePredicates clears all cached results for the given predicates. -func (c *Cache) InvalidatePredicates(predicateKeys sets.String) { - if len(predicateKeys) == 0 { - return - } - c.mu.RLock() - defer c.mu.RUnlock() - predicateIDs := c.predicateKeysToIDs(predicateKeys) - for _, n := range c.nodeToCache { - n.invalidatePreds(predicateIDs) - } - klog.V(5).Infof("Cache invalidation: node=*,predicates=%v", predicateKeys) - -} - -// InvalidatePredicatesOnNode clears cached results for the given predicates on one node. -func (c *Cache) InvalidatePredicatesOnNode(nodeName string, predicateKeys sets.String) { - if len(predicateKeys) == 0 { - return - } - c.mu.RLock() - defer c.mu.RUnlock() - predicateIDs := c.predicateKeysToIDs(predicateKeys) - if n, ok := c.nodeToCache[nodeName]; ok { - n.invalidatePreds(predicateIDs) - } - klog.V(5).Infof("Cache invalidation: node=%s,predicates=%v", nodeName, predicateKeys) -} - -// InvalidateAllPredicatesOnNode clears all cached results for one node. -func (c *Cache) InvalidateAllPredicatesOnNode(nodeName string) { - c.mu.RLock() - defer c.mu.RUnlock() - if node, ok := c.nodeToCache[nodeName]; ok { - node.invalidate() - } - klog.V(5).Infof("Cache invalidation: node=%s,predicates=*", nodeName) -} - -// InvalidateCachedPredicateItemForPodAdd is a wrapper of -// InvalidateCachedPredicateItem for pod add case -// TODO: This does not belong with the equivalence cache implementation. -func (c *Cache) InvalidateCachedPredicateItemForPodAdd(pod *v1.Pod, nodeName string) { - // MatchInterPodAffinity: we assume scheduler can make sure newly bound pod - // will not break the existing inter pod affinity. So we does not need to - // invalidate MatchInterPodAffinity when pod added. - // - // But when a pod is deleted, existing inter pod affinity may become invalid. - // (e.g. this pod was preferred by some else, or vice versa) - // - // NOTE: assumptions above will not stand when we implemented features like - // RequiredDuringSchedulingRequiredDuringExecutioc. - - // NoDiskConflict: the newly scheduled pod fits to existing pods on this node, - // it will also fits to equivalence class of existing pods - - // GeneralPredicates: will always be affected by adding a new pod - invalidPredicates := sets.NewString(predicates.GeneralPred) - - // MaxPDVolumeCountPredicate: we check the volumes of pod to make decisioc. - for _, vol := range pod.Spec.Volumes { - if vol.PersistentVolumeClaim != nil { - invalidPredicates.Insert( - predicates.MaxEBSVolumeCountPred, - predicates.MaxGCEPDVolumeCountPred, - predicates.MaxAzureDiskVolumeCountPred) - if utilfeature.DefaultFeatureGate.Enabled(features.AttachVolumeLimit) { - invalidPredicates.Insert(predicates.MaxCSIVolumeCountPred) - } - } else { - // We do not consider CSI volumes here because CSI - // volumes can not be used inline. - if vol.AWSElasticBlockStore != nil { - invalidPredicates.Insert(predicates.MaxEBSVolumeCountPred) - } - if vol.GCEPersistentDisk != nil { - invalidPredicates.Insert(predicates.MaxGCEPDVolumeCountPred) - } - if vol.AzureDisk != nil { - invalidPredicates.Insert(predicates.MaxAzureDiskVolumeCountPred) - } - } - } - c.InvalidatePredicatesOnNode(nodeName, invalidPredicates) -} - -// Class represents a set of pods which are equivalent from the perspective of -// the scheduler. i.e. the scheduler would make the same decision for any pod -// from the same class. -type Class struct { - // Equivalence hash - hash uint64 -} - -// NewClass returns the equivalence class for a given Pod. The returned Class -// objects will be equal for two Pods in the same class. nil values should not -// be considered equal to each other. -// -// NOTE: Make sure to compare types of Class and not *Class. -// TODO(misterikkit): Return error instead of nil *Class. -func NewClass(pod *v1.Pod) *Class { - equivalencePod := getEquivalencePod(pod) - if equivalencePod != nil { - hash := fnv.New32a() - hashutil.DeepHashObject(hash, equivalencePod) - return &Class{ - hash: uint64(hash.Sum32()), - } - } - return nil -} - -// predicateMap stores resultMaps with predicate ID as the key. -type predicateMap []resultMap - -// resultMap stores PredicateResult with pod equivalence hash as the key. -type resultMap map[uint64]predicateResult - -// predicateResult stores the output of a FitPredicate. -type predicateResult struct { - Fit bool - FailReasons []algorithm.PredicateFailureReason -} - -// RunPredicate returns a cached predicate result. In case of a cache miss, the predicate will be -// run and its results cached for the next call. -// -// NOTE: RunPredicate will not update the equivalence cache if generation does not match live version. -func (n *NodeCache) RunPredicate( - pred algorithm.FitPredicate, - predicateKey string, - predicateID int, - pod *v1.Pod, - meta algorithm.PredicateMetadata, - nodeInfo *schedulercache.NodeInfo, - equivClass *Class, -) (bool, []algorithm.PredicateFailureReason, error) { - if nodeInfo == nil || nodeInfo.Node() == nil { - // This may happen during tests. - return false, []algorithm.PredicateFailureReason{}, fmt.Errorf("nodeInfo is nil or node is invalid") - } - - result, ok := n.lookupResult(pod.GetName(), nodeInfo.Node().GetName(), predicateKey, predicateID, equivClass.hash) - if ok { - return result.Fit, result.FailReasons, nil - } - fit, reasons, err := pred(pod, meta, nodeInfo) - if err != nil { - return fit, reasons, err - } - n.updateResult(pod.GetName(), predicateKey, predicateID, fit, reasons, equivClass.hash, nodeInfo) - return fit, reasons, nil -} - -// updateResult updates the cached result of a predicate. -func (n *NodeCache) updateResult( - podName, predicateKey string, - predicateID int, - fit bool, - reasons []algorithm.PredicateFailureReason, - equivalenceHash uint64, - nodeInfo *schedulercache.NodeInfo, -) { - if nodeInfo == nil || nodeInfo.Node() == nil { - // This may happen during tests. - metrics.EquivalenceCacheWrites.WithLabelValues("discarded_bad_node").Inc() - return - } - - predicateItem := predicateResult{ - Fit: fit, - FailReasons: reasons, - } - - n.mu.Lock() - defer n.mu.Unlock() - if (n.snapshotGeneration != n.generation) || (n.snapshotPredicateGenerations[predicateID] != n.predicateGenerations[predicateID]) { - // Generation of node or predicate has been updated since we last took - // a snapshot, this indicates that we received a invalidation request - // during this time. Cache may be stale, skip update. - metrics.EquivalenceCacheWrites.WithLabelValues("discarded_stale").Inc() - return - } - // If cached predicate map already exists, just update the predicate by key - if predicates := n.cache[predicateID]; predicates != nil { - // maps in golang are references, no need to add them back - predicates[equivalenceHash] = predicateItem - } else { - n.cache[predicateID] = - resultMap{ - equivalenceHash: predicateItem, - } - } - n.predicateGenerations[predicateID]++ - - klog.V(5).Infof("Cache update: node=%s, predicate=%s,pod=%s,value=%v", - nodeInfo.Node().Name, predicateKey, podName, predicateItem) -} - -// lookupResult returns cached predicate results and a bool saying whether a -// cache entry was found. -func (n *NodeCache) lookupResult( - podName, nodeName, predicateKey string, - predicateID int, - equivalenceHash uint64, -) (value predicateResult, ok bool) { - n.mu.RLock() - defer n.mu.RUnlock() - value, ok = n.cache[predicateID][equivalenceHash] - if ok { - metrics.EquivalenceCacheHits.Inc() - } else { - metrics.EquivalenceCacheMisses.Inc() - } - return value, ok -} - -// invalidatePreds deletes cached predicates by given IDs. -func (n *NodeCache) invalidatePreds(predicateIDs []int) { - n.mu.Lock() - defer n.mu.Unlock() - for _, predicateID := range predicateIDs { - n.cache[predicateID] = nil - n.predicateGenerations[predicateID]++ - } -} - -// invalidate invalidates node cache. -func (n *NodeCache) invalidate() { - n.mu.Lock() - defer n.mu.Unlock() - n.cache = make(predicateMap, len(n.cache)) - n.generation++ -} - -// equivalencePod is the set of pod attributes which must match for two pods to -// be considered equivalent for scheduling purposes. For correctness, this must -// include any Pod field which is used by a FitPredicate. -// -// NOTE: For equivalence hash to be formally correct, lists and maps in the -// equivalencePod should be normalized. (e.g. by sorting them) However, the vast -// majority of equivalent pod classes are expected to be created from a single -// pod template, so they will all have the same ordering. -type equivalencePod struct { - Namespace *string - Labels map[string]string - Affinity *v1.Affinity - Containers []v1.Container // See note about ordering - InitContainers []v1.Container // See note about ordering - NodeName *string - NodeSelector map[string]string - Tolerations []v1.Toleration - Volumes []v1.Volume // See note about ordering -} - -// getEquivalencePod returns a normalized representation of a pod so that two -// "equivalent" pods will hash to the same value. -func getEquivalencePod(pod *v1.Pod) *equivalencePod { - ep := &equivalencePod{ - Namespace: &pod.Namespace, - Labels: pod.Labels, - Affinity: pod.Spec.Affinity, - Containers: pod.Spec.Containers, - InitContainers: pod.Spec.InitContainers, - NodeName: &pod.Spec.NodeName, - NodeSelector: pod.Spec.NodeSelector, - Tolerations: pod.Spec.Tolerations, - Volumes: pod.Spec.Volumes, - } - // DeepHashObject considers nil and empty slices to be different. Normalize them. - if len(ep.Containers) == 0 { - ep.Containers = nil - } - if len(ep.InitContainers) == 0 { - ep.InitContainers = nil - } - if len(ep.Tolerations) == 0 { - ep.Tolerations = nil - } - if len(ep.Volumes) == 0 { - ep.Volumes = nil - } - // Normalize empty maps also. - if len(ep.Labels) == 0 { - ep.Labels = nil - } - if len(ep.NodeSelector) == 0 { - ep.NodeSelector = nil - } - // TODO(misterikkit): Also normalize nested maps and slices. - return ep -} diff --git a/pkg/scheduler/core/equivalence/eqivalence_test.go b/pkg/scheduler/core/equivalence/eqivalence_test.go deleted file mode 100644 index f0f70b27b54..00000000000 --- a/pkg/scheduler/core/equivalence/eqivalence_test.go +++ /dev/null @@ -1,803 +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 equivalence - -import ( - "errors" - "reflect" - "testing" - - "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/api/resource" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/util/sets" - "k8s.io/kubernetes/pkg/scheduler/algorithm" - "k8s.io/kubernetes/pkg/scheduler/algorithm/predicates" - schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" -) - -// makeBasicPod returns a Pod object with many of the fields populated. -func makeBasicPod(name string) *v1.Pod { - isController := true - return &v1.Pod{ - ObjectMeta: metav1.ObjectMeta{ - Name: name, - Namespace: "test-ns", - Labels: map[string]string{"app": "web", "env": "prod"}, - OwnerReferences: []metav1.OwnerReference{ - { - APIVersion: "v1", - Kind: "ReplicationController", - Name: "rc", - UID: "123", - Controller: &isController, - }, - }, - }, - Spec: v1.PodSpec{ - Affinity: &v1.Affinity{ - NodeAffinity: &v1.NodeAffinity{ - RequiredDuringSchedulingIgnoredDuringExecution: &v1.NodeSelector{ - NodeSelectorTerms: []v1.NodeSelectorTerm{ - { - MatchExpressions: []v1.NodeSelectorRequirement{ - { - Key: "failure-domain.beta.kubernetes.io/zone", - Operator: "Exists", - }, - }, - }, - }, - }, - }, - PodAffinity: &v1.PodAffinity{ - RequiredDuringSchedulingIgnoredDuringExecution: []v1.PodAffinityTerm{ - { - LabelSelector: &metav1.LabelSelector{ - MatchLabels: map[string]string{"app": "db"}}, - TopologyKey: "kubernetes.io/hostname", - }, - }, - }, - PodAntiAffinity: &v1.PodAntiAffinity{ - RequiredDuringSchedulingIgnoredDuringExecution: []v1.PodAffinityTerm{ - { - LabelSelector: &metav1.LabelSelector{ - MatchLabels: map[string]string{"app": "web"}}, - TopologyKey: "kubernetes.io/hostname", - }, - }, - }, - }, - InitContainers: []v1.Container{ - { - Name: "init-pause", - Image: "gcr.io/google_containers/pause", - Resources: v1.ResourceRequirements{ - Limits: v1.ResourceList{ - "cpu": resource.MustParse("1"), - "mem": resource.MustParse("100Mi"), - }, - }, - }, - }, - Containers: []v1.Container{ - { - Name: "pause", - Image: "gcr.io/google_containers/pause", - Resources: v1.ResourceRequirements{ - Limits: v1.ResourceList{ - "cpu": resource.MustParse("1"), - "mem": resource.MustParse("100Mi"), - }, - }, - VolumeMounts: []v1.VolumeMount{ - { - Name: "nfs", - MountPath: "/srv/data", - }, - }, - }, - }, - NodeSelector: map[string]string{"node-type": "awesome"}, - Tolerations: []v1.Toleration{ - { - Effect: "NoSchedule", - Key: "experimental", - Operator: "Exists", - }, - }, - Volumes: []v1.Volume{ - { - VolumeSource: v1.VolumeSource{ - PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{ - ClaimName: "someEBSVol1", - }, - }, - }, - { - VolumeSource: v1.VolumeSource{ - PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{ - ClaimName: "someEBSVol2", - }, - }, - }, - { - Name: "nfs", - VolumeSource: v1.VolumeSource{ - NFS: &v1.NFSVolumeSource{ - Server: "nfs.corp.example.com", - }, - }, - }, - }, - }, - } -} - -type predicateItemType struct { - fit bool - reasons []algorithm.PredicateFailureReason -} - -// mockPredicate provides an algorithm.FitPredicate with pre-set return values. -type mockPredicate struct { - fit bool - reasons []algorithm.PredicateFailureReason - err error - callCount int -} - -func (p *mockPredicate) predicate(*v1.Pod, algorithm.PredicateMetadata, *schedulercache.NodeInfo) (bool, []algorithm.PredicateFailureReason, error) { - p.callCount++ - return p.fit, p.reasons, p.err -} - -func TestRunPredicate(t *testing.T) { - tests := []struct { - name string - pred mockPredicate - expectFit, expectCacheHit, expectCacheWrite bool - expectedReasons []algorithm.PredicateFailureReason - expectedError string - }{ - { - name: "pod fits/cache hit", - pred: mockPredicate{}, - expectFit: true, - expectCacheHit: true, - expectCacheWrite: false, - }, - { - name: "pod fits/cache miss", - pred: mockPredicate{fit: true}, - expectFit: true, - expectCacheHit: false, - expectCacheWrite: true, - }, - { - name: "pod doesn't fit/cache miss", - pred: mockPredicate{reasons: []algorithm.PredicateFailureReason{predicates.ErrFakePredicate}}, - expectFit: false, - expectCacheHit: false, - expectCacheWrite: true, - expectedReasons: []algorithm.PredicateFailureReason{predicates.ErrFakePredicate}, - }, - { - name: "pod doesn't fit/cache hit", - pred: mockPredicate{}, - expectFit: false, - expectCacheHit: true, - expectCacheWrite: false, - expectedReasons: []algorithm.PredicateFailureReason{predicates.ErrFakePredicate}, - }, - { - name: "predicate error", - pred: mockPredicate{err: errors.New("This is expected")}, - expectFit: false, - expectCacheHit: false, - expectCacheWrite: false, - expectedError: "This is expected", - }, - } - - predicatesOrdering := []string{"testPredicate"} - predicateID := 0 - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - node := schedulercache.NewNodeInfo() - testNode := &v1.Node{ObjectMeta: metav1.ObjectMeta{Name: "n1"}} - node.SetNode(testNode) - pod := &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "p1"}} - meta := algorithm.EmptyPredicateMetadataProducer(nil, nil) - - // Initialize and populate equivalence class cache. - ecache := NewCache(predicatesOrdering) - ecache.Snapshot() - nodeCache, _ := ecache.GetNodeCache(testNode.Name) - - equivClass := NewClass(pod) - if test.expectCacheHit { - nodeCache.updateResult(pod.Name, "testPredicate", predicateID, test.expectFit, test.expectedReasons, equivClass.hash, node) - } - - fit, reasons, err := nodeCache.RunPredicate(test.pred.predicate, "testPredicate", predicateID, pod, meta, node, equivClass) - - if err != nil { - if err.Error() != test.expectedError { - t.Errorf("Expected error %v but got %v", test.expectedError, err) - } - } else if len(test.expectedError) > 0 { - t.Errorf("Expected error %v but got nil", test.expectedError) - } - if fit && !test.expectFit { - t.Errorf("pod should not fit") - } - if !fit && test.expectFit { - t.Errorf("pod should fit") - } - if len(reasons) != len(test.expectedReasons) { - t.Errorf("Expected failures: %v but got %v", test.expectedReasons, reasons) - } else { - for i, reason := range reasons { - if reason != test.expectedReasons[i] { - t.Errorf("Expected failures: %v but got %v", test.expectedReasons, reasons) - break - } - } - } - if test.expectCacheHit && test.pred.callCount != 0 { - t.Errorf("Predicate should not be called") - } - if !test.expectCacheHit && test.pred.callCount == 0 { - t.Errorf("Predicate should be called") - } - _, ok := nodeCache.lookupResult(pod.Name, node.Node().Name, "testPredicate", predicateID, equivClass.hash) - if !ok && test.expectCacheWrite { - t.Errorf("Cache write should happen") - } - if !test.expectCacheHit && test.expectCacheWrite && !ok { - t.Errorf("Cache write should happen") - } - if !test.expectCacheHit && !test.expectCacheWrite && ok { - t.Errorf("Cache write should not happen") - } - }) - } -} - -func TestUpdateResult(t *testing.T) { - predicatesOrdering := []string{"GeneralPredicates"} - tests := []struct { - name string - pod string - predicateKey string - predicateID int - nodeName string - fit bool - reasons []algorithm.PredicateFailureReason - equivalenceHash uint64 - expectPredicateMap bool - expectCacheItem predicateResult - }{ - { - name: "test 1", - pod: "testPod", - predicateKey: "GeneralPredicates", - predicateID: 0, - nodeName: "node1", - fit: true, - equivalenceHash: 123, - expectPredicateMap: false, - expectCacheItem: predicateResult{ - Fit: true, - }, - }, - { - name: "test 2", - pod: "testPod", - predicateKey: "GeneralPredicates", - predicateID: 0, - nodeName: "node2", - fit: false, - equivalenceHash: 123, - expectPredicateMap: true, - expectCacheItem: predicateResult{ - Fit: false, - }, - }, - } - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - node := schedulercache.NewNodeInfo() - testNode := &v1.Node{ObjectMeta: metav1.ObjectMeta{Name: test.nodeName}} - node.SetNode(testNode) - - // Initialize and populate equivalence class cache. - ecache := NewCache(predicatesOrdering) - nodeCache, _ := ecache.GetNodeCache(testNode.Name) - - if test.expectPredicateMap { - predicateItem := predicateResult{ - Fit: true, - } - nodeCache.cache[test.predicateID] = - resultMap{ - test.equivalenceHash: predicateItem, - } - } - - nodeCache.updateResult( - test.pod, - test.predicateKey, - test.predicateID, - test.fit, - test.reasons, - test.equivalenceHash, - node, - ) - - cachedMapItem := nodeCache.cache[test.predicateID] - if cachedMapItem == nil { - t.Errorf("can't find expected cache item: %v", test.expectCacheItem) - } else { - if !reflect.DeepEqual(cachedMapItem[test.equivalenceHash], test.expectCacheItem) { - t.Errorf("expected cached item: %v, but got: %v", - test.expectCacheItem, cachedMapItem[test.equivalenceHash]) - } - } - }) - } -} - -// slicesEqual wraps reflect.DeepEqual, but returns true when comparing nil and empty slice. -func slicesEqual(a, b []algorithm.PredicateFailureReason) bool { - if len(a) == 0 && len(b) == 0 { - return true - } - return reflect.DeepEqual(a, b) -} - -func TestLookupResult(t *testing.T) { - predicatesOrdering := []string{"GeneralPredicates"} - tests := []struct { - name string - podName string - nodeName string - predicateKey string - predicateID int - equivalenceHashForUpdatePredicate uint64 - equivalenceHashForCalPredicate uint64 - cachedItem predicateItemType - expectedPredicateKeyMiss bool - expectedEquivalenceHashMiss bool - expectedPredicateItem predicateItemType - }{ - { - name: "test 1", - podName: "testPod", - nodeName: "node1", - equivalenceHashForUpdatePredicate: 123, - equivalenceHashForCalPredicate: 123, - predicateKey: "GeneralPredicates", - predicateID: 0, - cachedItem: predicateItemType{ - fit: false, - reasons: []algorithm.PredicateFailureReason{predicates.ErrPodNotFitsHostPorts}, - }, - expectedPredicateKeyMiss: true, - expectedPredicateItem: predicateItemType{ - fit: false, - reasons: []algorithm.PredicateFailureReason{}, - }, - }, - { - name: "test 2", - podName: "testPod", - nodeName: "node2", - equivalenceHashForUpdatePredicate: 123, - equivalenceHashForCalPredicate: 123, - predicateKey: "GeneralPredicates", - predicateID: 0, - cachedItem: predicateItemType{ - fit: true, - }, - expectedPredicateKeyMiss: false, - expectedPredicateItem: predicateItemType{ - fit: true, - reasons: []algorithm.PredicateFailureReason{}, - }, - }, - { - name: "test 3", - podName: "testPod", - nodeName: "node3", - equivalenceHashForUpdatePredicate: 123, - equivalenceHashForCalPredicate: 123, - predicateKey: "GeneralPredicates", - predicateID: 0, - cachedItem: predicateItemType{ - fit: false, - reasons: []algorithm.PredicateFailureReason{predicates.ErrPodNotFitsHostPorts}, - }, - expectedPredicateKeyMiss: false, - expectedPredicateItem: predicateItemType{ - fit: false, - reasons: []algorithm.PredicateFailureReason{predicates.ErrPodNotFitsHostPorts}, - }, - }, - { - name: "test 4", - podName: "testPod", - nodeName: "node4", - equivalenceHashForUpdatePredicate: 123, - equivalenceHashForCalPredicate: 456, - predicateKey: "GeneralPredicates", - predicateID: 0, - cachedItem: predicateItemType{ - fit: false, - reasons: []algorithm.PredicateFailureReason{predicates.ErrPodNotFitsHostPorts}, - }, - expectedPredicateKeyMiss: false, - expectedEquivalenceHashMiss: true, - expectedPredicateItem: predicateItemType{ - fit: false, - reasons: []algorithm.PredicateFailureReason{}, - }, - }, - } - - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - testNode := &v1.Node{ObjectMeta: metav1.ObjectMeta{Name: test.nodeName}} - - // Initialize and populate equivalence class cache. - ecache := NewCache(predicatesOrdering) - nodeCache, _ := ecache.GetNodeCache(testNode.Name) - - node := schedulercache.NewNodeInfo() - node.SetNode(testNode) - // set cached item to equivalence cache - nodeCache.updateResult( - test.podName, - test.predicateKey, - test.predicateID, - test.cachedItem.fit, - test.cachedItem.reasons, - test.equivalenceHashForUpdatePredicate, - node, - ) - // if we want to do invalid, invalid the cached item - if test.expectedPredicateKeyMiss { - predicateKeys := sets.NewString() - predicateKeys.Insert(test.predicateKey) - ecache.InvalidatePredicatesOnNode(test.nodeName, predicateKeys) - } - // calculate predicate with equivalence cache - result, ok := nodeCache.lookupResult(test.podName, - test.nodeName, - test.predicateKey, - test.predicateID, - test.equivalenceHashForCalPredicate, - ) - fit, reasons := result.Fit, result.FailReasons - // returned invalid should match expectedPredicateKeyMiss or expectedEquivalenceHashMiss - if test.equivalenceHashForUpdatePredicate != test.equivalenceHashForCalPredicate { - if ok && test.expectedEquivalenceHashMiss { - t.Errorf("Failed: %s, expected (equivalence hash) cache miss", test.name) - } - if !ok && !test.expectedEquivalenceHashMiss { - t.Errorf("Failed: %s, expected (equivalence hash) cache hit", test.name) - } - } else { - if ok && test.expectedPredicateKeyMiss { - t.Errorf("Failed: %s, expected (predicate key) cache miss", test.name) - } - if !ok && !test.expectedPredicateKeyMiss { - t.Errorf("Failed: %s, expected (predicate key) cache hit", test.name) - } - } - // returned predicate result should match expected predicate item - if fit != test.expectedPredicateItem.fit { - t.Errorf("Failed: %s, expected fit: %v, but got: %v", test.name, test.cachedItem.fit, fit) - } - if !slicesEqual(reasons, test.expectedPredicateItem.reasons) { - t.Errorf("Failed: %s, expected reasons: %v, but got: %v", - test.name, test.expectedPredicateItem.reasons, reasons) - } - }) - } -} - -func TestGetEquivalenceHash(t *testing.T) { - pod1 := makeBasicPod("pod1") - pod2 := makeBasicPod("pod2") - - pod3 := makeBasicPod("pod3") - pod3.Spec.Volumes = []v1.Volume{ - { - VolumeSource: v1.VolumeSource{ - PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{ - ClaimName: "someEBSVol111", - }, - }, - }, - } - - pod4 := makeBasicPod("pod4") - pod4.Spec.Volumes = []v1.Volume{ - { - VolumeSource: v1.VolumeSource{ - PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{ - ClaimName: "someEBSVol222", - }, - }, - }, - } - - pod5 := makeBasicPod("pod5") - pod5.Spec.Volumes = []v1.Volume{} - - pod6 := makeBasicPod("pod6") - pod6.Spec.Volumes = nil - - pod7 := makeBasicPod("pod7") - pod7.Spec.NodeSelector = nil - - pod8 := makeBasicPod("pod8") - pod8.Spec.NodeSelector = make(map[string]string) - - type podInfo struct { - pod *v1.Pod - hashIsValid bool - } - - tests := []struct { - name string - podInfoList []podInfo - isEquivalent bool - }{ - { - name: "pods with everything the same except name", - podInfoList: []podInfo{ - {pod: pod1, hashIsValid: true}, - {pod: pod2, hashIsValid: true}, - }, - isEquivalent: true, - }, - { - name: "pods that only differ in their PVC volume sources", - podInfoList: []podInfo{ - {pod: pod3, hashIsValid: true}, - {pod: pod4, hashIsValid: true}, - }, - isEquivalent: false, - }, - { - name: "pods that have no volumes, but one uses nil and one uses an empty slice", - podInfoList: []podInfo{ - {pod: pod5, hashIsValid: true}, - {pod: pod6, hashIsValid: true}, - }, - isEquivalent: true, - }, - { - name: "pods that have no NodeSelector, but one uses nil and one uses an empty map", - podInfoList: []podInfo{ - {pod: pod7, hashIsValid: true}, - {pod: pod8, hashIsValid: true}, - }, - isEquivalent: true, - }, - } - - var ( - targetPodInfo podInfo - targetHash uint64 - ) - - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - for i, podInfo := range test.podInfoList { - testPod := podInfo.pod - eclassInfo := NewClass(testPod) - if eclassInfo == nil && podInfo.hashIsValid { - t.Errorf("Failed: pod %v is expected to have valid hash", testPod) - } - - if eclassInfo != nil { - // NOTE(harry): the first element will be used as target so - // this logic can't verify more than two inequivalent pods - if i == 0 { - targetHash = eclassInfo.hash - targetPodInfo = podInfo - } else { - if targetHash != eclassInfo.hash { - if test.isEquivalent { - t.Errorf("Failed: pod: %v is expected to be equivalent to: %v", testPod, targetPodInfo.pod) - } - } - } - } - } - }) - } -} - -func TestInvalidateCachedPredicateItemOfAllNodes(t *testing.T) { - testPredicate := "GeneralPredicates" - testPredicateID := 0 - predicatesOrdering := []string{testPredicate} - // tests is used to initialize all nodes - tests := []struct { - name string - podName string - nodeName string - equivalenceHashForUpdatePredicate uint64 - cachedItem predicateItemType - }{ - { - name: "hash predicate 123 not fits host ports", - podName: "testPod", - nodeName: "node1", - equivalenceHashForUpdatePredicate: 123, - cachedItem: predicateItemType{ - fit: false, - reasons: []algorithm.PredicateFailureReason{ - predicates.ErrPodNotFitsHostPorts, - }, - }, - }, - { - name: "hash predicate 456 not fits host ports", - podName: "testPod", - nodeName: "node2", - equivalenceHashForUpdatePredicate: 456, - cachedItem: predicateItemType{ - fit: false, - reasons: []algorithm.PredicateFailureReason{ - predicates.ErrPodNotFitsHostPorts, - }, - }, - }, - { - name: "hash predicate 123 fits", - podName: "testPod", - nodeName: "node3", - equivalenceHashForUpdatePredicate: 123, - cachedItem: predicateItemType{ - fit: true, - }, - }, - } - ecache := NewCache(predicatesOrdering) - - for _, test := range tests { - node := schedulercache.NewNodeInfo() - testNode := &v1.Node{ObjectMeta: metav1.ObjectMeta{Name: test.nodeName}} - node.SetNode(testNode) - - nodeCache, _ := ecache.GetNodeCache(testNode.Name) - // set cached item to equivalence cache - nodeCache.updateResult( - test.podName, - testPredicate, - testPredicateID, - test.cachedItem.fit, - test.cachedItem.reasons, - test.equivalenceHashForUpdatePredicate, - node, - ) - } - - // invalidate cached predicate for all nodes - ecache.InvalidatePredicates(sets.NewString(testPredicate)) - - // there should be no cached predicate any more - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - if nodeCache, exist := ecache.nodeToCache[test.nodeName]; exist { - if cache := nodeCache.cache[testPredicateID]; cache != nil { - t.Errorf("Failed: cached item for predicate key: %v on node: %v should be invalidated", - testPredicate, test.nodeName) - } - } - }) - } -} - -func TestInvalidateAllCachedPredicateItemOfNode(t *testing.T) { - testPredicate := "GeneralPredicates" - testPredicateID := 0 - predicatesOrdering := []string{testPredicate} - // tests is used to initialize all nodes - tests := []struct { - name string - podName string - nodeName string - equivalenceHashForUpdatePredicate uint64 - cachedItem predicateItemType - }{ - { - name: "hash predicate 123 not fits host ports", - podName: "testPod", - nodeName: "node1", - equivalenceHashForUpdatePredicate: 123, - cachedItem: predicateItemType{ - fit: false, - reasons: []algorithm.PredicateFailureReason{predicates.ErrPodNotFitsHostPorts}, - }, - }, - { - name: "hash predicate 456 not fits host ports", - podName: "testPod", - nodeName: "node2", - equivalenceHashForUpdatePredicate: 456, - cachedItem: predicateItemType{ - fit: false, - reasons: []algorithm.PredicateFailureReason{predicates.ErrPodNotFitsHostPorts}, - }, - }, - { - name: "hash predicate 123 fits host ports", - podName: "testPod", - nodeName: "node3", - equivalenceHashForUpdatePredicate: 123, - cachedItem: predicateItemType{ - fit: true, - }, - }, - } - ecache := NewCache(predicatesOrdering) - - for _, test := range tests { - node := schedulercache.NewNodeInfo() - testNode := &v1.Node{ObjectMeta: metav1.ObjectMeta{Name: test.nodeName}} - node.SetNode(testNode) - - nodeCache, _ := ecache.GetNodeCache(testNode.Name) - // set cached item to equivalence cache - nodeCache.updateResult( - test.podName, - testPredicate, - testPredicateID, - test.cachedItem.fit, - test.cachedItem.reasons, - test.equivalenceHashForUpdatePredicate, - node, - ) - } - - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - oldNodeCache, _ := ecache.GetNodeCache(test.nodeName) - oldGeneration := oldNodeCache.generation - // invalidate cached predicate for all nodes - ecache.InvalidateAllPredicatesOnNode(test.nodeName) - if n, _ := ecache.GetNodeCache(test.nodeName); oldGeneration == n.generation { - t.Errorf("Failed: cached item for node: %v should be invalidated", test.nodeName) - } - }) - } -} - -func BenchmarkEquivalenceHash(b *testing.B) { - pod := makeBasicPod("test") - for i := 0; i < b.N; i++ { - getEquivalencePod(pod) - } -} diff --git a/pkg/scheduler/core/extender.go b/pkg/scheduler/core/extender.go index 9053a2e4ea2..d3830d047a4 100644 --- a/pkg/scheduler/core/extender.go +++ b/pkg/scheduler/core/extender.go @@ -30,7 +30,7 @@ import ( restclient "k8s.io/client-go/rest" "k8s.io/kubernetes/pkg/scheduler/algorithm" schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" - schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" + schedulernodeinfo "k8s.io/kubernetes/pkg/scheduler/nodeinfo" ) const ( @@ -55,7 +55,14 @@ type HTTPExtender struct { func makeTransport(config *schedulerapi.ExtenderConfig) (http.RoundTripper, error) { var cfg restclient.Config if config.TLSConfig != nil { - cfg.TLSClientConfig = *config.TLSConfig + cfg.TLSClientConfig.Insecure = config.TLSConfig.Insecure + cfg.TLSClientConfig.ServerName = config.TLSConfig.ServerName + cfg.TLSClientConfig.CertFile = config.TLSConfig.CertFile + cfg.TLSClientConfig.KeyFile = config.TLSConfig.KeyFile + cfg.TLSClientConfig.CAFile = config.TLSConfig.CAFile + cfg.TLSClientConfig.CertData = config.TLSConfig.CertData + cfg.TLSClientConfig.KeyData = config.TLSConfig.KeyData + cfg.TLSClientConfig.CAData = config.TLSConfig.CAData } if config.EnableHTTPS { hasCA := len(cfg.CAFile) > 0 || len(cfg.CAData) > 0 @@ -128,7 +135,7 @@ func (h *HTTPExtender) SupportsPreemption() bool { func (h *HTTPExtender) ProcessPreemption( pod *v1.Pod, nodeToVictims map[*v1.Node]*schedulerapi.Victims, - nodeNameToInfo map[string]*schedulercache.NodeInfo, + nodeNameToInfo map[string]*schedulernodeinfo.NodeInfo, ) (map[*v1.Node]*schedulerapi.Victims, error) { var ( result schedulerapi.ExtenderPreemptionResult @@ -172,7 +179,7 @@ func (h *HTTPExtender) ProcessPreemption( // such as UIDs and names, to object pointers. func (h *HTTPExtender) convertToNodeToVictims( nodeNameToMetaVictims map[string]*schedulerapi.MetaVictims, - nodeNameToInfo map[string]*schedulercache.NodeInfo, + nodeNameToInfo map[string]*schedulernodeinfo.NodeInfo, ) (map[*v1.Node]*schedulerapi.Victims, error) { nodeToVictims := map[*v1.Node]*schedulerapi.Victims{} for nodeName, metaVictims := range nodeNameToMetaVictims { @@ -198,8 +205,8 @@ func (h *HTTPExtender) convertToNodeToVictims( func (h *HTTPExtender) convertPodUIDToPod( metaPod *schedulerapi.MetaPod, nodeName string, - nodeNameToInfo map[string]*schedulercache.NodeInfo) (*v1.Pod, error) { - var nodeInfo *schedulercache.NodeInfo + nodeNameToInfo map[string]*schedulernodeinfo.NodeInfo) (*v1.Pod, error) { + var nodeInfo *schedulernodeinfo.NodeInfo if nodeInfo, ok := nodeNameToInfo[nodeName]; ok { for _, pod := range nodeInfo.Pods() { if string(pod.UID) == metaPod.UID { @@ -250,7 +257,7 @@ func convertToNodeNameToVictims( // the list of failed nodes and failure reasons. func (h *HTTPExtender) Filter( pod *v1.Pod, - nodes []*v1.Node, nodeNameToInfo map[string]*schedulercache.NodeInfo, + nodes []*v1.Node, nodeNameToInfo map[string]*schedulernodeinfo.NodeInfo, ) ([]*v1.Node, schedulerapi.FailedNodesMap, error) { var ( result schedulerapi.ExtenderFilterResult diff --git a/pkg/scheduler/core/extender_test.go b/pkg/scheduler/core/extender_test.go index e71f8805d67..a4c1efed632 100644 --- a/pkg/scheduler/core/extender_test.go +++ b/pkg/scheduler/core/extender_test.go @@ -18,6 +18,7 @@ package core import ( "fmt" + "reflect" "testing" "time" @@ -25,10 +26,11 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/wait" "k8s.io/kubernetes/pkg/scheduler/algorithm" + "k8s.io/kubernetes/pkg/scheduler/algorithm/predicates" schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" - schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" schedulerinternalcache "k8s.io/kubernetes/pkg/scheduler/internal/cache" internalqueue "k8s.io/kubernetes/pkg/scheduler/internal/queue" + schedulernodeinfo "k8s.io/kubernetes/pkg/scheduler/nodeinfo" schedulertesting "k8s.io/kubernetes/pkg/scheduler/testing" "k8s.io/kubernetes/pkg/scheduler/util" ) @@ -95,7 +97,7 @@ func machine2PrioritizerExtender(pod *v1.Pod, nodes []*v1.Node) (*schedulerapi.H return &result, nil } -func machine2Prioritizer(_ *v1.Pod, nodeNameToInfo map[string]*schedulercache.NodeInfo, nodes []*v1.Node) (schedulerapi.HostPriorityList, error) { +func machine2Prioritizer(_ *v1.Pod, nodeNameToInfo map[string]*schedulernodeinfo.NodeInfo, nodes []*v1.Node) (schedulerapi.HostPriorityList, error) { result := []schedulerapi.HostPriority{} for _, node := range nodes { score := 1 @@ -117,7 +119,7 @@ type FakeExtender struct { ignorable bool // Cached node information for fake extender - cachedNodeNameToInfo map[string]*schedulercache.NodeInfo + cachedNodeNameToInfo map[string]*schedulernodeinfo.NodeInfo } func (f *FakeExtender) Name() string { @@ -136,7 +138,7 @@ func (f *FakeExtender) SupportsPreemption() bool { func (f *FakeExtender) ProcessPreemption( pod *v1.Pod, nodeToVictims map[*v1.Node]*schedulerapi.Victims, - nodeNameToInfo map[string]*schedulercache.NodeInfo, + nodeNameToInfo map[string]*schedulernodeinfo.NodeInfo, ) (map[*v1.Node]*schedulerapi.Victims, error) { nodeToVictimsCopy := map[*v1.Node]*schedulerapi.Victims{} // We don't want to change the original nodeToVictims @@ -175,7 +177,7 @@ func (f *FakeExtender) ProcessPreemption( func (f *FakeExtender) selectVictimsOnNodeByExtender( pod *v1.Pod, node *v1.Node, - nodeNameToInfo map[string]*schedulercache.NodeInfo, + nodeNameToInfo map[string]*schedulernodeinfo.NodeInfo, ) ([]*v1.Pod, int, bool, error) { // If a extender support preemption but have no cached node info, let's run filter to make sure // default scheduler's decision still stand with given pod and node. @@ -264,7 +266,7 @@ func (f *FakeExtender) runPredicate(pod *v1.Pod, node *v1.Node) (bool, error) { return fits, nil } -func (f *FakeExtender) Filter(pod *v1.Pod, nodes []*v1.Node, nodeNameToInfo map[string]*schedulercache.NodeInfo) ([]*v1.Node, schedulerapi.FailedNodesMap, error) { +func (f *FakeExtender) Filter(pod *v1.Pod, nodes []*v1.Node, nodeNameToInfo map[string]*schedulernodeinfo.NodeInfo) ([]*v1.Node, schedulerapi.FailedNodesMap, error) { filtered := []*v1.Node{} failedNodesMap := schedulerapi.FailedNodesMap{} for _, node := range nodes { @@ -336,16 +338,16 @@ var _ algorithm.SchedulerExtender = &FakeExtender{} func TestGenericSchedulerWithExtenders(t *testing.T) { tests := []struct { - name string - predicates map[string]algorithm.FitPredicate - prioritizers []algorithm.PriorityConfig - extenders []FakeExtender - nodes []string - expectedHost string - expectsErr bool + name string + predicates map[string]predicates.FitPredicate + prioritizers []algorithm.PriorityConfig + extenders []FakeExtender + nodes []string + expectedResult ScheduleResult + expectsErr bool }{ { - predicates: map[string]algorithm.FitPredicate{"true": truePredicate}, + predicates: map[string]predicates.FitPredicate{"true": truePredicate}, prioritizers: []algorithm.PriorityConfig{{Map: EqualPriorityMap, Weight: 1}}, extenders: []FakeExtender{ { @@ -360,7 +362,7 @@ func TestGenericSchedulerWithExtenders(t *testing.T) { name: "test 1", }, { - predicates: map[string]algorithm.FitPredicate{"true": truePredicate}, + predicates: map[string]predicates.FitPredicate{"true": truePredicate}, prioritizers: []algorithm.PriorityConfig{{Map: EqualPriorityMap, Weight: 1}}, extenders: []FakeExtender{ { @@ -375,7 +377,7 @@ func TestGenericSchedulerWithExtenders(t *testing.T) { name: "test 2", }, { - predicates: map[string]algorithm.FitPredicate{"true": truePredicate}, + predicates: map[string]predicates.FitPredicate{"true": truePredicate}, prioritizers: []algorithm.PriorityConfig{{Map: EqualPriorityMap, Weight: 1}}, extenders: []FakeExtender{ { @@ -385,12 +387,16 @@ func TestGenericSchedulerWithExtenders(t *testing.T) { predicates: []fitPredicate{machine1PredicateExtender}, }, }, - nodes: []string{"machine1", "machine2"}, - expectedHost: "machine1", - name: "test 3", + nodes: []string{"machine1", "machine2"}, + expectedResult: ScheduleResult{ + SuggestedHost: "machine1", + EvaluatedNodes: 2, + FeasibleNodes: 1, + }, + name: "test 3", }, { - predicates: map[string]algorithm.FitPredicate{"true": truePredicate}, + predicates: map[string]predicates.FitPredicate{"true": truePredicate}, prioritizers: []algorithm.PriorityConfig{{Map: EqualPriorityMap, Weight: 1}}, extenders: []FakeExtender{ { @@ -405,7 +411,7 @@ func TestGenericSchedulerWithExtenders(t *testing.T) { name: "test 4", }, { - predicates: map[string]algorithm.FitPredicate{"true": truePredicate}, + predicates: map[string]predicates.FitPredicate{"true": truePredicate}, prioritizers: []algorithm.PriorityConfig{{Map: EqualPriorityMap, Weight: 1}}, extenders: []FakeExtender{ { @@ -414,12 +420,16 @@ func TestGenericSchedulerWithExtenders(t *testing.T) { weight: 1, }, }, - nodes: []string{"machine1"}, - expectedHost: "machine1", - name: "test 5", + nodes: []string{"machine1"}, + expectedResult: ScheduleResult{ + SuggestedHost: "machine1", + EvaluatedNodes: 1, + FeasibleNodes: 1, + }, + name: "test 5", }, { - predicates: map[string]algorithm.FitPredicate{"true": truePredicate}, + predicates: map[string]predicates.FitPredicate{"true": truePredicate}, prioritizers: []algorithm.PriorityConfig{{Map: EqualPriorityMap, Weight: 1}}, extenders: []FakeExtender{ { @@ -433,12 +443,16 @@ func TestGenericSchedulerWithExtenders(t *testing.T) { weight: 5, }, }, - nodes: []string{"machine1", "machine2"}, - expectedHost: "machine2", - name: "test 6", + nodes: []string{"machine1", "machine2"}, + expectedResult: ScheduleResult{ + SuggestedHost: "machine2", + EvaluatedNodes: 2, + FeasibleNodes: 2, + }, + name: "test 6", }, { - predicates: map[string]algorithm.FitPredicate{"true": truePredicate}, + predicates: map[string]predicates.FitPredicate{"true": truePredicate}, prioritizers: []algorithm.PriorityConfig{{Function: machine2Prioritizer, Weight: 20}}, extenders: []FakeExtender{ { @@ -447,9 +461,13 @@ func TestGenericSchedulerWithExtenders(t *testing.T) { weight: 1, }, }, - nodes: []string{"machine1", "machine2"}, - expectedHost: "machine2", // machine2 has higher score - name: "test 7", + nodes: []string{"machine1", "machine2"}, + expectedResult: ScheduleResult{ + SuggestedHost: "machine2", + EvaluatedNodes: 2, + FeasibleNodes: 2, + }, // machine2 has higher score + name: "test 7", }, { // Scheduler is expected to not send pod to extender in @@ -459,7 +477,7 @@ func TestGenericSchedulerWithExtenders(t *testing.T) { // If scheduler sends the pod by mistake, the test would fail // because of the errors from errorPredicateExtender and/or // errorPrioritizerExtender. - predicates: map[string]algorithm.FitPredicate{"true": truePredicate}, + predicates: map[string]predicates.FitPredicate{"true": truePredicate}, prioritizers: []algorithm.PriorityConfig{{Function: machine2Prioritizer, Weight: 1}}, extenders: []FakeExtender{ { @@ -468,10 +486,14 @@ func TestGenericSchedulerWithExtenders(t *testing.T) { unInterested: true, }, }, - nodes: []string{"machine1", "machine2"}, - expectsErr: false, - expectedHost: "machine2", // machine2 has higher score - name: "test 8", + nodes: []string{"machine1", "machine2"}, + expectsErr: false, + expectedResult: ScheduleResult{ + SuggestedHost: "machine2", + EvaluatedNodes: 2, + FeasibleNodes: 2, + }, // machine2 has higher score + name: "test 8", }, { // Scheduling is expected to not fail in @@ -479,7 +501,7 @@ func TestGenericSchedulerWithExtenders(t *testing.T) { // // If scheduler did not ignore the extender, the test would fail // because of the errors from errorPredicateExtender. - predicates: map[string]algorithm.FitPredicate{"true": truePredicate}, + predicates: map[string]predicates.FitPredicate{"true": truePredicate}, prioritizers: []algorithm.PriorityConfig{{Map: EqualPriorityMap, Weight: 1}}, extenders: []FakeExtender{ { @@ -490,10 +512,14 @@ func TestGenericSchedulerWithExtenders(t *testing.T) { predicates: []fitPredicate{machine1PredicateExtender}, }, }, - nodes: []string{"machine1", "machine2"}, - expectsErr: false, - expectedHost: "machine1", - name: "test 9", + nodes: []string{"machine1", "machine2"}, + expectsErr: false, + expectedResult: ScheduleResult{ + SuggestedHost: "machine1", + EvaluatedNodes: 2, + FeasibleNodes: 1, + }, + name: "test 9", }, } @@ -507,15 +533,15 @@ func TestGenericSchedulerWithExtenders(t *testing.T) { for _, name := range test.nodes { cache.AddNode(createNode(name)) } - queue := internalqueue.NewSchedulingQueue() + queue := internalqueue.NewSchedulingQueue(nil) scheduler := NewGenericScheduler( cache, - nil, queue, test.predicates, - algorithm.EmptyPredicateMetadataProducer, + predicates.EmptyPredicateMetadataProducer, test.prioritizers, algorithm.EmptyPriorityMetadataProducer, + emptyPluginSet, extenders, nil, schedulertesting.FakePersistentVolumeClaimLister{}, @@ -524,18 +550,19 @@ func TestGenericSchedulerWithExtenders(t *testing.T) { false, schedulerapi.DefaultPercentageOfNodesToScore) podIgnored := &v1.Pod{} - machine, err := scheduler.Schedule(podIgnored, schedulertesting.FakeNodeLister(makeNodeList(test.nodes))) + result, err := scheduler.Schedule(podIgnored, schedulertesting.FakeNodeLister(makeNodeList(test.nodes))) if test.expectsErr { if err == nil { - t.Errorf("Unexpected non-error, machine %s", machine) + t.Errorf("Unexpected non-error, result %+v", result) } } else { if err != nil { t.Errorf("Unexpected error: %v", err) return } - if test.expectedHost != machine { - t.Errorf("Expected: %s, Saw: %s", test.expectedHost, machine) + + if !reflect.DeepEqual(result, test.expectedResult) { + t.Errorf("Expected: %+v, Saw: %+v", test.expectedResult, result) } } }) diff --git a/pkg/scheduler/core/generic_scheduler.go b/pkg/scheduler/core/generic_scheduler.go index 8d5a73d1466..2f49b0733f6 100644 --- a/pkg/scheduler/core/generic_scheduler.go +++ b/pkg/scheduler/core/generic_scheduler.go @@ -39,11 +39,11 @@ import ( "k8s.io/kubernetes/pkg/scheduler/algorithm" "k8s.io/kubernetes/pkg/scheduler/algorithm/predicates" schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" - schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" - "k8s.io/kubernetes/pkg/scheduler/core/equivalence" schedulerinternalcache "k8s.io/kubernetes/pkg/scheduler/internal/cache" internalqueue "k8s.io/kubernetes/pkg/scheduler/internal/queue" "k8s.io/kubernetes/pkg/scheduler/metrics" + schedulernodeinfo "k8s.io/kubernetes/pkg/scheduler/nodeinfo" + pluginsv1alpha1 "k8s.io/kubernetes/pkg/scheduler/plugins/v1alpha1" "k8s.io/kubernetes/pkg/scheduler/util" "k8s.io/kubernetes/pkg/scheduler/volumebinder" ) @@ -54,10 +54,15 @@ const ( // certain minimum of nodes are checked for feasibility. This in turn helps // ensure a minimum level of spreading. minFeasibleNodesToFind = 100 + // minFeasibleNodesPercentageToFind is the minimum percentage of nodes that + // would be scored in each scheduling cycle. This is a semi-arbitrary value + // to ensure that a certain minimum of nodes are checked for feasibility. + // This in turn helps ensure a minimum level of spreading. + minFeasibleNodesPercentageToFind = 5 ) // FailedPredicateMap declares a map[string][]algorithm.PredicateFailureReason type. -type FailedPredicateMap map[string][]algorithm.PredicateFailureReason +type FailedPredicateMap map[string][]predicates.PredicateFailureReason // FitError describes a fit error of a pod. type FitError struct { @@ -95,18 +100,47 @@ func (f *FitError) Error() string { return reasonMsg } +// ScheduleAlgorithm is an interface implemented by things that know how to schedule pods +// onto machines. +// TODO: Rename this type. +type ScheduleAlgorithm interface { + Schedule(*v1.Pod, algorithm.NodeLister) (scheduleResult ScheduleResult, err error) + // Preempt receives scheduling errors for a pod and tries to create room for + // the pod by preempting lower priority pods if possible. + // It returns the node where preemption happened, a list of preempted pods, a + // list of pods whose nominated node name should be removed, and error if any. + Preempt(*v1.Pod, algorithm.NodeLister, error) (selectedNode *v1.Node, preemptedPods []*v1.Pod, cleanupNominatedPods []*v1.Pod, err error) + // Predicates() returns a pointer to a map of predicate functions. This is + // exposed for testing. + Predicates() map[string]predicates.FitPredicate + // Prioritizers returns a slice of priority config. This is exposed for + // testing. + Prioritizers() []algorithm.PriorityConfig +} + +// ScheduleResult represents the result of one pod scheduled. It will contain +// the final selected Node, along with the selected intermediate information. +type ScheduleResult struct { + // Name of the scheduler suggest host + SuggestedHost string + // Number of nodes scheduler evaluated on one pod scheduled + EvaluatedNodes int + // Number of feasible nodes on one pod scheduled + FeasibleNodes int +} + type genericScheduler struct { cache schedulerinternalcache.Cache - equivalenceCache *equivalence.Cache schedulingQueue internalqueue.SchedulingQueue - predicates map[string]algorithm.FitPredicate + predicates map[string]predicates.FitPredicate priorityMetaProducer algorithm.PriorityMetadataProducer - predicateMetaProducer algorithm.PredicateMetadataProducer + predicateMetaProducer predicates.PredicateMetadataProducer prioritizers []algorithm.PriorityConfig + pluginSet pluginsv1alpha1.PluginSet extenders []algorithm.SchedulerExtender lastNodeIndex uint64 alwaysCheckAllPredicates bool - cachedNodeInfoMap map[string]*schedulercache.NodeInfo + cachedNodeInfoMap map[string]*schedulernodeinfo.NodeInfo volumeBinder *volumebinder.VolumeBinder pvcLister corelisters.PersistentVolumeClaimLister pdbLister algorithm.PDBLister @@ -114,21 +148,9 @@ type genericScheduler struct { percentageOfNodesToScore int32 } -// snapshot snapshots equivalane cache and node infos for all fit and priority +// snapshot snapshots scheduler cache and node infos for all fit and priority // functions. func (g *genericScheduler) snapshot() error { - // IMPORTANT NOTE: We must snapshot equivalence cache before snapshotting - // scheduler cache, otherwise stale data may be written into equivalence - // cache, e.g. - // 1. snapshot cache - // 2. event arrives, updating cache and invalidating predicates or whole node cache - // 3. snapshot ecache - // 4. evaludate predicates - // 5. stale result will be written to ecache - if g.equivalenceCache != nil { - g.equivalenceCache.Snapshot() - } - // Used for all fit and priority funcs. return g.cache.UpdateNodeNameToInfoMap(g.cachedNodeInfoMap) } @@ -136,36 +158,35 @@ func (g *genericScheduler) snapshot() error { // Schedule tries to schedule the given pod to one of the nodes in the node list. // If it succeeds, it will return the name of the node. // If it fails, it will return a FitError error with reasons. -func (g *genericScheduler) Schedule(pod *v1.Pod, nodeLister algorithm.NodeLister) (string, error) { +func (g *genericScheduler) Schedule(pod *v1.Pod, nodeLister algorithm.NodeLister) (result ScheduleResult, err error) { trace := utiltrace.New(fmt.Sprintf("Scheduling %s/%s", pod.Namespace, pod.Name)) defer trace.LogIfLong(100 * time.Millisecond) if err := podPassesBasicChecks(pod, g.pvcLister); err != nil { - return "", err + return result, err } nodes, err := nodeLister.List() if err != nil { - return "", err + return result, err } if len(nodes) == 0 { - return "", ErrNoNodesAvailable + return result, ErrNoNodesAvailable } - err = g.snapshot() - if err != nil { - return "", err + if err := g.snapshot(); err != nil { + return result, err } trace.Step("Computing predicates") startPredicateEvalTime := time.Now() filteredNodes, failedPredicateMap, err := g.findNodesThatFit(pod, nodes) if err != nil { - return "", err + return result, err } if len(filteredNodes) == 0 { - return "", &FitError{ + return result, &FitError{ Pod: pod, NumAllNodes: len(nodes), FailedPredicates: failedPredicateMap, @@ -179,19 +200,29 @@ func (g *genericScheduler) Schedule(pod *v1.Pod, nodeLister algorithm.NodeLister // When only one node after predicate, just use it. if len(filteredNodes) == 1 { metrics.SchedulingAlgorithmPriorityEvaluationDuration.Observe(metrics.SinceInMicroseconds(startPriorityEvalTime)) - return filteredNodes[0].Name, nil + return ScheduleResult{ + SuggestedHost: filteredNodes[0].Name, + EvaluatedNodes: 1 + len(failedPredicateMap), + FeasibleNodes: 1, + }, nil } metaPrioritiesInterface := g.priorityMetaProducer(pod, g.cachedNodeInfoMap) priorityList, err := PrioritizeNodes(pod, g.cachedNodeInfoMap, metaPrioritiesInterface, g.prioritizers, filteredNodes, g.extenders) if err != nil { - return "", err + return result, err } metrics.SchedulingAlgorithmPriorityEvaluationDuration.Observe(metrics.SinceInMicroseconds(startPriorityEvalTime)) metrics.SchedulingLatency.WithLabelValues(metrics.PriorityEvaluation).Observe(metrics.SinceInSeconds(startPriorityEvalTime)) trace.Step("Selecting host") - return g.selectHost(priorityList) + + host, err := g.selectHost(priorityList) + return ScheduleResult{ + SuggestedHost: host, + EvaluatedNodes: len(filteredNodes) + len(failedPredicateMap), + FeasibleNodes: len(filteredNodes), + }, err } // Prioritizers returns a slice containing all the scheduler's priority @@ -202,7 +233,7 @@ func (g *genericScheduler) Prioritizers() []algorithm.PriorityConfig { // Predicates returns a map containing all the scheduler's predicate // functions. It is exposed for testing only. -func (g *genericScheduler) Predicates() map[string]algorithm.FitPredicate { +func (g *genericScheduler) Predicates() map[string]predicates.FitPredicate { return g.predicates } @@ -289,7 +320,7 @@ func (g *genericScheduler) Preempt(pod *v1.Pod, nodeLister algorithm.NodeLister, candidateNode := pickOneNodeForPreemption(nodeToVictims) if candidateNode == nil { - return nil, nil, nil, err + return nil, nil, nil, nil } // Lower priority pods nominated to run on this node, may no longer fit on @@ -298,7 +329,7 @@ func (g *genericScheduler) Preempt(pod *v1.Pod, nodeLister algorithm.NodeLister, // lets scheduler find another place for them. nominatedPods := g.getLowerPriorityNominatedPods(pod, candidateNode.Name) if nodeInfo, ok := g.cachedNodeInfoMap[candidateNode.Name]; ok { - return nodeInfo.Node(), nodeToVictims[candidateNode].Pods, nominatedPods, err + return nodeInfo.Node(), nodeToVictims[candidateNode].Pods, nominatedPods, nil } return nil, nil, nil, fmt.Errorf( @@ -351,7 +382,7 @@ func (g *genericScheduler) processPreemptionWithExtenders( // worth the complexity, especially because we generally expect to have a very // small number of nominated pods per node. func (g *genericScheduler) getLowerPriorityNominatedPods(pod *v1.Pod, nodeName string) []*v1.Pod { - pods := g.schedulingQueue.WaitingPodsForNode(nodeName) + pods := g.schedulingQueue.NominatedPodsForNode(nodeName) if len(pods) == 0 { return nil @@ -369,15 +400,24 @@ func (g *genericScheduler) getLowerPriorityNominatedPods(pod *v1.Pod, nodeName s // numFeasibleNodesToFind returns the number of feasible nodes that once found, the scheduler stops // its search for more feasible nodes. -func (g *genericScheduler) numFeasibleNodesToFind(numAllNodes int32) int32 { - if numAllNodes < minFeasibleNodesToFind || g.percentageOfNodesToScore <= 0 || - g.percentageOfNodesToScore >= 100 { +func (g *genericScheduler) numFeasibleNodesToFind(numAllNodes int32) (numNodes int32) { + if numAllNodes < minFeasibleNodesToFind || g.percentageOfNodesToScore >= 100 { return numAllNodes } - numNodes := numAllNodes * g.percentageOfNodesToScore / 100 + + adaptivePercentage := g.percentageOfNodesToScore + if adaptivePercentage <= 0 { + adaptivePercentage = schedulerapi.DefaultPercentageOfNodesToScore - numAllNodes/125 + if adaptivePercentage < minFeasibleNodesPercentageToFind { + adaptivePercentage = minFeasibleNodesPercentageToFind + } + } + + numNodes = numAllNodes * adaptivePercentage / 100 if numNodes < minFeasibleNodesToFind { return minFeasibleNodesToFind } + return numNodes } @@ -400,7 +440,6 @@ func (g *genericScheduler) findNodesThatFit(pod *v1.Pod, nodes []*v1.Node) ([]*v var ( predicateResultLock sync.Mutex filteredLen int32 - equivClass *equivalence.Class ) ctx, cancel := context.WithCancel(context.Background()) @@ -408,26 +447,15 @@ func (g *genericScheduler) findNodesThatFit(pod *v1.Pod, nodes []*v1.Node) ([]*v // We can use the same metadata producer for all nodes. meta := g.predicateMetaProducer(pod, g.cachedNodeInfoMap) - if g.equivalenceCache != nil { - // getEquivalenceClassInfo will return immediately if no equivalence pod found - equivClass = equivalence.NewClass(pod) - } - checkNode := func(i int) { - var nodeCache *equivalence.NodeCache nodeName := g.cache.NodeTree().Next() - if g.equivalenceCache != nil { - nodeCache = g.equivalenceCache.LoadNodeCache(nodeName) - } fits, failedPredicates, err := podFitsOnNode( pod, meta, g.cachedNodeInfoMap[nodeName], g.predicates, - nodeCache, g.schedulingQueue, g.alwaysCheckAllPredicates, - equivClass, ) if err != nil { predicateResultLock.Lock() @@ -478,7 +506,7 @@ func (g *genericScheduler) findNodesThatFit(pod *v1.Pod, nodes []*v1.Node) ([]*v for failedNodeName, failedMsg := range failedMap { if _, found := failedPredicateMap[failedNodeName]; !found { - failedPredicateMap[failedNodeName] = []algorithm.PredicateFailureReason{} + failedPredicateMap[failedNodeName] = []predicates.PredicateFailureReason{} } failedPredicateMap[failedNodeName] = append(failedPredicateMap[failedNodeName], predicates.NewFailureReason(failedMsg)) } @@ -494,18 +522,18 @@ func (g *genericScheduler) findNodesThatFit(pod *v1.Pod, nodes []*v1.Node) ([]*v // addNominatedPods adds pods with equal or greater priority which are nominated // to run on the node given in nodeInfo to meta and nodeInfo. It returns 1) whether // any pod was found, 2) augmented meta data, 3) augmented nodeInfo. -func addNominatedPods(pod *v1.Pod, meta algorithm.PredicateMetadata, - nodeInfo *schedulercache.NodeInfo, queue internalqueue.SchedulingQueue) (bool, algorithm.PredicateMetadata, - *schedulercache.NodeInfo) { +func addNominatedPods(pod *v1.Pod, meta predicates.PredicateMetadata, + nodeInfo *schedulernodeinfo.NodeInfo, queue internalqueue.SchedulingQueue) (bool, predicates.PredicateMetadata, + *schedulernodeinfo.NodeInfo) { if queue == nil || nodeInfo == nil || nodeInfo.Node() == nil { // This may happen only in tests. return false, meta, nodeInfo } - nominatedPods := queue.WaitingPodsForNode(nodeInfo.Node().Name) + nominatedPods := queue.NominatedPodsForNode(nodeInfo.Node().Name) if nominatedPods == nil || len(nominatedPods) == 0 { return false, meta, nodeInfo } - var metaOut algorithm.PredicateMetadata + var metaOut predicates.PredicateMetadata if meta != nil { metaOut = meta.ShallowCopy() } @@ -533,18 +561,13 @@ func addNominatedPods(pod *v1.Pod, meta algorithm.PredicateMetadata, // It removes victims from meta and NodeInfo before calling this function. func podFitsOnNode( pod *v1.Pod, - meta algorithm.PredicateMetadata, - info *schedulercache.NodeInfo, - predicateFuncs map[string]algorithm.FitPredicate, - nodeCache *equivalence.NodeCache, + meta predicates.PredicateMetadata, + info *schedulernodeinfo.NodeInfo, + predicateFuncs map[string]predicates.FitPredicate, queue internalqueue.SchedulingQueue, alwaysCheckAllPredicates bool, - equivClass *equivalence.Class, -) (bool, []algorithm.PredicateFailureReason, error) { - var ( - eCacheAvailable bool - failedPredicates []algorithm.PredicateFailureReason - ) +) (bool, []predicates.PredicateFailureReason, error) { + var failedPredicates []predicates.PredicateFailureReason podsAdded := false // We run predicates twice in some cases. If the node has greater or equal priority @@ -573,25 +596,17 @@ func podFitsOnNode( } else if !podsAdded || len(failedPredicates) != 0 { break } - // Bypass eCache if node has any nominated pods. - // TODO(bsalamat): consider using eCache and adding proper eCache invalidations - // when pods are nominated or their nominations change. - eCacheAvailable = equivClass != nil && nodeCache != nil && !podsAdded - for predicateID, predicateKey := range predicates.Ordering() { + for _, predicateKey := range predicates.Ordering() { var ( fit bool - reasons []algorithm.PredicateFailureReason + reasons []predicates.PredicateFailureReason err error ) //TODO (yastij) : compute average predicate restrictiveness to export it as Prometheus metric if predicate, exist := predicateFuncs[predicateKey]; exist { - if eCacheAvailable { - fit, reasons, err = nodeCache.RunPredicate(predicate, predicateKey, predicateID, pod, metaToUse, nodeInfoToUse, equivClass) - } else { - fit, reasons, err = predicate(pod, metaToUse, nodeInfoToUse) - } + fit, reasons, err = predicate(pod, metaToUse, nodeInfoToUse) if err != nil { - return false, []algorithm.PredicateFailureReason{}, err + return false, []predicates.PredicateFailureReason{}, err } if !fit { @@ -620,7 +635,7 @@ func podFitsOnNode( // All scores are finally combined (added) to get the total weighted scores of all nodes func PrioritizeNodes( pod *v1.Pod, - nodeNameToInfo map[string]*schedulercache.NodeInfo, + nodeNameToInfo map[string]*schedulernodeinfo.NodeInfo, meta interface{}, priorityConfigs []algorithm.PriorityConfig, nodes []*v1.Node, @@ -655,24 +670,26 @@ func PrioritizeNodes( // DEPRECATED: we can remove this when all priorityConfigs implement the // Map-Reduce pattern. - workqueue.ParallelizeUntil(context.TODO(), 16, len(priorityConfigs), func(i int) { - priorityConfig := priorityConfigs[i] - if priorityConfig.Function == nil { + for i := range priorityConfigs { + if priorityConfigs[i].Function != nil { + wg.Add(1) + go func(index int) { + defer wg.Done() + var err error + results[index], err = priorityConfigs[index].Function(pod, nodeNameToInfo, nodes) + if err != nil { + appendError(err) + } + }(i) + } else { results[i] = make(schedulerapi.HostPriorityList, len(nodes)) - return } - - var err error - results[i], err = priorityConfig.Function(pod, nodeNameToInfo, nodes) - if err != nil { - appendError(err) - } - }) + } workqueue.ParallelizeUntil(context.TODO(), 16, len(nodes), func(index int) { nodeInfo := nodeNameToInfo[nodes[index].Name] - for i, priorityConfig := range priorityConfigs { - if priorityConfig.Function != nil { + for i := range priorityConfigs { + if priorityConfigs[i].Function != nil { continue } @@ -685,22 +702,22 @@ func PrioritizeNodes( } }) - for i, priorityConfig := range priorityConfigs { - if priorityConfig.Reduce == nil { + for i := range priorityConfigs { + if priorityConfigs[i].Reduce == nil { continue } wg.Add(1) - go func(index int, config algorithm.PriorityConfig) { + go func(index int) { defer wg.Done() - if err := config.Reduce(pod, meta, nodeNameToInfo, results[index]); err != nil { + if err := priorityConfigs[index].Reduce(pod, meta, nodeNameToInfo, results[index]); err != nil { appendError(err) } if klog.V(10) { for _, hostPriority := range results[index] { - klog.Infof("%v -> %v: %v, Score: (%d)", util.GetPodFullName(pod), hostPriority.Host, config.Name, hostPriority.Score) + klog.Infof("%v -> %v: %v, Score: (%d)", util.GetPodFullName(pod), hostPriority.Host, priorityConfigs[index].Name, hostPriority.Score) } } - }(i, priorityConfig) + }(i) } // Wait for all computations to be finished. wg.Wait() @@ -720,14 +737,14 @@ func PrioritizeNodes( if len(extenders) != 0 && nodes != nil { combinedScores := make(map[string]int, len(nodeNameToInfo)) - for _, extender := range extenders { - if !extender.IsInterested(pod) { + for i := range extenders { + if !extenders[i].IsInterested(pod) { continue } wg.Add(1) - go func(ext algorithm.SchedulerExtender) { + go func(extIndex int) { defer wg.Done() - prioritizedList, weight, err := ext.Prioritize(pod, nodes) + prioritizedList, weight, err := extenders[extIndex].Prioritize(pod, nodes) if err != nil { // Prioritization errors from extender can be ignored, let k8s/other extenders determine the priorities return @@ -736,12 +753,12 @@ func PrioritizeNodes( for i := range *prioritizedList { host, score := (*prioritizedList)[i].Host, (*prioritizedList)[i].Score if klog.V(10) { - klog.Infof("%v -> %v: %v, Score: (%d)", util.GetPodFullName(pod), host, ext.Name(), score) + klog.Infof("%v -> %v: %v, Score: (%d)", util.GetPodFullName(pod), host, extenders[extIndex].Name(), score) } combinedScores[host] += score * weight } mu.Unlock() - }(extender) + }(i) } // wait for all go routines to finish wg.Wait() @@ -759,7 +776,7 @@ func PrioritizeNodes( } // EqualPriorityMap is a prioritizer function that gives an equal weight of one to all nodes -func EqualPriorityMap(_ *v1.Pod, _ interface{}, nodeInfo *schedulercache.NodeInfo) (schedulerapi.HostPriority, error) { +func EqualPriorityMap(_ *v1.Pod, _ interface{}, nodeInfo *schedulernodeinfo.NodeInfo) (schedulerapi.HostPriority, error) { node := nodeInfo.Node() if node == nil { return schedulerapi.HostPriority{}, fmt.Errorf("node not found") @@ -888,10 +905,10 @@ func pickOneNodeForPreemption(nodesToVictims map[*v1.Node]*schedulerapi.Victims) // selectNodesForPreemption finds all the nodes with possible victims for // preemption in parallel. func selectNodesForPreemption(pod *v1.Pod, - nodeNameToInfo map[string]*schedulercache.NodeInfo, + nodeNameToInfo map[string]*schedulernodeinfo.NodeInfo, potentialNodes []*v1.Node, - predicates map[string]algorithm.FitPredicate, - metadataProducer algorithm.PredicateMetadataProducer, + fitPredicates map[string]predicates.FitPredicate, + metadataProducer predicates.PredicateMetadataProducer, queue internalqueue.SchedulingQueue, pdbs []*policy.PodDisruptionBudget, ) (map[*v1.Node]*schedulerapi.Victims, error) { @@ -902,11 +919,11 @@ func selectNodesForPreemption(pod *v1.Pod, meta := metadataProducer(pod, nodeNameToInfo) checkNode := func(i int) { nodeName := potentialNodes[i].Name - var metaCopy algorithm.PredicateMetadata + var metaCopy predicates.PredicateMetadata if meta != nil { metaCopy = meta.ShallowCopy() } - pods, numPDBViolations, fits := selectVictimsOnNode(pod, metaCopy, nodeNameToInfo[nodeName], predicates, queue, pdbs) + pods, numPDBViolations, fits := selectVictimsOnNode(pod, metaCopy, nodeNameToInfo[nodeName], fitPredicates, queue, pdbs) if fits { resultLock.Lock() victims := schedulerapi.Victims{ @@ -977,9 +994,9 @@ func filterPodsWithPDBViolation(pods []interface{}, pdbs []*policy.PodDisruption // these predicates can be satisfied by removing more pods from the node. func selectVictimsOnNode( pod *v1.Pod, - meta algorithm.PredicateMetadata, - nodeInfo *schedulercache.NodeInfo, - fitPredicates map[string]algorithm.FitPredicate, + meta predicates.PredicateMetadata, + nodeInfo *schedulernodeinfo.NodeInfo, + fitPredicates map[string]predicates.FitPredicate, queue internalqueue.SchedulingQueue, pdbs []*policy.PodDisruptionBudget, ) ([]*v1.Pod, int, bool) { @@ -1016,7 +1033,7 @@ func selectVictimsOnNode( // that we should check is if the "pod" is failing to schedule due to pod affinity // failure. // TODO(bsalamat): Consider checking affinity to lower priority pods if feasible with reasonable performance. - if fits, _, err := podFitsOnNode(pod, meta, nodeInfoCopy, fitPredicates, nil, queue, false, nil); !fits { + if fits, _, err := podFitsOnNode(pod, meta, nodeInfoCopy, fitPredicates, queue, false); !fits { if err != nil { klog.Warningf("Encountered error while selecting victims on node %v: %v", nodeInfo.Node().Name, err) } @@ -1030,11 +1047,11 @@ func selectVictimsOnNode( violatingVictims, nonViolatingVictims := filterPodsWithPDBViolation(potentialVictims.Items, pdbs) reprievePod := func(p *v1.Pod) bool { addPod(p) - fits, _, _ := podFitsOnNode(pod, meta, nodeInfoCopy, fitPredicates, nil, queue, false, nil) + fits, _, _ := podFitsOnNode(pod, meta, nodeInfoCopy, fitPredicates, queue, false) if !fits { removePod(p) victims = append(victims, p) - klog.V(5).Infof("Pod %v is a potential preemption victim on node %v.", p.Name, nodeInfo.Node().Name) + klog.V(5).Infof("Pod %v/%v is a potential preemption victim on node %v.", p.Namespace, p.Name, nodeInfo.Node().Name) } return fits } @@ -1078,7 +1095,6 @@ func nodesWherePreemptionMightHelp(nodes []*v1.Node, failedPredicatesMap FailedP predicates.ErrNodeUnderDiskPressure, predicates.ErrNodeUnderPIDPressure, predicates.ErrNodeUnderMemoryPressure, - predicates.ErrNodeOutOfDisk, predicates.ErrNodeUnschedulable, predicates.ErrNodeUnknownCondition, predicates.ErrVolumeZoneConflict, @@ -1102,7 +1118,7 @@ func nodesWherePreemptionMightHelp(nodes []*v1.Node, failedPredicatesMap FailedP // considered for preemption. // We look at the node that is nominated for this pod and as long as there are // terminating pods on the node, we don't consider this for preempting more pods. -func podEligibleToPreemptOthers(pod *v1.Pod, nodeNameToInfo map[string]*schedulercache.NodeInfo) bool { +func podEligibleToPreemptOthers(pod *v1.Pod, nodeNameToInfo map[string]*schedulernodeinfo.NodeInfo) bool { nomNodeName := pod.Status.NominatedNodeName if len(nomNodeName) > 0 { if nodeInfo, found := nodeNameToInfo[nomNodeName]; found { @@ -1146,12 +1162,12 @@ func podPassesBasicChecks(pod *v1.Pod, pvcLister corelisters.PersistentVolumeCla // NewGenericScheduler creates a genericScheduler object. func NewGenericScheduler( cache schedulerinternalcache.Cache, - eCache *equivalence.Cache, podQueue internalqueue.SchedulingQueue, - predicates map[string]algorithm.FitPredicate, - predicateMetaProducer algorithm.PredicateMetadataProducer, + predicates map[string]predicates.FitPredicate, + predicateMetaProducer predicates.PredicateMetadataProducer, prioritizers []algorithm.PriorityConfig, priorityMetaProducer algorithm.PriorityMetadataProducer, + pluginSet pluginsv1alpha1.PluginSet, extenders []algorithm.SchedulerExtender, volumeBinder *volumebinder.VolumeBinder, pvcLister corelisters.PersistentVolumeClaimLister, @@ -1159,17 +1175,17 @@ func NewGenericScheduler( alwaysCheckAllPredicates bool, disablePreemption bool, percentageOfNodesToScore int32, -) algorithm.ScheduleAlgorithm { +) ScheduleAlgorithm { return &genericScheduler{ cache: cache, - equivalenceCache: eCache, schedulingQueue: podQueue, predicates: predicates, predicateMetaProducer: predicateMetaProducer, prioritizers: prioritizers, priorityMetaProducer: priorityMetaProducer, + pluginSet: pluginSet, extenders: extenders, - cachedNodeInfoMap: make(map[string]*schedulercache.NodeInfo), + cachedNodeInfoMap: make(map[string]*schedulernodeinfo.NodeInfo), volumeBinder: volumeBinder, pvcLister: pvcLister, pdbLister: pdbLister, diff --git a/pkg/scheduler/core/generic_scheduler_test.go b/pkg/scheduler/core/generic_scheduler_test.go index d0152a9fbb6..f72f2026eef 100644 --- a/pkg/scheduler/core/generic_scheduler_test.go +++ b/pkg/scheduler/core/generic_scheduler_test.go @@ -22,7 +22,6 @@ import ( "reflect" "strconv" "strings" - "sync" "testing" "time" @@ -39,10 +38,10 @@ import ( algorithmpriorities "k8s.io/kubernetes/pkg/scheduler/algorithm/priorities" priorityutil "k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/util" schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" - schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" - "k8s.io/kubernetes/pkg/scheduler/core/equivalence" schedulerinternalcache "k8s.io/kubernetes/pkg/scheduler/internal/cache" internalqueue "k8s.io/kubernetes/pkg/scheduler/internal/queue" + schedulernodeinfo "k8s.io/kubernetes/pkg/scheduler/nodeinfo" + plugins "k8s.io/kubernetes/pkg/scheduler/plugins/v1alpha1" schedulertesting "k8s.io/kubernetes/pkg/scheduler/testing" ) @@ -51,15 +50,15 @@ var ( order = []string{"false", "true", "matches", "nopods", algorithmpredicates.MatchInterPodAffinityPred} ) -func falsePredicate(pod *v1.Pod, meta algorithm.PredicateMetadata, nodeInfo *schedulercache.NodeInfo) (bool, []algorithm.PredicateFailureReason, error) { - return false, []algorithm.PredicateFailureReason{algorithmpredicates.ErrFakePredicate}, nil +func falsePredicate(pod *v1.Pod, meta algorithmpredicates.PredicateMetadata, nodeInfo *schedulernodeinfo.NodeInfo) (bool, []algorithmpredicates.PredicateFailureReason, error) { + return false, []algorithmpredicates.PredicateFailureReason{algorithmpredicates.ErrFakePredicate}, nil } -func truePredicate(pod *v1.Pod, meta algorithm.PredicateMetadata, nodeInfo *schedulercache.NodeInfo) (bool, []algorithm.PredicateFailureReason, error) { +func truePredicate(pod *v1.Pod, meta algorithmpredicates.PredicateMetadata, nodeInfo *schedulernodeinfo.NodeInfo) (bool, []algorithmpredicates.PredicateFailureReason, error) { return true, nil, nil } -func matchesPredicate(pod *v1.Pod, meta algorithm.PredicateMetadata, nodeInfo *schedulercache.NodeInfo) (bool, []algorithm.PredicateFailureReason, error) { +func matchesPredicate(pod *v1.Pod, meta algorithmpredicates.PredicateMetadata, nodeInfo *schedulernodeinfo.NodeInfo) (bool, []algorithmpredicates.PredicateFailureReason, error) { node := nodeInfo.Node() if node == nil { return false, nil, fmt.Errorf("node not found") @@ -67,17 +66,17 @@ func matchesPredicate(pod *v1.Pod, meta algorithm.PredicateMetadata, nodeInfo *s if pod.Name == node.Name { return true, nil, nil } - return false, []algorithm.PredicateFailureReason{algorithmpredicates.ErrFakePredicate}, nil + return false, []algorithmpredicates.PredicateFailureReason{algorithmpredicates.ErrFakePredicate}, nil } -func hasNoPodsPredicate(pod *v1.Pod, meta algorithm.PredicateMetadata, nodeInfo *schedulercache.NodeInfo) (bool, []algorithm.PredicateFailureReason, error) { +func hasNoPodsPredicate(pod *v1.Pod, meta algorithmpredicates.PredicateMetadata, nodeInfo *schedulernodeinfo.NodeInfo) (bool, []algorithmpredicates.PredicateFailureReason, error) { if len(nodeInfo.Pods()) == 0 { return true, nil, nil } - return false, []algorithm.PredicateFailureReason{algorithmpredicates.ErrFakePredicate}, nil + return false, []algorithmpredicates.PredicateFailureReason{algorithmpredicates.ErrFakePredicate}, nil } -func numericPriority(pod *v1.Pod, nodeNameToInfo map[string]*schedulercache.NodeInfo, nodes []*v1.Node) (schedulerapi.HostPriorityList, error) { +func numericPriority(pod *v1.Pod, nodeNameToInfo map[string]*schedulernodeinfo.NodeInfo, nodes []*v1.Node) (schedulerapi.HostPriorityList, error) { result := []schedulerapi.HostPriority{} for _, node := range nodes { score, err := strconv.Atoi(node.Name) @@ -92,7 +91,7 @@ func numericPriority(pod *v1.Pod, nodeNameToInfo map[string]*schedulercache.Node return result, nil } -func reverseNumericPriority(pod *v1.Pod, nodeNameToInfo map[string]*schedulercache.NodeInfo, nodes []*v1.Node) (schedulerapi.HostPriorityList, error) { +func reverseNumericPriority(pod *v1.Pod, nodeNameToInfo map[string]*schedulernodeinfo.NodeInfo, nodes []*v1.Node) (schedulerapi.HostPriorityList, error) { var maxScore float64 minScore := math.MaxFloat64 reverseResult := []schedulerapi.HostPriority{} @@ -115,18 +114,18 @@ func reverseNumericPriority(pod *v1.Pod, nodeNameToInfo map[string]*schedulercac return reverseResult, nil } -func trueMapPriority(pod *v1.Pod, meta interface{}, nodeInfo *schedulercache.NodeInfo) (schedulerapi.HostPriority, error) { +func trueMapPriority(pod *v1.Pod, meta interface{}, nodeInfo *schedulernodeinfo.NodeInfo) (schedulerapi.HostPriority, error) { return schedulerapi.HostPriority{ Host: nodeInfo.Node().Name, Score: 1, }, nil } -func falseMapPriority(pod *v1.Pod, meta interface{}, nodeInfo *schedulercache.NodeInfo) (schedulerapi.HostPriority, error) { +func falseMapPriority(pod *v1.Pod, meta interface{}, nodeInfo *schedulernodeinfo.NodeInfo) (schedulerapi.HostPriority, error) { return schedulerapi.HostPriority{}, errPrioritize } -func getNodeReducePriority(pod *v1.Pod, meta interface{}, nodeNameToInfo map[string]*schedulercache.NodeInfo, result schedulerapi.HostPriorityList) error { +func getNodeReducePriority(pod *v1.Pod, meta interface{}, nodeNameToInfo map[string]*schedulernodeinfo.NodeInfo, result schedulerapi.HostPriorityList) error { for _, host := range result { if host.Host == "" { return fmt.Errorf("unexpected empty host name") @@ -135,6 +134,28 @@ func getNodeReducePriority(pod *v1.Pod, meta interface{}, nodeNameToInfo map[str return nil } +// EmptyPluginSet is a test plugin set used by the default scheduler. +type EmptyPluginSet struct{} + +var _ plugins.PluginSet = EmptyPluginSet{} + +// ReservePlugins returns a slice of default reserve plugins. +func (r EmptyPluginSet) ReservePlugins() []plugins.ReservePlugin { + return []plugins.ReservePlugin{} +} + +// PrebindPlugins returns a slice of default prebind plugins. +func (r EmptyPluginSet) PrebindPlugins() []plugins.PrebindPlugin { + return []plugins.PrebindPlugin{} +} + +// Data returns a pointer to PluginData. +func (r EmptyPluginSet) Data() *plugins.PluginData { + return &plugins.PluginData{} +} + +var emptyPluginSet = &EmptyPluginSet{} + func makeNodeList(nodeNames []string) []*v1.Node { result := make([]*v1.Node, 0, len(nodeNames)) for _, nodeName := range nodeNames { @@ -217,7 +238,7 @@ func TestGenericScheduler(t *testing.T) { algorithmpredicates.SetPredicatesOrdering(order) tests := []struct { name string - predicates map[string]algorithm.FitPredicate + predicates map[string]algorithmpredicates.FitPredicate prioritizers []algorithm.PriorityConfig alwaysCheckAllPredicates bool nodes []string @@ -229,7 +250,7 @@ func TestGenericScheduler(t *testing.T) { wErr error }{ { - predicates: map[string]algorithm.FitPredicate{"false": falsePredicate}, + predicates: map[string]algorithmpredicates.FitPredicate{"false": falsePredicate}, prioritizers: []algorithm.PriorityConfig{{Map: EqualPriorityMap, Weight: 1}}, nodes: []string{"machine1", "machine2"}, expectsErr: true, @@ -239,12 +260,12 @@ func TestGenericScheduler(t *testing.T) { Pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "2", UID: types.UID("2")}}, NumAllNodes: 2, FailedPredicates: FailedPredicateMap{ - "machine1": []algorithm.PredicateFailureReason{algorithmpredicates.ErrFakePredicate}, - "machine2": []algorithm.PredicateFailureReason{algorithmpredicates.ErrFakePredicate}, + "machine1": []algorithmpredicates.PredicateFailureReason{algorithmpredicates.ErrFakePredicate}, + "machine2": []algorithmpredicates.PredicateFailureReason{algorithmpredicates.ErrFakePredicate}, }}, }, { - predicates: map[string]algorithm.FitPredicate{"true": truePredicate}, + predicates: map[string]algorithmpredicates.FitPredicate{"true": truePredicate}, prioritizers: []algorithm.PriorityConfig{{Map: EqualPriorityMap, Weight: 1}}, nodes: []string{"machine1", "machine2"}, pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "ignore", UID: types.UID("ignore")}}, @@ -254,7 +275,7 @@ func TestGenericScheduler(t *testing.T) { }, { // Fits on a machine where the pod ID matches the machine name - predicates: map[string]algorithm.FitPredicate{"matches": matchesPredicate}, + predicates: map[string]algorithmpredicates.FitPredicate{"matches": matchesPredicate}, prioritizers: []algorithm.PriorityConfig{{Map: EqualPriorityMap, Weight: 1}}, nodes: []string{"machine1", "machine2"}, pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "machine2", UID: types.UID("machine2")}}, @@ -263,7 +284,7 @@ func TestGenericScheduler(t *testing.T) { wErr: nil, }, { - predicates: map[string]algorithm.FitPredicate{"true": truePredicate}, + predicates: map[string]algorithmpredicates.FitPredicate{"true": truePredicate}, prioritizers: []algorithm.PriorityConfig{{Function: numericPriority, Weight: 1}}, nodes: []string{"3", "2", "1"}, pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "ignore", UID: types.UID("ignore")}}, @@ -272,7 +293,7 @@ func TestGenericScheduler(t *testing.T) { wErr: nil, }, { - predicates: map[string]algorithm.FitPredicate{"matches": matchesPredicate}, + predicates: map[string]algorithmpredicates.FitPredicate{"matches": matchesPredicate}, prioritizers: []algorithm.PriorityConfig{{Function: numericPriority, Weight: 1}}, nodes: []string{"3", "2", "1"}, pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "2", UID: types.UID("2")}}, @@ -281,7 +302,7 @@ func TestGenericScheduler(t *testing.T) { wErr: nil, }, { - predicates: map[string]algorithm.FitPredicate{"true": truePredicate}, + predicates: map[string]algorithmpredicates.FitPredicate{"true": truePredicate}, prioritizers: []algorithm.PriorityConfig{{Function: numericPriority, Weight: 1}, {Function: reverseNumericPriority, Weight: 2}}, nodes: []string{"3", "2", "1"}, pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "2", UID: types.UID("2")}}, @@ -290,7 +311,7 @@ func TestGenericScheduler(t *testing.T) { wErr: nil, }, { - predicates: map[string]algorithm.FitPredicate{"true": truePredicate, "false": falsePredicate}, + predicates: map[string]algorithmpredicates.FitPredicate{"true": truePredicate, "false": falsePredicate}, prioritizers: []algorithm.PriorityConfig{{Function: numericPriority, Weight: 1}}, nodes: []string{"3", "2", "1"}, pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "2", UID: types.UID("2")}}, @@ -300,14 +321,14 @@ func TestGenericScheduler(t *testing.T) { Pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "2", UID: types.UID("2")}}, NumAllNodes: 3, FailedPredicates: FailedPredicateMap{ - "3": []algorithm.PredicateFailureReason{algorithmpredicates.ErrFakePredicate}, - "2": []algorithm.PredicateFailureReason{algorithmpredicates.ErrFakePredicate}, - "1": []algorithm.PredicateFailureReason{algorithmpredicates.ErrFakePredicate}, + "3": []algorithmpredicates.PredicateFailureReason{algorithmpredicates.ErrFakePredicate}, + "2": []algorithmpredicates.PredicateFailureReason{algorithmpredicates.ErrFakePredicate}, + "1": []algorithmpredicates.PredicateFailureReason{algorithmpredicates.ErrFakePredicate}, }, }, }, { - predicates: map[string]algorithm.FitPredicate{ + predicates: map[string]algorithmpredicates.FitPredicate{ "nopods": hasNoPodsPredicate, "matches": matchesPredicate, }, @@ -331,14 +352,14 @@ func TestGenericScheduler(t *testing.T) { Pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "2", UID: types.UID("2")}}, NumAllNodes: 2, FailedPredicates: FailedPredicateMap{ - "1": []algorithm.PredicateFailureReason{algorithmpredicates.ErrFakePredicate}, - "2": []algorithm.PredicateFailureReason{algorithmpredicates.ErrFakePredicate}, + "1": []algorithmpredicates.PredicateFailureReason{algorithmpredicates.ErrFakePredicate}, + "2": []algorithmpredicates.PredicateFailureReason{algorithmpredicates.ErrFakePredicate}, }, }, }, { // Pod with existing PVC - predicates: map[string]algorithm.FitPredicate{"true": truePredicate}, + predicates: map[string]algorithmpredicates.FitPredicate{"true": truePredicate}, prioritizers: []algorithm.PriorityConfig{{Map: EqualPriorityMap, Weight: 1}}, nodes: []string{"machine1", "machine2"}, pvcs: []*v1.PersistentVolumeClaim{{ObjectMeta: metav1.ObjectMeta{Name: "existingPVC"}}}, @@ -362,7 +383,7 @@ func TestGenericScheduler(t *testing.T) { }, { // Pod with non existing PVC - predicates: map[string]algorithm.FitPredicate{"true": truePredicate}, + predicates: map[string]algorithmpredicates.FitPredicate{"true": truePredicate}, prioritizers: []algorithm.PriorityConfig{{Map: EqualPriorityMap, Weight: 1}}, nodes: []string{"machine1", "machine2"}, pod: &v1.Pod{ @@ -385,7 +406,7 @@ func TestGenericScheduler(t *testing.T) { }, { // Pod with deleting PVC - predicates: map[string]algorithm.FitPredicate{"true": truePredicate}, + predicates: map[string]algorithmpredicates.FitPredicate{"true": truePredicate}, prioritizers: []algorithm.PriorityConfig{{Map: EqualPriorityMap, Weight: 1}}, nodes: []string{"machine1", "machine2"}, pvcs: []*v1.PersistentVolumeClaim{{ObjectMeta: metav1.ObjectMeta{Name: "existingPVC", DeletionTimestamp: &metav1.Time{}}}}, @@ -409,7 +430,7 @@ func TestGenericScheduler(t *testing.T) { }, { // alwaysCheckAllPredicates is true - predicates: map[string]algorithm.FitPredicate{"true": truePredicate, "matches": matchesPredicate, "false": falsePredicate}, + predicates: map[string]algorithmpredicates.FitPredicate{"true": truePredicate, "matches": matchesPredicate, "false": falsePredicate}, prioritizers: []algorithm.PriorityConfig{{Map: EqualPriorityMap, Weight: 1}}, alwaysCheckAllPredicates: true, nodes: []string{"1"}, @@ -419,12 +440,12 @@ func TestGenericScheduler(t *testing.T) { Pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "2", UID: types.UID("2")}}, NumAllNodes: 1, FailedPredicates: FailedPredicateMap{ - "1": []algorithm.PredicateFailureReason{algorithmpredicates.ErrFakePredicate, algorithmpredicates.ErrFakePredicate}, + "1": []algorithmpredicates.PredicateFailureReason{algorithmpredicates.ErrFakePredicate, algorithmpredicates.ErrFakePredicate}, }, }, }, { - predicates: map[string]algorithm.FitPredicate{"true": truePredicate}, + predicates: map[string]algorithmpredicates.FitPredicate{"true": truePredicate}, prioritizers: []algorithm.PriorityConfig{{Map: falseMapPriority, Weight: 1}, {Map: trueMapPriority, Reduce: getNodeReducePriority, Weight: 2}}, nodes: []string{"2", "1"}, pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "2"}}, @@ -448,12 +469,12 @@ func TestGenericScheduler(t *testing.T) { scheduler := NewGenericScheduler( cache, - nil, - internalqueue.NewSchedulingQueue(), + internalqueue.NewSchedulingQueue(nil), test.predicates, - algorithm.EmptyPredicateMetadataProducer, + algorithmpredicates.EmptyPredicateMetadataProducer, test.prioritizers, algorithm.EmptyPriorityMetadataProducer, + emptyPluginSet, []algorithm.SchedulerExtender{}, nil, pvcLister, @@ -461,20 +482,20 @@ func TestGenericScheduler(t *testing.T) { test.alwaysCheckAllPredicates, false, schedulerapi.DefaultPercentageOfNodesToScore) - machine, err := scheduler.Schedule(test.pod, schedulertesting.FakeNodeLister(makeNodeList(test.nodes))) + result, err := scheduler.Schedule(test.pod, schedulertesting.FakeNodeLister(makeNodeList(test.nodes))) if !reflect.DeepEqual(err, test.wErr) { t.Errorf("Unexpected error: %v, expected: %v", err, test.wErr) } - if test.expectedHosts != nil && !test.expectedHosts.Has(machine) { - t.Errorf("Expected: %s, got: %s", test.expectedHosts, machine) + if test.expectedHosts != nil && !test.expectedHosts.Has(result.SuggestedHost) { + t.Errorf("Expected: %s, got: %s", test.expectedHosts, result.SuggestedHost) } }) } } // makeScheduler makes a simple genericScheduler for testing. -func makeScheduler(predicates map[string]algorithm.FitPredicate, nodes []*v1.Node) *genericScheduler { +func makeScheduler(predicates map[string]algorithmpredicates.FitPredicate, nodes []*v1.Node) *genericScheduler { algorithmpredicates.SetPredicatesOrdering(order) cache := schedulerinternalcache.New(time.Duration(0), wait.NeverStop) for _, n := range nodes { @@ -484,12 +505,12 @@ func makeScheduler(predicates map[string]algorithm.FitPredicate, nodes []*v1.Nod s := NewGenericScheduler( cache, - nil, - internalqueue.NewSchedulingQueue(), + internalqueue.NewSchedulingQueue(nil), predicates, - algorithm.EmptyPredicateMetadataProducer, + algorithmpredicates.EmptyPredicateMetadataProducer, prioritizers, algorithm.EmptyPriorityMetadataProducer, + emptyPluginSet, nil, nil, nil, nil, false, false, schedulerapi.DefaultPercentageOfNodesToScore) cache.UpdateNodeNameToInfoMap(s.(*genericScheduler).cachedNodeInfoMap) @@ -498,7 +519,7 @@ func makeScheduler(predicates map[string]algorithm.FitPredicate, nodes []*v1.Nod } func TestFindFitAllError(t *testing.T) { - predicates := map[string]algorithm.FitPredicate{"true": truePredicate, "matches": matchesPredicate} + predicates := map[string]algorithmpredicates.FitPredicate{"true": truePredicate, "matches": matchesPredicate} nodes := makeNodeList([]string{"3", "2", "1"}) scheduler := makeScheduler(predicates, nodes) @@ -526,7 +547,7 @@ func TestFindFitAllError(t *testing.T) { } func TestFindFitSomeError(t *testing.T) { - predicates := map[string]algorithm.FitPredicate{"true": truePredicate, "matches": matchesPredicate} + predicates := map[string]algorithmpredicates.FitPredicate{"true": truePredicate, "matches": matchesPredicate} nodes := makeNodeList([]string{"3", "2", "1"}) scheduler := makeScheduler(predicates, nodes) @@ -581,9 +602,9 @@ func TestHumanReadableFitError(t *testing.T) { Pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "2", UID: types.UID("2")}}, NumAllNodes: 3, FailedPredicates: FailedPredicateMap{ - "1": []algorithm.PredicateFailureReason{algorithmpredicates.ErrNodeUnderMemoryPressure}, - "2": []algorithm.PredicateFailureReason{algorithmpredicates.ErrNodeUnderDiskPressure}, - "3": []algorithm.PredicateFailureReason{algorithmpredicates.ErrNodeUnderDiskPressure}, + "1": []algorithmpredicates.PredicateFailureReason{algorithmpredicates.ErrNodeUnderMemoryPressure}, + "2": []algorithmpredicates.PredicateFailureReason{algorithmpredicates.ErrNodeUnderDiskPressure}, + "3": []algorithmpredicates.PredicateFailureReason{algorithmpredicates.ErrNodeUnderDiskPressure}, }, } if strings.Contains(err.Error(), "0/3 nodes are available") { @@ -704,7 +725,7 @@ func TestZeroRequest(t *testing.T) { pc := algorithm.PriorityConfig{Map: selectorSpreadPriorityMap, Reduce: selectorSpreadPriorityReduce, Weight: 1} priorityConfigs = append(priorityConfigs, pc) - nodeNameToInfo := schedulercache.CreateNodeNameToInfoMap(test.pods, test.nodes) + nodeNameToInfo := schedulernodeinfo.CreateNodeNameToInfoMap(test.pods, test.nodes) metaDataProducer := algorithmpriorities.NewPriorityMetadataFactory( schedulertesting.FakeServiceLister([]*v1.Service{}), @@ -775,7 +796,7 @@ func (n FakeNodeInfo) GetNodeInfo(nodeName string) (*v1.Node, error) { return &node, nil } -func PredicateMetadata(p *v1.Pod, nodeInfo map[string]*schedulercache.NodeInfo) algorithm.PredicateMetadata { +func PredicateMetadata(p *v1.Pod, nodeInfo map[string]*schedulernodeinfo.NodeInfo) algorithmpredicates.PredicateMetadata { return algorithmpredicates.NewPredicateMetadataFactory(schedulertesting.FakePodLister{p})(p, nodeInfo) } @@ -835,7 +856,7 @@ func TestSelectNodesForPreemption(t *testing.T) { algorithmpredicates.SetPredicatesOrdering(order) tests := []struct { name string - predicates map[string]algorithm.FitPredicate + predicates map[string]algorithmpredicates.FitPredicate nodes []string pod *v1.Pod pods []*v1.Pod @@ -844,7 +865,7 @@ func TestSelectNodesForPreemption(t *testing.T) { }{ { name: "a pod that does not fit on any machine", - predicates: map[string]algorithm.FitPredicate{"matches": falsePredicate}, + predicates: map[string]algorithmpredicates.FitPredicate{"matches": falsePredicate}, nodes: []string{"machine1", "machine2"}, pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "new", UID: types.UID("new")}, Spec: v1.PodSpec{Priority: &highPriority}}, pods: []*v1.Pod{ @@ -854,7 +875,7 @@ func TestSelectNodesForPreemption(t *testing.T) { }, { name: "a pod that fits with no preemption", - predicates: map[string]algorithm.FitPredicate{"matches": truePredicate}, + predicates: map[string]algorithmpredicates.FitPredicate{"matches": truePredicate}, nodes: []string{"machine1", "machine2"}, pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "new", UID: types.UID("new")}, Spec: v1.PodSpec{Priority: &highPriority}}, pods: []*v1.Pod{ @@ -864,7 +885,7 @@ func TestSelectNodesForPreemption(t *testing.T) { }, { name: "a pod that fits on one machine with no preemption", - predicates: map[string]algorithm.FitPredicate{"matches": matchesPredicate}, + predicates: map[string]algorithmpredicates.FitPredicate{"matches": matchesPredicate}, nodes: []string{"machine1", "machine2"}, pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "machine1", UID: types.UID("machine1")}, Spec: v1.PodSpec{Priority: &highPriority}}, pods: []*v1.Pod{ @@ -874,7 +895,7 @@ func TestSelectNodesForPreemption(t *testing.T) { }, { name: "a pod that fits on both machines when lower priority pods are preempted", - predicates: map[string]algorithm.FitPredicate{"matches": algorithmpredicates.PodFitsResources}, + predicates: map[string]algorithmpredicates.FitPredicate{"matches": algorithmpredicates.PodFitsResources}, nodes: []string{"machine1", "machine2"}, pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "machine1", UID: types.UID("machine1")}, Spec: v1.PodSpec{Containers: largeContainers, Priority: &highPriority}}, pods: []*v1.Pod{ @@ -884,7 +905,7 @@ func TestSelectNodesForPreemption(t *testing.T) { }, { name: "a pod that would fit on the machines, but other pods running are higher priority", - predicates: map[string]algorithm.FitPredicate{"matches": algorithmpredicates.PodFitsResources}, + predicates: map[string]algorithmpredicates.FitPredicate{"matches": algorithmpredicates.PodFitsResources}, nodes: []string{"machine1", "machine2"}, pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "machine1", UID: types.UID("machine1")}, Spec: v1.PodSpec{Containers: largeContainers, Priority: &lowPriority}}, pods: []*v1.Pod{ @@ -894,7 +915,7 @@ func TestSelectNodesForPreemption(t *testing.T) { }, { name: "medium priority pod is preempted, but lower priority one stays as it is small", - predicates: map[string]algorithm.FitPredicate{"matches": algorithmpredicates.PodFitsResources}, + predicates: map[string]algorithmpredicates.FitPredicate{"matches": algorithmpredicates.PodFitsResources}, nodes: []string{"machine1", "machine2"}, pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "machine1", UID: types.UID("machine1")}, Spec: v1.PodSpec{Containers: largeContainers, Priority: &highPriority}}, pods: []*v1.Pod{ @@ -905,7 +926,7 @@ func TestSelectNodesForPreemption(t *testing.T) { }, { name: "mixed priority pods are preempted", - predicates: map[string]algorithm.FitPredicate{"matches": algorithmpredicates.PodFitsResources}, + predicates: map[string]algorithmpredicates.FitPredicate{"matches": algorithmpredicates.PodFitsResources}, nodes: []string{"machine1", "machine2"}, pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "machine1", UID: types.UID("machine1")}, Spec: v1.PodSpec{Containers: largeContainers, Priority: &highPriority}}, pods: []*v1.Pod{ @@ -918,7 +939,7 @@ func TestSelectNodesForPreemption(t *testing.T) { }, { name: "pod with anti-affinity is preempted", - predicates: map[string]algorithm.FitPredicate{"matches": algorithmpredicates.PodFitsResources}, + predicates: map[string]algorithmpredicates.FitPredicate{"matches": algorithmpredicates.PodFitsResources}, nodes: []string{"machine1", "machine2"}, pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{ Name: "machine1", @@ -959,7 +980,7 @@ func TestSelectNodesForPreemption(t *testing.T) { if test.addAffinityPredicate { test.predicates[algorithmpredicates.MatchInterPodAffinityPred] = algorithmpredicates.NewPodAffinityPredicate(FakeNodeInfo(*nodes[0]), schedulertesting.FakePodLister(test.pods)) } - nodeNameToInfo := schedulercache.CreateNodeNameToInfoMap(test.pods, nodes) + nodeNameToInfo := schedulernodeinfo.CreateNodeNameToInfoMap(test.pods, nodes) // newnode simulate a case that a new node is added to the cluster, but nodeNameToInfo // doesn't have it yet. newnode := makeNode("newnode", 1000*5, priorityutil.DefaultMemoryRequest*5) @@ -981,7 +1002,7 @@ func TestPickOneNodeForPreemption(t *testing.T) { algorithmpredicates.SetPredicatesOrdering(order) tests := []struct { name string - predicates map[string]algorithm.FitPredicate + predicates map[string]algorithmpredicates.FitPredicate nodes []string pod *v1.Pod pods []*v1.Pod @@ -989,7 +1010,7 @@ func TestPickOneNodeForPreemption(t *testing.T) { }{ { name: "No node needs preemption", - predicates: map[string]algorithm.FitPredicate{"matches": algorithmpredicates.PodFitsResources}, + predicates: map[string]algorithmpredicates.FitPredicate{"matches": algorithmpredicates.PodFitsResources}, nodes: []string{"machine1"}, pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "machine1", UID: types.UID("machine1")}, Spec: v1.PodSpec{Containers: largeContainers, Priority: &highPriority}}, pods: []*v1.Pod{ @@ -998,7 +1019,7 @@ func TestPickOneNodeForPreemption(t *testing.T) { }, { name: "a pod that fits on both machines when lower priority pods are preempted", - predicates: map[string]algorithm.FitPredicate{"matches": algorithmpredicates.PodFitsResources}, + predicates: map[string]algorithmpredicates.FitPredicate{"matches": algorithmpredicates.PodFitsResources}, nodes: []string{"machine1", "machine2"}, pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "machine1", UID: types.UID("machine1")}, Spec: v1.PodSpec{Containers: largeContainers, Priority: &highPriority}}, pods: []*v1.Pod{ @@ -1009,7 +1030,7 @@ func TestPickOneNodeForPreemption(t *testing.T) { }, { name: "a pod that fits on a machine with no preemption", - predicates: map[string]algorithm.FitPredicate{"matches": algorithmpredicates.PodFitsResources}, + predicates: map[string]algorithmpredicates.FitPredicate{"matches": algorithmpredicates.PodFitsResources}, nodes: []string{"machine1", "machine2", "machine3"}, pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "machine1", UID: types.UID("machine1")}, Spec: v1.PodSpec{Containers: largeContainers, Priority: &highPriority}}, pods: []*v1.Pod{ @@ -1020,7 +1041,7 @@ func TestPickOneNodeForPreemption(t *testing.T) { }, { name: "machine with min highest priority pod is picked", - predicates: map[string]algorithm.FitPredicate{"matches": algorithmpredicates.PodFitsResources}, + predicates: map[string]algorithmpredicates.FitPredicate{"matches": algorithmpredicates.PodFitsResources}, nodes: []string{"machine1", "machine2", "machine3"}, pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "machine1", UID: types.UID("machine1")}, Spec: v1.PodSpec{Containers: veryLargeContainers, Priority: &highPriority}}, pods: []*v1.Pod{ @@ -1037,7 +1058,7 @@ func TestPickOneNodeForPreemption(t *testing.T) { }, { name: "when highest priorities are the same, minimum sum of priorities is picked", - predicates: map[string]algorithm.FitPredicate{"matches": algorithmpredicates.PodFitsResources}, + predicates: map[string]algorithmpredicates.FitPredicate{"matches": algorithmpredicates.PodFitsResources}, nodes: []string{"machine1", "machine2", "machine3"}, pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "machine1", UID: types.UID("machine1")}, Spec: v1.PodSpec{Containers: veryLargeContainers, Priority: &highPriority}}, pods: []*v1.Pod{ @@ -1054,7 +1075,7 @@ func TestPickOneNodeForPreemption(t *testing.T) { }, { name: "when highest priority and sum are the same, minimum number of pods is picked", - predicates: map[string]algorithm.FitPredicate{"matches": algorithmpredicates.PodFitsResources}, + predicates: map[string]algorithmpredicates.FitPredicate{"matches": algorithmpredicates.PodFitsResources}, nodes: []string{"machine1", "machine2", "machine3"}, pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "machine1", UID: types.UID("machine1")}, Spec: v1.PodSpec{Containers: veryLargeContainers, Priority: &highPriority}}, pods: []*v1.Pod{ @@ -1076,7 +1097,7 @@ func TestPickOneNodeForPreemption(t *testing.T) { // pickOneNodeForPreemption adjusts pod priorities when finding the sum of the victims. This // test ensures that the logic works correctly. name: "sum of adjusted priorities is considered", - predicates: map[string]algorithm.FitPredicate{"matches": algorithmpredicates.PodFitsResources}, + predicates: map[string]algorithmpredicates.FitPredicate{"matches": algorithmpredicates.PodFitsResources}, nodes: []string{"machine1", "machine2", "machine3"}, pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "machine1", UID: types.UID("machine1")}, Spec: v1.PodSpec{Containers: veryLargeContainers, Priority: &highPriority}}, pods: []*v1.Pod{ @@ -1095,7 +1116,7 @@ func TestPickOneNodeForPreemption(t *testing.T) { }, { name: "non-overlapping lowest high priority, sum priorities, and number of pods", - predicates: map[string]algorithm.FitPredicate{"matches": algorithmpredicates.PodFitsResources}, + predicates: map[string]algorithmpredicates.FitPredicate{"matches": algorithmpredicates.PodFitsResources}, nodes: []string{"machine1", "machine2", "machine3", "machine4"}, pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "pod1", UID: types.UID("pod1")}, Spec: v1.PodSpec{Containers: veryLargeContainers, Priority: &veryHighPriority}}, pods: []*v1.Pod{ @@ -1124,7 +1145,7 @@ func TestPickOneNodeForPreemption(t *testing.T) { for _, n := range test.nodes { nodes = append(nodes, makeNode(n, priorityutil.DefaultMilliCPURequest*5, priorityutil.DefaultMemoryRequest*5)) } - nodeNameToInfo := schedulercache.CreateNodeNameToInfoMap(test.pods, nodes) + nodeNameToInfo := schedulernodeinfo.CreateNodeNameToInfoMap(test.pods, nodes) candidateNodes, _ := selectNodesForPreemption(test.pod, nodeNameToInfo, nodes, test.predicates, PredicateMetadata, nil, nil) node := pickOneNodeForPreemption(candidateNodes) found := false @@ -1156,73 +1177,72 @@ func TestNodesWherePreemptionMightHelp(t *testing.T) { { name: "No node should be attempted", failedPredMap: FailedPredicateMap{ - "machine1": []algorithm.PredicateFailureReason{algorithmpredicates.ErrNodeSelectorNotMatch}, - "machine2": []algorithm.PredicateFailureReason{algorithmpredicates.ErrPodNotMatchHostName}, - "machine3": []algorithm.PredicateFailureReason{algorithmpredicates.ErrTaintsTolerationsNotMatch}, - "machine4": []algorithm.PredicateFailureReason{algorithmpredicates.ErrNodeLabelPresenceViolated}, + "machine1": []algorithmpredicates.PredicateFailureReason{algorithmpredicates.ErrNodeSelectorNotMatch}, + "machine2": []algorithmpredicates.PredicateFailureReason{algorithmpredicates.ErrPodNotMatchHostName}, + "machine3": []algorithmpredicates.PredicateFailureReason{algorithmpredicates.ErrTaintsTolerationsNotMatch}, + "machine4": []algorithmpredicates.PredicateFailureReason{algorithmpredicates.ErrNodeLabelPresenceViolated}, }, expected: map[string]bool{}, }, { name: "ErrPodAffinityNotMatch should be tried as it indicates that the pod is unschedulable due to inter-pod affinity or anti-affinity", failedPredMap: FailedPredicateMap{ - "machine1": []algorithm.PredicateFailureReason{algorithmpredicates.ErrPodAffinityNotMatch}, - "machine2": []algorithm.PredicateFailureReason{algorithmpredicates.ErrPodNotMatchHostName}, - "machine3": []algorithm.PredicateFailureReason{algorithmpredicates.ErrNodeUnschedulable}, + "machine1": []algorithmpredicates.PredicateFailureReason{algorithmpredicates.ErrPodAffinityNotMatch}, + "machine2": []algorithmpredicates.PredicateFailureReason{algorithmpredicates.ErrPodNotMatchHostName}, + "machine3": []algorithmpredicates.PredicateFailureReason{algorithmpredicates.ErrNodeUnschedulable}, }, expected: map[string]bool{"machine1": true, "machine4": true}, }, { name: "pod with both pod affinity and anti-affinity should be tried", failedPredMap: FailedPredicateMap{ - "machine1": []algorithm.PredicateFailureReason{algorithmpredicates.ErrPodAffinityNotMatch}, - "machine2": []algorithm.PredicateFailureReason{algorithmpredicates.ErrPodNotMatchHostName}, + "machine1": []algorithmpredicates.PredicateFailureReason{algorithmpredicates.ErrPodAffinityNotMatch}, + "machine2": []algorithmpredicates.PredicateFailureReason{algorithmpredicates.ErrPodNotMatchHostName}, }, expected: map[string]bool{"machine1": true, "machine3": true, "machine4": true}, }, { name: "ErrPodAffinityRulesNotMatch should not be tried as it indicates that the pod is unschedulable due to inter-pod affinity, but ErrPodAffinityNotMatch should be tried as it indicates that the pod is unschedulable due to inter-pod affinity or anti-affinity", failedPredMap: FailedPredicateMap{ - "machine1": []algorithm.PredicateFailureReason{algorithmpredicates.ErrPodAffinityRulesNotMatch}, - "machine2": []algorithm.PredicateFailureReason{algorithmpredicates.ErrPodAffinityNotMatch}, + "machine1": []algorithmpredicates.PredicateFailureReason{algorithmpredicates.ErrPodAffinityRulesNotMatch}, + "machine2": []algorithmpredicates.PredicateFailureReason{algorithmpredicates.ErrPodAffinityNotMatch}, }, expected: map[string]bool{"machine2": true, "machine3": true, "machine4": true}, }, { name: "Mix of failed predicates works fine", failedPredMap: FailedPredicateMap{ - "machine1": []algorithm.PredicateFailureReason{algorithmpredicates.ErrNodeSelectorNotMatch, algorithmpredicates.ErrNodeOutOfDisk, algorithmpredicates.NewInsufficientResourceError(v1.ResourceMemory, 1000, 500, 300)}, - "machine2": []algorithm.PredicateFailureReason{algorithmpredicates.ErrPodNotMatchHostName, algorithmpredicates.ErrDiskConflict}, - "machine3": []algorithm.PredicateFailureReason{algorithmpredicates.NewInsufficientResourceError(v1.ResourceMemory, 1000, 600, 400)}, - "machine4": []algorithm.PredicateFailureReason{}, + "machine1": []algorithmpredicates.PredicateFailureReason{algorithmpredicates.ErrNodeSelectorNotMatch, algorithmpredicates.ErrNodeUnderDiskPressure, algorithmpredicates.NewInsufficientResourceError(v1.ResourceMemory, 1000, 500, 300)}, + "machine2": []algorithmpredicates.PredicateFailureReason{algorithmpredicates.ErrPodNotMatchHostName, algorithmpredicates.ErrDiskConflict}, + "machine3": []algorithmpredicates.PredicateFailureReason{algorithmpredicates.NewInsufficientResourceError(v1.ResourceMemory, 1000, 600, 400)}, + "machine4": []algorithmpredicates.PredicateFailureReason{}, }, expected: map[string]bool{"machine3": true, "machine4": true}, }, { name: "Node condition errors should be considered unresolvable", failedPredMap: FailedPredicateMap{ - "machine1": []algorithm.PredicateFailureReason{algorithmpredicates.ErrNodeUnderDiskPressure}, - "machine2": []algorithm.PredicateFailureReason{algorithmpredicates.ErrNodeUnderPIDPressure}, - "machine3": []algorithm.PredicateFailureReason{algorithmpredicates.ErrNodeUnderMemoryPressure}, - "machine4": []algorithm.PredicateFailureReason{algorithmpredicates.ErrNodeOutOfDisk}, + "machine1": []algorithmpredicates.PredicateFailureReason{algorithmpredicates.ErrNodeUnderDiskPressure}, + "machine2": []algorithmpredicates.PredicateFailureReason{algorithmpredicates.ErrNodeUnderPIDPressure}, + "machine3": []algorithmpredicates.PredicateFailureReason{algorithmpredicates.ErrNodeUnderMemoryPressure}, }, - expected: map[string]bool{}, + expected: map[string]bool{"machine4": true}, }, { name: "Node condition errors and ErrNodeUnknownCondition should be considered unresolvable", failedPredMap: FailedPredicateMap{ - "machine1": []algorithm.PredicateFailureReason{algorithmpredicates.ErrNodeNotReady}, - "machine2": []algorithm.PredicateFailureReason{algorithmpredicates.ErrNodeNetworkUnavailable}, - "machine3": []algorithm.PredicateFailureReason{algorithmpredicates.ErrNodeUnknownCondition}, + "machine1": []algorithmpredicates.PredicateFailureReason{algorithmpredicates.ErrNodeNotReady}, + "machine2": []algorithmpredicates.PredicateFailureReason{algorithmpredicates.ErrNodeNetworkUnavailable}, + "machine3": []algorithmpredicates.PredicateFailureReason{algorithmpredicates.ErrNodeUnknownCondition}, }, expected: map[string]bool{"machine4": true}, }, { name: "ErrVolume... errors should not be tried as it indicates that the pod is unschedulable due to no matching volumes for pod on node", failedPredMap: FailedPredicateMap{ - "machine1": []algorithm.PredicateFailureReason{algorithmpredicates.ErrVolumeZoneConflict}, - "machine2": []algorithm.PredicateFailureReason{algorithmpredicates.ErrVolumeNodeConflict}, - "machine3": []algorithm.PredicateFailureReason{algorithmpredicates.ErrVolumeBindConflict}, + "machine1": []algorithmpredicates.PredicateFailureReason{algorithmpredicates.ErrVolumeZoneConflict}, + "machine2": []algorithmpredicates.PredicateFailureReason{algorithmpredicates.ErrVolumeNodeConflict}, + "machine3": []algorithmpredicates.PredicateFailureReason{algorithmpredicates.ErrVolumeBindConflict}, }, expected: map[string]bool{"machine4": true}, }, @@ -1245,9 +1265,9 @@ func TestNodesWherePreemptionMightHelp(t *testing.T) { func TestPreempt(t *testing.T) { failedPredMap := FailedPredicateMap{ - "machine1": []algorithm.PredicateFailureReason{algorithmpredicates.NewInsufficientResourceError(v1.ResourceMemory, 1000, 500, 300)}, - "machine2": []algorithm.PredicateFailureReason{algorithmpredicates.ErrDiskConflict}, - "machine3": []algorithm.PredicateFailureReason{algorithmpredicates.NewInsufficientResourceError(v1.ResourceMemory, 1000, 600, 400)}, + "machine1": []algorithmpredicates.PredicateFailureReason{algorithmpredicates.NewInsufficientResourceError(v1.ResourceMemory, 1000, 500, 300)}, + "machine2": []algorithmpredicates.PredicateFailureReason{algorithmpredicates.ErrDiskConflict}, + "machine3": []algorithmpredicates.PredicateFailureReason{algorithmpredicates.NewInsufficientResourceError(v1.ResourceMemory, 1000, 600, 400)}, } // Prepare 3 node names. nodeNames := []string{} @@ -1392,13 +1412,13 @@ func TestPreempt(t *testing.T) { for _, pod := range test.pods { cache.AddPod(pod) } - cachedNodeInfoMap := map[string]*schedulercache.NodeInfo{} + cachedNodeInfoMap := map[string]*schedulernodeinfo.NodeInfo{} for _, name := range nodeNames { node := makeNode(name, 1000*5, priorityutil.DefaultMemoryRequest*5) cache.AddNode(node) // Set nodeInfo to extenders to mock extenders' cache for preemption. - cachedNodeInfo := schedulercache.NewNodeInfo() + cachedNodeInfo := schedulernodeinfo.NewNodeInfo() cachedNodeInfo.SetNode(node) cachedNodeInfoMap[name] = cachedNodeInfo } @@ -1410,12 +1430,12 @@ func TestPreempt(t *testing.T) { } scheduler := NewGenericScheduler( cache, - nil, - internalqueue.NewSchedulingQueue(), - map[string]algorithm.FitPredicate{"matches": algorithmpredicates.PodFitsResources}, - algorithm.EmptyPredicateMetadataProducer, + internalqueue.NewSchedulingQueue(nil), + map[string]algorithmpredicates.FitPredicate{"matches": algorithmpredicates.PodFitsResources}, + algorithmpredicates.EmptyPredicateMetadataProducer, []algorithm.PriorityConfig{{Function: numericPriority, Weight: 1}}, algorithm.EmptyPriorityMetadataProducer, + emptyPluginSet, extenders, nil, schedulertesting.FakePersistentVolumeClaimLister{}, @@ -1463,186 +1483,55 @@ func TestPreempt(t *testing.T) { } } -// syncingMockCache delegates method calls to an actual Cache, -// but calls to UpdateNodeNameToInfoMap synchronize with the test. -type syncingMockCache struct { - schedulerinternalcache.Cache - cycleStart, cacheInvalidated chan struct{} - once sync.Once -} - -// UpdateNodeNameToInfoMap delegates to the real implementation, but on the first call, it -// synchronizes with the test. -// -// Since UpdateNodeNameToInfoMap is one of the first steps of (*genericScheduler).Schedule, we use -// this point to signal to the test that a scheduling cycle has started. -func (c *syncingMockCache) UpdateNodeNameToInfoMap(infoMap map[string]*schedulercache.NodeInfo) error { - err := c.Cache.UpdateNodeNameToInfoMap(infoMap) - c.once.Do(func() { - c.cycleStart <- struct{}{} - <-c.cacheInvalidated - }) - return err -} - -// TestCacheInvalidationRace tests that equivalence cache invalidation is correctly -// handled when an invalidation event happens early in a scheduling cycle. Specifically, the event -// occurs after schedulercache is snapshotted and before equivalence cache lock is acquired. -func TestCacheInvalidationRace(t *testing.T) { - // Create a predicate that returns false the first time and true on subsequent calls. - podWillFit := false - var callCount int - testPredicate := func(pod *v1.Pod, - meta algorithm.PredicateMetadata, - nodeInfo *schedulercache.NodeInfo) (bool, []algorithm.PredicateFailureReason, error) { - callCount++ - if !podWillFit { - podWillFit = true - return false, []algorithm.PredicateFailureReason{algorithmpredicates.ErrFakePredicate}, nil - } - return true, nil, nil +func TestNumFeasibleNodesToFind(t *testing.T) { + tests := []struct { + name string + percentageOfNodesToScore int32 + numAllNodes int32 + wantNumNodes int32 + }{ + { + name: "not set percentageOfNodesToScore and nodes number not more than 50", + numAllNodes: 10, + wantNumNodes: 10, + }, + { + name: "set percentageOfNodesToScore and nodes number not more than 50", + percentageOfNodesToScore: 40, + numAllNodes: 10, + wantNumNodes: 10, + }, + { + name: "not set percentageOfNodesToScore and nodes number more than 50", + numAllNodes: 1000, + wantNumNodes: 420, + }, + { + name: "set percentageOfNodesToScore and nodes number more than 50", + percentageOfNodesToScore: 40, + numAllNodes: 1000, + wantNumNodes: 400, + }, + { + name: "not set percentageOfNodesToScore and nodes number more than 50*125", + numAllNodes: 6000, + wantNumNodes: 300, + }, + { + name: "set percentageOfNodesToScore and nodes number more than 50*125", + percentageOfNodesToScore: 40, + numAllNodes: 6000, + wantNumNodes: 2400, + }, } - - // Set up the mock cache. - cache := schedulerinternalcache.New(time.Duration(0), wait.NeverStop) - testNode := &v1.Node{ObjectMeta: metav1.ObjectMeta{Name: "machine1"}} - cache.AddNode(testNode) - mockCache := &syncingMockCache{ - Cache: cache, - cycleStart: make(chan struct{}), - cacheInvalidated: make(chan struct{}), - } - - ps := map[string]algorithm.FitPredicate{"testPredicate": testPredicate} - algorithmpredicates.SetPredicatesOrdering([]string{"testPredicate"}) - eCache := equivalence.NewCache(algorithmpredicates.Ordering()) - eCache.GetNodeCache(testNode.Name) - // Ensure that equivalence cache invalidation happens after the scheduling cycle starts, but before - // the equivalence cache would be updated. - go func() { - <-mockCache.cycleStart - pod := &v1.Pod{ - ObjectMeta: metav1.ObjectMeta{Name: "new-pod", UID: "new-pod"}, - Spec: v1.PodSpec{NodeName: "machine1"}} - if err := cache.AddPod(pod); err != nil { - t.Errorf("Could not add pod to cache: %v", err) - } - eCache.InvalidateAllPredicatesOnNode("machine1") - mockCache.cacheInvalidated <- struct{}{} - }() - - // Set up the scheduler. - prioritizers := []algorithm.PriorityConfig{{Map: EqualPriorityMap, Weight: 1}} - pvcLister := schedulertesting.FakePersistentVolumeClaimLister([]*v1.PersistentVolumeClaim{}) - pdbLister := schedulertesting.FakePDBLister{} - scheduler := NewGenericScheduler( - mockCache, - eCache, - internalqueue.NewSchedulingQueue(), - ps, - algorithm.EmptyPredicateMetadataProducer, - prioritizers, - algorithm.EmptyPriorityMetadataProducer, - nil, nil, pvcLister, pdbLister, - true, false, - schedulerapi.DefaultPercentageOfNodesToScore) - - // First scheduling attempt should fail. - nodeLister := schedulertesting.FakeNodeLister(makeNodeList([]string{"machine1"})) - pod := &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "test-pod"}} - machine, err := scheduler.Schedule(pod, nodeLister) - if machine != "" || err == nil { - t.Error("First scheduling attempt did not fail") - } - - // Second scheduling attempt should succeed because cache was invalidated. - _, err = scheduler.Schedule(pod, nodeLister) - if err != nil { - t.Errorf("Second scheduling attempt failed: %v", err) - } - if callCount != 2 { - t.Errorf("Predicate should have been called twice. Was called %d times.", callCount) - } -} - -// TestCacheInvalidationRace2 tests that cache invalidation is correctly handled -// when an invalidation event happens while a predicate is running. -func TestCacheInvalidationRace2(t *testing.T) { - // Create a predicate that returns false the first time and true on subsequent calls. - var ( - podWillFit = false - callCount int - cycleStart = make(chan struct{}) - cacheInvalidated = make(chan struct{}) - once sync.Once - ) - testPredicate := func(pod *v1.Pod, - meta algorithm.PredicateMetadata, - nodeInfo *schedulercache.NodeInfo) (bool, []algorithm.PredicateFailureReason, error) { - callCount++ - once.Do(func() { - cycleStart <- struct{}{} - <-cacheInvalidated + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + g := &genericScheduler{ + percentageOfNodesToScore: tt.percentageOfNodesToScore, + } + if gotNumNodes := g.numFeasibleNodesToFind(tt.numAllNodes); gotNumNodes != tt.wantNumNodes { + t.Errorf("genericScheduler.numFeasibleNodesToFind() = %v, want %v", gotNumNodes, tt.wantNumNodes) + } }) - if !podWillFit { - podWillFit = true - return false, []algorithm.PredicateFailureReason{algorithmpredicates.ErrFakePredicate}, nil - } - return true, nil, nil - } - - // Set up the mock cache. - cache := schedulerinternalcache.New(time.Duration(0), wait.NeverStop) - testNode := &v1.Node{ObjectMeta: metav1.ObjectMeta{Name: "machine1"}} - cache.AddNode(testNode) - - ps := map[string]algorithm.FitPredicate{"testPredicate": testPredicate} - algorithmpredicates.SetPredicatesOrdering([]string{"testPredicate"}) - eCache := equivalence.NewCache(algorithmpredicates.Ordering()) - eCache.GetNodeCache(testNode.Name) - // Ensure that equivalence cache invalidation happens after the scheduling cycle starts, but before - // the equivalence cache would be updated. - go func() { - <-cycleStart - pod := &v1.Pod{ - ObjectMeta: metav1.ObjectMeta{Name: "new-pod", UID: "new-pod"}, - Spec: v1.PodSpec{NodeName: "machine1"}} - if err := cache.AddPod(pod); err != nil { - t.Errorf("Could not add pod to cache: %v", err) - } - eCache.InvalidateAllPredicatesOnNode("machine1") - cacheInvalidated <- struct{}{} - }() - - // Set up the scheduler. - prioritizers := []algorithm.PriorityConfig{{Map: EqualPriorityMap, Weight: 1}} - pvcLister := schedulertesting.FakePersistentVolumeClaimLister([]*v1.PersistentVolumeClaim{}) - pdbLister := schedulertesting.FakePDBLister{} - scheduler := NewGenericScheduler( - cache, - eCache, - internalqueue.NewSchedulingQueue(), - ps, - algorithm.EmptyPredicateMetadataProducer, - prioritizers, - algorithm.EmptyPriorityMetadataProducer, - nil, nil, pvcLister, pdbLister, true, false, - schedulerapi.DefaultPercentageOfNodesToScore) - - // First scheduling attempt should fail. - nodeLister := schedulertesting.FakeNodeLister(makeNodeList([]string{"machine1"})) - pod := &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "test-pod"}} - machine, err := scheduler.Schedule(pod, nodeLister) - if machine != "" || err == nil { - t.Error("First scheduling attempt did not fail") - } - - // Second scheduling attempt should succeed because cache was invalidated. - _, err = scheduler.Schedule(pod, nodeLister) - if err != nil { - t.Errorf("Second scheduling attempt failed: %v", err) - } - if callCount != 2 { - t.Errorf("Predicate should have been called twice. Was called %d times.", callCount) } } diff --git a/pkg/scheduler/factory/BUILD b/pkg/scheduler/factory/BUILD index 7be893b0606..2017f8a476f 100644 --- a/pkg/scheduler/factory/BUILD +++ b/pkg/scheduler/factory/BUILD @@ -5,15 +5,11 @@ go_library( srcs = [ "factory.go", "plugins.go", - "signal.go", - "signal_windows.go", ], importpath = "k8s.io/kubernetes/pkg/scheduler/factory", visibility = ["//visibility:public"], deps = [ "//pkg/api/v1/pod:go_default_library", - "//pkg/apis/core/helper:go_default_library", - "//pkg/features:go_default_library", "//pkg/kubelet/apis:go_default_library", "//pkg/scheduler/algorithm:go_default_library", "//pkg/scheduler/algorithm/predicates:go_default_library", @@ -21,10 +17,11 @@ go_library( "//pkg/scheduler/api:go_default_library", "//pkg/scheduler/api/validation:go_default_library", "//pkg/scheduler/core:go_default_library", - "//pkg/scheduler/core/equivalence:go_default_library", "//pkg/scheduler/internal/cache:go_default_library", "//pkg/scheduler/internal/cache/debugger:go_default_library", "//pkg/scheduler/internal/queue:go_default_library", + "//pkg/scheduler/plugins:go_default_library", + "//pkg/scheduler/plugins/v1alpha1:go_default_library", "//pkg/scheduler/util:go_default_library", "//pkg/scheduler/volumebinder:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library", @@ -38,7 +35,6 @@ go_library( "//staging/src/k8s.io/apimachinery/pkg/util/runtime:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library", - "//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library", "//staging/src/k8s.io/client-go/informers/apps/v1:go_default_library", "//staging/src/k8s.io/client-go/informers/core/v1:go_default_library", "//staging/src/k8s.io/client-go/informers/policy/v1beta1:go_default_library", @@ -64,15 +60,16 @@ go_test( deps = [ "//pkg/api/testing:go_default_library", "//pkg/scheduler/algorithm:go_default_library", + "//pkg/scheduler/algorithm/predicates:go_default_library", "//pkg/scheduler/algorithm/priorities:go_default_library", "//pkg/scheduler/api:go_default_library", "//pkg/scheduler/api/latest:go_default_library", - "//pkg/scheduler/cache:go_default_library", "//pkg/scheduler/internal/cache/fake:go_default_library", "//pkg/scheduler/internal/queue:go_default_library", - "//pkg/scheduler/testing:go_default_library", + "//pkg/scheduler/nodeinfo:go_default_library", "//pkg/scheduler/util:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library", + "//staging/src/k8s.io/apimachinery/pkg/api/resource:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library", diff --git a/pkg/scheduler/factory/factory.go b/pkg/scheduler/factory/factory.go index aa420bcb173..bb2e3ee7a24 100644 --- a/pkg/scheduler/factory/factory.go +++ b/pkg/scheduler/factory/factory.go @@ -20,14 +20,10 @@ package factory import ( "fmt" - "os" - "os/signal" "reflect" "time" - "k8s.io/klog" - - "k8s.io/api/core/v1" + v1 "k8s.io/api/core/v1" storagev1 "k8s.io/api/storage/v1" "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -38,7 +34,6 @@ import ( "k8s.io/apimachinery/pkg/util/runtime" "k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/wait" - utilfeature "k8s.io/apiserver/pkg/util/feature" appsinformers "k8s.io/client-go/informers/apps/v1" coreinformers "k8s.io/client-go/informers/core/v1" policyinformers "k8s.io/client-go/informers/policy/v1beta1" @@ -50,19 +45,19 @@ import ( storagelisters "k8s.io/client-go/listers/storage/v1" "k8s.io/client-go/tools/cache" "k8s.io/client-go/tools/record" + "k8s.io/klog" podutil "k8s.io/kubernetes/pkg/api/v1/pod" - "k8s.io/kubernetes/pkg/apis/core/helper" - "k8s.io/kubernetes/pkg/features" kubeletapis "k8s.io/kubernetes/pkg/kubelet/apis" "k8s.io/kubernetes/pkg/scheduler/algorithm" "k8s.io/kubernetes/pkg/scheduler/algorithm/predicates" schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" "k8s.io/kubernetes/pkg/scheduler/api/validation" "k8s.io/kubernetes/pkg/scheduler/core" - "k8s.io/kubernetes/pkg/scheduler/core/equivalence" schedulerinternalcache "k8s.io/kubernetes/pkg/scheduler/internal/cache" cachedebugger "k8s.io/kubernetes/pkg/scheduler/internal/cache/debugger" internalqueue "k8s.io/kubernetes/pkg/scheduler/internal/queue" + "k8s.io/kubernetes/pkg/scheduler/plugins" + pluginsv1alpha1 "k8s.io/kubernetes/pkg/scheduler/plugins/v1alpha1" "k8s.io/kubernetes/pkg/scheduler/util" "k8s.io/kubernetes/pkg/scheduler/volumebinder" ) @@ -97,11 +92,9 @@ type Config struct { // It is expected that changes made via SchedulerCache will be observed // by NodeLister and Algorithm. SchedulerCache schedulerinternalcache.Cache - // Ecache is used for optimistically invalid affected cache items after - // successfully binding a pod - Ecache *equivalence.Cache + NodeLister algorithm.NodeLister - Algorithm algorithm.ScheduleAlgorithm + Algorithm core.ScheduleAlgorithm GetBinder func(pod *v1.Pod) Binder // PodConditionUpdater is used only in case of scheduling errors. If we succeed // with scheduling, PodScheduled condition will be updated in apiserver in /bind @@ -109,6 +102,8 @@ type Config struct { PodConditionUpdater PodConditionUpdater // PodPreemptor is used to evict pods and update pod annotations. PodPreemptor PodPreemptor + // PlugingSet has a set of plugins and data used to run them. + PluginSet pluginsv1alpha1.PluginSet // NextPod should be a function that blocks until the next pod // is available. We don't use a channel for this, because scheduling @@ -159,8 +154,8 @@ type Configurator interface { MakeDefaultErrorFunc(backoff *util.PodBackoff, podQueue internalqueue.SchedulingQueue) func(pod *v1.Pod, err error) // Predicate related accessors to be exposed for use by k8s.io/autoscaler/cluster-autoscaler - GetPredicateMetadataProducer() (algorithm.PredicateMetadataProducer, error) - GetPredicates(predicateKeys sets.String) (map[string]algorithm.FitPredicate, error) + GetPredicateMetadataProducer() (predicates.PredicateMetadataProducer, error) + GetPredicates(predicateKeys sets.String) (map[string]predicates.FitPredicate, error) // Needs to be exposed for things like integration tests where we want to make fake nodes. GetNodeLister() corelisters.NodeLister @@ -202,6 +197,8 @@ type configFactory struct { pdbLister policylisters.PodDisruptionBudgetLister // a means to list all StorageClasses storageClassLister storagelisters.StorageClassLister + // pluginRunner has a set of plugins and the context used for running them. + pluginSet pluginsv1alpha1.PluginSet // Close this to stop all reflectors StopEverything <-chan struct{} @@ -219,12 +216,6 @@ type configFactory struct { // HardPodAffinitySymmetricWeight represents the weight of implicit PreferredDuringScheduling affinity rule, in the range 0-100. hardPodAffinitySymmetricWeight int32 - // Equivalence class cache - equivalencePodCache *equivalence.Cache - - // Enable equivalence class cache - enableEquivalenceClassCache bool - // Handles volume binding decisions volumeBinder *volumebinder.VolumeBinder @@ -253,7 +244,6 @@ type ConfigFactoryArgs struct { PdbInformer policyinformers.PodDisruptionBudgetInformer StorageClassInformer storageinformers.StorageClassInformer HardPodAffinitySymmetricWeight int32 - EnableEquivalenceClassCache bool DisablePreemption bool PercentageOfNodesToScore int32 BindTimeoutSeconds int64 @@ -277,7 +267,7 @@ func NewConfigFactory(args *ConfigFactoryArgs) Configurator { c := &configFactory{ client: args.Client, podLister: schedulerCache, - podQueue: internalqueue.NewSchedulingQueue(), + podQueue: internalqueue.NewSchedulingQueue(stopEverything), nodeLister: args.NodeInformer.Lister(), pVLister: args.PvInformer.Lister(), pVCLister: args.PvcInformer.Lister(), @@ -291,7 +281,6 @@ func NewConfigFactory(args *ConfigFactoryArgs) Configurator { StopEverything: stopEverything, schedulerName: args.SchedulerName, hardPodAffinitySymmetricWeight: args.HardPodAffinitySymmetricWeight, - enableEquivalenceClassCache: args.EnableEquivalenceClassCache, disablePreemption: args.DisablePreemption, percentageOfNodesToScore: args.PercentageOfNodesToScore, } @@ -359,14 +348,11 @@ func NewConfigFactory(args *ConfigFactoryArgs) Configurator { }, ) - // On add and delete of PVs, it will affect equivalence cache items - // related to persistent volume args.PvInformer.Informer().AddEventHandler( cache.ResourceEventHandlerFuncs{ // MaxPDVolumeCountPredicate: since it relies on the counts of PV. AddFunc: c.onPvAdd, UpdateFunc: c.onPvUpdate, - DeleteFunc: c.onPvDelete, }, ) @@ -375,13 +361,10 @@ func NewConfigFactory(args *ConfigFactoryArgs) Configurator { cache.ResourceEventHandlerFuncs{ AddFunc: c.onPvcAdd, UpdateFunc: c.onPvcUpdate, - DeleteFunc: c.onPvcDelete, }, ) // This is for ServiceAffinity: affected by the selector of the service is updated. - // Also, if new service is added, equivalence cache will also become invalid since - // existing pods may be "captured" by this service and change this predicate result. args.ServiceInformer.Informer().AddEventHandler( cache.ResourceEventHandlerFuncs{ AddFunc: c.onServiceAdd, @@ -390,43 +373,27 @@ func NewConfigFactory(args *ConfigFactoryArgs) Configurator { }, ) - // Existing equivalence cache should not be affected by add/delete RC/Deployment etc, - // it only make sense when pod is scheduled or deleted + // Setup volume binder + c.volumeBinder = volumebinder.NewVolumeBinder(args.Client, args.NodeInformer, args.PvcInformer, args.PvInformer, args.StorageClassInformer, time.Duration(args.BindTimeoutSeconds)*time.Second) - if utilfeature.DefaultFeatureGate.Enabled(features.VolumeScheduling) { - // Setup volume binder - c.volumeBinder = volumebinder.NewVolumeBinder(args.Client, args.PvcInformer, args.PvInformer, args.StorageClassInformer, time.Duration(args.BindTimeoutSeconds)*time.Second) + args.StorageClassInformer.Informer().AddEventHandler( + cache.ResourceEventHandlerFuncs{ + AddFunc: c.onStorageClassAdd, + }, + ) - args.StorageClassInformer.Informer().AddEventHandler( - cache.ResourceEventHandlerFuncs{ - AddFunc: c.onStorageClassAdd, - DeleteFunc: c.onStorageClassDelete, - }, - ) - } - - // Setup cache comparer + // Setup cache debugger debugger := cachedebugger.New( args.NodeInformer.Lister(), args.PodInformer.Lister(), c.schedulerCache, c.podQueue, ) - - ch := make(chan os.Signal, 1) - signal.Notify(ch, compareSignal) + debugger.ListenForSignal(c.StopEverything) go func() { - for { - select { - case <-c.StopEverything: - c.podQueue.Close() - return - case <-ch: - debugger.Comparer.Compare() - debugger.Dumper.DumpAll() - } - } + <-c.StopEverything + c.podQueue.Close() }() return c @@ -480,14 +447,6 @@ func (c *configFactory) skipPodUpdate(pod *v1.Pod) bool { } func (c *configFactory) onPvAdd(obj interface{}) { - if c.enableEquivalenceClassCache { - pv, ok := obj.(*v1.PersistentVolume) - if !ok { - klog.Errorf("cannot convert to *v1.PersistentVolume: %v", obj) - return - } - c.invalidatePredicatesForPv(pv) - } // Pods created when there are no PVs available will be stuck in // unschedulable queue. But unbound PVs created for static provisioning and // delay binding storage class are skipped in PV controller dynamic @@ -498,19 +457,6 @@ func (c *configFactory) onPvAdd(obj interface{}) { } func (c *configFactory) onPvUpdate(old, new interface{}) { - if c.enableEquivalenceClassCache { - newPV, ok := new.(*v1.PersistentVolume) - if !ok { - klog.Errorf("cannot convert to *v1.PersistentVolume: %v", new) - return - } - oldPV, ok := old.(*v1.PersistentVolume) - if !ok { - klog.Errorf("cannot convert to *v1.PersistentVolume: %v", old) - return - } - c.invalidatePredicatesForPvUpdate(oldPV, newPV) - } // Scheduler.bindVolumesWorker may fail to update assumed pod volume // bindings due to conflicts if PVs are updated by PV controller or other // parties, then scheduler will add pod back to unschedulable queue. We @@ -518,180 +464,19 @@ func (c *configFactory) onPvUpdate(old, new interface{}) { c.podQueue.MoveAllToActiveQueue() } -func (c *configFactory) invalidatePredicatesForPvUpdate(oldPV, newPV *v1.PersistentVolume) { - invalidPredicates := sets.NewString() - // CheckVolumeBinding predicate calls SchedulerVolumeBinder.FindPodVolumes - // which will cache PVs in PodBindingCache. When PV got updated, we should - // invalidate cache, otherwise PVAssumeCache.Assume will fail with out of sync - // error. - if utilfeature.DefaultFeatureGate.Enabled(features.VolumeScheduling) { - invalidPredicates.Insert(predicates.CheckVolumeBindingPred) - } - for k, v := range newPV.Labels { - // If PV update modifies the zone/region labels. - if isZoneRegionLabel(k) && !reflect.DeepEqual(v, oldPV.Labels[k]) { - invalidPredicates.Insert(predicates.NoVolumeZoneConflictPred) - break - } - } - c.equivalencePodCache.InvalidatePredicates(invalidPredicates) -} - // isZoneRegionLabel check if given key of label is zone or region label. func isZoneRegionLabel(k string) bool { return k == kubeletapis.LabelZoneFailureDomain || k == kubeletapis.LabelZoneRegion } -func (c *configFactory) onPvDelete(obj interface{}) { - if c.enableEquivalenceClassCache { - var pv *v1.PersistentVolume - switch t := obj.(type) { - case *v1.PersistentVolume: - pv = t - case cache.DeletedFinalStateUnknown: - var ok bool - pv, ok = t.Obj.(*v1.PersistentVolume) - if !ok { - klog.Errorf("cannot convert to *v1.PersistentVolume: %v", t.Obj) - return - } - default: - klog.Errorf("cannot convert to *v1.PersistentVolume: %v", t) - return - } - c.invalidatePredicatesForPv(pv) - } -} - -func (c *configFactory) invalidatePredicatesForPv(pv *v1.PersistentVolume) { - // You could have a PVC that points to a PV, but the PV object doesn't exist. - // So when the PV object gets added, we can recount. - invalidPredicates := sets.NewString() - - // PV types which impact MaxPDVolumeCountPredicate - if pv.Spec.AWSElasticBlockStore != nil { - invalidPredicates.Insert(predicates.MaxEBSVolumeCountPred) - } - if pv.Spec.GCEPersistentDisk != nil { - invalidPredicates.Insert(predicates.MaxGCEPDVolumeCountPred) - } - if pv.Spec.AzureDisk != nil { - invalidPredicates.Insert(predicates.MaxAzureDiskVolumeCountPred) - } - - if pv.Spec.CSI != nil && utilfeature.DefaultFeatureGate.Enabled(features.AttachVolumeLimit) { - invalidPredicates.Insert(predicates.MaxCSIVolumeCountPred) - } - - // If PV contains zone related label, it may impact cached NoVolumeZoneConflict - for k := range pv.Labels { - if isZoneRegionLabel(k) { - invalidPredicates.Insert(predicates.NoVolumeZoneConflictPred) - break - } - } - - if utilfeature.DefaultFeatureGate.Enabled(features.VolumeScheduling) { - // Add/delete impacts the available PVs to choose from - invalidPredicates.Insert(predicates.CheckVolumeBindingPred) - } - - c.equivalencePodCache.InvalidatePredicates(invalidPredicates) -} - func (c *configFactory) onPvcAdd(obj interface{}) { - if c.enableEquivalenceClassCache { - pvc, ok := obj.(*v1.PersistentVolumeClaim) - if !ok { - klog.Errorf("cannot convert to *v1.PersistentVolumeClaim: %v", obj) - return - } - c.invalidatePredicatesForPvc(pvc) - } c.podQueue.MoveAllToActiveQueue() } func (c *configFactory) onPvcUpdate(old, new interface{}) { - if !utilfeature.DefaultFeatureGate.Enabled(features.VolumeScheduling) { - return - } - - if c.enableEquivalenceClassCache { - newPVC, ok := new.(*v1.PersistentVolumeClaim) - if !ok { - klog.Errorf("cannot convert to *v1.PersistentVolumeClaim: %v", new) - return - } - oldPVC, ok := old.(*v1.PersistentVolumeClaim) - if !ok { - klog.Errorf("cannot convert to *v1.PersistentVolumeClaim: %v", old) - return - } - c.invalidatePredicatesForPvcUpdate(oldPVC, newPVC) - } c.podQueue.MoveAllToActiveQueue() } -func (c *configFactory) onPvcDelete(obj interface{}) { - if c.enableEquivalenceClassCache { - var pvc *v1.PersistentVolumeClaim - switch t := obj.(type) { - case *v1.PersistentVolumeClaim: - pvc = t - case cache.DeletedFinalStateUnknown: - var ok bool - pvc, ok = t.Obj.(*v1.PersistentVolumeClaim) - if !ok { - klog.Errorf("cannot convert to *v1.PersistentVolumeClaim: %v", t.Obj) - return - } - default: - klog.Errorf("cannot convert to *v1.PersistentVolumeClaim: %v", t) - return - } - c.invalidatePredicatesForPvc(pvc) - } -} - -func (c *configFactory) invalidatePredicatesForPvc(pvc *v1.PersistentVolumeClaim) { - // We need to do this here because the ecache uses PVC uid as part of equivalence hash of pod - - // The bound volume type may change - invalidPredicates := sets.NewString(maxPDVolumeCountPredicateKeys...) - - if utilfeature.DefaultFeatureGate.Enabled(features.AttachVolumeLimit) { - invalidPredicates.Insert(predicates.MaxCSIVolumeCountPred) - } - - // The bound volume's label may change - invalidPredicates.Insert(predicates.NoVolumeZoneConflictPred) - - if utilfeature.DefaultFeatureGate.Enabled(features.VolumeScheduling) { - // Add/delete impacts the available PVs to choose from - invalidPredicates.Insert(predicates.CheckVolumeBindingPred) - } - c.equivalencePodCache.InvalidatePredicates(invalidPredicates) -} - -func (c *configFactory) invalidatePredicatesForPvcUpdate(old, new *v1.PersistentVolumeClaim) { - invalidPredicates := sets.NewString() - - if old.Spec.VolumeName != new.Spec.VolumeName { - if utilfeature.DefaultFeatureGate.Enabled(features.VolumeScheduling) { - // PVC volume binding has changed - invalidPredicates.Insert(predicates.CheckVolumeBindingPred) - } - // The bound volume type may change - invalidPredicates.Insert(maxPDVolumeCountPredicateKeys...) - - if utilfeature.DefaultFeatureGate.Enabled(features.AttachVolumeLimit) { - invalidPredicates.Insert(predicates.MaxCSIVolumeCountPred) - } - } - - c.equivalencePodCache.InvalidatePredicates(invalidPredicates) -} - func (c *configFactory) onStorageClassAdd(obj interface{}) { sc, ok := obj.(*storagev1.StorageClass) if !ok { @@ -703,71 +488,20 @@ func (c *configFactory) onStorageClassAdd(obj interface{}) { // PVCs have specified StorageClass name, creating StorageClass objects // with late binding will cause predicates to pass, so we need to move pods // to active queue. - // We don't need to invalidate cached results because results will not be - // cached for pod that has unbound immediate PVCs. if sc.VolumeBindingMode != nil && *sc.VolumeBindingMode == storagev1.VolumeBindingWaitForFirstConsumer { c.podQueue.MoveAllToActiveQueue() } } -func (c *configFactory) onStorageClassDelete(obj interface{}) { - if c.enableEquivalenceClassCache { - var sc *storagev1.StorageClass - switch t := obj.(type) { - case *storagev1.StorageClass: - sc = t - case cache.DeletedFinalStateUnknown: - var ok bool - sc, ok = t.Obj.(*storagev1.StorageClass) - if !ok { - klog.Errorf("cannot convert to *storagev1.StorageClass: %v", t.Obj) - return - } - default: - klog.Errorf("cannot convert to *storagev1.StorageClass: %v", t) - return - } - c.invalidatePredicatesForStorageClass(sc) - } -} - -func (c *configFactory) invalidatePredicatesForStorageClass(sc *storagev1.StorageClass) { - invalidPredicates := sets.NewString() - - if utilfeature.DefaultFeatureGate.Enabled(features.VolumeScheduling) { - if sc.VolumeBindingMode != nil && *sc.VolumeBindingMode == storagev1.VolumeBindingWaitForFirstConsumer { - // Delete can cause predicates to fail - invalidPredicates.Insert(predicates.CheckVolumeBindingPred) - invalidPredicates.Insert(predicates.NoVolumeZoneConflictPred) - } - } - - c.equivalencePodCache.InvalidatePredicates(invalidPredicates) -} - func (c *configFactory) onServiceAdd(obj interface{}) { - if c.enableEquivalenceClassCache { - c.equivalencePodCache.InvalidatePredicates(serviceAffinitySet) - } c.podQueue.MoveAllToActiveQueue() } func (c *configFactory) onServiceUpdate(oldObj interface{}, newObj interface{}) { - if c.enableEquivalenceClassCache { - // TODO(resouer) We may need to invalidate this for specified group of pods only - oldService := oldObj.(*v1.Service) - newService := newObj.(*v1.Service) - if !reflect.DeepEqual(oldService.Spec.Selector, newService.Spec.Selector) { - c.equivalencePodCache.InvalidatePredicates(serviceAffinitySet) - } - } c.podQueue.MoveAllToActiveQueue() } func (c *configFactory) onServiceDelete(obj interface{}) { - if c.enableEquivalenceClassCache { - c.equivalencePodCache.InvalidatePredicates(serviceAffinitySet) - } c.podQueue.MoveAllToActiveQueue() } @@ -806,9 +540,6 @@ func (c *configFactory) addPodToCache(obj interface{}) { } c.podQueue.AssignedPodAdded(pod) - - // NOTE: Updating equivalence cache of addPodToCache has been - // handled optimistically in: pkg/scheduler/scheduler.go#assume() } func (c *configFactory) updatePodInCache(oldObj, newObj interface{}) { @@ -823,16 +554,10 @@ func (c *configFactory) updatePodInCache(oldObj, newObj interface{}) { return } - // NOTE: Updates must be written to scheduler cache before invalidating - // equivalence cache, because we could snapshot equivalence cache after the - // invalidation and then snapshot the cache itself. If the cache is - // snapshotted before updates are written, we would update equivalence - // cache with stale information which is based on snapshot of old cache. if err := c.schedulerCache.UpdatePod(oldPod, newPod); err != nil { klog.Errorf("scheduler cache UpdatePod failed: %v", err) } - c.invalidateCachedPredicatesOnUpdatePod(newPod, oldPod) c.podQueue.AssignedPodUpdated(newPod) } @@ -877,27 +602,6 @@ func (c *configFactory) deletePodFromSchedulingQueue(obj interface{}) { } } -func (c *configFactory) invalidateCachedPredicatesOnUpdatePod(newPod *v1.Pod, oldPod *v1.Pod) { - if c.enableEquivalenceClassCache { - // if the pod does not have bound node, updating equivalence cache is meaningless; - // if pod's bound node has been changed, that case should be handled by pod add & delete. - if len(newPod.Spec.NodeName) != 0 && newPod.Spec.NodeName == oldPod.Spec.NodeName { - if !reflect.DeepEqual(oldPod.GetLabels(), newPod.GetLabels()) { - // MatchInterPodAffinity need to be reconsidered for this node, - // as well as all nodes in its same failure domain. - c.equivalencePodCache.InvalidatePredicates( - matchInterPodAffinitySet) - } - // if requested container resource changed, invalidate GeneralPredicates of this node - if !reflect.DeepEqual(predicates.GetResourceRequest(newPod), - predicates.GetResourceRequest(oldPod)) { - c.equivalencePodCache.InvalidatePredicatesOnNode( - newPod.Spec.NodeName, generalPredicatesSets) - } - } - } -} - func (c *configFactory) deletePodFromCache(obj interface{}) { var pod *v1.Pod switch t := obj.(type) { @@ -914,40 +618,14 @@ func (c *configFactory) deletePodFromCache(obj interface{}) { klog.Errorf("cannot convert to *v1.Pod: %v", t) return } - // NOTE: Updates must be written to scheduler cache before invalidating - // equivalence cache, because we could snapshot equivalence cache after the - // invalidation and then snapshot the cache itself. If the cache is - // snapshotted before updates are written, we would update equivalence - // cache with stale information which is based on snapshot of old cache. + if err := c.schedulerCache.RemovePod(pod); err != nil { klog.Errorf("scheduler cache RemovePod failed: %v", err) } - c.invalidateCachedPredicatesOnDeletePod(pod) c.podQueue.MoveAllToActiveQueue() } -func (c *configFactory) invalidateCachedPredicatesOnDeletePod(pod *v1.Pod) { - if c.enableEquivalenceClassCache { - // part of this case is the same as pod add. - c.equivalencePodCache.InvalidateCachedPredicateItemForPodAdd(pod, pod.Spec.NodeName) - // MatchInterPodAffinity need to be reconsidered for this node, - // as well as all nodes in its same failure domain. - // TODO(resouer) can we just do this for nodes in the same failure domain - c.equivalencePodCache.InvalidatePredicates( - matchInterPodAffinitySet) - - // if this pod have these PV, cached result of disk conflict will become invalid. - for _, volume := range pod.Spec.Volumes { - if volume.GCEPersistentDisk != nil || volume.AWSElasticBlockStore != nil || - volume.RBD != nil || volume.ISCSI != nil { - c.equivalencePodCache.InvalidatePredicatesOnNode( - pod.Spec.NodeName, noDiskConflictSet) - } - } - } -} - func (c *configFactory) addNodeToCache(obj interface{}) { node, ok := obj.(*v1.Node) if !ok { @@ -955,19 +633,11 @@ func (c *configFactory) addNodeToCache(obj interface{}) { return } - // NOTE: Because the scheduler uses equivalence cache for nodes, we need - // to create it before adding node into scheduler cache. - if c.enableEquivalenceClassCache { - // GetNodeCache() will lazily create NodeCache for given node if it does not exist. - c.equivalencePodCache.GetNodeCache(node.GetName()) - } - if err := c.schedulerCache.AddNode(node); err != nil { klog.Errorf("scheduler cache AddNode failed: %v", err) } c.podQueue.MoveAllToActiveQueue() - // NOTE: add a new node does not affect existing predicates in equivalence cache } func (c *configFactory) updateNodeInCache(oldObj, newObj interface{}) { @@ -982,86 +652,65 @@ func (c *configFactory) updateNodeInCache(oldObj, newObj interface{}) { return } - // NOTE: Updates must be written to scheduler cache before invalidating - // equivalence cache, because we could snapshot equivalence cache after the - // invalidation and then snapshot the cache itself. If the cache is - // snapshotted before updates are written, we would update equivalence - // cache with stale information which is based on snapshot of old cache. if err := c.schedulerCache.UpdateNode(oldNode, newNode); err != nil { klog.Errorf("scheduler cache UpdateNode failed: %v", err) } - c.invalidateCachedPredicatesOnNodeUpdate(newNode, oldNode) - c.podQueue.MoveAllToActiveQueue() + // Only activate unschedulable pods if the node became more schedulable. + // We skip the node property comparison when there is no unschedulable pods in the queue + // to save processing cycles. We still trigger a move to active queue to cover the case + // that a pod being processed by the scheduler is determined unschedulable. We want this + // pod to be reevaluated when a change in the cluster happens. + if c.podQueue.NumUnschedulablePods() == 0 || nodeSchedulingPropertiesChanged(newNode, oldNode) { + c.podQueue.MoveAllToActiveQueue() + } } -func (c *configFactory) invalidateCachedPredicatesOnNodeUpdate(newNode *v1.Node, oldNode *v1.Node) { - if c.enableEquivalenceClassCache { - // Begin to update equivalence cache based on node update - // TODO(resouer): think about lazily initialize this set - invalidPredicates := sets.NewString() - - if !reflect.DeepEqual(oldNode.Status.Allocatable, newNode.Status.Allocatable) { - invalidPredicates.Insert(predicates.GeneralPred) // "PodFitsResources" - } - if !reflect.DeepEqual(oldNode.GetLabels(), newNode.GetLabels()) { - invalidPredicates.Insert(predicates.GeneralPred, predicates.CheckServiceAffinityPred) // "PodSelectorMatches" - for k, v := range oldNode.GetLabels() { - // any label can be topology key of pod, we have to invalidate in all cases - if v != newNode.GetLabels()[k] { - invalidPredicates.Insert(predicates.MatchInterPodAffinityPred) - } - // NoVolumeZoneConflict will only be affected by zone related label change - if isZoneRegionLabel(k) { - if v != newNode.GetLabels()[k] { - invalidPredicates.Insert(predicates.NoVolumeZoneConflictPred) - } - } - } - } - - oldTaints, oldErr := helper.GetTaintsFromNodeAnnotations(oldNode.GetAnnotations()) - if oldErr != nil { - klog.Errorf("Failed to get taints from old node annotation for equivalence cache") - } - newTaints, newErr := helper.GetTaintsFromNodeAnnotations(newNode.GetAnnotations()) - if newErr != nil { - klog.Errorf("Failed to get taints from new node annotation for equivalence cache") - } - if !reflect.DeepEqual(oldTaints, newTaints) || - !reflect.DeepEqual(oldNode.Spec.Taints, newNode.Spec.Taints) { - invalidPredicates.Insert(predicates.PodToleratesNodeTaintsPred) - } - - if !reflect.DeepEqual(oldNode.Status.Conditions, newNode.Status.Conditions) { - oldConditions := make(map[v1.NodeConditionType]v1.ConditionStatus) - newConditions := make(map[v1.NodeConditionType]v1.ConditionStatus) - for _, cond := range oldNode.Status.Conditions { - oldConditions[cond.Type] = cond.Status - } - for _, cond := range newNode.Status.Conditions { - newConditions[cond.Type] = cond.Status - } - if oldConditions[v1.NodeMemoryPressure] != newConditions[v1.NodeMemoryPressure] { - invalidPredicates.Insert(predicates.CheckNodeMemoryPressurePred) - } - if oldConditions[v1.NodeDiskPressure] != newConditions[v1.NodeDiskPressure] { - invalidPredicates.Insert(predicates.CheckNodeDiskPressurePred) - } - if oldConditions[v1.NodePIDPressure] != newConditions[v1.NodePIDPressure] { - invalidPredicates.Insert(predicates.CheckNodePIDPressurePred) - } - if oldConditions[v1.NodeReady] != newConditions[v1.NodeReady] || - oldConditions[v1.NodeOutOfDisk] != newConditions[v1.NodeOutOfDisk] || - oldConditions[v1.NodeNetworkUnavailable] != newConditions[v1.NodeNetworkUnavailable] { - invalidPredicates.Insert(predicates.CheckNodeConditionPred) - } - } - if newNode.Spec.Unschedulable != oldNode.Spec.Unschedulable { - invalidPredicates.Insert(predicates.CheckNodeConditionPred) - } - c.equivalencePodCache.InvalidatePredicatesOnNode(newNode.GetName(), invalidPredicates) +func nodeSchedulingPropertiesChanged(newNode *v1.Node, oldNode *v1.Node) bool { + if nodeSpecUnschedulableChanged(newNode, oldNode) { + return true } + if nodeAllocatableChanged(newNode, oldNode) { + return true + } + if nodeLabelsChanged(newNode, oldNode) { + return true + } + if nodeTaintsChanged(newNode, oldNode) { + return true + } + if nodeConditionsChanged(newNode, oldNode) { + return true + } + + return false +} + +func nodeAllocatableChanged(newNode *v1.Node, oldNode *v1.Node) bool { + return !reflect.DeepEqual(oldNode.Status.Allocatable, newNode.Status.Allocatable) +} + +func nodeLabelsChanged(newNode *v1.Node, oldNode *v1.Node) bool { + return !reflect.DeepEqual(oldNode.GetLabels(), newNode.GetLabels()) +} + +func nodeTaintsChanged(newNode *v1.Node, oldNode *v1.Node) bool { + return !reflect.DeepEqual(newNode.Spec.Taints, oldNode.Spec.Taints) +} + +func nodeConditionsChanged(newNode *v1.Node, oldNode *v1.Node) bool { + strip := func(conditions []v1.NodeCondition) map[v1.NodeConditionType]v1.ConditionStatus { + conditionStatuses := make(map[v1.NodeConditionType]v1.ConditionStatus, len(conditions)) + for i := range conditions { + conditionStatuses[conditions[i].Type] = conditions[i].Status + } + return conditionStatuses + } + return !reflect.DeepEqual(strip(oldNode.Status.Conditions), strip(newNode.Status.Conditions)) +} + +func nodeSpecUnschedulableChanged(newNode *v1.Node, oldNode *v1.Node) bool { + return newNode.Spec.Unschedulable != oldNode.Spec.Unschedulable && newNode.Spec.Unschedulable == false } func (c *configFactory) deleteNodeFromCache(obj interface{}) { @@ -1080,17 +729,10 @@ func (c *configFactory) deleteNodeFromCache(obj interface{}) { klog.Errorf("cannot convert to *v1.Node: %v", t) return } - // NOTE: Updates must be written to scheduler cache before invalidating - // equivalence cache, because we could snapshot equivalence cache after the - // invalidation and then snapshot the cache itself. If the cache is - // snapshotted before updates are written, we would update equivalence - // cache with stale information which is based on snapshot of old cache. + if err := c.schedulerCache.RemoveNode(node); err != nil { klog.Errorf("scheduler cache RemoveNode failed: %v", err) } - if c.enableEquivalenceClassCache { - c.equivalencePodCache.InvalidateAllPredicatesOnNode(node.GetName()) - } } // Create creates a scheduler with the default algorithm provider. @@ -1225,20 +867,17 @@ func (c *configFactory) CreateFromKeys(predicateKeys, priorityKeys sets.String, return nil, err } - // Init equivalence class cache - if c.enableEquivalenceClassCache { - c.equivalencePodCache = equivalence.NewCache(predicates.Ordering()) - klog.Info("Created equivalence class cache") - } + // TODO(bsalamat): the default registrar should be able to process config files. + c.pluginSet = plugins.NewDefaultPluginSet(pluginsv1alpha1.NewPluginContext(), &c.schedulerCache) algo := core.NewGenericScheduler( c.schedulerCache, - c.equivalencePodCache, c.podQueue, predicateFuncs, predicateMetaProducer, priorityConfigs, priorityMetaProducer, + c.pluginSet, extenders, c.volumeBinder, c.pVCLister, @@ -1251,13 +890,13 @@ func (c *configFactory) CreateFromKeys(predicateKeys, priorityKeys sets.String, podBackoff := util.CreateDefaultPodBackoff() return &Config{ SchedulerCache: c.schedulerCache, - Ecache: c.equivalencePodCache, // The scheduler only needs to consider schedulable nodes. NodeLister: &nodeLister{c.nodeLister}, Algorithm: algo, GetBinder: c.getBinderFunc(extenders), PodConditionUpdater: &podConditionUpdater{c.client}, PodPreemptor: &podPreemptor{c.client}, + PluginSet: c.pluginSet, WaitForCacheSync: func() bool { return cache.WaitForCacheSync(c.StopEverything, c.scheduledPodsHasSynced) }, @@ -1297,7 +936,7 @@ func (c *configFactory) GetPriorityMetadataProducer() (algorithm.PriorityMetadat return getPriorityMetadataProducer(*pluginArgs) } -func (c *configFactory) GetPredicateMetadataProducer() (algorithm.PredicateMetadataProducer, error) { +func (c *configFactory) GetPredicateMetadataProducer() (predicates.PredicateMetadataProducer, error) { pluginArgs, err := c.getPluginArgs() if err != nil { return nil, err @@ -1305,7 +944,7 @@ func (c *configFactory) GetPredicateMetadataProducer() (algorithm.PredicateMetad return getPredicateMetadataProducer(*pluginArgs) } -func (c *configFactory) GetPredicates(predicateKeys sets.String) (map[string]algorithm.FitPredicate, error) { +func (c *configFactory) GetPredicates(predicateKeys sets.String) (map[string]predicates.FitPredicate, error) { pluginArgs, err := c.getPluginArgs() if err != nil { return nil, err @@ -1449,16 +1088,7 @@ func (c *configFactory) MakeDefaultErrorFunc(backoff *util.PodBackoff, podQueue _, err := c.client.CoreV1().Nodes().Get(nodeName, metav1.GetOptions{}) if err != nil && errors.IsNotFound(err) { node := v1.Node{ObjectMeta: metav1.ObjectMeta{Name: nodeName}} - // NOTE: Updates must be written to scheduler cache before invalidating - // equivalence cache, because we could snapshot equivalence cache after the - // invalidation and then snapshot the cache itself. If the cache is - // snapshotted before updates are written, we would update equivalence - // cache with stale information which is based on snapshot of old cache. c.schedulerCache.RemoveNode(&node) - // invalidate cached predicate for the node - if c.enableEquivalenceClassCache { - c.equivalencePodCache.InvalidateAllPredicatesOnNode(nodeName) - } } } } else { @@ -1482,8 +1112,7 @@ func (c *configFactory) MakeDefaultErrorFunc(backoff *util.PodBackoff, podQueue // to run on a node, scheduler takes the pod into account when running // predicates for the node. if !util.PodPriorityEnabled() { - entry := backoff.GetEntry(podID) - if !entry.TryWait(backoff.MaxDuration()) { + if !backoff.TryBackoffAndWait(podID, c.StopEverything) { klog.Warningf("Request for pod %v already in flight, abandoning", podID) return } @@ -1555,7 +1184,7 @@ type podConditionUpdater struct { } func (p *podConditionUpdater) Update(pod *v1.Pod, condition *v1.PodCondition) error { - klog.V(3).Infof("Updating pod condition for %s/%s to (%s==%s)", pod.Namespace, pod.Name, condition.Type, condition.Status) + klog.V(3).Infof("Updating pod condition for %s/%s to (%s==%s, Reason=%s)", pod.Namespace, pod.Name, condition.Type, condition.Status, condition.Reason) if podutil.UpdatePodCondition(&pod.Status, condition) { _, err := p.Client.CoreV1().Pods(pod.Namespace).UpdateStatus(pod) return err diff --git a/pkg/scheduler/factory/factory_test.go b/pkg/scheduler/factory/factory_test.go index aa68c716fc0..a85c81f8969 100644 --- a/pkg/scheduler/factory/factory_test.go +++ b/pkg/scheduler/factory/factory_test.go @@ -24,6 +24,7 @@ import ( "time" "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/sets" @@ -35,19 +36,18 @@ import ( "k8s.io/client-go/tools/cache" apitesting "k8s.io/kubernetes/pkg/api/testing" "k8s.io/kubernetes/pkg/scheduler/algorithm" + "k8s.io/kubernetes/pkg/scheduler/algorithm/predicates" schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" latestschedulerapi "k8s.io/kubernetes/pkg/scheduler/api/latest" - schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" fakecache "k8s.io/kubernetes/pkg/scheduler/internal/cache/fake" internalqueue "k8s.io/kubernetes/pkg/scheduler/internal/queue" - schedulertesting "k8s.io/kubernetes/pkg/scheduler/testing" + schedulernodeinfo "k8s.io/kubernetes/pkg/scheduler/nodeinfo" "k8s.io/kubernetes/pkg/scheduler/util" ) const ( - enableEquivalenceCache = true - disablePodPreemption = false - bindTimeoutSeconds = 600 + disablePodPreemption = false + bindTimeoutSeconds = 600 ) func TestCreate(t *testing.T) { @@ -230,19 +230,19 @@ func TestCreateFromConfigWithEmptyPredicatesOrPriorities(t *testing.T) { } } -func PredicateOne(pod *v1.Pod, meta algorithm.PredicateMetadata, nodeInfo *schedulercache.NodeInfo) (bool, []algorithm.PredicateFailureReason, error) { +func PredicateOne(pod *v1.Pod, meta predicates.PredicateMetadata, nodeInfo *schedulernodeinfo.NodeInfo) (bool, []predicates.PredicateFailureReason, error) { return true, nil, nil } -func PredicateTwo(pod *v1.Pod, meta algorithm.PredicateMetadata, nodeInfo *schedulercache.NodeInfo) (bool, []algorithm.PredicateFailureReason, error) { +func PredicateTwo(pod *v1.Pod, meta predicates.PredicateMetadata, nodeInfo *schedulernodeinfo.NodeInfo) (bool, []predicates.PredicateFailureReason, error) { return true, nil, nil } -func PriorityOne(pod *v1.Pod, nodeNameToInfo map[string]*schedulercache.NodeInfo, nodes []*v1.Node) (schedulerapi.HostPriorityList, error) { +func PriorityOne(pod *v1.Pod, nodeNameToInfo map[string]*schedulernodeinfo.NodeInfo, nodes []*v1.Node) (schedulerapi.HostPriorityList, error) { return []schedulerapi.HostPriority{}, nil } -func PriorityTwo(pod *v1.Pod, nodeNameToInfo map[string]*schedulercache.NodeInfo, nodes []*v1.Node) (schedulerapi.HostPriorityList, error) { +func PriorityTwo(pod *v1.Pod, nodeNameToInfo map[string]*schedulernodeinfo.NodeInfo, nodes []*v1.Node) (schedulerapi.HostPriorityList, error) { return []schedulerapi.HostPriority{}, nil } @@ -366,18 +366,15 @@ func testBind(binding *v1.Binding, t *testing.T) { pod := client.CoreV1().Pods(metav1.NamespaceDefault).(*fakeV1.FakePods) - bind, err := pod.GetBinding(binding.GetName()) + actualBinding, err := pod.GetBinding(binding.GetName()) if err != nil { t.Fatalf("Unexpected error: %v", err) return } - - expectedBody := runtime.EncodeOrDie(schedulertesting.Test.Codec(), binding) - bind.APIVersion = "" - bind.Kind = "" - body := runtime.EncodeOrDie(schedulertesting.Test.Codec(), bind) - if expectedBody != body { - t.Errorf("Expected body %s, Got %s", expectedBody, body) + if !reflect.DeepEqual(binding, actualBinding) { + t.Errorf("Binding did not match expectation") + t.Logf("Expected: %v", binding) + t.Logf("Actual: %v", actualBinding) } } @@ -535,7 +532,6 @@ func newConfigFactory(client clientset.Interface, hardPodAffinitySymmetricWeight informerFactory.Policy().V1beta1().PodDisruptionBudgets(), informerFactory.Storage().V1().StorageClasses(), hardPodAffinitySymmetricWeight, - enableEquivalenceCache, disablePodPreemption, schedulerapi.DefaultPercentageOfNodesToScore, bindTimeoutSeconds, @@ -560,7 +556,7 @@ func (f *fakeExtender) IsIgnorable() bool { func (f *fakeExtender) ProcessPreemption( pod *v1.Pod, nodeToVictims map[*v1.Node]*schedulerapi.Victims, - nodeNameToInfo map[string]*schedulercache.NodeInfo, + nodeNameToInfo map[string]*schedulernodeinfo.NodeInfo, ) (map[*v1.Node]*schedulerapi.Victims, error) { return nil, nil } @@ -572,7 +568,7 @@ func (f *fakeExtender) SupportsPreemption() bool { func (f *fakeExtender) Filter( pod *v1.Pod, nodes []*v1.Node, - nodeNameToInfo map[string]*schedulercache.NodeInfo, + nodeNameToInfo map[string]*schedulernodeinfo.NodeInfo, ) (filteredNodes []*v1.Node, failedNodesMap schedulerapi.FailedNodesMap, err error) { return nil, nil, nil } @@ -657,3 +653,146 @@ func testGetBinderFunc(expectedBinderType, podName string, extenders []algorithm t.Errorf("Expected binder %q but got %q", expectedBinderType, binderType) } } + +func TestNodeAllocatableChanged(t *testing.T) { + newQuantity := func(value int64) resource.Quantity { + return *resource.NewQuantity(value, resource.BinarySI) + } + for _, c := range []struct { + Name string + Changed bool + OldAllocatable v1.ResourceList + NewAllocatable v1.ResourceList + }{ + { + Name: "no allocatable resources changed", + Changed: false, + OldAllocatable: v1.ResourceList{v1.ResourceMemory: newQuantity(1024)}, + NewAllocatable: v1.ResourceList{v1.ResourceMemory: newQuantity(1024)}, + }, + { + Name: "new node has more allocatable resources", + Changed: true, + OldAllocatable: v1.ResourceList{v1.ResourceMemory: newQuantity(1024)}, + NewAllocatable: v1.ResourceList{v1.ResourceMemory: newQuantity(1024), v1.ResourceStorage: newQuantity(1024)}, + }, + } { + oldNode := &v1.Node{Status: v1.NodeStatus{Allocatable: c.OldAllocatable}} + newNode := &v1.Node{Status: v1.NodeStatus{Allocatable: c.NewAllocatable}} + changed := nodeAllocatableChanged(newNode, oldNode) + if changed != c.Changed { + t.Errorf("nodeAllocatableChanged should be %t, got %t", c.Changed, changed) + } + } +} + +func TestNodeLabelsChanged(t *testing.T) { + for _, c := range []struct { + Name string + Changed bool + OldLabels map[string]string + NewLabels map[string]string + }{ + { + Name: "no labels changed", + Changed: false, + OldLabels: map[string]string{"foo": "bar"}, + NewLabels: map[string]string{"foo": "bar"}, + }, + // Labels changed. + { + Name: "new node has more labels", + Changed: true, + OldLabels: map[string]string{"foo": "bar"}, + NewLabels: map[string]string{"foo": "bar", "test": "value"}, + }, + } { + oldNode := &v1.Node{ObjectMeta: metav1.ObjectMeta{Labels: c.OldLabels}} + newNode := &v1.Node{ObjectMeta: metav1.ObjectMeta{Labels: c.NewLabels}} + changed := nodeLabelsChanged(newNode, oldNode) + if changed != c.Changed { + t.Errorf("Test case %q failed: should be %t, got %t", c.Name, c.Changed, changed) + } + } +} + +func TestNodeTaintsChanged(t *testing.T) { + for _, c := range []struct { + Name string + Changed bool + OldTaints []v1.Taint + NewTaints []v1.Taint + }{ + { + Name: "no taint changed", + Changed: false, + OldTaints: []v1.Taint{{Key: "key", Value: "value"}}, + NewTaints: []v1.Taint{{Key: "key", Value: "value"}}, + }, + { + Name: "taint value changed", + Changed: true, + OldTaints: []v1.Taint{{Key: "key", Value: "value1"}}, + NewTaints: []v1.Taint{{Key: "key", Value: "value2"}}, + }, + } { + oldNode := &v1.Node{Spec: v1.NodeSpec{Taints: c.OldTaints}} + newNode := &v1.Node{Spec: v1.NodeSpec{Taints: c.NewTaints}} + changed := nodeTaintsChanged(newNode, oldNode) + if changed != c.Changed { + t.Errorf("Test case %q failed: should be %t, not %t", c.Name, c.Changed, changed) + } + } +} + +func TestNodeConditionsChanged(t *testing.T) { + nodeConditionType := reflect.TypeOf(v1.NodeCondition{}) + if nodeConditionType.NumField() != 6 { + t.Errorf("NodeCondition type has changed. The nodeConditionsChanged() function must be reevaluated.") + } + + for _, c := range []struct { + Name string + Changed bool + OldConditions []v1.NodeCondition + NewConditions []v1.NodeCondition + }{ + { + Name: "no condition changed", + Changed: false, + OldConditions: []v1.NodeCondition{{Type: v1.NodeOutOfDisk, Status: v1.ConditionTrue}}, + NewConditions: []v1.NodeCondition{{Type: v1.NodeOutOfDisk, Status: v1.ConditionTrue}}, + }, + { + Name: "only LastHeartbeatTime changed", + Changed: false, + OldConditions: []v1.NodeCondition{{Type: v1.NodeOutOfDisk, Status: v1.ConditionTrue, LastHeartbeatTime: metav1.Unix(1, 0)}}, + NewConditions: []v1.NodeCondition{{Type: v1.NodeOutOfDisk, Status: v1.ConditionTrue, LastHeartbeatTime: metav1.Unix(2, 0)}}, + }, + { + Name: "new node has more healthy conditions", + Changed: true, + OldConditions: []v1.NodeCondition{}, + NewConditions: []v1.NodeCondition{{Type: v1.NodeReady, Status: v1.ConditionTrue}}, + }, + { + Name: "new node has less unhealthy conditions", + Changed: true, + OldConditions: []v1.NodeCondition{{Type: v1.NodeOutOfDisk, Status: v1.ConditionTrue}}, + NewConditions: []v1.NodeCondition{}, + }, + { + Name: "condition status changed", + Changed: true, + OldConditions: []v1.NodeCondition{{Type: v1.NodeReady, Status: v1.ConditionFalse}}, + NewConditions: []v1.NodeCondition{{Type: v1.NodeReady, Status: v1.ConditionTrue}}, + }, + } { + oldNode := &v1.Node{Status: v1.NodeStatus{Conditions: c.OldConditions}} + newNode := &v1.Node{Status: v1.NodeStatus{Conditions: c.NewConditions}} + changed := nodeConditionsChanged(newNode, oldNode) + if changed != c.Changed { + t.Errorf("Test case %q failed: should be %t, got %t", c.Name, c.Changed, changed) + } + } +} diff --git a/pkg/scheduler/factory/plugins.go b/pkg/scheduler/factory/plugins.go index 216a93f7e60..17d7efcfe32 100644 --- a/pkg/scheduler/factory/plugins.go +++ b/pkg/scheduler/factory/plugins.go @@ -54,10 +54,10 @@ type PluginFactoryArgs struct { type PriorityMetadataProducerFactory func(PluginFactoryArgs) algorithm.PriorityMetadataProducer // PredicateMetadataProducerFactory produces PredicateMetadataProducer from the given args. -type PredicateMetadataProducerFactory func(PluginFactoryArgs) algorithm.PredicateMetadataProducer +type PredicateMetadataProducerFactory func(PluginFactoryArgs) predicates.PredicateMetadataProducer // FitPredicateFactory produces a FitPredicate from the given args. -type FitPredicateFactory func(PluginFactoryArgs) algorithm.FitPredicate +type FitPredicateFactory func(PluginFactoryArgs) predicates.FitPredicate // PriorityFunctionFactory produces a PriorityConfig from the given args. // DEPRECATED @@ -103,8 +103,8 @@ type AlgorithmProviderConfig struct { // RegisterFitPredicate registers a fit predicate with the algorithm // registry. Returns the name with which the predicate was registered. -func RegisterFitPredicate(name string, predicate algorithm.FitPredicate) string { - return RegisterFitPredicateFactory(name, func(PluginFactoryArgs) algorithm.FitPredicate { return predicate }) +func RegisterFitPredicate(name string, predicate predicates.FitPredicate) string { + return RegisterFitPredicateFactory(name, func(PluginFactoryArgs) predicates.FitPredicate { return predicate }) } // RemoveFitPredicate removes a fit predicate from factory. @@ -181,11 +181,11 @@ func InsertPriorityKeyToAlgorithmProviderMap(key string) { // RegisterMandatoryFitPredicate registers a fit predicate with the algorithm registry, the predicate is used by // kubelet, DaemonSet; it is always included in configuration. Returns the name with which the predicate was // registered. -func RegisterMandatoryFitPredicate(name string, predicate algorithm.FitPredicate) string { +func RegisterMandatoryFitPredicate(name string, predicate predicates.FitPredicate) string { schedulerFactoryMutex.Lock() defer schedulerFactoryMutex.Unlock() validateAlgorithmNameOrDie(name) - fitPredicateMap[name] = func(PluginFactoryArgs) algorithm.FitPredicate { return predicate } + fitPredicateMap[name] = func(PluginFactoryArgs) predicates.FitPredicate { return predicate } mandatoryFitPredicates.Insert(name) return name } @@ -211,7 +211,7 @@ func RegisterCustomFitPredicate(policy schedulerapi.PredicatePolicy) string { // generate the predicate function, if a custom type is requested if policy.Argument != nil { if policy.Argument.ServiceAffinity != nil { - predicateFactory = func(args PluginFactoryArgs) algorithm.FitPredicate { + predicateFactory = func(args PluginFactoryArgs) predicates.FitPredicate { predicate, precomputationFunction := predicates.NewServiceAffinityPredicate( args.PodLister, args.ServiceLister, @@ -224,7 +224,7 @@ func RegisterCustomFitPredicate(policy schedulerapi.PredicatePolicy) string { return predicate } } else if policy.Argument.LabelsPresence != nil { - predicateFactory = func(args PluginFactoryArgs) algorithm.FitPredicate { + predicateFactory = func(args PluginFactoryArgs) predicates.FitPredicate { return predicates.NewNodeLabelPredicate( policy.Argument.LabelsPresence.Labels, policy.Argument.LabelsPresence.Presence, @@ -408,11 +408,11 @@ func GetAlgorithmProvider(name string) (*AlgorithmProviderConfig, error) { return &provider, nil } -func getFitPredicateFunctions(names sets.String, args PluginFactoryArgs) (map[string]algorithm.FitPredicate, error) { +func getFitPredicateFunctions(names sets.String, args PluginFactoryArgs) (map[string]predicates.FitPredicate, error) { schedulerFactoryMutex.Lock() defer schedulerFactoryMutex.Unlock() - predicates := map[string]algorithm.FitPredicate{} + predicates := map[string]predicates.FitPredicate{} for _, name := range names.List() { factory, ok := fitPredicateMap[name] if !ok { @@ -441,12 +441,12 @@ func getPriorityMetadataProducer(args PluginFactoryArgs) (algorithm.PriorityMeta return priorityMetadataProducer(args), nil } -func getPredicateMetadataProducer(args PluginFactoryArgs) (algorithm.PredicateMetadataProducer, error) { +func getPredicateMetadataProducer(args PluginFactoryArgs) (predicates.PredicateMetadataProducer, error) { schedulerFactoryMutex.Lock() defer schedulerFactoryMutex.Unlock() if predicateMetadataProducer == nil { - return algorithm.EmptyPredicateMetadataProducer, nil + return predicates.EmptyPredicateMetadataProducer, nil } return predicateMetadataProducer(args), nil } diff --git a/pkg/scheduler/internal/cache/BUILD b/pkg/scheduler/internal/cache/BUILD index f2273ee9ee3..0f710594d20 100644 --- a/pkg/scheduler/internal/cache/BUILD +++ b/pkg/scheduler/internal/cache/BUILD @@ -11,7 +11,8 @@ go_library( visibility = ["//visibility:public"], deps = [ "//pkg/features:go_default_library", - "//pkg/scheduler/cache:go_default_library", + "//pkg/scheduler/algorithm:go_default_library", + "//pkg/scheduler/nodeinfo:go_default_library", "//pkg/util/node:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/labels:go_default_library", @@ -33,7 +34,7 @@ go_test( "//pkg/features:go_default_library", "//pkg/kubelet/apis:go_default_library", "//pkg/scheduler/algorithm/priorities/util:go_default_library", - "//pkg/scheduler/cache:go_default_library", + "//pkg/scheduler/nodeinfo:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/resource:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", diff --git a/pkg/scheduler/internal/cache/cache.go b/pkg/scheduler/internal/cache/cache.go index 535236e5c1f..00d4cc1b348 100644 --- a/pkg/scheduler/internal/cache/cache.go +++ b/pkg/scheduler/internal/cache/cache.go @@ -27,7 +27,8 @@ import ( "k8s.io/apimachinery/pkg/util/wait" utilfeature "k8s.io/apiserver/pkg/util/feature" "k8s.io/kubernetes/pkg/features" - schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" + "k8s.io/kubernetes/pkg/scheduler/algorithm" + schedulernodeinfo "k8s.io/kubernetes/pkg/scheduler/nodeinfo" "k8s.io/klog" ) @@ -58,7 +59,7 @@ type schedulerCache struct { assumedPods map[string]bool // a map from pod key to podState. podStates map[string]*podState - nodes map[string]*schedulercache.NodeInfo + nodes map[string]*schedulernodeinfo.NodeInfo nodeTree *NodeTree // A map from image name to its imageState. imageStates map[string]*imageState @@ -80,8 +81,8 @@ type imageState struct { } // createImageStateSummary returns a summarizing snapshot of the given image's state. -func (cache *schedulerCache) createImageStateSummary(state *imageState) *schedulercache.ImageStateSummary { - return &schedulercache.ImageStateSummary{ +func (cache *schedulerCache) createImageStateSummary(state *imageState) *schedulernodeinfo.ImageStateSummary { + return &schedulernodeinfo.ImageStateSummary{ Size: state.size, NumNodes: len(state.nodes), } @@ -93,7 +94,7 @@ func newSchedulerCache(ttl, period time.Duration, stop <-chan struct{}) *schedul period: period, stop: stop, - nodes: make(map[string]*schedulercache.NodeInfo), + nodes: make(map[string]*schedulernodeinfo.NodeInfo), nodeTree: newNodeTree(nil), assumedPods: make(map[string]bool), podStates: make(map[string]*podState), @@ -107,7 +108,7 @@ func (cache *schedulerCache) Snapshot() *Snapshot { cache.mu.RLock() defer cache.mu.RUnlock() - nodes := make(map[string]*schedulercache.NodeInfo) + nodes := make(map[string]*schedulernodeinfo.NodeInfo) for k, v := range cache.nodes { nodes[k] = v.Clone() } @@ -123,7 +124,7 @@ func (cache *schedulerCache) Snapshot() *Snapshot { } } -func (cache *schedulerCache) UpdateNodeNameToInfoMap(nodeNameToInfo map[string]*schedulercache.NodeInfo) error { +func (cache *schedulerCache) UpdateNodeNameToInfoMap(nodeNameToInfo map[string]*schedulernodeinfo.NodeInfo) error { cache.mu.Lock() defer cache.mu.Unlock() @@ -149,7 +150,7 @@ func (cache *schedulerCache) List(selector labels.Selector) ([]*v1.Pod, error) { return cache.FilteredList(alwaysTrue, selector) } -func (cache *schedulerCache) FilteredList(podFilter PodFilter, selector labels.Selector) ([]*v1.Pod, error) { +func (cache *schedulerCache) FilteredList(podFilter algorithm.PodFilter, selector labels.Selector) ([]*v1.Pod, error) { cache.mu.RLock() defer cache.mu.RUnlock() // podFilter is expected to return true for most or all of the pods. We @@ -171,7 +172,7 @@ func (cache *schedulerCache) FilteredList(podFilter PodFilter, selector labels.S } func (cache *schedulerCache) AssumePod(pod *v1.Pod) error { - key, err := schedulercache.GetPodKey(pod) + key, err := schedulernodeinfo.GetPodKey(pod) if err != nil { return err } @@ -197,7 +198,7 @@ func (cache *schedulerCache) FinishBinding(pod *v1.Pod) error { // finishBinding exists to make tests determinitistic by injecting now as an argument func (cache *schedulerCache) finishBinding(pod *v1.Pod, now time.Time) error { - key, err := schedulercache.GetPodKey(pod) + key, err := schedulernodeinfo.GetPodKey(pod) if err != nil { return err } @@ -216,7 +217,7 @@ func (cache *schedulerCache) finishBinding(pod *v1.Pod, now time.Time) error { } func (cache *schedulerCache) ForgetPod(pod *v1.Pod) error { - key, err := schedulercache.GetPodKey(pod) + key, err := schedulernodeinfo.GetPodKey(pod) if err != nil { return err } @@ -248,7 +249,7 @@ func (cache *schedulerCache) ForgetPod(pod *v1.Pod) error { func (cache *schedulerCache) addPod(pod *v1.Pod) { n, ok := cache.nodes[pod.Spec.NodeName] if !ok { - n = schedulercache.NewNodeInfo() + n = schedulernodeinfo.NewNodeInfo() cache.nodes[pod.Spec.NodeName] = n } n.AddPod(pod) @@ -276,7 +277,7 @@ func (cache *schedulerCache) removePod(pod *v1.Pod) error { } func (cache *schedulerCache) AddPod(pod *v1.Pod) error { - key, err := schedulercache.GetPodKey(pod) + key, err := schedulernodeinfo.GetPodKey(pod) if err != nil { return err } @@ -311,7 +312,7 @@ func (cache *schedulerCache) AddPod(pod *v1.Pod) error { } func (cache *schedulerCache) UpdatePod(oldPod, newPod *v1.Pod) error { - key, err := schedulercache.GetPodKey(oldPod) + key, err := schedulernodeinfo.GetPodKey(oldPod) if err != nil { return err } @@ -339,7 +340,7 @@ func (cache *schedulerCache) UpdatePod(oldPod, newPod *v1.Pod) error { } func (cache *schedulerCache) RemovePod(pod *v1.Pod) error { - key, err := schedulercache.GetPodKey(pod) + key, err := schedulernodeinfo.GetPodKey(pod) if err != nil { return err } @@ -368,7 +369,7 @@ func (cache *schedulerCache) RemovePod(pod *v1.Pod) error { } func (cache *schedulerCache) IsAssumedPod(pod *v1.Pod) (bool, error) { - key, err := schedulercache.GetPodKey(pod) + key, err := schedulernodeinfo.GetPodKey(pod) if err != nil { return false, err } @@ -384,7 +385,7 @@ func (cache *schedulerCache) IsAssumedPod(pod *v1.Pod) (bool, error) { } func (cache *schedulerCache) GetPod(pod *v1.Pod) (*v1.Pod, error) { - key, err := schedulercache.GetPodKey(pod) + key, err := schedulernodeinfo.GetPodKey(pod) if err != nil { return nil, err } @@ -406,7 +407,7 @@ func (cache *schedulerCache) AddNode(node *v1.Node) error { n, ok := cache.nodes[node.Name] if !ok { - n = schedulercache.NewNodeInfo() + n = schedulernodeinfo.NewNodeInfo() cache.nodes[node.Name] = n } else { cache.removeNodeImageStates(n.Node()) @@ -423,7 +424,7 @@ func (cache *schedulerCache) UpdateNode(oldNode, newNode *v1.Node) error { n, ok := cache.nodes[newNode.Name] if !ok { - n = schedulercache.NewNodeInfo() + n = schedulernodeinfo.NewNodeInfo() cache.nodes[newNode.Name] = n } else { cache.removeNodeImageStates(n.Node()) @@ -457,8 +458,8 @@ func (cache *schedulerCache) RemoveNode(node *v1.Node) error { // addNodeImageStates adds states of the images on given node to the given nodeInfo and update the imageStates in // scheduler cache. This function assumes the lock to scheduler cache has been acquired. -func (cache *schedulerCache) addNodeImageStates(node *v1.Node, nodeInfo *schedulercache.NodeInfo) { - newSum := make(map[string]*schedulercache.ImageStateSummary) +func (cache *schedulerCache) addNodeImageStates(node *v1.Node, nodeInfo *schedulernodeinfo.NodeInfo) { + newSum := make(map[string]*schedulernodeinfo.ImageStateSummary) for _, image := range node.Status.Images { for _, name := range image.Names { diff --git a/pkg/scheduler/internal/cache/cache_test.go b/pkg/scheduler/internal/cache/cache_test.go index dd65de078cd..e7f15291c65 100644 --- a/pkg/scheduler/internal/cache/cache_test.go +++ b/pkg/scheduler/internal/cache/cache_test.go @@ -32,10 +32,10 @@ import ( utilfeaturetesting "k8s.io/apiserver/pkg/util/feature/testing" "k8s.io/kubernetes/pkg/features" priorityutil "k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/util" - schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" + schedulernodeinfo "k8s.io/kubernetes/pkg/scheduler/nodeinfo" ) -func deepEqualWithoutGeneration(t *testing.T, testcase int, actual, expected *schedulercache.NodeInfo) { +func deepEqualWithoutGeneration(t *testing.T, testcase int, actual, expected *schedulernodeinfo.NodeInfo) { // Ignore generation field. if actual != nil { actual.SetGeneration(0) @@ -66,21 +66,21 @@ func (b *hostPortInfoBuilder) add(protocol, ip string, port int32) *hostPortInfo return b } -func (b *hostPortInfoBuilder) build() schedulercache.HostPortInfo { - res := make(schedulercache.HostPortInfo) +func (b *hostPortInfoBuilder) build() schedulernodeinfo.HostPortInfo { + res := make(schedulernodeinfo.HostPortInfo) for _, param := range b.inputs { res.Add(param.ip, param.protocol, param.port) } return res } -func newNodeInfo(requestedResource *schedulercache.Resource, - nonzeroRequest *schedulercache.Resource, +func newNodeInfo(requestedResource *schedulernodeinfo.Resource, + nonzeroRequest *schedulernodeinfo.Resource, pods []*v1.Pod, - usedPorts schedulercache.HostPortInfo, - imageStates map[string]*schedulercache.ImageStateSummary, -) *schedulercache.NodeInfo { - nodeInfo := schedulercache.NewNodeInfo(pods...) + usedPorts schedulernodeinfo.HostPortInfo, + imageStates map[string]*schedulernodeinfo.ImageStateSummary, +) *schedulernodeinfo.NodeInfo { + nodeInfo := schedulernodeinfo.NewNodeInfo(pods...) nodeInfo.SetRequestedResource(requestedResource) nodeInfo.SetNonZeroRequest(nonzeroRequest) nodeInfo.SetUsedPorts(usedPorts) @@ -108,98 +108,98 @@ func TestAssumePodScheduled(t *testing.T) { tests := []struct { pods []*v1.Pod - wNodeInfo *schedulercache.NodeInfo + wNodeInfo *schedulernodeinfo.NodeInfo }{{ pods: []*v1.Pod{testPods[0]}, wNodeInfo: newNodeInfo( - &schedulercache.Resource{ + &schedulernodeinfo.Resource{ MilliCPU: 100, Memory: 500, }, - &schedulercache.Resource{ + &schedulernodeinfo.Resource{ MilliCPU: 100, Memory: 500, }, []*v1.Pod{testPods[0]}, newHostPortInfoBuilder().add("TCP", "127.0.0.1", 80).build(), - make(map[string]*schedulercache.ImageStateSummary), + make(map[string]*schedulernodeinfo.ImageStateSummary), ), }, { pods: []*v1.Pod{testPods[1], testPods[2]}, wNodeInfo: newNodeInfo( - &schedulercache.Resource{ + &schedulernodeinfo.Resource{ MilliCPU: 300, Memory: 1524, }, - &schedulercache.Resource{ + &schedulernodeinfo.Resource{ MilliCPU: 300, Memory: 1524, }, []*v1.Pod{testPods[1], testPods[2]}, newHostPortInfoBuilder().add("TCP", "127.0.0.1", 80).add("TCP", "127.0.0.1", 8080).build(), - make(map[string]*schedulercache.ImageStateSummary), + make(map[string]*schedulernodeinfo.ImageStateSummary), ), }, { // test non-zero request pods: []*v1.Pod{testPods[3]}, wNodeInfo: newNodeInfo( - &schedulercache.Resource{ + &schedulernodeinfo.Resource{ MilliCPU: 0, Memory: 0, }, - &schedulercache.Resource{ + &schedulernodeinfo.Resource{ MilliCPU: priorityutil.DefaultMilliCPURequest, Memory: priorityutil.DefaultMemoryRequest, }, []*v1.Pod{testPods[3]}, newHostPortInfoBuilder().add("TCP", "127.0.0.1", 80).build(), - make(map[string]*schedulercache.ImageStateSummary), + make(map[string]*schedulernodeinfo.ImageStateSummary), ), }, { pods: []*v1.Pod{testPods[4]}, wNodeInfo: newNodeInfo( - &schedulercache.Resource{ + &schedulernodeinfo.Resource{ MilliCPU: 100, Memory: 500, ScalarResources: map[v1.ResourceName]int64{"example.com/foo": 3}, }, - &schedulercache.Resource{ + &schedulernodeinfo.Resource{ MilliCPU: 100, Memory: 500, }, []*v1.Pod{testPods[4]}, newHostPortInfoBuilder().add("TCP", "127.0.0.1", 80).build(), - make(map[string]*schedulercache.ImageStateSummary), + make(map[string]*schedulernodeinfo.ImageStateSummary), ), }, { pods: []*v1.Pod{testPods[4], testPods[5]}, wNodeInfo: newNodeInfo( - &schedulercache.Resource{ + &schedulernodeinfo.Resource{ MilliCPU: 300, Memory: 1524, ScalarResources: map[v1.ResourceName]int64{"example.com/foo": 8}, }, - &schedulercache.Resource{ + &schedulernodeinfo.Resource{ MilliCPU: 300, Memory: 1524, }, []*v1.Pod{testPods[4], testPods[5]}, newHostPortInfoBuilder().add("TCP", "127.0.0.1", 80).add("TCP", "127.0.0.1", 8080).build(), - make(map[string]*schedulercache.ImageStateSummary), + make(map[string]*schedulernodeinfo.ImageStateSummary), ), }, { pods: []*v1.Pod{testPods[6]}, wNodeInfo: newNodeInfo( - &schedulercache.Resource{ + &schedulernodeinfo.Resource{ MilliCPU: 100, Memory: 500, }, - &schedulercache.Resource{ + &schedulernodeinfo.Resource{ MilliCPU: 100, Memory: 500, }, []*v1.Pod{testPods[6]}, newHostPortInfoBuilder().build(), - make(map[string]*schedulercache.ImageStateSummary), + make(map[string]*schedulernodeinfo.ImageStateSummary), ), }, } @@ -253,7 +253,7 @@ func TestExpirePod(t *testing.T) { pods []*testExpirePodStruct cleanupTime time.Time - wNodeInfo *schedulercache.NodeInfo + wNodeInfo *schedulernodeinfo.NodeInfo }{{ // assumed pod would expires pods: []*testExpirePodStruct{ {pod: testPods[0], assumedTime: now}, @@ -267,17 +267,17 @@ func TestExpirePod(t *testing.T) { }, cleanupTime: now.Add(2 * ttl), wNodeInfo: newNodeInfo( - &schedulercache.Resource{ + &schedulernodeinfo.Resource{ MilliCPU: 200, Memory: 1024, }, - &schedulercache.Resource{ + &schedulernodeinfo.Resource{ MilliCPU: 200, Memory: 1024, }, []*v1.Pod{testPods[1]}, newHostPortInfoBuilder().add("TCP", "127.0.0.1", 8080).build(), - make(map[string]*schedulercache.ImageStateSummary), + make(map[string]*schedulernodeinfo.ImageStateSummary), ), }} @@ -313,22 +313,22 @@ func TestAddPodWillConfirm(t *testing.T) { podsToAssume []*v1.Pod podsToAdd []*v1.Pod - wNodeInfo *schedulercache.NodeInfo + wNodeInfo *schedulernodeinfo.NodeInfo }{{ // two pod were assumed at same time. But first one is called Add() and gets confirmed. podsToAssume: []*v1.Pod{testPods[0], testPods[1]}, podsToAdd: []*v1.Pod{testPods[0]}, wNodeInfo: newNodeInfo( - &schedulercache.Resource{ + &schedulernodeinfo.Resource{ MilliCPU: 100, Memory: 500, }, - &schedulercache.Resource{ + &schedulernodeinfo.Resource{ MilliCPU: 100, Memory: 500, }, []*v1.Pod{testPods[0]}, newHostPortInfoBuilder().add("TCP", "127.0.0.1", 80).build(), - make(map[string]*schedulercache.ImageStateSummary), + make(map[string]*schedulernodeinfo.ImageStateSummary), ), }} @@ -405,25 +405,25 @@ func TestAddPodWillReplaceAssumed(t *testing.T) { podsToAdd []*v1.Pod podsToUpdate [][]*v1.Pod - wNodeInfo map[string]*schedulercache.NodeInfo + wNodeInfo map[string]*schedulernodeinfo.NodeInfo }{{ podsToAssume: []*v1.Pod{assumedPod.DeepCopy()}, podsToAdd: []*v1.Pod{addedPod.DeepCopy()}, podsToUpdate: [][]*v1.Pod{{addedPod.DeepCopy(), updatedPod.DeepCopy()}}, - wNodeInfo: map[string]*schedulercache.NodeInfo{ + wNodeInfo: map[string]*schedulernodeinfo.NodeInfo{ "assumed-node": nil, "actual-node": newNodeInfo( - &schedulercache.Resource{ + &schedulernodeinfo.Resource{ MilliCPU: 200, Memory: 500, }, - &schedulercache.Resource{ + &schedulernodeinfo.Resource{ MilliCPU: 200, Memory: 500, }, []*v1.Pod{updatedPod.DeepCopy()}, newHostPortInfoBuilder().add("TCP", "0.0.0.0", 90).build(), - make(map[string]*schedulercache.ImageStateSummary), + make(map[string]*schedulernodeinfo.ImageStateSummary), ), }, }} @@ -463,21 +463,21 @@ func TestAddPodAfterExpiration(t *testing.T) { tests := []struct { pod *v1.Pod - wNodeInfo *schedulercache.NodeInfo + wNodeInfo *schedulernodeinfo.NodeInfo }{{ pod: basePod, wNodeInfo: newNodeInfo( - &schedulercache.Resource{ + &schedulernodeinfo.Resource{ MilliCPU: 100, Memory: 500, }, - &schedulercache.Resource{ + &schedulernodeinfo.Resource{ MilliCPU: 100, Memory: 500, }, []*v1.Pod{basePod}, newHostPortInfoBuilder().add("TCP", "127.0.0.1", 80).build(), - make(map[string]*schedulercache.ImageStateSummary), + make(map[string]*schedulernodeinfo.ImageStateSummary), ), }} @@ -516,34 +516,34 @@ func TestUpdatePod(t *testing.T) { podsToAdd []*v1.Pod podsToUpdate []*v1.Pod - wNodeInfo []*schedulercache.NodeInfo + wNodeInfo []*schedulernodeinfo.NodeInfo }{{ // add a pod and then update it twice podsToAdd: []*v1.Pod{testPods[0]}, podsToUpdate: []*v1.Pod{testPods[0], testPods[1], testPods[0]}, - wNodeInfo: []*schedulercache.NodeInfo{newNodeInfo( - &schedulercache.Resource{ + wNodeInfo: []*schedulernodeinfo.NodeInfo{newNodeInfo( + &schedulernodeinfo.Resource{ MilliCPU: 200, Memory: 1024, }, - &schedulercache.Resource{ + &schedulernodeinfo.Resource{ MilliCPU: 200, Memory: 1024, }, []*v1.Pod{testPods[1]}, newHostPortInfoBuilder().add("TCP", "127.0.0.1", 8080).build(), - make(map[string]*schedulercache.ImageStateSummary), + make(map[string]*schedulernodeinfo.ImageStateSummary), ), newNodeInfo( - &schedulercache.Resource{ + &schedulernodeinfo.Resource{ MilliCPU: 100, Memory: 500, }, - &schedulercache.Resource{ + &schedulernodeinfo.Resource{ MilliCPU: 100, Memory: 500, }, []*v1.Pod{testPods[0]}, newHostPortInfoBuilder().add("TCP", "127.0.0.1", 80).build(), - make(map[string]*schedulercache.ImageStateSummary), + make(map[string]*schedulernodeinfo.ImageStateSummary), )}, }} @@ -643,35 +643,35 @@ func TestExpireAddUpdatePod(t *testing.T) { podsToAdd []*v1.Pod podsToUpdate []*v1.Pod - wNodeInfo []*schedulercache.NodeInfo + wNodeInfo []*schedulernodeinfo.NodeInfo }{{ // Pod is assumed, expired, and added. Then it would be updated twice. podsToAssume: []*v1.Pod{testPods[0]}, podsToAdd: []*v1.Pod{testPods[0]}, podsToUpdate: []*v1.Pod{testPods[0], testPods[1], testPods[0]}, - wNodeInfo: []*schedulercache.NodeInfo{newNodeInfo( - &schedulercache.Resource{ + wNodeInfo: []*schedulernodeinfo.NodeInfo{newNodeInfo( + &schedulernodeinfo.Resource{ MilliCPU: 200, Memory: 1024, }, - &schedulercache.Resource{ + &schedulernodeinfo.Resource{ MilliCPU: 200, Memory: 1024, }, []*v1.Pod{testPods[1]}, newHostPortInfoBuilder().add("TCP", "127.0.0.1", 8080).build(), - make(map[string]*schedulercache.ImageStateSummary), + make(map[string]*schedulernodeinfo.ImageStateSummary), ), newNodeInfo( - &schedulercache.Resource{ + &schedulernodeinfo.Resource{ MilliCPU: 100, Memory: 500, }, - &schedulercache.Resource{ + &schedulernodeinfo.Resource{ MilliCPU: 100, Memory: 500, }, []*v1.Pod{testPods[0]}, newHostPortInfoBuilder().add("TCP", "127.0.0.1", 80).build(), - make(map[string]*schedulercache.ImageStateSummary), + make(map[string]*schedulernodeinfo.ImageStateSummary), )}, }} @@ -733,21 +733,21 @@ func TestEphemeralStorageResource(t *testing.T) { podE := makePodWithEphemeralStorage(nodeName, "500") tests := []struct { pod *v1.Pod - wNodeInfo *schedulercache.NodeInfo + wNodeInfo *schedulernodeinfo.NodeInfo }{ { pod: podE, wNodeInfo: newNodeInfo( - &schedulercache.Resource{ + &schedulernodeinfo.Resource{ EphemeralStorage: 500, }, - &schedulercache.Resource{ + &schedulernodeinfo.Resource{ MilliCPU: priorityutil.DefaultMilliCPURequest, Memory: priorityutil.DefaultMemoryRequest, }, []*v1.Pod{podE}, - schedulercache.HostPortInfo{}, - make(map[string]*schedulercache.ImageStateSummary), + schedulernodeinfo.HostPortInfo{}, + make(map[string]*schedulernodeinfo.ImageStateSummary), ), }, } @@ -778,21 +778,21 @@ func TestRemovePod(t *testing.T) { basePod := makeBasePod(t, nodeName, "test", "100m", "500", "", []v1.ContainerPort{{HostIP: "127.0.0.1", HostPort: 80, Protocol: "TCP"}}) tests := []struct { pod *v1.Pod - wNodeInfo *schedulercache.NodeInfo + wNodeInfo *schedulernodeinfo.NodeInfo }{{ pod: basePod, wNodeInfo: newNodeInfo( - &schedulercache.Resource{ + &schedulernodeinfo.Resource{ MilliCPU: 100, Memory: 500, }, - &schedulercache.Resource{ + &schedulernodeinfo.Resource{ MilliCPU: 100, Memory: 500, }, []*v1.Pod{basePod}, newHostPortInfoBuilder().add("TCP", "127.0.0.1", 80).build(), - make(map[string]*schedulercache.ImageStateSummary), + make(map[string]*schedulernodeinfo.ImageStateSummary), ), }} @@ -872,7 +872,7 @@ func TestForgetPod(t *testing.T) { // getResourceRequest returns the resource request of all containers in Pods; // excuding initContainers. func getResourceRequest(pod *v1.Pod) v1.ResourceList { - result := &schedulercache.Resource{} + result := &schedulernodeinfo.Resource{} for _, container := range pod.Spec.Containers { result.Add(container.Resources.Requests) } @@ -881,13 +881,13 @@ func getResourceRequest(pod *v1.Pod) v1.ResourceList { } // buildNodeInfo creates a NodeInfo by simulating node operations in cache. -func buildNodeInfo(node *v1.Node, pods []*v1.Pod) *schedulercache.NodeInfo { - expected := schedulercache.NewNodeInfo() +func buildNodeInfo(node *v1.Node, pods []*v1.Pod) *schedulernodeinfo.NodeInfo { + expected := schedulernodeinfo.NewNodeInfo() // Simulate SetNode. expected.SetNode(node) - expected.SetAllocatableResource(schedulercache.NewResource(node.Status.Allocatable)) + expected.SetAllocatableResource(schedulernodeinfo.NewResource(node.Status.Allocatable)) expected.SetTaints(node.Spec.Taints) expected.SetGeneration(expected.GetGeneration() + 1) @@ -1068,7 +1068,7 @@ func TestNodeOperators(t *testing.T) { } // Case 2: dump cached nodes successfully. - cachedNodes := map[string]*schedulercache.NodeInfo{} + cachedNodes := map[string]*schedulernodeinfo.NodeInfo{} cache.UpdateNodeNameToInfoMap(cachedNodes) newNode, found := cachedNodes[node.Name] if !found || len(cachedNodes) != 1 { @@ -1089,7 +1089,7 @@ func TestNodeOperators(t *testing.T) { cache.UpdateNode(nil, node) got, found = cache.nodes[node.Name] if !found { - t.Errorf("Failed to find node %v in schedulercache after UpdateNode.", node.Name) + t.Errorf("Failed to find node %v in schedulernodeinfo after UpdateNode.", node.Name) } if got.GetGeneration() <= expected.GetGeneration() { t.Errorf("Generation is not incremented. got: %v, expected: %v", got.GetGeneration(), expected.GetGeneration()) @@ -1097,7 +1097,7 @@ func TestNodeOperators(t *testing.T) { expected.SetGeneration(got.GetGeneration()) if !reflect.DeepEqual(got, expected) { - t.Errorf("Failed to update node in schedulercache:\n got: %+v \nexpected: %+v", got, expected) + t.Errorf("Failed to update node in schedulernodeinfo:\n got: %+v \nexpected: %+v", got, expected) } // Check nodeTree after update if cache.nodeTree.NumNodes() != 1 || cache.nodeTree.Next() != node.Name { @@ -1131,7 +1131,7 @@ func BenchmarkUpdate1kNodes30kPods(b *testing.B) { cache := setupCacheOf1kNodes30kPods(b) b.ResetTimer() for n := 0; n < b.N; n++ { - cachedNodes := map[string]*schedulercache.NodeInfo{} + cachedNodes := map[string]*schedulernodeinfo.NodeInfo{} cache.UpdateNodeNameToInfoMap(cachedNodes) } } diff --git a/pkg/scheduler/internal/cache/debugger/BUILD b/pkg/scheduler/internal/cache/debugger/BUILD index 320c9734fba..bab16194a5f 100644 --- a/pkg/scheduler/internal/cache/debugger/BUILD +++ b/pkg/scheduler/internal/cache/debugger/BUILD @@ -6,13 +6,15 @@ go_library( "comparer.go", "debugger.go", "dumper.go", + "signal.go", + "signal_windows.go", ], importpath = "k8s.io/kubernetes/pkg/scheduler/internal/cache/debugger", visibility = ["//pkg/scheduler:__subpackages__"], deps = [ - "//pkg/scheduler/cache:go_default_library", "//pkg/scheduler/internal/cache:go_default_library", "//pkg/scheduler/internal/queue:go_default_library", + "//pkg/scheduler/nodeinfo:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/labels:go_default_library", "//staging/src/k8s.io/client-go/listers/core/v1:go_default_library", @@ -25,7 +27,7 @@ go_test( srcs = ["comparer_test.go"], embed = [":go_default_library"], deps = [ - "//pkg/scheduler/cache:go_default_library", + "//pkg/scheduler/nodeinfo:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/types:go_default_library", ], diff --git a/pkg/scheduler/internal/cache/debugger/comparer.go b/pkg/scheduler/internal/cache/debugger/comparer.go index e78df11184a..ac0c1ff4d62 100644 --- a/pkg/scheduler/internal/cache/debugger/comparer.go +++ b/pkg/scheduler/internal/cache/debugger/comparer.go @@ -24,9 +24,9 @@ import ( "k8s.io/apimachinery/pkg/labels" corelisters "k8s.io/client-go/listers/core/v1" "k8s.io/klog" - schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" schedulerinternalcache "k8s.io/kubernetes/pkg/scheduler/internal/cache" internalqueue "k8s.io/kubernetes/pkg/scheduler/internal/queue" + schedulernodeinfo "k8s.io/kubernetes/pkg/scheduler/nodeinfo" ) // CacheComparer is an implementation of the Scheduler's cache comparer. @@ -54,13 +54,13 @@ func (c *CacheComparer) Compare() error { snapshot := c.Cache.Snapshot() - waitingPods := c.PodQueue.WaitingPods() + pendingPods := c.PodQueue.PendingPods() if missed, redundant := c.CompareNodes(nodes, snapshot.Nodes); len(missed)+len(redundant) != 0 { klog.Warningf("cache mismatch: missed nodes: %s; redundant nodes: %s", missed, redundant) } - if missed, redundant := c.ComparePods(pods, waitingPods, snapshot.Nodes); len(missed)+len(redundant) != 0 { + if missed, redundant := c.ComparePods(pods, pendingPods, snapshot.Nodes); len(missed)+len(redundant) != 0 { klog.Warningf("cache mismatch: missed pods: %s; redundant pods: %s", missed, redundant) } @@ -68,7 +68,7 @@ func (c *CacheComparer) Compare() error { } // CompareNodes compares actual nodes with cached nodes. -func (c *CacheComparer) CompareNodes(nodes []*v1.Node, nodeinfos map[string]*schedulercache.NodeInfo) (missed, redundant []string) { +func (c *CacheComparer) CompareNodes(nodes []*v1.Node, nodeinfos map[string]*schedulernodeinfo.NodeInfo) (missed, redundant []string) { actual := []string{} for _, node := range nodes { actual = append(actual, node.Name) @@ -83,7 +83,7 @@ func (c *CacheComparer) CompareNodes(nodes []*v1.Node, nodeinfos map[string]*sch } // ComparePods compares actual pods with cached pods. -func (c *CacheComparer) ComparePods(pods, waitingPods []*v1.Pod, nodeinfos map[string]*schedulercache.NodeInfo) (missed, redundant []string) { +func (c *CacheComparer) ComparePods(pods, waitingPods []*v1.Pod, nodeinfos map[string]*schedulernodeinfo.NodeInfo) (missed, redundant []string) { actual := []string{} for _, pod := range pods { actual = append(actual, string(pod.UID)) diff --git a/pkg/scheduler/internal/cache/debugger/comparer_test.go b/pkg/scheduler/internal/cache/debugger/comparer_test.go index 967b4027b5d..ab1e1ee5e47 100644 --- a/pkg/scheduler/internal/cache/debugger/comparer_test.go +++ b/pkg/scheduler/internal/cache/debugger/comparer_test.go @@ -22,7 +22,7 @@ import ( "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/types" - schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" + schedulernodeinfo "k8s.io/kubernetes/pkg/scheduler/nodeinfo" ) func TestCompareNodes(t *testing.T) { @@ -72,9 +72,9 @@ func testCompareNodes(actual, cached, missing, redundant []string, t *testing.T) nodes = append(nodes, node) } - nodeInfo := make(map[string]*schedulercache.NodeInfo) + nodeInfo := make(map[string]*schedulernodeinfo.NodeInfo) for _, nodeName := range cached { - nodeInfo[nodeName] = &schedulercache.NodeInfo{} + nodeInfo[nodeName] = &schedulernodeinfo.NodeInfo{} } m, r := compare.CompareNodes(nodes, nodeInfo) @@ -170,14 +170,14 @@ func testComparePods(actual, cached, queued, missing, redundant []string, t *tes queuedPods = append(queuedPods, pod) } - nodeInfo := make(map[string]*schedulercache.NodeInfo) + nodeInfo := make(map[string]*schedulernodeinfo.NodeInfo) for _, uid := range cached { pod := &v1.Pod{} pod.UID = types.UID(uid) pod.Namespace = "ns" pod.Name = uid - nodeInfo[uid] = schedulercache.NewNodeInfo(pod) + nodeInfo[uid] = schedulernodeinfo.NewNodeInfo(pod) } m, r := compare.ComparePods(pods, queuedPods, nodeInfo) diff --git a/pkg/scheduler/internal/cache/debugger/debugger.go b/pkg/scheduler/internal/cache/debugger/debugger.go index 64428d5693e..d8839ec67e8 100644 --- a/pkg/scheduler/internal/cache/debugger/debugger.go +++ b/pkg/scheduler/internal/cache/debugger/debugger.go @@ -17,6 +17,9 @@ limitations under the License. package debugger import ( + "os" + "os/signal" + corelisters "k8s.io/client-go/listers/core/v1" internalcache "k8s.io/kubernetes/pkg/scheduler/internal/cache" internalqueue "k8s.io/kubernetes/pkg/scheduler/internal/queue" @@ -48,3 +51,22 @@ func New( }, } } + +// ListenForSignal starts a goroutine that will trigger the CacheDebugger's +// behavior when the process receives SIGINT (Windows) or SIGUSER2 (non-Windows). +func (d *CacheDebugger) ListenForSignal(stopCh <-chan struct{}) { + ch := make(chan os.Signal, 1) + signal.Notify(ch, compareSignal) + + go func() { + for { + select { + case <-stopCh: + return + case <-ch: + d.Comparer.Compare() + d.Dumper.DumpAll() + } + } + }() +} diff --git a/pkg/scheduler/internal/cache/debugger/dumper.go b/pkg/scheduler/internal/cache/debugger/dumper.go index b9084d377d9..497d4b1b71f 100644 --- a/pkg/scheduler/internal/cache/debugger/dumper.go +++ b/pkg/scheduler/internal/cache/debugger/dumper.go @@ -23,9 +23,9 @@ import ( "k8s.io/klog" "k8s.io/api/core/v1" - "k8s.io/kubernetes/pkg/scheduler/cache" internalcache "k8s.io/kubernetes/pkg/scheduler/internal/cache" "k8s.io/kubernetes/pkg/scheduler/internal/queue" + schedulernodeinfo "k8s.io/kubernetes/pkg/scheduler/nodeinfo" ) // CacheDumper writes some information from the scheduler cache and the scheduling queue to the @@ -52,16 +52,16 @@ func (d *CacheDumper) dumpNodes() { // dumpSchedulingQueue writes pods in the scheduling queue to the scheduler logs. func (d *CacheDumper) dumpSchedulingQueue() { - waitingPods := d.podQueue.WaitingPods() + pendingPods := d.podQueue.PendingPods() var podData strings.Builder - for _, p := range waitingPods { + for _, p := range pendingPods { podData.WriteString(printPod(p)) } klog.Infof("Dump of scheduling queue:\n%s", podData.String()) } // printNodeInfo writes parts of NodeInfo to a string. -func printNodeInfo(n *cache.NodeInfo) string { +func printNodeInfo(n *schedulernodeinfo.NodeInfo) string { var nodeData strings.Builder nodeData.WriteString(fmt.Sprintf("\nNode name: %+v\nRequested Resources: %+v\nAllocatable Resources:%+v\nNumber of Pods: %v\nPods:\n", n.Node().Name, n.RequestedResource(), n.AllocatableResource(), len(n.Pods()))) diff --git a/pkg/scheduler/factory/signal.go b/pkg/scheduler/internal/cache/debugger/signal.go similarity index 97% rename from pkg/scheduler/factory/signal.go rename to pkg/scheduler/internal/cache/debugger/signal.go index 8ec17048ebb..9a56b04d8d7 100644 --- a/pkg/scheduler/factory/signal.go +++ b/pkg/scheduler/internal/cache/debugger/signal.go @@ -16,7 +16,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package factory +package debugger import "syscall" diff --git a/pkg/scheduler/factory/signal_windows.go b/pkg/scheduler/internal/cache/debugger/signal_windows.go similarity index 97% rename from pkg/scheduler/factory/signal_windows.go rename to pkg/scheduler/internal/cache/debugger/signal_windows.go index 9df239874c3..25c015b0e17 100644 --- a/pkg/scheduler/factory/signal_windows.go +++ b/pkg/scheduler/internal/cache/debugger/signal_windows.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package factory +package debugger import "os" diff --git a/pkg/scheduler/internal/cache/fake/BUILD b/pkg/scheduler/internal/cache/fake/BUILD index ba642f5ea71..06c1d501a8a 100644 --- a/pkg/scheduler/internal/cache/fake/BUILD +++ b/pkg/scheduler/internal/cache/fake/BUILD @@ -6,8 +6,9 @@ go_library( importpath = "k8s.io/kubernetes/pkg/scheduler/internal/cache/fake", visibility = ["//pkg/scheduler:__subpackages__"], deps = [ - "//pkg/scheduler/cache:go_default_library", + "//pkg/scheduler/algorithm:go_default_library", "//pkg/scheduler/internal/cache:go_default_library", + "//pkg/scheduler/nodeinfo:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/labels:go_default_library", ], diff --git a/pkg/scheduler/internal/cache/fake/fake_cache.go b/pkg/scheduler/internal/cache/fake/fake_cache.go index 82419e9600f..05873d35cb7 100644 --- a/pkg/scheduler/internal/cache/fake/fake_cache.go +++ b/pkg/scheduler/internal/cache/fake/fake_cache.go @@ -19,8 +19,9 @@ package fake import ( "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/labels" - schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" + "k8s.io/kubernetes/pkg/scheduler/algorithm" schedulerinternalcache "k8s.io/kubernetes/pkg/scheduler/internal/cache" + schedulernodeinfo "k8s.io/kubernetes/pkg/scheduler/nodeinfo" ) // Cache is used for testing @@ -75,7 +76,7 @@ func (c *Cache) UpdateNode(oldNode, newNode *v1.Node) error { return nil } func (c *Cache) RemoveNode(node *v1.Node) error { return nil } // UpdateNodeNameToInfoMap is a fake method for testing. -func (c *Cache) UpdateNodeNameToInfoMap(infoMap map[string]*schedulercache.NodeInfo) error { +func (c *Cache) UpdateNodeNameToInfoMap(infoMap map[string]*schedulernodeinfo.NodeInfo) error { return nil } @@ -83,7 +84,7 @@ func (c *Cache) UpdateNodeNameToInfoMap(infoMap map[string]*schedulercache.NodeI func (c *Cache) List(s labels.Selector) ([]*v1.Pod, error) { return nil, nil } // FilteredList is a fake method for testing. -func (c *Cache) FilteredList(filter schedulerinternalcache.PodFilter, selector labels.Selector) ([]*v1.Pod, error) { +func (c *Cache) FilteredList(filter algorithm.PodFilter, selector labels.Selector) ([]*v1.Pod, error) { return nil, nil } diff --git a/pkg/scheduler/internal/cache/interface.go b/pkg/scheduler/internal/cache/interface.go index 878c2aa0741..204659d8625 100644 --- a/pkg/scheduler/internal/cache/interface.go +++ b/pkg/scheduler/internal/cache/interface.go @@ -19,12 +19,10 @@ package cache import ( "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/labels" - schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" + "k8s.io/kubernetes/pkg/scheduler/algorithm" + schedulernodeinfo "k8s.io/kubernetes/pkg/scheduler/nodeinfo" ) -// PodFilter is a function to filter a pod. If pod passed return true else return false. -type PodFilter func(*v1.Pod) bool - // Cache collects pods' information and provides node-level aggregated information. // It's intended for generic scheduler to do efficient lookup. // Cache's operations are pod centric. It does incremental updates based on pod events. @@ -100,13 +98,13 @@ type Cache interface { // UpdateNodeNameToInfoMap updates the passed infoMap to the current contents of Cache. // The node info contains aggregated information of pods scheduled (including assumed to be) // on this node. - UpdateNodeNameToInfoMap(infoMap map[string]*schedulercache.NodeInfo) error + UpdateNodeNameToInfoMap(infoMap map[string]*schedulernodeinfo.NodeInfo) error // List lists all cached pods (including assumed ones). List(labels.Selector) ([]*v1.Pod, error) // FilteredList returns all cached pods that pass the filter. - FilteredList(filter PodFilter, selector labels.Selector) ([]*v1.Pod, error) + FilteredList(filter algorithm.PodFilter, selector labels.Selector) ([]*v1.Pod, error) // Snapshot takes a snapshot on current cache Snapshot() *Snapshot @@ -118,5 +116,5 @@ type Cache interface { // Snapshot is a snapshot of cache state type Snapshot struct { AssumedPods map[string]bool - Nodes map[string]*schedulercache.NodeInfo + Nodes map[string]*schedulernodeinfo.NodeInfo } diff --git a/pkg/scheduler/internal/queue/BUILD b/pkg/scheduler/internal/queue/BUILD index c675f859248..ea7b66fe3f4 100644 --- a/pkg/scheduler/internal/queue/BUILD +++ b/pkg/scheduler/internal/queue/BUILD @@ -12,6 +12,8 @@ go_library( "//pkg/scheduler/util:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + "//staging/src/k8s.io/apimachinery/pkg/types:go_default_library", + "//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library", "//staging/src/k8s.io/client-go/tools/cache:go_default_library", "//vendor/k8s.io/klog:go_default_library", ], @@ -22,9 +24,11 @@ go_test( srcs = ["scheduling_queue_test.go"], embed = [":go_default_library"], deps = [ + "//pkg/api/v1/pod:go_default_library", "//pkg/scheduler/util:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + "//staging/src/k8s.io/apimachinery/pkg/types:go_default_library", ], ) diff --git a/pkg/scheduler/internal/queue/scheduling_queue.go b/pkg/scheduler/internal/queue/scheduling_queue.go index 6f5aa682c98..17e17abe824 100644 --- a/pkg/scheduler/internal/queue/scheduling_queue.go +++ b/pkg/scheduler/internal/queue/scheduling_queue.go @@ -27,15 +27,17 @@ limitations under the License. package queue import ( - "container/heap" "fmt" "reflect" "sync" + "time" "k8s.io/klog" "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + ktypes "k8s.io/apimachinery/pkg/types" + "k8s.io/apimachinery/pkg/util/wait" "k8s.io/client-go/tools/cache" podutil "k8s.io/kubernetes/pkg/api/v1/pod" "k8s.io/kubernetes/pkg/scheduler/algorithm/predicates" @@ -62,20 +64,25 @@ type SchedulingQueue interface { MoveAllToActiveQueue() AssignedPodAdded(pod *v1.Pod) AssignedPodUpdated(pod *v1.Pod) - WaitingPodsForNode(nodeName string) []*v1.Pod - WaitingPods() []*v1.Pod + NominatedPodsForNode(nodeName string) []*v1.Pod + PendingPods() []*v1.Pod // Close closes the SchedulingQueue so that the goroutine which is // waiting to pop items can exit gracefully. Close() + // UpdateNominatedPodForNode adds the given pod to the nominated pod map or + // updates it if it already exists. + UpdateNominatedPodForNode(pod *v1.Pod, nodeName string) // DeleteNominatedPodIfExists deletes nominatedPod from internal cache DeleteNominatedPodIfExists(pod *v1.Pod) + // NumUnschedulablePods returns the number of unschedulable pods exist in the SchedulingQueue. + NumUnschedulablePods() int } // NewSchedulingQueue initializes a new scheduling queue. If pod priority is // enabled a priority queue is returned. If it is disabled, a FIFO is returned. -func NewSchedulingQueue() SchedulingQueue { +func NewSchedulingQueue(stop <-chan struct{}) SchedulingQueue { if util.PodPriorityEnabled() { - return NewPriorityQueue() + return NewPriorityQueue(stop) } return NewFIFO() } @@ -127,8 +134,8 @@ func (f *FIFO) Pop() (*v1.Pod, error) { return result.(*v1.Pod), err } -// WaitingPods returns all the waiting pods in the queue. -func (f *FIFO) WaitingPods() []*v1.Pod { +// PendingPods returns all the pods in the queue. +func (f *FIFO) PendingPods() []*v1.Pod { result := []*v1.Pod{} for _, pod := range f.FIFO.List() { result = append(result, pod.(*v1.Pod)) @@ -148,9 +155,9 @@ func (f *FIFO) AssignedPodUpdated(pod *v1.Pod) {} // MoveAllToActiveQueue does nothing in FIFO as all pods are always in the active queue. func (f *FIFO) MoveAllToActiveQueue() {} -// WaitingPodsForNode returns pods that are nominated to run on the given node, +// NominatedPodsForNode returns pods that are nominated to run on the given node, // but FIFO does not support it. -func (f *FIFO) WaitingPodsForNode(nodeName string) []*v1.Pod { +func (f *FIFO) NominatedPodsForNode(nodeName string) []*v1.Pod { return nil } @@ -162,6 +169,14 @@ func (f *FIFO) Close() { // DeleteNominatedPodIfExists does nothing in FIFO. func (f *FIFO) DeleteNominatedPodIfExists(pod *v1.Pod) {} +// UpdateNominatedPodForNode does nothing in FIFO. +func (f *FIFO) UpdateNominatedPodForNode(pod *v1.Pod, nodeName string) {} + +// NumUnschedulablePods returns the number of unschedulable pods exist in the SchedulingQueue. +func (f *FIFO) NumUnschedulablePods() int { + return 0 +} + // NewFIFO creates a FIFO object. func NewFIFO() *FIFO { return &FIFO{FIFO: cache.NewFIFO(cache.MetaNamespaceKeyFunc)} @@ -174,23 +189,31 @@ func NominatedNodeName(pod *v1.Pod) string { // PriorityQueue implements a scheduling queue. It is an alternative to FIFO. // The head of PriorityQueue is the highest priority pending pod. This structure -// has two sub queues. One sub-queue holds pods that are being considered for +// has three sub queues. One sub-queue holds pods that are being considered for // scheduling. This is called activeQ and is a Heap. Another queue holds // pods that are already tried and are determined to be unschedulable. The latter -// is called unschedulableQ. +// is called unschedulableQ. The third queue holds pods that are moved from +// unschedulable queues and will be moved to active queue when backoff are completed. type PriorityQueue struct { + stop <-chan struct{} + clock util.Clock + // podBackoff tracks backoff for pods attempting to be rescheduled + podBackoff *util.PodBackoff + lock sync.RWMutex cond sync.Cond // activeQ is heap structure that scheduler actively looks at to find pods to // schedule. Head of heap is the highest priority pod. - activeQ *Heap + activeQ *util.Heap + // podBackoffQ is a heap ordered by backoff expiry. Pods which have completed backoff + // are popped from this heap before the scheduler looks at activeQ + podBackoffQ *util.Heap // unschedulableQ holds pods that have been tried and determined unschedulable. unschedulableQ *UnschedulablePodsMap - // nominatedPods is a map keyed by a node name and the value is a list of - // pods which are nominated to run on the node. These are pods which can be in - // the activeQ or unschedulableQ. - nominatedPods map[string][]*v1.Pod + // nominatedPods is a structures that stores pods which are nominated to run + // on nodes. + nominatedPods *nominatedPodMap // receivedMoveRequest is set to true whenever we receive a request to move a // pod from the unschedulableQ to the activeQ, and is set to false, when we pop // a pod from the activeQ. It indicates if we received a move request when a @@ -206,79 +229,80 @@ type PriorityQueue struct { // Making sure that PriorityQueue implements SchedulingQueue. var _ = SchedulingQueue(&PriorityQueue{}) +// podTimeStamp returns pod's last schedule time or its creation time if the +// scheduler has never tried scheduling it. +func podTimestamp(pod *v1.Pod) *metav1.Time { + _, condition := podutil.GetPodCondition(&pod.Status, v1.PodScheduled) + if condition == nil { + return &pod.CreationTimestamp + } + return &condition.LastTransitionTime +} + +// activeQComp is the function used by the activeQ heap algorithm to sort pods. +// It sorts pods based on their priority. When priorities are equal, it uses +// podTimestamp. +func activeQComp(pod1, pod2 interface{}) bool { + p1 := pod1.(*v1.Pod) + p2 := pod2.(*v1.Pod) + prio1 := util.GetPodPriority(p1) + prio2 := util.GetPodPriority(p2) + return (prio1 > prio2) || (prio1 == prio2 && podTimestamp(p1).Before(podTimestamp(p2))) +} + // NewPriorityQueue creates a PriorityQueue object. -func NewPriorityQueue() *PriorityQueue { +func NewPriorityQueue(stop <-chan struct{}) *PriorityQueue { + return NewPriorityQueueWithClock(stop, util.RealClock{}) +} + +// NewPriorityQueueWithClock creates a PriorityQueue which uses the passed clock for time. +func NewPriorityQueueWithClock(stop <-chan struct{}, clock util.Clock) *PriorityQueue { pq := &PriorityQueue{ - activeQ: newHeap(cache.MetaNamespaceKeyFunc, util.HigherPriorityPod), + clock: clock, + stop: stop, + podBackoff: util.CreatePodBackoffWithClock(1*time.Second, 10*time.Second, clock), + activeQ: util.NewHeap(cache.MetaNamespaceKeyFunc, activeQComp), unschedulableQ: newUnschedulablePodsMap(), - nominatedPods: map[string][]*v1.Pod{}, + nominatedPods: newNominatedPodMap(), } pq.cond.L = &pq.lock + pq.podBackoffQ = util.NewHeap(cache.MetaNamespaceKeyFunc, pq.podsCompareBackoffCompleted) + + pq.run() + return pq } -// addNominatedPodIfNeeded adds a pod to nominatedPods if it has a NominatedNodeName and it does not -// already exist in the map. Adding an existing pod is not going to update the pod. -func (p *PriorityQueue) addNominatedPodIfNeeded(pod *v1.Pod) { - nnn := NominatedNodeName(pod) - if len(nnn) > 0 { - for _, np := range p.nominatedPods[nnn] { - if np.UID == pod.UID { - klog.V(4).Infof("Pod %v/%v already exists in the nominated map!", pod.Namespace, pod.Name) - return - } - } - p.nominatedPods[nnn] = append(p.nominatedPods[nnn], pod) - } -} - -// deleteNominatedPodIfExists deletes a pod from the nominatedPods. -// NOTE: this function assumes lock has been acquired in caller. -func (p *PriorityQueue) deleteNominatedPodIfExists(pod *v1.Pod) { - nnn := NominatedNodeName(pod) - if len(nnn) > 0 { - for i, np := range p.nominatedPods[nnn] { - if np.UID == pod.UID { - p.nominatedPods[nnn] = append(p.nominatedPods[nnn][:i], p.nominatedPods[nnn][i+1:]...) - if len(p.nominatedPods[nnn]) == 0 { - delete(p.nominatedPods, nnn) - } - break - } - } - } -} - -// updateNominatedPod updates a pod in the nominatedPods. -func (p *PriorityQueue) updateNominatedPod(oldPod, newPod *v1.Pod) { - // Even if the nominated node name of the Pod is not changed, we must delete and add it again - // to ensure that its pointer is updated. - p.deleteNominatedPodIfExists(oldPod) - p.addNominatedPodIfNeeded(newPod) +// run starts the goroutine to pump from podBackoffQ to activeQ +func (p *PriorityQueue) run() { + go wait.Until(p.flushBackoffQCompleted, 1.0*time.Second, p.stop) } // Add adds a pod to the active queue. It should be called only when a new pod -// is added so there is no chance the pod is already in either queue. +// is added so there is no chance the pod is already in active/unschedulable/backoff queues func (p *PriorityQueue) Add(pod *v1.Pod) error { p.lock.Lock() defer p.lock.Unlock() - err := p.activeQ.Add(pod) - if err != nil { + if err := p.activeQ.Add(pod); err != nil { klog.Errorf("Error adding pod %v/%v to the scheduling queue: %v", pod.Namespace, pod.Name, err) - } else { - if p.unschedulableQ.get(pod) != nil { - klog.Errorf("Error: pod %v/%v is already in the unschedulable queue.", pod.Namespace, pod.Name) - p.deleteNominatedPodIfExists(pod) - p.unschedulableQ.delete(pod) - } - p.addNominatedPodIfNeeded(pod) - p.cond.Broadcast() + return err } - return err + if p.unschedulableQ.get(pod) != nil { + klog.Errorf("Error: pod %v/%v is already in the unschedulable queue.", pod.Namespace, pod.Name) + p.unschedulableQ.delete(pod) + } + // Delete pod from backoffQ if it is backing off + if err := p.podBackoffQ.Delete(pod); err == nil { + klog.Errorf("Error: pod %v/%v is already in the podBackoff queue.", pod.Namespace, pod.Name) + } + p.nominatedPods.add(pod, "") + p.cond.Broadcast() + + return nil } // AddIfNotPresent adds a pod to the active queue if it is not present in any of -// the two queues. If it is present in any, it doesn't do any thing. +// the queues. If it is present in any, it doesn't do any thing. func (p *PriorityQueue) AddIfNotPresent(pod *v1.Pod) error { p.lock.Lock() defer p.lock.Unlock() @@ -288,11 +312,14 @@ func (p *PriorityQueue) AddIfNotPresent(pod *v1.Pod) error { if _, exists, _ := p.activeQ.Get(pod); exists { return nil } + if _, exists, _ := p.podBackoffQ.Get(pod); exists { + return nil + } err := p.activeQ.Add(pod) if err != nil { klog.Errorf("Error adding pod %v/%v to the scheduling queue: %v", pod.Namespace, pod.Name, err) } else { - p.addNominatedPodIfNeeded(pod) + p.nominatedPods.add(pod, "") p.cond.Broadcast() } return err @@ -303,9 +330,45 @@ func isPodUnschedulable(pod *v1.Pod) bool { return cond != nil && cond.Status == v1.ConditionFalse && cond.Reason == v1.PodReasonUnschedulable } -// AddUnschedulableIfNotPresent does nothing if the pod is present in either -// queue. Otherwise it adds the pod to the unschedulable queue if -// p.receivedMoveRequest is false, and to the activeQ if p.receivedMoveRequest is true. +// nsNameForPod returns a namespacedname for a pod +func nsNameForPod(pod *v1.Pod) ktypes.NamespacedName { + return ktypes.NamespacedName{ + Namespace: pod.Namespace, + Name: pod.Name, + } +} + +// clearPodBackoff clears all backoff state for a pod (resets expiry) +func (p *PriorityQueue) clearPodBackoff(pod *v1.Pod) { + p.podBackoff.ClearPodBackoff(nsNameForPod(pod)) +} + +// isPodBackingOff returns whether a pod is currently undergoing backoff in the podBackoff structure +func (p *PriorityQueue) isPodBackingOff(pod *v1.Pod) bool { + boTime, exists := p.podBackoff.GetBackoffTime(nsNameForPod(pod)) + if !exists { + return false + } + return boTime.After(p.clock.Now()) +} + +// backoffPod checks if pod is currently undergoing backoff. If it is not it updates the backoff +// timeout otherwise it does nothing. +func (p *PriorityQueue) backoffPod(pod *v1.Pod) { + p.podBackoff.Gc() + + podID := nsNameForPod(pod) + boTime, found := p.podBackoff.GetBackoffTime(podID) + if !found || boTime.Before(p.clock.Now()) { + p.podBackoff.BackoffPod(podID) + } +} + +// AddUnschedulableIfNotPresent does nothing if the pod is present in any +// queue. If pod is unschedulable, it adds pod to unschedulable queue if +// p.receivedMoveRequest is false or to backoff queue if p.receivedMoveRequest +// is true but pod is subject to backoff. In other cases, it adds pod to active +// queue. func (p *PriorityQueue) AddUnschedulableIfNotPresent(pod *v1.Pod) error { p.lock.Lock() defer p.lock.Unlock() @@ -315,26 +378,75 @@ func (p *PriorityQueue) AddUnschedulableIfNotPresent(pod *v1.Pod) error { if _, exists, _ := p.activeQ.Get(pod); exists { return fmt.Errorf("pod is already present in the activeQ") } + if _, exists, _ := p.podBackoffQ.Get(pod); exists { + return fmt.Errorf("pod is already present in the backoffQ") + } if !p.receivedMoveRequest && isPodUnschedulable(pod) { + p.backoffPod(pod) p.unschedulableQ.addOrUpdate(pod) - p.addNominatedPodIfNeeded(pod) + p.nominatedPods.add(pod, "") return nil } + + // If a move request has been received and the pod is subject to backoff, move it to the BackoffQ. + if p.isPodBackingOff(pod) && isPodUnschedulable(pod) { + err := p.podBackoffQ.Add(pod) + if err != nil { + klog.Errorf("Error adding pod %v to the backoff queue: %v", pod.Name, err) + } else { + p.nominatedPods.add(pod, "") + } + return err + } + err := p.activeQ.Add(pod) if err == nil { - p.addNominatedPodIfNeeded(pod) + p.nominatedPods.add(pod, "") p.cond.Broadcast() } return err } +// flushBackoffQCompleted Moves all pods from backoffQ which have completed backoff in to activeQ +func (p *PriorityQueue) flushBackoffQCompleted() { + p.lock.Lock() + defer p.lock.Unlock() + + for { + rawPod := p.podBackoffQ.Peek() + if rawPod == nil { + return + } + pod := rawPod.(*v1.Pod) + boTime, found := p.podBackoff.GetBackoffTime(nsNameForPod(pod)) + if !found { + klog.Errorf("Unable to find backoff value for pod %v in backoffQ", nsNameForPod(pod)) + p.podBackoffQ.Pop() + p.activeQ.Add(pod) + defer p.cond.Broadcast() + continue + } + + if boTime.After(p.clock.Now()) { + return + } + _, err := p.podBackoffQ.Pop() + if err != nil { + klog.Errorf("Unable to pop pod %v from backoffQ despite backoff completion.", nsNameForPod(pod)) + return + } + p.activeQ.Add(pod) + defer p.cond.Broadcast() + } +} + // Pop removes the head of the active queue and returns it. It blocks if the // activeQ is empty and waits until a new item is added to the queue. It also // clears receivedMoveRequest to mark the beginning of a new scheduling cycle. func (p *PriorityQueue) Pop() (*v1.Pod, error) { p.lock.Lock() defer p.lock.Unlock() - for len(p.activeQ.data.queue) == 0 { + for p.activeQ.Len() == 0 { // When the queue is empty, invocation of Pop() is blocked until new item is enqueued. // When Close() is called, the p.closed is set and the condition is broadcast, // which causes this loop to continue and return from the Pop(). @@ -365,22 +477,40 @@ func isPodUpdated(oldPod, newPod *v1.Pod) bool { return !reflect.DeepEqual(strip(oldPod), strip(newPod)) } -// Update updates a pod in the active queue if present. Otherwise, it removes -// the item from the unschedulable queue and adds the updated one to the active -// queue. +// Update updates a pod in the active or backoff queue if present. Otherwise, it removes +// the item from the unschedulable queue if pod is updated in a way that it may +// become schedulable and adds the updated one to the active queue. +// If pod is not present in any of the queues, it is added to the active queue. func (p *PriorityQueue) Update(oldPod, newPod *v1.Pod) error { p.lock.Lock() defer p.lock.Unlock() - // If the pod is already in the active queue, just update it there. - if _, exists, _ := p.activeQ.Get(newPod); exists { - p.updateNominatedPod(oldPod, newPod) - err := p.activeQ.Update(newPod) - return err + + if oldPod != nil { + // If the pod is already in the active queue, just update it there. + if _, exists, _ := p.activeQ.Get(oldPod); exists { + p.nominatedPods.update(oldPod, newPod) + err := p.activeQ.Update(newPod) + return err + } + + // If the pod is in the backoff queue, update it there. + if _, exists, _ := p.podBackoffQ.Get(oldPod); exists { + p.nominatedPods.update(oldPod, newPod) + p.podBackoffQ.Delete(newPod) + err := p.activeQ.Add(newPod) + if err == nil { + p.cond.Broadcast() + } + return err + } } + // If the pod is in the unschedulable queue, updating it may make it schedulable. if usPod := p.unschedulableQ.get(newPod); usPod != nil { - p.updateNominatedPod(oldPod, newPod) + p.nominatedPods.update(oldPod, newPod) if isPodUpdated(oldPod, newPod) { + // If the pod is updated reset backoff + p.clearPodBackoff(newPod) p.unschedulableQ.delete(usPod) err := p.activeQ.Add(newPod) if err == nil { @@ -388,13 +518,14 @@ func (p *PriorityQueue) Update(oldPod, newPod *v1.Pod) error { } return err } + // Pod is already in unschedulable queue and hasnt updated, no need to backoff again p.unschedulableQ.addOrUpdate(newPod) return nil } - // If pod is not in any of the two queue, we put it in the active queue. + // If pod is not in any of the queues, we put it in the active queue. err := p.activeQ.Add(newPod) if err == nil { - p.addNominatedPodIfNeeded(newPod) + p.nominatedPods.add(newPod, "") p.cond.Broadcast() } return err @@ -405,9 +536,11 @@ func (p *PriorityQueue) Update(oldPod, newPod *v1.Pod) error { func (p *PriorityQueue) Delete(pod *v1.Pod) error { p.lock.Lock() defer p.lock.Unlock() - p.deleteNominatedPodIfExists(pod) + p.nominatedPods.delete(pod) err := p.activeQ.Delete(pod) if err != nil { // The item was probably not found in the activeQ. + p.clearPodBackoff(pod) + p.podBackoffQ.Delete(pod) p.unschedulableQ.delete(pod) } return nil @@ -433,16 +566,18 @@ func (p *PriorityQueue) AssignedPodUpdated(pod *v1.Pod) { // function adds all pods and then signals the condition variable to ensure that // if Pop() is waiting for an item, it receives it after all the pods are in the // queue and the head is the highest priority pod. -// TODO(bsalamat): We should add a back-off mechanism here so that a high priority -// pod which is unschedulable does not go to the head of the queue frequently. For -// example in a cluster where a lot of pods being deleted, such a high priority -// pod can deprive other pods from getting scheduled. func (p *PriorityQueue) MoveAllToActiveQueue() { p.lock.Lock() defer p.lock.Unlock() for _, pod := range p.unschedulableQ.pods { - if err := p.activeQ.Add(pod); err != nil { - klog.Errorf("Error adding pod %v/%v to the scheduling queue: %v", pod.Namespace, pod.Name, err) + if p.isPodBackingOff(pod) { + if err := p.podBackoffQ.Add(pod); err != nil { + klog.Errorf("Error adding pod %v to the backoff queue: %v", pod.Name, err) + } + } else { + if err := p.activeQ.Add(pod); err != nil { + klog.Errorf("Error adding pod %v to the scheduling queue: %v", pod.Name, err) + } } } p.unschedulableQ.clear() @@ -453,11 +588,16 @@ func (p *PriorityQueue) MoveAllToActiveQueue() { // NOTE: this function assumes lock has been acquired in caller func (p *PriorityQueue) movePodsToActiveQueue(pods []*v1.Pod) { for _, pod := range pods { - if err := p.activeQ.Add(pod); err == nil { - p.unschedulableQ.delete(pod) + if p.isPodBackingOff(pod) { + if err := p.podBackoffQ.Add(pod); err != nil { + klog.Errorf("Error adding pod %v to the backoff queue: %v", pod.Name, err) + } } else { - klog.Errorf("Error adding pod %v/%v to the scheduling queue: %v", pod.Namespace, pod.Name, err) + if err := p.activeQ.Add(pod); err != nil { + klog.Errorf("Error adding pod %v to the scheduling queue: %v", pod.Name, err) + } } + p.unschedulableQ.delete(pod) } p.receivedMoveRequest = true p.cond.Broadcast() @@ -488,20 +628,18 @@ func (p *PriorityQueue) getUnschedulablePodsWithMatchingAffinityTerm(pod *v1.Pod return podsToMove } -// WaitingPodsForNode returns pods that are nominated to run on the given node, +// NominatedPodsForNode returns pods that are nominated to run on the given node, // but they are waiting for other pods to be removed from the node before they // can be actually scheduled. -func (p *PriorityQueue) WaitingPodsForNode(nodeName string) []*v1.Pod { +func (p *PriorityQueue) NominatedPodsForNode(nodeName string) []*v1.Pod { p.lock.RLock() defer p.lock.RUnlock() - if list, ok := p.nominatedPods[nodeName]; ok { - return list - } - return nil + return p.nominatedPods.podsForNode(nodeName) } -// WaitingPods returns all the waiting pods in the queue. -func (p *PriorityQueue) WaitingPods() []*v1.Pod { +// PendingPods returns all the pending pods in the queue. This function is +// used for debugging purposes in the scheduler cache dumper and comparer. +func (p *PriorityQueue) PendingPods() []*v1.Pod { p.lock.Lock() defer p.lock.Unlock() @@ -509,6 +647,9 @@ func (p *PriorityQueue) WaitingPods() []*v1.Pod { for _, pod := range p.activeQ.List() { result = append(result, pod.(*v1.Pod)) } + for _, pod := range p.podBackoffQ.List() { + result = append(result, pod.(*v1.Pod)) + } for _, pod := range p.unschedulableQ.pods { result = append(result, pod) } @@ -523,13 +664,36 @@ func (p *PriorityQueue) Close() { p.cond.Broadcast() } -// DeleteNominatedPodIfExists deletes pod from internal cache if it's a nominatedPod +// DeleteNominatedPodIfExists deletes pod nominatedPods. func (p *PriorityQueue) DeleteNominatedPodIfExists(pod *v1.Pod) { p.lock.Lock() - p.deleteNominatedPodIfExists(pod) + p.nominatedPods.delete(pod) p.lock.Unlock() } +// UpdateNominatedPodForNode adds a pod to the nominated pods of the given node. +// This is called during the preemption process after a node is nominated to run +// the pod. We update the structure before sending a request to update the pod +// object to avoid races with the following scheduling cycles. +func (p *PriorityQueue) UpdateNominatedPodForNode(pod *v1.Pod, nodeName string) { + p.lock.Lock() + p.nominatedPods.add(pod, nodeName) + p.lock.Unlock() +} + +func (p *PriorityQueue) podsCompareBackoffCompleted(p1, p2 interface{}) bool { + bo1, _ := p.podBackoff.GetBackoffTime(nsNameForPod(p1.(*v1.Pod))) + bo2, _ := p.podBackoff.GetBackoffTime(nsNameForPod(p2.(*v1.Pod))) + return bo1.Before(bo2) +} + +// NumUnschedulablePods returns the number of unschedulable pods exist in the SchedulingQueue. +func (p *PriorityQueue) NumUnschedulablePods() int { + p.lock.RLock() + defer p.lock.RUnlock() + return len(p.unschedulableQ.pods) +} + // UnschedulablePodsMap holds pods that cannot be scheduled. This data structure // is used to implement unschedulableQ. type UnschedulablePodsMap struct { @@ -571,199 +735,76 @@ func newUnschedulablePodsMap() *UnschedulablePodsMap { } } -// Below is the implementation of the a heap. The logic is pretty much the same -// as cache.heap, however, this heap does not perform synchronization. It leaves -// synchronization to the SchedulingQueue. - -// LessFunc is a function type to compare two objects. -type LessFunc func(interface{}, interface{}) bool - -// KeyFunc is a function type to get the key from an object. -type KeyFunc func(obj interface{}) (string, error) - -type heapItem struct { - obj interface{} // The object which is stored in the heap. - index int // The index of the object's key in the Heap.queue. +// nominatedPodMap is a structure that stores pods nominated to run on nodes. +// It exists because nominatedNodeName of pod objects stored in the structure +// may be different than what scheduler has here. We should be able to find pods +// by their UID and update/delete them. +type nominatedPodMap struct { + // nominatedPods is a map keyed by a node name and the value is a list of + // pods which are nominated to run on the node. These are pods which can be in + // the activeQ or unschedulableQ. + nominatedPods map[string][]*v1.Pod + // nominatedPodToNode is map keyed by a Pod UID to the node name where it is + // nominated. + nominatedPodToNode map[ktypes.UID]string } -type itemKeyValue struct { - key string - obj interface{} -} +func (npm *nominatedPodMap) add(p *v1.Pod, nodeName string) { + // always delete the pod if it already exist, to ensure we never store more than + // one instance of the pod. + npm.delete(p) -// heapData is an internal struct that implements the standard heap interface -// and keeps the data stored in the heap. -type heapData struct { - // items is a map from key of the objects to the objects and their index. - // We depend on the property that items in the map are in the queue and vice versa. - items map[string]*heapItem - // queue implements a heap data structure and keeps the order of elements - // according to the heap invariant. The queue keeps the keys of objects stored - // in "items". - queue []string - - // keyFunc is used to make the key used for queued item insertion and retrieval, and - // should be deterministic. - keyFunc KeyFunc - // lessFunc is used to compare two objects in the heap. - lessFunc LessFunc -} - -var ( - _ = heap.Interface(&heapData{}) // heapData is a standard heap -) - -// Less compares two objects and returns true if the first one should go -// in front of the second one in the heap. -func (h *heapData) Less(i, j int) bool { - if i > len(h.queue) || j > len(h.queue) { - return false + nnn := nodeName + if len(nnn) == 0 { + nnn = NominatedNodeName(p) + if len(nnn) == 0 { + return + } } - itemi, ok := h.items[h.queue[i]] + npm.nominatedPodToNode[p.UID] = nnn + for _, np := range npm.nominatedPods[nnn] { + if np.UID == p.UID { + klog.V(4).Infof("Pod %v/%v already exists in the nominated map!", p.Namespace, p.Name) + return + } + } + npm.nominatedPods[nnn] = append(npm.nominatedPods[nnn], p) +} + +func (npm *nominatedPodMap) delete(p *v1.Pod) { + nnn, ok := npm.nominatedPodToNode[p.UID] if !ok { - return false + return } - itemj, ok := h.items[h.queue[j]] - if !ok { - return false + for i, np := range npm.nominatedPods[nnn] { + if np.UID == p.UID { + npm.nominatedPods[nnn] = append(npm.nominatedPods[nnn][:i], npm.nominatedPods[nnn][i+1:]...) + if len(npm.nominatedPods[nnn]) == 0 { + delete(npm.nominatedPods, nnn) + } + break + } } - return h.lessFunc(itemi.obj, itemj.obj) + delete(npm.nominatedPodToNode, p.UID) } -// Len returns the number of items in the Heap. -func (h *heapData) Len() int { return len(h.queue) } - -// Swap implements swapping of two elements in the heap. This is a part of standard -// heap interface and should never be called directly. -func (h *heapData) Swap(i, j int) { - h.queue[i], h.queue[j] = h.queue[j], h.queue[i] - item := h.items[h.queue[i]] - item.index = i - item = h.items[h.queue[j]] - item.index = j +func (npm *nominatedPodMap) update(oldPod, newPod *v1.Pod) { + // We update irrespective of the nominatedNodeName changed or not, to ensure + // that pod pointer is updated. + npm.delete(oldPod) + npm.add(newPod, "") } -// Push is supposed to be called by heap.Push only. -func (h *heapData) Push(kv interface{}) { - keyValue := kv.(*itemKeyValue) - n := len(h.queue) - h.items[keyValue.key] = &heapItem{keyValue.obj, n} - h.queue = append(h.queue, keyValue.key) -} - -// Pop is supposed to be called by heap.Pop only. -func (h *heapData) Pop() interface{} { - key := h.queue[len(h.queue)-1] - h.queue = h.queue[0 : len(h.queue)-1] - item, ok := h.items[key] - if !ok { - // This is an error - return nil - } - delete(h.items, key) - return item.obj -} - -// Heap is a producer/consumer queue that implements a heap data structure. -// It can be used to implement priority queues and similar data structures. -type Heap struct { - // data stores objects and has a queue that keeps their ordering according - // to the heap invariant. - data *heapData -} - -// Add inserts an item, and puts it in the queue. The item is updated if it -// already exists. -func (h *Heap) Add(obj interface{}) error { - key, err := h.data.keyFunc(obj) - if err != nil { - return cache.KeyError{Obj: obj, Err: err} - } - if _, exists := h.data.items[key]; exists { - h.data.items[key].obj = obj - heap.Fix(h.data, h.data.items[key].index) - } else { - heap.Push(h.data, &itemKeyValue{key, obj}) +func (npm *nominatedPodMap) podsForNode(nodeName string) []*v1.Pod { + if list, ok := npm.nominatedPods[nodeName]; ok { + return list } return nil } -// AddIfNotPresent inserts an item, and puts it in the queue. If an item with -// the key is present in the map, no changes is made to the item. -func (h *Heap) AddIfNotPresent(obj interface{}) error { - key, err := h.data.keyFunc(obj) - if err != nil { - return cache.KeyError{Obj: obj, Err: err} - } - if _, exists := h.data.items[key]; !exists { - heap.Push(h.data, &itemKeyValue{key, obj}) - } - return nil -} - -// Update is the same as Add in this implementation. When the item does not -// exist, it is added. -func (h *Heap) Update(obj interface{}) error { - return h.Add(obj) -} - -// Delete removes an item. -func (h *Heap) Delete(obj interface{}) error { - key, err := h.data.keyFunc(obj) - if err != nil { - return cache.KeyError{Obj: obj, Err: err} - } - if item, ok := h.data.items[key]; ok { - heap.Remove(h.data, item.index) - return nil - } - return fmt.Errorf("object not found") -} - -// Pop returns the head of the heap. -func (h *Heap) Pop() (interface{}, error) { - obj := heap.Pop(h.data) - if obj != nil { - return obj, nil - } - return nil, fmt.Errorf("object was removed from heap data") -} - -// Get returns the requested item, or sets exists=false. -func (h *Heap) Get(obj interface{}) (interface{}, bool, error) { - key, err := h.data.keyFunc(obj) - if err != nil { - return nil, false, cache.KeyError{Obj: obj, Err: err} - } - return h.GetByKey(key) -} - -// GetByKey returns the requested item, or sets exists=false. -func (h *Heap) GetByKey(key string) (interface{}, bool, error) { - item, exists := h.data.items[key] - if !exists { - return nil, false, nil - } - return item.obj, true, nil -} - -// List returns a list of all the items. -func (h *Heap) List() []interface{} { - list := make([]interface{}, 0, len(h.data.items)) - for _, item := range h.data.items { - list = append(list, item.obj) - } - return list -} - -// newHeap returns a Heap which can be used to queue up items to process. -func newHeap(keyFn KeyFunc, lessFn LessFunc) *Heap { - return &Heap{ - data: &heapData{ - items: map[string]*heapItem{}, - queue: []string{}, - keyFunc: keyFn, - lessFunc: lessFn, - }, +func newNominatedPodMap() *nominatedPodMap { + return &nominatedPodMap{ + nominatedPods: make(map[string][]*v1.Pod), + nominatedPodToNode: make(map[ktypes.UID]string), } } diff --git a/pkg/scheduler/internal/queue/scheduling_queue_test.go b/pkg/scheduler/internal/queue/scheduling_queue_test.go index ca0e3369656..a77e756d125 100644 --- a/pkg/scheduler/internal/queue/scheduling_queue_test.go +++ b/pkg/scheduler/internal/queue/scheduling_queue_test.go @@ -24,6 +24,8 @@ import ( "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + podutil "k8s.io/kubernetes/pkg/api/v1/pod" "k8s.io/kubernetes/pkg/scheduler/util" ) @@ -93,12 +95,24 @@ var highPriorityPod, highPriNominatedPod, medPriorityPod, unschedulablePod = v1. } func TestPriorityQueue_Add(t *testing.T) { - q := NewPriorityQueue() - q.Add(&medPriorityPod) - q.Add(&unschedulablePod) - q.Add(&highPriorityPod) - expectedNominatedPods := map[string][]*v1.Pod{ - "node1": {&medPriorityPod, &unschedulablePod}, + q := NewPriorityQueue(nil) + if err := q.Add(&medPriorityPod); err != nil { + t.Errorf("add failed: %v", err) + } + if err := q.Add(&unschedulablePod); err != nil { + t.Errorf("add failed: %v", err) + } + if err := q.Add(&highPriorityPod); err != nil { + t.Errorf("add failed: %v", err) + } + expectedNominatedPods := &nominatedPodMap{ + nominatedPodToNode: map[types.UID]string{ + medPriorityPod.UID: "node1", + unschedulablePod.UID: "node1", + }, + nominatedPods: map[string][]*v1.Pod{ + "node1": {&medPriorityPod, &unschedulablePod}, + }, } if !reflect.DeepEqual(q.nominatedPods, expectedNominatedPods) { t.Errorf("Unexpected nominated map after adding pods. Expected: %v, got: %v", expectedNominatedPods, q.nominatedPods) @@ -112,19 +126,25 @@ func TestPriorityQueue_Add(t *testing.T) { if p, err := q.Pop(); err != nil || p != &unschedulablePod { t.Errorf("Expected: %v after Pop, but got: %v", unschedulablePod.Name, p.Name) } - if len(q.nominatedPods["node1"]) != 2 { - t.Errorf("Expected medPriorityPod and unschedulablePod to be still present in nomindatePods: %v", q.nominatedPods["node1"]) + if len(q.nominatedPods.nominatedPods["node1"]) != 2 { + t.Errorf("Expected medPriorityPod and unschedulablePod to be still present in nomindatePods: %v", q.nominatedPods.nominatedPods["node1"]) } } func TestPriorityQueue_AddIfNotPresent(t *testing.T) { - q := NewPriorityQueue() + q := NewPriorityQueue(nil) q.unschedulableQ.addOrUpdate(&highPriNominatedPod) q.AddIfNotPresent(&highPriNominatedPod) // Must not add anything. q.AddIfNotPresent(&medPriorityPod) q.AddIfNotPresent(&unschedulablePod) - expectedNominatedPods := map[string][]*v1.Pod{ - "node1": {&medPriorityPod, &unschedulablePod}, + expectedNominatedPods := &nominatedPodMap{ + nominatedPodToNode: map[types.UID]string{ + medPriorityPod.UID: "node1", + unschedulablePod.UID: "node1", + }, + nominatedPods: map[string][]*v1.Pod{ + "node1": {&medPriorityPod, &unschedulablePod}, + }, } if !reflect.DeepEqual(q.nominatedPods, expectedNominatedPods) { t.Errorf("Unexpected nominated map after adding pods. Expected: %v, got: %v", expectedNominatedPods, q.nominatedPods) @@ -135,8 +155,8 @@ func TestPriorityQueue_AddIfNotPresent(t *testing.T) { if p, err := q.Pop(); err != nil || p != &unschedulablePod { t.Errorf("Expected: %v after Pop, but got: %v", unschedulablePod.Name, p.Name) } - if len(q.nominatedPods["node1"]) != 2 { - t.Errorf("Expected medPriorityPod and unschedulablePod to be still present in nomindatePods: %v", q.nominatedPods["node1"]) + if len(q.nominatedPods.nominatedPods["node1"]) != 2 { + t.Errorf("Expected medPriorityPod and unschedulablePod to be still present in nomindatePods: %v", q.nominatedPods.nominatedPods["node1"]) } if q.unschedulableQ.get(&highPriNominatedPod) != &highPriNominatedPod { t.Errorf("Pod %v was not found in the unschedulableQ.", highPriNominatedPod.Name) @@ -144,13 +164,20 @@ func TestPriorityQueue_AddIfNotPresent(t *testing.T) { } func TestPriorityQueue_AddUnschedulableIfNotPresent(t *testing.T) { - q := NewPriorityQueue() + q := NewPriorityQueue(nil) q.Add(&highPriNominatedPod) q.AddUnschedulableIfNotPresent(&highPriNominatedPod) // Must not add anything. q.AddUnschedulableIfNotPresent(&medPriorityPod) // This should go to activeQ. q.AddUnschedulableIfNotPresent(&unschedulablePod) - expectedNominatedPods := map[string][]*v1.Pod{ - "node1": {&highPriNominatedPod, &medPriorityPod, &unschedulablePod}, + expectedNominatedPods := &nominatedPodMap{ + nominatedPodToNode: map[types.UID]string{ + medPriorityPod.UID: "node1", + unschedulablePod.UID: "node1", + highPriNominatedPod.UID: "node1", + }, + nominatedPods: map[string][]*v1.Pod{ + "node1": {&highPriNominatedPod, &medPriorityPod, &unschedulablePod}, + }, } if !reflect.DeepEqual(q.nominatedPods, expectedNominatedPods) { t.Errorf("Unexpected nominated map after adding pods. Expected: %v, got: %v", expectedNominatedPods, q.nominatedPods) @@ -161,7 +188,7 @@ func TestPriorityQueue_AddUnschedulableIfNotPresent(t *testing.T) { if p, err := q.Pop(); err != nil || p != &medPriorityPod { t.Errorf("Expected: %v after Pop, but got: %v", medPriorityPod.Name, p.Name) } - if len(q.nominatedPods) != 1 { + if len(q.nominatedPods.nominatedPods) != 1 { t.Errorf("Expected nomindatePods to have one element: %v", q.nominatedPods) } if q.unschedulableQ.get(&unschedulablePod) != &unschedulablePod { @@ -170,7 +197,7 @@ func TestPriorityQueue_AddUnschedulableIfNotPresent(t *testing.T) { } func TestPriorityQueue_Pop(t *testing.T) { - q := NewPriorityQueue() + q := NewPriorityQueue(nil) wg := sync.WaitGroup{} wg.Add(1) go func() { @@ -178,8 +205,8 @@ func TestPriorityQueue_Pop(t *testing.T) { if p, err := q.Pop(); err != nil || p != &medPriorityPod { t.Errorf("Expected: %v after Pop, but got: %v", medPriorityPod.Name, p.Name) } - if len(q.nominatedPods["node1"]) != 1 { - t.Errorf("Expected medPriorityPod to be present in nomindatePods: %v", q.nominatedPods["node1"]) + if len(q.nominatedPods.nominatedPods["node1"]) != 1 { + t.Errorf("Expected medPriorityPod to be present in nomindatePods: %v", q.nominatedPods.nominatedPods["node1"]) } }() q.Add(&medPriorityPod) @@ -187,20 +214,20 @@ func TestPriorityQueue_Pop(t *testing.T) { } func TestPriorityQueue_Update(t *testing.T) { - q := NewPriorityQueue() + q := NewPriorityQueue(nil) q.Update(nil, &highPriorityPod) if _, exists, _ := q.activeQ.Get(&highPriorityPod); !exists { t.Errorf("Expected %v to be added to activeQ.", highPriorityPod.Name) } - if len(q.nominatedPods) != 0 { + if len(q.nominatedPods.nominatedPods) != 0 { t.Errorf("Expected nomindatePods to be empty: %v", q.nominatedPods) } // Update highPriorityPod and add a nominatedNodeName to it. q.Update(&highPriorityPod, &highPriNominatedPod) - if q.activeQ.data.Len() != 1 { + if q.activeQ.Len() != 1 { t.Error("Expected only one item in activeQ.") } - if len(q.nominatedPods) != 1 { + if len(q.nominatedPods.nominatedPods) != 1 { t.Errorf("Expected one item in nomindatePods map: %v", q.nominatedPods) } // Updating an unschedulable pod which is not in any of the two queues, should @@ -223,32 +250,36 @@ func TestPriorityQueue_Update(t *testing.T) { } func TestPriorityQueue_Delete(t *testing.T) { - q := NewPriorityQueue() + q := NewPriorityQueue(nil) q.Update(&highPriorityPod, &highPriNominatedPod) q.Add(&unschedulablePod) - q.Delete(&highPriNominatedPod) + if err := q.Delete(&highPriNominatedPod); err != nil { + t.Errorf("delete failed: %v", err) + } if _, exists, _ := q.activeQ.Get(&unschedulablePod); !exists { t.Errorf("Expected %v to be in activeQ.", unschedulablePod.Name) } if _, exists, _ := q.activeQ.Get(&highPriNominatedPod); exists { t.Errorf("Didn't expect %v to be in activeQ.", highPriorityPod.Name) } - if len(q.nominatedPods) != 1 { - t.Errorf("Expected nomindatePods to have only 'unschedulablePod': %v", q.nominatedPods) + if len(q.nominatedPods.nominatedPods) != 1 { + t.Errorf("Expected nomindatePods to have only 'unschedulablePod': %v", q.nominatedPods.nominatedPods) } - q.Delete(&unschedulablePod) - if len(q.nominatedPods) != 0 { + if err := q.Delete(&unschedulablePod); err != nil { + t.Errorf("delete failed: %v", err) + } + if len(q.nominatedPods.nominatedPods) != 0 { t.Errorf("Expected nomindatePods to be empty: %v", q.nominatedPods) } } func TestPriorityQueue_MoveAllToActiveQueue(t *testing.T) { - q := NewPriorityQueue() + q := NewPriorityQueue(nil) q.Add(&medPriorityPod) q.unschedulableQ.addOrUpdate(&unschedulablePod) q.unschedulableQ.addOrUpdate(&highPriorityPod) q.MoveAllToActiveQueue() - if q.activeQ.data.Len() != 3 { + if q.activeQ.Len() != 3 { t.Error("Expected all items to be in activeQ.") } } @@ -289,7 +320,7 @@ func TestPriorityQueue_AssignedPodAdded(t *testing.T) { Spec: v1.PodSpec{NodeName: "machine1"}, } - q := NewPriorityQueue() + q := NewPriorityQueue(nil) q.Add(&medPriorityPod) // Add a couple of pods to the unschedulableQ. q.unschedulableQ.addOrUpdate(&unschedulablePod) @@ -309,8 +340,8 @@ func TestPriorityQueue_AssignedPodAdded(t *testing.T) { } } -func TestPriorityQueue_WaitingPodsForNode(t *testing.T) { - q := NewPriorityQueue() +func TestPriorityQueue_NominatedPodsForNode(t *testing.T) { + q := NewPriorityQueue(nil) q.Add(&medPriorityPod) q.Add(&unschedulablePod) q.Add(&highPriorityPod) @@ -318,14 +349,99 @@ func TestPriorityQueue_WaitingPodsForNode(t *testing.T) { t.Errorf("Expected: %v after Pop, but got: %v", highPriorityPod.Name, p.Name) } expectedList := []*v1.Pod{&medPriorityPod, &unschedulablePod} - if !reflect.DeepEqual(expectedList, q.WaitingPodsForNode("node1")) { + if !reflect.DeepEqual(expectedList, q.NominatedPodsForNode("node1")) { t.Error("Unexpected list of nominated Pods for node.") } - if q.WaitingPodsForNode("node2") != nil { + if q.NominatedPodsForNode("node2") != nil { t.Error("Expected list of nominated Pods for node2 to be empty.") } } +func TestPriorityQueue_PendingPods(t *testing.T) { + q := NewPriorityQueue(nil) + q.Add(&medPriorityPod) + q.unschedulableQ.addOrUpdate(&unschedulablePod) + q.unschedulableQ.addOrUpdate(&highPriorityPod) + expectedList := []*v1.Pod{&medPriorityPod, &unschedulablePod, &highPriorityPod} + if !reflect.DeepEqual(expectedList, q.PendingPods()) { + t.Error("Unexpected list of pending Pods for node.") + } + // Move all to active queue. We should still see the same set of pods. + q.MoveAllToActiveQueue() + if !reflect.DeepEqual(expectedList, q.PendingPods()) { + t.Error("Unexpected list of pending Pods for node.") + } +} + +func TestPriorityQueue_UpdateNominatedPodForNode(t *testing.T) { + q := NewPriorityQueue(nil) + if err := q.Add(&medPriorityPod); err != nil { + t.Errorf("add failed: %v", err) + } + // Update unschedulablePod on a different node than specified in the pod. + q.UpdateNominatedPodForNode(&unschedulablePod, "node5") + + // Update nominated node name of a pod on a node that is not specified in the pod object. + q.UpdateNominatedPodForNode(&highPriorityPod, "node2") + expectedNominatedPods := &nominatedPodMap{ + nominatedPodToNode: map[types.UID]string{ + medPriorityPod.UID: "node1", + highPriorityPod.UID: "node2", + unschedulablePod.UID: "node5", + }, + nominatedPods: map[string][]*v1.Pod{ + "node1": {&medPriorityPod}, + "node2": {&highPriorityPod}, + "node5": {&unschedulablePod}, + }, + } + if !reflect.DeepEqual(q.nominatedPods, expectedNominatedPods) { + t.Errorf("Unexpected nominated map after adding pods. Expected: %v, got: %v", expectedNominatedPods, q.nominatedPods) + } + if p, err := q.Pop(); err != nil || p != &medPriorityPod { + t.Errorf("Expected: %v after Pop, but got: %v", medPriorityPod.Name, p.Name) + } + // List of nominated pods shouldn't change after popping them from the queue. + if !reflect.DeepEqual(q.nominatedPods, expectedNominatedPods) { + t.Errorf("Unexpected nominated map after popping pods. Expected: %v, got: %v", expectedNominatedPods, q.nominatedPods) + } + // Update one of the nominated pods that doesn't have nominatedNodeName in the + // pod object. It should be updated correctly. + q.UpdateNominatedPodForNode(&highPriorityPod, "node4") + expectedNominatedPods = &nominatedPodMap{ + nominatedPodToNode: map[types.UID]string{ + medPriorityPod.UID: "node1", + highPriorityPod.UID: "node4", + unschedulablePod.UID: "node5", + }, + nominatedPods: map[string][]*v1.Pod{ + "node1": {&medPriorityPod}, + "node4": {&highPriorityPod}, + "node5": {&unschedulablePod}, + }, + } + if !reflect.DeepEqual(q.nominatedPods, expectedNominatedPods) { + t.Errorf("Unexpected nominated map after updating pods. Expected: %v, got: %v", expectedNominatedPods, q.nominatedPods) + } + + // Delete a nominated pod that doesn't have nominatedNodeName in the pod + // object. It should be deleted. + q.DeleteNominatedPodIfExists(&highPriorityPod) + expectedNominatedPods = &nominatedPodMap{ + nominatedPodToNode: map[types.UID]string{ + medPriorityPod.UID: "node1", + unschedulablePod.UID: "node5", + }, + nominatedPods: map[string][]*v1.Pod{ + "node1": {&medPriorityPod}, + "node5": {&unschedulablePod}, + }, + } + if !reflect.DeepEqual(q.nominatedPods, expectedNominatedPods) { + t.Errorf("Unexpected nominated map after deleting pods. Expected: %v, got: %v", expectedNominatedPods, q.nominatedPods) + } +} + func TestUnschedulablePodsMap(t *testing.T) { var pods = []*v1.Pod{ { @@ -489,7 +605,7 @@ func TestSchedulingQueue_Close(t *testing.T) { }, { name: "PriorityQueue close", - q: NewPriorityQueue(), + q: NewPriorityQueue(nil), expectedErr: fmt.Errorf(queueClosed), }, } @@ -512,3 +628,119 @@ func TestSchedulingQueue_Close(t *testing.T) { }) } } + +// TestRecentlyTriedPodsGoBack tests that pods which are recently tried and are +// unschedulable go behind other pods with the same priority. This behavior +// ensures that an unschedulable pod does not block head of the queue when there +// are frequent events that move pods to the active queue. +func TestRecentlyTriedPodsGoBack(t *testing.T) { + q := NewPriorityQueue(nil) + // Add a few pods to priority queue. + for i := 0; i < 5; i++ { + p := v1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: fmt.Sprintf("test-pod-%v", i), + Namespace: "ns1", + UID: types.UID(fmt.Sprintf("tp00%v", i)), + }, + Spec: v1.PodSpec{ + Priority: &highPriority, + }, + Status: v1.PodStatus{ + NominatedNodeName: "node1", + }, + } + q.Add(&p) + } + // Simulate a pod being popped by the scheduler, determined unschedulable, and + // then moved back to the active queue. + p1, err := q.Pop() + if err != nil { + t.Errorf("Error while popping the head of the queue: %v", err) + } + // Update pod condition to unschedulable. + podutil.UpdatePodCondition(&p1.Status, &v1.PodCondition{ + Type: v1.PodScheduled, + Status: v1.ConditionFalse, + Reason: v1.PodReasonUnschedulable, + Message: "fake scheduling failure", + }) + // Put in the unschedulable queue. + q.AddUnschedulableIfNotPresent(p1) + // Move all unschedulable pods to the active queue. + q.MoveAllToActiveQueue() + // Simulation is over. Now let's pop all pods. The pod popped first should be + // the last one we pop here. + for i := 0; i < 5; i++ { + p, err := q.Pop() + if err != nil { + t.Errorf("Error while popping pods from the queue: %v", err) + } + if (i == 4) != (p1 == p) { + t.Errorf("A pod tried before is not the last pod popped: i: %v, pod name: %v", i, p.Name) + } + } +} + +// TestHighPriorityBackoff tests that a high priority pod does not block +// other pods if it is unschedulable +func TestHighProirotyBackoff(t *testing.T) { + q := NewPriorityQueue(nil) + + midPod := v1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-midpod", + Namespace: "ns1", + UID: types.UID("tp-mid"), + }, + Spec: v1.PodSpec{ + Priority: &midPriority, + }, + Status: v1.PodStatus{ + NominatedNodeName: "node1", + }, + } + highPod := v1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-highpod", + Namespace: "ns1", + UID: types.UID("tp-high"), + }, + Spec: v1.PodSpec{ + Priority: &highPriority, + }, + Status: v1.PodStatus{ + NominatedNodeName: "node1", + }, + } + q.Add(&midPod) + q.Add(&highPod) + // Simulate a pod being popped by the scheduler, determined unschedulable, and + // then moved back to the active queue. + p, err := q.Pop() + if err != nil { + t.Errorf("Error while popping the head of the queue: %v", err) + } + if p != &highPod { + t.Errorf("Expected to get high prority pod, got: %v", p) + } + // Update pod condition to unschedulable. + podutil.UpdatePodCondition(&p.Status, &v1.PodCondition{ + Type: v1.PodScheduled, + Status: v1.ConditionFalse, + Reason: v1.PodReasonUnschedulable, + Message: "fake scheduling failure", + }) + // Put in the unschedulable queue. + q.AddUnschedulableIfNotPresent(p) + // Move all unschedulable pods to the active queue. + q.MoveAllToActiveQueue() + + p, err = q.Pop() + if err != nil { + t.Errorf("Error while popping the head of the queue: %v", err) + } + if p != &midPod { + t.Errorf("Expected to get mid prority pod, got: %v", p) + } +} diff --git a/pkg/scheduler/metrics/metrics.go b/pkg/scheduler/metrics/metrics.go index 0ebbd4f8ef6..b05ff33eb2e 100644 --- a/pkg/scheduler/metrics/metrics.go +++ b/pkg/scheduler/metrics/metrics.go @@ -131,22 +131,6 @@ var ( Help: "Total preemption attempts in the cluster till now", }) - equivalenceCacheLookups = prometheus.NewCounterVec( - prometheus.CounterOpts{ - Subsystem: SchedulerSubsystem, - Name: "equiv_cache_lookups_total", - Help: "Total number of equivalence cache lookups, by whether or not a cache entry was found", - }, []string{"result"}) - EquivalenceCacheHits = equivalenceCacheLookups.With(prometheus.Labels{"result": "hit"}) - EquivalenceCacheMisses = equivalenceCacheLookups.With(prometheus.Labels{"result": "miss"}) - - EquivalenceCacheWrites = prometheus.NewCounterVec( - prometheus.CounterOpts{ - Subsystem: SchedulerSubsystem, - Name: "equiv_cache_writes", - Help: "Total number of equivalence cache writes, by result", - }, []string{"result"}) - metricsList = []prometheus.Collector{ scheduleAttempts, SchedulingLatency, @@ -158,8 +142,6 @@ var ( SchedulingAlgorithmPremptionEvaluationDuration, PreemptionVictims, PreemptionAttempts, - equivalenceCacheLookups, - EquivalenceCacheWrites, } ) diff --git a/pkg/scheduler/cache/BUILD b/pkg/scheduler/nodeinfo/BUILD similarity index 96% rename from pkg/scheduler/cache/BUILD rename to pkg/scheduler/nodeinfo/BUILD index ba0ac4da9a7..c9631738f6f 100644 --- a/pkg/scheduler/cache/BUILD +++ b/pkg/scheduler/nodeinfo/BUILD @@ -7,7 +7,7 @@ go_library( "node_info.go", "util.go", ], - importpath = "k8s.io/kubernetes/pkg/scheduler/cache", + importpath = "k8s.io/kubernetes/pkg/scheduler/nodeinfo", visibility = ["//visibility:public"], deps = [ "//pkg/apis/core/v1/helper:go_default_library", diff --git a/pkg/scheduler/cache/host_ports.go b/pkg/scheduler/nodeinfo/host_ports.go similarity index 99% rename from pkg/scheduler/cache/host_ports.go rename to pkg/scheduler/nodeinfo/host_ports.go index e96c6be374a..8f1090ff706 100644 --- a/pkg/scheduler/cache/host_ports.go +++ b/pkg/scheduler/nodeinfo/host_ports.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package cache +package nodeinfo import ( "k8s.io/api/core/v1" diff --git a/pkg/scheduler/cache/host_ports_test.go b/pkg/scheduler/nodeinfo/host_ports_test.go similarity index 99% rename from pkg/scheduler/cache/host_ports_test.go rename to pkg/scheduler/nodeinfo/host_ports_test.go index 390d4d1510f..53a1c4ebbf0 100644 --- a/pkg/scheduler/cache/host_ports_test.go +++ b/pkg/scheduler/nodeinfo/host_ports_test.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package cache +package nodeinfo import ( "testing" diff --git a/pkg/scheduler/cache/node_info.go b/pkg/scheduler/nodeinfo/node_info.go similarity index 99% rename from pkg/scheduler/cache/node_info.go rename to pkg/scheduler/nodeinfo/node_info.go index 8b623c72ca3..6a6703a4fa6 100644 --- a/pkg/scheduler/cache/node_info.go +++ b/pkg/scheduler/nodeinfo/node_info.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package cache +package nodeinfo import ( "errors" diff --git a/pkg/scheduler/cache/node_info_test.go b/pkg/scheduler/nodeinfo/node_info_test.go similarity index 99% rename from pkg/scheduler/cache/node_info_test.go rename to pkg/scheduler/nodeinfo/node_info_test.go index 38c498a3d79..24744e1ac2e 100644 --- a/pkg/scheduler/cache/node_info_test.go +++ b/pkg/scheduler/nodeinfo/node_info_test.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package cache +package nodeinfo import ( "fmt" diff --git a/pkg/scheduler/cache/util.go b/pkg/scheduler/nodeinfo/util.go similarity index 99% rename from pkg/scheduler/cache/util.go rename to pkg/scheduler/nodeinfo/util.go index 5a252b6402e..bb1fd0ce612 100644 --- a/pkg/scheduler/cache/util.go +++ b/pkg/scheduler/nodeinfo/util.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package cache +package nodeinfo import ( "k8s.io/api/core/v1" diff --git a/pkg/scheduler/cache/util_test.go b/pkg/scheduler/nodeinfo/util_test.go similarity index 99% rename from pkg/scheduler/cache/util_test.go rename to pkg/scheduler/nodeinfo/util_test.go index 7b0b5f111c8..0e108773e2b 100644 --- a/pkg/scheduler/cache/util_test.go +++ b/pkg/scheduler/nodeinfo/util_test.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package cache +package nodeinfo import ( "reflect" diff --git a/pkg/scheduler/plugins/BUILD b/pkg/scheduler/plugins/BUILD new file mode 100644 index 00000000000..8de218f021c --- /dev/null +++ b/pkg/scheduler/plugins/BUILD @@ -0,0 +1,30 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = ["registrar.go"], + importpath = "k8s.io/kubernetes/pkg/scheduler/plugins", + visibility = ["//visibility:public"], + deps = [ + "//pkg/scheduler/internal/cache:go_default_library", + "//pkg/scheduler/plugins/v1alpha1:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [ + ":package-srcs", + "//pkg/scheduler/plugins/examples:all-srcs", + "//pkg/scheduler/plugins/v1alpha1:all-srcs", + ], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/pkg/scheduler/plugins/examples/BUILD b/pkg/scheduler/plugins/examples/BUILD new file mode 100644 index 00000000000..bc26941c8eb --- /dev/null +++ b/pkg/scheduler/plugins/examples/BUILD @@ -0,0 +1,31 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = [ + "multipoint.go", + "prebind.go", + "stateful.go", + ], + importpath = "k8s.io/kubernetes/pkg/scheduler/plugins/examples", + visibility = ["//visibility:public"], + deps = [ + "//pkg/scheduler/plugins/v1alpha1:go_default_library", + "//staging/src/k8s.io/api/core/v1:go_default_library", + "//vendor/k8s.io/klog:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/pkg/scheduler/plugins/examples/multipoint.go b/pkg/scheduler/plugins/examples/multipoint.go new file mode 100644 index 00000000000..3b82f219802 --- /dev/null +++ b/pkg/scheduler/plugins/examples/multipoint.go @@ -0,0 +1,62 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package examples + +import ( + "fmt" + + "k8s.io/api/core/v1" + plugins "k8s.io/kubernetes/pkg/scheduler/plugins/v1alpha1" +) + +// MultipointCommunicatingPlugin is an example of a plugin that implements two +// extension points. It communicates through pluginContext with another function. +type MultipointCommunicatingPlugin struct{} + +var _ = plugins.ReservePlugin(MultipointCommunicatingPlugin{}) + +// Name returns name of the plugin. It is used in logs, etc. +func (mc MultipointCommunicatingPlugin) Name() string { + return "multipoint-communicating-plugin" +} + +// Reserve is the functions invoked by the framework at "reserve" extension point. +func (mc MultipointCommunicatingPlugin) Reserve(ps plugins.PluginSet, pod *v1.Pod, nodeName string) error { + if pod == nil { + return fmt.Errorf("pod cannot be nil") + } + if pod.Name == "my-test-pod" { + ps.Data().Ctx.SyncWrite(plugins.ContextKey(pod.Name), "never bind") + } + return nil +} + +// Prebind is the functions invoked by the framework at "prebind" extension point. +func (mc MultipointCommunicatingPlugin) Prebind(ps plugins.PluginSet, pod *v1.Pod, nodeName string) (bool, error) { + if pod == nil { + return false, fmt.Errorf("pod cannot be nil") + } + if v, e := ps.Data().Ctx.SyncRead(plugins.ContextKey(pod.Name)); e == nil && v == "never bind" { + return false, nil + } + return true, nil +} + +// NewMultipointCommunicatingPlugin initializes a new plugin and returns it. +func NewMultipointCommunicatingPlugin() *MultipointCommunicatingPlugin { + return &MultipointCommunicatingPlugin{} +} diff --git a/pkg/scheduler/plugins/examples/prebind.go b/pkg/scheduler/plugins/examples/prebind.go new file mode 100644 index 00000000000..13e71eb0bd3 --- /dev/null +++ b/pkg/scheduler/plugins/examples/prebind.go @@ -0,0 +1,48 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package examples + +import ( + "fmt" + + "k8s.io/api/core/v1" + plugins "k8s.io/kubernetes/pkg/scheduler/plugins/v1alpha1" +) + +// StatelessPrebindExample is an example of a simple plugin that has no state +// and implements only one hook for prebind. +type StatelessPrebindExample struct{} + +var _ = plugins.PrebindPlugin(StatelessPrebindExample{}) + +// Name returns name of the plugin. It is used in logs, etc. +func (sr StatelessPrebindExample) Name() string { + return "stateless-prebind-plugin-example" +} + +// Prebind is the functions invoked by the framework at "prebind" extension point. +func (sr StatelessPrebindExample) Prebind(ps plugins.PluginSet, pod *v1.Pod, nodeName string) (bool, error) { + if pod == nil { + return false, fmt.Errorf("pod cannot be nil") + } + return true, nil +} + +// NewStatelessPrebindExample initializes a new plugin and returns it. +func NewStatelessPrebindExample() *StatelessPrebindExample { + return &StatelessPrebindExample{} +} diff --git a/pkg/scheduler/plugins/examples/stateful.go b/pkg/scheduler/plugins/examples/stateful.go new file mode 100644 index 00000000000..2b8b210305e --- /dev/null +++ b/pkg/scheduler/plugins/examples/stateful.go @@ -0,0 +1,68 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package examples + +import ( + "fmt" + "k8s.io/klog" + + "k8s.io/api/core/v1" + plugins "k8s.io/kubernetes/pkg/scheduler/plugins/v1alpha1" +) + +// StatefulMultipointExample is an example plugin that is executed at multiple extension points. +// This plugin is stateful. It receives arguments at initialization (NewMultipointPlugin) +// and changes its state when it is executed. +type StatefulMultipointExample struct { + mpState map[int]string + numRuns int +} + +var _ = plugins.ReservePlugin(&StatefulMultipointExample{}) +var _ = plugins.PrebindPlugin(&StatefulMultipointExample{}) + +// Name returns name of the plugin. It is used in logs, etc. +func (mp *StatefulMultipointExample) Name() string { + return "multipoint-plugin-example" +} + +// Reserve is the functions invoked by the framework at "reserve" extension point. +func (mp *StatefulMultipointExample) Reserve(ps plugins.PluginSet, pod *v1.Pod, nodeName string) error { + mp.numRuns++ + return nil +} + +// Prebind is the functions invoked by the framework at "prebind" extension point. +func (mp *StatefulMultipointExample) Prebind(ps plugins.PluginSet, pod *v1.Pod, nodeName string) (bool, error) { + mp.numRuns++ + if pod == nil { + return false, fmt.Errorf("pod must not be nil") + } + return true, nil +} + +// NewStatefulMultipointExample initializes a new plugin and returns it. +func NewStatefulMultipointExample(initState ...interface{}) *StatefulMultipointExample { + if len(initState) == 0 { + klog.Error("StatefulMultipointExample needs exactly one argument for initialization") + return nil + } + mp := StatefulMultipointExample{ + mpState: initState[0].(map[int]string), + } + return &mp +} diff --git a/pkg/scheduler/plugins/registrar.go b/pkg/scheduler/plugins/registrar.go new file mode 100644 index 00000000000..62de362d962 --- /dev/null +++ b/pkg/scheduler/plugins/registrar.go @@ -0,0 +1,77 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package plugins + +import ( + "k8s.io/kubernetes/pkg/scheduler/internal/cache" + plugins "k8s.io/kubernetes/pkg/scheduler/plugins/v1alpha1" +) + +// DefaultPluginSet is the default plugin registrar used by the default scheduler. +type DefaultPluginSet struct { + data *plugins.PluginData + reservePlugins []plugins.ReservePlugin + prebindPlugins []plugins.PrebindPlugin +} + +var _ = plugins.PluginSet(&DefaultPluginSet{}) + +// ReservePlugins returns a slice of default reserve plugins. +func (r *DefaultPluginSet) ReservePlugins() []plugins.ReservePlugin { + return r.reservePlugins +} + +// PrebindPlugins returns a slice of default prebind plugins. +func (r *DefaultPluginSet) PrebindPlugins() []plugins.PrebindPlugin { + return r.prebindPlugins +} + +// Data returns a pointer to PluginData. +func (r *DefaultPluginSet) Data() *plugins.PluginData { + return r.data +} + +// NewDefaultPluginSet initializes default plugin set and returns its pointer. +func NewDefaultPluginSet(ctx *plugins.PluginContext, schedulerCache *cache.Cache) *DefaultPluginSet { + defaultRegistrar := DefaultPluginSet{ + data: &plugins.PluginData{ + Ctx: ctx, + SchedulerCache: schedulerCache, + }, + } + defaultRegistrar.registerReservePlugins() + defaultRegistrar.registerPrebindPlugins() + return &defaultRegistrar +} + +func (r *DefaultPluginSet) registerReservePlugins() { + r.reservePlugins = []plugins.ReservePlugin{ + // Init functions of all reserve plugins go here. They are called in the + // same order that they are registered. + // Example: + // examples.NewStatefulMultipointExample(map[int]string{1: "test1", 2: "test2"}), + } +} + +func (r *DefaultPluginSet) registerPrebindPlugins() { + r.prebindPlugins = []plugins.PrebindPlugin{ + // Init functions of all prebind plugins go here. They are called in the + // same order that they are registered. + // Example: + // examples.NewStatelessPrebindExample(), + } +} diff --git a/pkg/scheduler/plugins/v1alpha1/BUILD b/pkg/scheduler/plugins/v1alpha1/BUILD new file mode 100644 index 00000000000..619bd4685a9 --- /dev/null +++ b/pkg/scheduler/plugins/v1alpha1/BUILD @@ -0,0 +1,29 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = [ + "context.go", + "interface.go", + ], + importpath = "k8s.io/kubernetes/pkg/scheduler/plugins/v1alpha1", + visibility = ["//visibility:public"], + deps = [ + "//pkg/scheduler/internal/cache:go_default_library", + "//staging/src/k8s.io/api/core/v1:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/pkg/scheduler/plugins/v1alpha1/context.go b/pkg/scheduler/plugins/v1alpha1/context.go new file mode 100644 index 00000000000..0631b5f0d8b --- /dev/null +++ b/pkg/scheduler/plugins/v1alpha1/context.go @@ -0,0 +1,94 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1alpha1 + +import ( + "errors" + "sync" +) + +const ( + // NotFound is the not found error message. + NotFound = "not found" +) + +// ContextData is a generic type for arbitrary data stored in PluginContext. +type ContextData interface{} + +// ContextKey is the type of keys stored in PluginContext. +type ContextKey string + +// PluginContext provides a mechanism for plugins to store and retrieve arbitrary data. +// ContextData stored by one plugin can be read, altered, or deleted by another plugin. +// PluginContext does not provide any data protection, as all plugins are assumed to be +// trusted. +type PluginContext struct { + Mx sync.RWMutex + storage map[ContextKey]ContextData +} + +// NewPluginContext initializes a new PluginContext and returns its pointer. +func NewPluginContext() *PluginContext { + return &PluginContext{ + storage: make(map[ContextKey]ContextData), + } +} + +// Read retrieves data with the given "key" from PluginContext. If the key is not +// present an error is returned. +func (c *PluginContext) Read(key ContextKey) (ContextData, error) { + if v, ok := c.storage[key]; ok { + return v, nil + } + return nil, errors.New(NotFound) +} + +// SyncRead is the thread safe version of Read(...). +func (c *PluginContext) SyncRead(key ContextKey) (ContextData, error) { + c.Mx.RLock() + defer c.Mx.RUnlock() + return c.Read(key) +} + +// Write stores the given "val" in PluginContext with the given "key". +func (c *PluginContext) Write(key ContextKey, val ContextData) { + c.storage[key] = val +} + +// SyncWrite is the thread safe version of Write(...). +func (c *PluginContext) SyncWrite(key ContextKey, val ContextData) { + c.Mx.Lock() + defer c.Mx.Unlock() + c.Write(key, val) +} + +// Delete deletes data with the given key from PluginContext. +func (c *PluginContext) Delete(key ContextKey) { + delete(c.storage, key) +} + +// SyncDelete is the thread safe version of Write(...). +func (c *PluginContext) SyncDelete(key ContextKey) { + c.Mx.Lock() + defer c.Mx.Unlock() + c.Delete(key) +} + +// Reset removes all the information in the PluginContext. +func (c *PluginContext) Reset() { + c.storage = make(map[ContextKey]ContextData) +} diff --git a/pkg/scheduler/plugins/v1alpha1/interface.go b/pkg/scheduler/plugins/v1alpha1/interface.go new file mode 100644 index 00000000000..0d0c90b43e6 --- /dev/null +++ b/pkg/scheduler/plugins/v1alpha1/interface.go @@ -0,0 +1,63 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// This file defines the scheduling framework plugin interfaces. + +package v1alpha1 + +import ( + "k8s.io/api/core/v1" + "k8s.io/kubernetes/pkg/scheduler/internal/cache" +) + +// PluginData carries information that plugins may need. +type PluginData struct { + Ctx *PluginContext + SchedulerCache *cache.Cache + // We may want to add the scheduling queue here too. +} + +// Plugin is the parent type for all the scheduling framework plugins. +type Plugin interface { + Name() string +} + +// ReservePlugin is an interface for Reserve plugins. These plugins are called +// at the reservation point, AKA "assume". These are meant to updated the state +// of the plugin. They do not return any value (other than error). +type ReservePlugin interface { + Plugin + // Reserve is called by the scheduling framework when the scheduler cache is + // updated. + Reserve(ps PluginSet, p *v1.Pod, nodeName string) error +} + +// PrebindPlugin is an interface that must be implemented by "prebind" plugins. +// These plugins are called before a pod being scheduled +type PrebindPlugin interface { + Plugin + // Prebind is called before binding a pod. All prebind plugins must return + // or the pod will not be sent for binding. + Prebind(ps PluginSet, p *v1.Pod, nodeName string) (bool, error) +} + +// PluginSet registers plugins used by the scheduling framework. +// The plugins registered are called at specified points in an scheduling cycle. +type PluginSet interface { + Data() *PluginData + ReservePlugins() []ReservePlugin + PrebindPlugins() []PrebindPlugin +} diff --git a/pkg/scheduler/scheduler.go b/pkg/scheduler/scheduler.go index 0237036b1cd..999f25b2bfe 100644 --- a/pkg/scheduler/scheduler.go +++ b/pkg/scheduler/scheduler.go @@ -17,25 +17,24 @@ limitations under the License. package scheduler import ( + "errors" "fmt" "io/ioutil" "os" "time" + "k8s.io/klog" + "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/wait" - utilfeature "k8s.io/apiserver/pkg/util/feature" appsinformers "k8s.io/client-go/informers/apps/v1" coreinformers "k8s.io/client-go/informers/core/v1" policyinformers "k8s.io/client-go/informers/policy/v1beta1" storageinformers "k8s.io/client-go/informers/storage/v1" clientset "k8s.io/client-go/kubernetes" "k8s.io/client-go/tools/record" - "k8s.io/kubernetes/pkg/features" - "k8s.io/kubernetes/pkg/scheduler/algorithm/predicates" schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" latestschedulerapi "k8s.io/kubernetes/pkg/scheduler/api/latest" kubeschedulerconfig "k8s.io/kubernetes/pkg/scheduler/apis/config" @@ -44,13 +43,13 @@ import ( schedulerinternalcache "k8s.io/kubernetes/pkg/scheduler/internal/cache" "k8s.io/kubernetes/pkg/scheduler/metrics" "k8s.io/kubernetes/pkg/scheduler/util" - - "k8s.io/klog" ) const ( // BindTimeoutSeconds defines the default bind timeout BindTimeoutSeconds = 100 + // SchedulerError is the reason recorded for events when an error occurs during scheduling a pod. + SchedulerError = "SchedulerError" ) // Scheduler watches for new unscheduled pods. It attempts to find @@ -67,7 +66,6 @@ func (sched *Scheduler) Cache() schedulerinternalcache.Cache { type schedulerOptions struct { schedulerName string hardPodAffinitySymmetricWeight int32 - enableEquivalenceClassCache bool disablePreemption bool percentageOfNodesToScore int32 bindTimeoutSeconds int64 @@ -90,13 +88,6 @@ func WithHardPodAffinitySymmetricWeight(hardPodAffinitySymmetricWeight int32) Op } } -// WithEquivalenceClassCacheEnabled sets enableEquivalenceClassCache for Scheduler, the default value is false -func WithEquivalenceClassCacheEnabled(enableEquivalenceClassCache bool) Option { - return func(o *schedulerOptions) { - o.enableEquivalenceClassCache = enableEquivalenceClassCache - } -} - // WithPreemptionDisabled sets disablePreemption for Scheduler, the default value is false func WithPreemptionDisabled(disablePreemption bool) Option { return func(o *schedulerOptions) { @@ -121,7 +112,6 @@ func WithBindTimeoutSeconds(bindTimeoutSeconds int64) Option { var defaultSchedulerOptions = schedulerOptions{ schedulerName: v1.DefaultSchedulerName, hardPodAffinitySymmetricWeight: v1.DefaultHardPodAffinitySymmetricWeight, - enableEquivalenceClassCache: false, disablePreemption: false, percentageOfNodesToScore: schedulerapi.DefaultPercentageOfNodesToScore, bindTimeoutSeconds: BindTimeoutSeconds, @@ -164,7 +154,6 @@ func New(client clientset.Interface, PdbInformer: pdbInformer, StorageClassInformer: storageClassInformer, HardPodAffinitySymmetricWeight: options.hardPodAffinitySymmetricWeight, - EnableEquivalenceClassCache: options.enableEquivalenceClassCache, DisablePreemption: options.disablePreemption, PercentageOfNodesToScore: options.percentageOfNodesToScore, BindTimeoutSeconds: options.bindTimeoutSeconds, @@ -286,33 +275,36 @@ func (sched *Scheduler) Config() *factory.Config { return sched.config } -// schedule implements the scheduling algorithm and returns the suggested host. -func (sched *Scheduler) schedule(pod *v1.Pod) (string, error) { - host, err := sched.config.Algorithm.Schedule(pod, sched.config.NodeLister) +// recordFailedSchedulingEvent records an event for the pod that indicates the +// pod has failed to schedule. +// NOTE: This function modifies "pod". "pod" should be copied before being passed. +func (sched *Scheduler) recordSchedulingFailure(pod *v1.Pod, err error, reason string, message string) { + sched.config.Error(pod, err) + sched.config.Recorder.Event(pod, v1.EventTypeWarning, "FailedScheduling", message) + sched.config.PodConditionUpdater.Update(pod, &v1.PodCondition{ + Type: v1.PodScheduled, + Status: v1.ConditionFalse, + Reason: reason, + Message: err.Error(), + }) +} + +// schedule implements the scheduling algorithm and returns the suggested result(host, +// evaluated nodes number,feasible nodes number). +func (sched *Scheduler) schedule(pod *v1.Pod) (core.ScheduleResult, error) { + result, err := sched.config.Algorithm.Schedule(pod, sched.config.NodeLister) if err != nil { pod = pod.DeepCopy() - sched.config.Error(pod, err) - sched.config.Recorder.Eventf(pod, v1.EventTypeWarning, "FailedScheduling", "%v", err) - sched.config.PodConditionUpdater.Update(pod, &v1.PodCondition{ - Type: v1.PodScheduled, - Status: v1.ConditionFalse, - Reason: v1.PodReasonUnschedulable, - Message: err.Error(), - }) - return "", err + sched.recordSchedulingFailure(pod, err, v1.PodReasonUnschedulable, err.Error()) + return core.ScheduleResult{}, err } - return host, err + return result, err } // preempt tries to create room for a pod that has failed to schedule, by preempting lower priority pods if possible. // If it succeeds, it adds the name of the node where preemption has happened to the pod annotations. // It returns the node name and an error if any. func (sched *Scheduler) preempt(preemptor *v1.Pod, scheduleErr error) (string, error) { - if !util.PodPriorityEnabled() || sched.config.DisablePreemption { - klog.V(3).Infof("Pod priority feature is not enabled or preemption is disabled by scheduler configuration." + - " No preemption is performed.") - return "", nil - } preemptor, err := sched.config.PodPreemptor.GetUpdatedPod(preemptor) if err != nil { klog.Errorf("Error getting the updated preemptor pod object: %v", err) @@ -320,7 +312,6 @@ func (sched *Scheduler) preempt(preemptor *v1.Pod, scheduleErr error) (string, e } node, victims, nominatedPodsToClear, err := sched.config.Algorithm.Preempt(preemptor, sched.config.NodeLister, scheduleErr) - metrics.PreemptionVictims.Set(float64(len(victims))) if err != nil { klog.Errorf("Error preempting victims to make room for %v/%v.", preemptor.Namespace, preemptor.Name) return "", err @@ -328,11 +319,19 @@ func (sched *Scheduler) preempt(preemptor *v1.Pod, scheduleErr error) (string, e var nodeName = "" if node != nil { nodeName = node.Name + // Update the scheduling queue with the nominated pod information. Without + // this, there would be a race condition between the next scheduling cycle + // and the time the scheduler receives a Pod Update for the nominated pod. + sched.config.SchedulingQueue.UpdateNominatedPodForNode(preemptor, nodeName) + + // Make a call to update nominated node name of the pod on the API server. err = sched.config.PodPreemptor.SetNominatedNodeName(preemptor, nodeName) if err != nil { klog.Errorf("Error in preemption process. Cannot update pod %v/%v annotations: %v", preemptor.Namespace, preemptor.Name, err) + sched.config.SchedulingQueue.DeleteNominatedPodIfExists(preemptor) return "", err } + for _, victim := range victims { if err := sched.config.PodPreemptor.DeletePod(victim); err != nil { klog.Errorf("Error preempting pod %v/%v: %v", victim.Namespace, victim.Name, err) @@ -340,6 +339,7 @@ func (sched *Scheduler) preempt(preemptor *v1.Pod, scheduleErr error) (string, e } sched.config.Recorder.Eventf(victim, v1.EventTypeNormal, "Preempted", "by %v/%v on node %v", preemptor.Namespace, preemptor.Name, nodeName) } + metrics.PreemptionVictims.Set(float64(len(victims))) } // Clearing nominated pods should happen outside of "if node != nil". Node could // be nil when a pod with nominated node name is eligible to preempt again, @@ -359,24 +359,10 @@ func (sched *Scheduler) preempt(preemptor *v1.Pod, scheduleErr error) (string, e // // This function modifies assumed if volume binding is required. func (sched *Scheduler) assumeVolumes(assumed *v1.Pod, host string) (allBound bool, err error) { - if utilfeature.DefaultFeatureGate.Enabled(features.VolumeScheduling) { - allBound, err = sched.config.VolumeBinder.Binder.AssumePodVolumes(assumed, host) - if err != nil { - sched.config.Error(assumed, err) - sched.config.Recorder.Eventf(assumed, v1.EventTypeWarning, "FailedScheduling", "AssumePodVolumes failed: %v", err) - sched.config.PodConditionUpdater.Update(assumed, &v1.PodCondition{ - Type: v1.PodScheduled, - Status: v1.ConditionFalse, - Reason: "SchedulerError", - Message: err.Error(), - }) - } - // Invalidate ecache because assumed volumes could have affected the cached - // pvs for other pods - if sched.config.Ecache != nil { - invalidPredicates := sets.NewString(predicates.CheckVolumeBindingPred) - sched.config.Ecache.InvalidatePredicates(invalidPredicates) - } + allBound, err = sched.config.VolumeBinder.Binder.AssumePodVolumes(assumed, host) + if err != nil { + sched.recordSchedulingFailure(assumed, err, SchedulerError, + fmt.Sprintf("AssumePodVolumes failed: %v", err)) } return } @@ -387,9 +373,6 @@ func (sched *Scheduler) assumeVolumes(assumed *v1.Pod, host string) (allBound bo // If binding errors, times out or gets undone, then an error will be returned to // retry scheduling. func (sched *Scheduler) bindVolumes(assumed *v1.Pod) error { - var reason string - var eventType string - klog.V(5).Infof("Trying to bind volumes for pod \"%v/%v\"", assumed.Namespace, assumed.Name) err := sched.config.VolumeBinder.Binder.BindPodVolumes(assumed) if err != nil { @@ -404,15 +387,7 @@ func (sched *Scheduler) bindVolumes(assumed *v1.Pod) error { // stale pod binding cache. sched.config.VolumeBinder.DeletePodBindings(assumed) - reason = "VolumeBindingFailed" - eventType = v1.EventTypeWarning - sched.config.Error(assumed, err) - sched.config.Recorder.Eventf(assumed, eventType, "FailedScheduling", "%v", err) - sched.config.PodConditionUpdater.Update(assumed, &v1.PodCondition{ - Type: v1.PodScheduled, - Status: v1.ConditionFalse, - Reason: reason, - }) + sched.recordSchedulingFailure(assumed, err, "VolumeBindingFailed", err.Error()) return err } @@ -428,11 +403,7 @@ func (sched *Scheduler) assume(assumed *v1.Pod, host string) error { // If the binding fails, scheduler will release resources allocated to assumed pod // immediately. assumed.Spec.NodeName = host - // NOTE: Updates must be written to scheduler cache before invalidating - // equivalence cache, because we could snapshot equivalence cache after the - // invalidation and then snapshot the cache itself. If the cache is - // snapshotted before updates are written, we would update equivalence - // cache with stale information which is based on snapshot of old cache. + if err := sched.config.SchedulerCache.AssumePod(assumed); err != nil { klog.Errorf("scheduler cache AssumePod failed: %v", err) @@ -441,14 +412,8 @@ func (sched *Scheduler) assume(assumed *v1.Pod, host string) error { // This relies on the fact that Error will check if the pod has been bound // to a node and if so will not add it back to the unscheduled pods queue // (otherwise this would cause an infinite loop). - sched.config.Error(assumed, err) - sched.config.Recorder.Eventf(assumed, v1.EventTypeWarning, "FailedScheduling", "AssumePod failed: %v", err) - sched.config.PodConditionUpdater.Update(assumed, &v1.PodCondition{ - Type: v1.PodScheduled, - Status: v1.ConditionFalse, - Reason: "SchedulerError", - Message: err.Error(), - }) + sched.recordSchedulingFailure(assumed, err, SchedulerError, + fmt.Sprintf("AssumePod failed: %v", err)) return err } // if "assumed" is a nominated pod, we should remove it from internal cache @@ -456,12 +421,6 @@ func (sched *Scheduler) assume(assumed *v1.Pod, host string) error { sched.config.SchedulingQueue.DeleteNominatedPodIfExists(assumed) } - // Optimistically assume that the binding will succeed, so we need to invalidate affected - // predicates in equivalence cache. - // If the binding fails, these invalidated item will not break anything. - if sched.config.Ecache != nil { - sched.config.Ecache.InvalidateCachedPredicateItemForPodAdd(assumed, host) - } return nil } @@ -480,13 +439,8 @@ func (sched *Scheduler) bind(assumed *v1.Pod, b *v1.Binding) error { if err := sched.config.SchedulerCache.ForgetPod(assumed); err != nil { klog.Errorf("scheduler cache ForgetPod failed: %v", err) } - sched.config.Error(assumed, err) - sched.config.Recorder.Eventf(assumed, v1.EventTypeWarning, "FailedScheduling", "Binding rejected: %v", err) - sched.config.PodConditionUpdater.Update(assumed, &v1.PodCondition{ - Type: v1.PodScheduled, - Status: v1.ConditionFalse, - Reason: "BindingRejected", - }) + sched.recordSchedulingFailure(assumed, err, SchedulerError, + fmt.Sprintf("Binding rejected: %v", err)) return err } @@ -498,6 +452,12 @@ func (sched *Scheduler) bind(assumed *v1.Pod, b *v1.Binding) error { // scheduleOne does the entire scheduling workflow for a single pod. It is serialized on the scheduling algorithm's host fitting. func (sched *Scheduler) scheduleOne() { + plugins := sched.config.PluginSet + // Remove all plugin context data at the beginning of a scheduling cycle. + if plugins.Data().Ctx != nil { + plugins.Data().Ctx.Reset() + } + pod := sched.config.NextPod() // pod could be nil when schedulerQueue is closed if pod == nil { @@ -513,18 +473,23 @@ func (sched *Scheduler) scheduleOne() { // Synchronously attempt to find a fit for the pod. start := time.Now() - suggestedHost, err := sched.schedule(pod) + scheduleResult, err := sched.schedule(pod) if err != nil { // schedule() may have failed because the pod would not fit on any host, so we try to // preempt, with the expectation that the next time the pod is tried for scheduling it // will fit due to the preemption. It is also possible that a different pod will schedule // into the resources that were preempted, but this is harmless. if fitError, ok := err.(*core.FitError); ok { - preemptionStartTime := time.Now() - sched.preempt(pod, fitError) - metrics.PreemptionAttempts.Inc() - metrics.SchedulingAlgorithmPremptionEvaluationDuration.Observe(metrics.SinceInMicroseconds(preemptionStartTime)) - metrics.SchedulingLatency.WithLabelValues(metrics.PreemptionEvaluation).Observe(metrics.SinceInSeconds(preemptionStartTime)) + if !util.PodPriorityEnabled() || sched.config.DisablePreemption { + klog.V(3).Infof("Pod priority feature is not enabled or preemption is disabled by scheduler configuration." + + " No preemption is performed.") + } else { + preemptionStartTime := time.Now() + sched.preempt(pod, fitError) + metrics.PreemptionAttempts.Inc() + metrics.SchedulingAlgorithmPremptionEvaluationDuration.Observe(metrics.SinceInMicroseconds(preemptionStartTime)) + metrics.SchedulingLatency.WithLabelValues(metrics.PreemptionEvaluation).Observe(metrics.SinceInSeconds(preemptionStartTime)) + } // Pod did not fit anywhere, so it is counted as a failure. If preemption // succeeds, the pod should get counted as a success the next time we try to // schedule it. (hopefully) @@ -547,15 +512,25 @@ func (sched *Scheduler) scheduleOne() { // Otherwise, binding of volumes is started after the pod is assumed, but before pod binding. // // This function modifies 'assumedPod' if volume binding is required. - allBound, err := sched.assumeVolumes(assumedPod, suggestedHost) + allBound, err := sched.assumeVolumes(assumedPod, scheduleResult.SuggestedHost) if err != nil { klog.Errorf("error assuming volumes: %v", err) metrics.PodScheduleErrors.Inc() return } - // assume modifies `assumedPod` by setting NodeName=suggestedHost - err = sched.assume(assumedPod, suggestedHost) + // Run "reserve" plugins. + for _, pl := range plugins.ReservePlugins() { + if err := pl.Reserve(plugins, assumedPod, scheduleResult.SuggestedHost); err != nil { + klog.Errorf("error while running %v reserve plugin for pod %v: %v", pl.Name(), assumedPod.Name, err) + sched.recordSchedulingFailure(assumedPod, err, SchedulerError, + fmt.Sprintf("reserve plugin %v failed", pl.Name())) + metrics.PodScheduleErrors.Inc() + return + } + } + // assume modifies `assumedPod` by setting NodeName=scheduleResult.SuggestedHost + err = sched.assume(assumedPod, scheduleResult.SuggestedHost) if err != nil { klog.Errorf("error assuming pod: %v", err) metrics.PodScheduleErrors.Inc() @@ -573,11 +548,35 @@ func (sched *Scheduler) scheduleOne() { } } + // Run "prebind" plugins. + for _, pl := range plugins.PrebindPlugins() { + approved, err := pl.Prebind(plugins, assumedPod, scheduleResult.SuggestedHost) + if err != nil { + approved = false + klog.Errorf("error while running %v prebind plugin for pod %v: %v", pl.Name(), assumedPod.Name, err) + metrics.PodScheduleErrors.Inc() + } + if !approved { + sched.Cache().ForgetPod(assumedPod) + var reason string + if err == nil { + msg := fmt.Sprintf("prebind plugin %v rejected pod %v.", pl.Name(), assumedPod.Name) + klog.V(4).Infof(msg) + err = errors.New(msg) + reason = v1.PodReasonUnschedulable + } else { + reason = SchedulerError + } + sched.recordSchedulingFailure(assumedPod, err, reason, err.Error()) + return + } + } + err := sched.bind(assumedPod, &v1.Binding{ ObjectMeta: metav1.ObjectMeta{Namespace: assumedPod.Namespace, Name: assumedPod.Name, UID: assumedPod.UID}, Target: v1.ObjectReference{ Kind: "Node", - Name: suggestedHost, + Name: scheduleResult.SuggestedHost, }, }) metrics.E2eSchedulingLatency.Observe(metrics.SinceInMicroseconds(start)) @@ -585,6 +584,7 @@ func (sched *Scheduler) scheduleOne() { klog.Errorf("error binding pod: %v", err) metrics.PodScheduleErrors.Inc() } else { + klog.V(2).Infof("pod %v/%v is bound successfully on node %v, %d nodes evaluated, %d nodes were found feasible", assumedPod.Namespace, assumedPod.Name, scheduleResult.SuggestedHost, scheduleResult.EvaluatedNodes, scheduleResult.FeasibleNodes) metrics.PodScheduleSuccesses.Inc() } }() diff --git a/pkg/scheduler/scheduler_test.go b/pkg/scheduler/scheduler_test.go index 4dac1a7bd2d..d60a4cea3bc 100644 --- a/pkg/scheduler/scheduler_test.go +++ b/pkg/scheduler/scheduler_test.go @@ -32,8 +32,6 @@ import ( "k8s.io/apimachinery/pkg/util/diff" "k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/wait" - utilfeature "k8s.io/apiserver/pkg/util/feature" - utilfeaturetesting "k8s.io/apiserver/pkg/util/feature/testing" "k8s.io/client-go/informers" clientsetfake "k8s.io/client-go/kubernetes/fake" corelister "k8s.io/client-go/listers/core/v1" @@ -41,16 +39,15 @@ import ( "k8s.io/client-go/tools/record" "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/controller/volume/persistentvolume" - "k8s.io/kubernetes/pkg/features" "k8s.io/kubernetes/pkg/scheduler/algorithm" "k8s.io/kubernetes/pkg/scheduler/algorithm/predicates" "k8s.io/kubernetes/pkg/scheduler/api" kubeschedulerconfig "k8s.io/kubernetes/pkg/scheduler/apis/config" - schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" "k8s.io/kubernetes/pkg/scheduler/core" "k8s.io/kubernetes/pkg/scheduler/factory" schedulerinternalcache "k8s.io/kubernetes/pkg/scheduler/internal/cache" fakecache "k8s.io/kubernetes/pkg/scheduler/internal/cache/fake" + schedulernodeinfo "k8s.io/kubernetes/pkg/scheduler/nodeinfo" "k8s.io/kubernetes/pkg/scheduler/volumebinder" ) @@ -136,24 +133,24 @@ func podWithResources(id, desiredHost string, limits v1.ResourceList, requests v return pod } -func PredicateOne(pod *v1.Pod, meta algorithm.PredicateMetadata, nodeInfo *schedulercache.NodeInfo) (bool, []algorithm.PredicateFailureReason, error) { +func PredicateOne(pod *v1.Pod, meta predicates.PredicateMetadata, nodeInfo *schedulernodeinfo.NodeInfo) (bool, []predicates.PredicateFailureReason, error) { return true, nil, nil } -func PriorityOne(pod *v1.Pod, nodeNameToInfo map[string]*schedulercache.NodeInfo, nodes []*v1.Node) (api.HostPriorityList, error) { +func PriorityOne(pod *v1.Pod, nodeNameToInfo map[string]*schedulernodeinfo.NodeInfo, nodes []*v1.Node) (api.HostPriorityList, error) { return []api.HostPriority{}, nil } type mockScheduler struct { - machine string - err error + result core.ScheduleResult + err error } -func (es mockScheduler) Schedule(pod *v1.Pod, ml algorithm.NodeLister) (string, error) { - return es.machine, es.err +func (es mockScheduler) Schedule(pod *v1.Pod, ml algorithm.NodeLister) (core.ScheduleResult, error) { + return es.result, es.err } -func (es mockScheduler) Predicates() map[string]algorithm.FitPredicate { +func (es mockScheduler) Predicates() map[string]predicates.FitPredicate { return nil } func (es mockScheduler) Prioritizers() []algorithm.PriorityConfig { @@ -211,7 +208,7 @@ func TestScheduler(t *testing.T) { name string injectBindError error sendPod *v1.Pod - algo algorithm.ScheduleAlgorithm + algo core.ScheduleAlgorithm expectErrorPod *v1.Pod expectForgetPod *v1.Pod expectAssumedPod *v1.Pod @@ -222,7 +219,7 @@ func TestScheduler(t *testing.T) { { name: "bind assumed pod scheduled", sendPod: podWithID("foo", ""), - algo: mockScheduler{testNode.Name, nil}, + algo: mockScheduler{core.ScheduleResult{SuggestedHost: testNode.Name, EvaluatedNodes: 1, FeasibleNodes: 1}, nil}, expectBind: &v1.Binding{ObjectMeta: metav1.ObjectMeta{Name: "foo", UID: types.UID("foo")}, Target: v1.ObjectReference{Kind: "Node", Name: testNode.Name}}, expectAssumedPod: podWithID("foo", testNode.Name), eventReason: "Scheduled", @@ -230,7 +227,7 @@ func TestScheduler(t *testing.T) { { name: "error pod failed scheduling", sendPod: podWithID("foo", ""), - algo: mockScheduler{testNode.Name, errS}, + algo: mockScheduler{core.ScheduleResult{SuggestedHost: testNode.Name, EvaluatedNodes: 1, FeasibleNodes: 1}, errS}, expectError: errS, expectErrorPod: podWithID("foo", ""), eventReason: "FailedScheduling", @@ -238,7 +235,7 @@ func TestScheduler(t *testing.T) { { name: "error bind forget pod failed scheduling", sendPod: podWithID("foo", ""), - algo: mockScheduler{testNode.Name, nil}, + algo: mockScheduler{core.ScheduleResult{SuggestedHost: testNode.Name, EvaluatedNodes: 1, FeasibleNodes: 1}, nil}, expectBind: &v1.Binding{ObjectMeta: metav1.ObjectMeta{Name: "foo", UID: types.UID("foo")}, Target: v1.ObjectReference{Kind: "Node", Name: testNode.Name}}, expectAssumedPod: podWithID("foo", testNode.Name), injectBindError: errB, @@ -248,7 +245,7 @@ func TestScheduler(t *testing.T) { eventReason: "FailedScheduling", }, { sendPod: deletingPod("foo"), - algo: mockScheduler{"", nil}, + algo: mockScheduler{core.ScheduleResult{}, nil}, eventReason: "FailedScheduling", }, } @@ -295,6 +292,7 @@ func TestScheduler(t *testing.T) { NextPod: func() *v1.Pod { return item.sendPod }, + PluginSet: &EmptyPluginSet{}, Recorder: eventBroadcaster.NewRecorder(legacyscheme.Scheme, v1.EventSource{Component: "scheduler"}), VolumeBinder: volumebinder.NewFakeVolumeBinder(&persistentvolume.FakeVolumeBinderConfig{AllBound: true}), }, @@ -340,7 +338,7 @@ func TestSchedulerNoPhantomPodAfterExpire(t *testing.T) { scache.AddNode(&node) client := clientsetfake.NewSimpleClientset(&node) informerFactory := informers.NewSharedInformerFactory(client, 0) - predicateMap := map[string]algorithm.FitPredicate{"PodFitsHostPorts": predicates.PodFitsHostPorts} + predicateMap := map[string]predicates.FitPredicate{"PodFitsHostPorts": predicates.PodFitsHostPorts} scheduler, bindingChan, _ := setupTestSchedulerWithOnePodOnNode(t, queuedPodStore, scache, informerFactory, stop, predicateMap, pod, &node) waitPodExpireChan := make(chan struct{}) @@ -399,7 +397,7 @@ func TestSchedulerNoPhantomPodAfterDelete(t *testing.T) { scache.AddNode(&node) client := clientsetfake.NewSimpleClientset(&node) informerFactory := informers.NewSharedInformerFactory(client, 0) - predicateMap := map[string]algorithm.FitPredicate{"PodFitsHostPorts": predicates.PodFitsHostPorts} + predicateMap := map[string]predicates.FitPredicate{"PodFitsHostPorts": predicates.PodFitsHostPorts} scheduler, bindingChan, errChan := setupTestSchedulerWithOnePodOnNode(t, queuedPodStore, scache, informerFactory, stop, predicateMap, firstPod, &node) // We use conflicted pod ports to incur fit predicate failure. @@ -414,7 +412,7 @@ func TestSchedulerNoPhantomPodAfterDelete(t *testing.T) { expectErr := &core.FitError{ Pod: secondPod, NumAllNodes: 1, - FailedPredicates: core.FailedPredicateMap{node.Name: []algorithm.PredicateFailureReason{predicates.ErrPodNotFitsHostPorts}}, + FailedPredicates: core.FailedPredicateMap{node.Name: []predicates.PredicateFailureReason{predicates.ErrPodNotFitsHostPorts}}, } if !reflect.DeepEqual(expectErr, err) { t.Errorf("err want=%v, get=%v", expectErr, err) @@ -424,8 +422,8 @@ func TestSchedulerNoPhantomPodAfterDelete(t *testing.T) { } // We mimic the workflow of cache behavior when a pod is removed by user. - // Note: if the schedulercache timeout would be super short, the first pod would expire - // and would be removed itself (without any explicit actions on schedulercache). Even in that case, + // Note: if the schedulernodeinfo timeout would be super short, the first pod would expire + // and would be removed itself (without any explicit actions on schedulernodeinfo). Even in that case, // explicitly AddPod will as well correct the behavior. firstPod.Spec.NodeName = node.Name if err := scache.AddPod(firstPod); err != nil { @@ -488,7 +486,7 @@ func TestSchedulerErrorWithLongBinding(t *testing.T) { client := clientsetfake.NewSimpleClientset(&node) informerFactory := informers.NewSharedInformerFactory(client, 0) - predicateMap := map[string]algorithm.FitPredicate{"PodFitsHostPorts": predicates.PodFitsHostPorts} + predicateMap := map[string]predicates.FitPredicate{"PodFitsHostPorts": predicates.PodFitsHostPorts} scheduler, bindingChan := setupTestSchedulerLongBindingWithRetry( queuedPodStore, scache, informerFactory, predicateMap, stop, test.BindingDuration) @@ -523,7 +521,7 @@ func TestSchedulerErrorWithLongBinding(t *testing.T) { // queuedPodStore: pods queued before processing. // cache: scheduler cache that might contain assumed pods. func setupTestSchedulerWithOnePodOnNode(t *testing.T, queuedPodStore *clientcache.FIFO, scache schedulerinternalcache.Cache, - informerFactory informers.SharedInformerFactory, stop chan struct{}, predicateMap map[string]algorithm.FitPredicate, pod *v1.Pod, node *v1.Node) (*Scheduler, chan *v1.Binding, chan error) { + informerFactory informers.SharedInformerFactory, stop chan struct{}, predicateMap map[string]predicates.FitPredicate, pod *v1.Pod, node *v1.Node) (*Scheduler, chan *v1.Binding, chan error) { scheduler, bindingChan, errChan := setupTestScheduler(queuedPodStore, scache, informerFactory, predicateMap, nil) @@ -595,14 +593,14 @@ func TestSchedulerFailedSchedulingReasons(t *testing.T) { } client := clientsetfake.NewSimpleClientset(objects...) informerFactory := informers.NewSharedInformerFactory(client, 0) - predicateMap := map[string]algorithm.FitPredicate{ + predicateMap := map[string]predicates.FitPredicate{ "PodFitsResources": predicates.PodFitsResources, } // Create expected failure reasons for all the nodes. Hopefully they will get rolled up into a non-spammy summary. failedPredicatesMap := core.FailedPredicateMap{} for _, node := range nodes { - failedPredicatesMap[node.Name] = []algorithm.PredicateFailureReason{ + failedPredicatesMap[node.Name] = []predicates.PredicateFailureReason{ predicates.NewInsufficientResourceError(v1.ResourceCPU, 4000, 0, 2000), predicates.NewInsufficientResourceError(v1.ResourceMemory, 500, 0, 100), } @@ -634,15 +632,15 @@ func TestSchedulerFailedSchedulingReasons(t *testing.T) { // queuedPodStore: pods queued before processing. // scache: scheduler cache that might contain assumed pods. -func setupTestScheduler(queuedPodStore *clientcache.FIFO, scache schedulerinternalcache.Cache, informerFactory informers.SharedInformerFactory, predicateMap map[string]algorithm.FitPredicate, recorder record.EventRecorder) (*Scheduler, chan *v1.Binding, chan error) { +func setupTestScheduler(queuedPodStore *clientcache.FIFO, scache schedulerinternalcache.Cache, informerFactory informers.SharedInformerFactory, predicateMap map[string]predicates.FitPredicate, recorder record.EventRecorder) (*Scheduler, chan *v1.Binding, chan error) { algo := core.NewGenericScheduler( scache, nil, - nil, predicateMap, - algorithm.EmptyPredicateMetadataProducer, + predicates.EmptyPredicateMetadataProducer, []algorithm.PriorityConfig{}, algorithm.EmptyPriorityMetadataProducer, + &EmptyPluginSet{}, []algorithm.SchedulerExtender{}, nil, informerFactory.Core().V1().PersistentVolumeClaims().Lister(), @@ -672,6 +670,7 @@ func setupTestScheduler(queuedPodStore *clientcache.FIFO, scache schedulerintern Recorder: &record.FakeRecorder{}, PodConditionUpdater: fakePodConditionUpdater{}, PodPreemptor: fakePodPreemptor{}, + PluginSet: &EmptyPluginSet{}, VolumeBinder: volumebinder.NewFakeVolumeBinder(&persistentvolume.FakeVolumeBinderConfig{AllBound: true}), }, } @@ -685,15 +684,15 @@ func setupTestScheduler(queuedPodStore *clientcache.FIFO, scache schedulerintern return sched, bindingChan, errChan } -func setupTestSchedulerLongBindingWithRetry(queuedPodStore *clientcache.FIFO, scache schedulerinternalcache.Cache, informerFactory informers.SharedInformerFactory, predicateMap map[string]algorithm.FitPredicate, stop chan struct{}, bindingTime time.Duration) (*Scheduler, chan *v1.Binding) { +func setupTestSchedulerLongBindingWithRetry(queuedPodStore *clientcache.FIFO, scache schedulerinternalcache.Cache, informerFactory informers.SharedInformerFactory, predicateMap map[string]predicates.FitPredicate, stop chan struct{}, bindingTime time.Duration) (*Scheduler, chan *v1.Binding) { algo := core.NewGenericScheduler( scache, nil, - nil, predicateMap, - algorithm.EmptyPredicateMetadataProducer, + predicates.EmptyPredicateMetadataProducer, []algorithm.PriorityConfig{}, algorithm.EmptyPriorityMetadataProducer, + &EmptyPluginSet{}, []algorithm.SchedulerExtender{}, nil, informerFactory.Core().V1().PersistentVolumeClaims().Lister(), @@ -727,6 +726,7 @@ func setupTestSchedulerLongBindingWithRetry(queuedPodStore *clientcache.FIFO, sc PodConditionUpdater: fakePodConditionUpdater{}, PodPreemptor: fakePodPreemptor{}, StopEverything: stop, + PluginSet: &EmptyPluginSet{}, VolumeBinder: volumebinder.NewFakeVolumeBinder(&persistentvolume.FakeVolumeBinderConfig{AllBound: true}), }, } @@ -745,7 +745,7 @@ func setupTestSchedulerWithVolumeBinding(fakeVolumeBinder *volumebinder.VolumeBi client := clientsetfake.NewSimpleClientset(&testNode) informerFactory := informers.NewSharedInformerFactory(client, 0) - predicateMap := map[string]algorithm.FitPredicate{ + predicateMap := map[string]predicates.FitPredicate{ predicates.CheckVolumeBindingPred: predicates.NewVolumeBindingPredicate(fakeVolumeBinder), } @@ -776,8 +776,6 @@ func TestSchedulerWithVolumeBinding(t *testing.T) { // This can be small because we wait for pod to finish scheduling first chanTimeout := 2 * time.Second - defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.VolumeScheduling, true)() - table := []struct { name string expectError error diff --git a/pkg/scheduler/testing/BUILD b/pkg/scheduler/testing/BUILD index 91acca08c54..8b9a1e8e885 100644 --- a/pkg/scheduler/testing/BUILD +++ b/pkg/scheduler/testing/BUILD @@ -1,31 +1,18 @@ package(default_visibility = ["//visibility:public"]) -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", - "go_test", -) +load("@io_bazel_rules_go//go:def.bzl", "go_library") go_library( name = "go_default_library", - srcs = [ - "fake_lister.go", - "util.go", - ], + srcs = ["fake_lister.go"], importpath = "k8s.io/kubernetes/pkg/scheduler/testing", deps = [ - "//pkg/api/legacyscheme:go_default_library", - "//pkg/apis/core:go_default_library", - "//pkg/apis/core/install:go_default_library", "//pkg/scheduler/algorithm:go_default_library", - "//pkg/scheduler/internal/cache:go_default_library", "//staging/src/k8s.io/api/apps/v1:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library", "//staging/src/k8s.io/api/policy/v1beta1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/labels:go_default_library", - "//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library", - "//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", "//staging/src/k8s.io/client-go/listers/core/v1:go_default_library", ], ) @@ -42,13 +29,3 @@ filegroup( srcs = [":package-srcs"], tags = ["automanaged"], ) - -go_test( - name = "go_default_test", - srcs = ["util_test.go"], - embed = [":go_default_library"], - deps = [ - "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library", - ], -) diff --git a/pkg/scheduler/testing/fake_lister.go b/pkg/scheduler/testing/fake_lister.go index 5fb36525977..343800a388e 100644 --- a/pkg/scheduler/testing/fake_lister.go +++ b/pkg/scheduler/testing/fake_lister.go @@ -26,7 +26,6 @@ import ( "k8s.io/apimachinery/pkg/labels" corelisters "k8s.io/client-go/listers/core/v1" "k8s.io/kubernetes/pkg/scheduler/algorithm" - schedulerinternalcache "k8s.io/kubernetes/pkg/scheduler/internal/cache" ) var _ algorithm.NodeLister = &FakeNodeLister{} @@ -55,7 +54,7 @@ func (f FakePodLister) List(s labels.Selector) (selected []*v1.Pod, err error) { } // FilteredList returns pods matching a pod filter and a label selector. -func (f FakePodLister) FilteredList(podFilter schedulerinternalcache.PodFilter, s labels.Selector) (selected []*v1.Pod, err error) { +func (f FakePodLister) FilteredList(podFilter algorithm.PodFilter, s labels.Selector) (selected []*v1.Pod, err error) { for _, pod := range f { if podFilter(pod) && s.Matches(labels.Set(pod.Labels)) { selected = append(selected, pod) diff --git a/pkg/scheduler/testing/util.go b/pkg/scheduler/testing/util.go deleted file mode 100644 index 25921a2e058..00000000000 --- a/pkg/scheduler/testing/util.go +++ /dev/null @@ -1,173 +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 testing - -import ( - "fmt" - "mime" - "os" - "reflect" - "strings" - - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/schema" - "k8s.io/kubernetes/pkg/api/legacyscheme" - api "k8s.io/kubernetes/pkg/apis/core" - - // Init the core api installation - _ "k8s.io/kubernetes/pkg/apis/core/install" -) - -// TestGroup defines a api group for testing. -type TestGroup struct { - externalGroupVersion schema.GroupVersion - internalGroupVersion schema.GroupVersion - internalTypes map[string]reflect.Type - externalTypes map[string]reflect.Type -} - -var ( - // Groups defines a TestGroup map. - Groups = make(map[string]TestGroup) - // Test defines a TestGroup object. - Test TestGroup - - serializer runtime.SerializerInfo -) - -func init() { - if apiMediaType := os.Getenv("KUBE_TEST_API_TYPE"); len(apiMediaType) > 0 { - var ok bool - mediaType, _, err := mime.ParseMediaType(apiMediaType) - if err != nil { - panic(err) - } - serializer, ok = runtime.SerializerInfoForMediaType(legacyscheme.Codecs.SupportedMediaTypes(), mediaType) - if !ok { - panic(fmt.Sprintf("no serializer for %s", apiMediaType)) - } - } - - kubeTestAPI := os.Getenv("KUBE_TEST_API") - if len(kubeTestAPI) != 0 { - // priority is "first in list preferred", so this has to run in reverse order - testGroupVersions := strings.Split(kubeTestAPI, ",") - for i := len(testGroupVersions) - 1; i >= 0; i-- { - gvString := testGroupVersions[i] - groupVersion, err := schema.ParseGroupVersion(gvString) - if err != nil { - panic(fmt.Sprintf("Error parsing groupversion %v: %v", gvString, err)) - } - - internalGroupVersion := schema.GroupVersion{Group: groupVersion.Group, Version: runtime.APIVersionInternal} - Groups[groupVersion.Group] = TestGroup{ - externalGroupVersion: groupVersion, - internalGroupVersion: internalGroupVersion, - internalTypes: legacyscheme.Scheme.KnownTypes(internalGroupVersion), - externalTypes: legacyscheme.Scheme.KnownTypes(groupVersion), - } - } - } - - if _, ok := Groups[api.GroupName]; !ok { - externalGroupVersion := schema.GroupVersion{Group: api.GroupName, Version: "v1"} - Groups[api.GroupName] = TestGroup{ - externalGroupVersion: externalGroupVersion, - internalGroupVersion: api.SchemeGroupVersion, - internalTypes: legacyscheme.Scheme.KnownTypes(api.SchemeGroupVersion), - externalTypes: legacyscheme.Scheme.KnownTypes(externalGroupVersion), - } - } - - Test = Groups[api.GroupName] -} - -// Codec returns the codec for the API version to test against, as set by the -// KUBE_TEST_API_TYPE env var. -func (g TestGroup) Codec() runtime.Codec { - if serializer.Serializer == nil { - return legacyscheme.Codecs.LegacyCodec(g.externalGroupVersion) - } - return legacyscheme.Codecs.CodecForVersions(serializer.Serializer, legacyscheme.Codecs.UniversalDeserializer(), schema.GroupVersions{g.externalGroupVersion}, nil) -} - -// SelfLink returns a self link that will appear to be for the version Version(). -// 'resource' should be the resource path, e.g. "pods" for the Pod type. 'name' should be -// empty for lists. -func (g TestGroup) SelfLink(resource, name string) string { - if g.externalGroupVersion.Group == api.GroupName { - if name == "" { - return fmt.Sprintf("/api/%s/%s", g.externalGroupVersion.Version, resource) - } - return fmt.Sprintf("/api/%s/%s/%s", g.externalGroupVersion.Version, resource, name) - } - - // TODO: will need a /apis prefix once we have proper multi-group - // support - if name == "" { - return fmt.Sprintf("/apis/%s/%s/%s", g.externalGroupVersion.Group, g.externalGroupVersion.Version, resource) - } - return fmt.Sprintf("/apis/%s/%s/%s/%s", g.externalGroupVersion.Group, g.externalGroupVersion.Version, resource, name) -} - -// ResourcePathWithPrefix returns the appropriate path for the given prefix (watch, proxy, redirect, etc), resource, namespace and name. -// For ex, this is of the form: -// /api/v1/watch/namespaces/foo/pods/pod0 for v1. -func (g TestGroup) ResourcePathWithPrefix(prefix, resource, namespace, name string) string { - var path string - if g.externalGroupVersion.Group == api.GroupName { - path = "/api/" + g.externalGroupVersion.Version - } else { - // TODO: switch back once we have proper multiple group support - // path = "/apis/" + g.Group + "/" + Version(group...) - path = "/apis/" + g.externalGroupVersion.Group + "/" + g.externalGroupVersion.Version - } - - if prefix != "" { - path = path + "/" + prefix - } - if namespace != "" { - path = path + "/namespaces/" + namespace - } - // Resource names are lower case. - resource = strings.ToLower(resource) - if resource != "" { - path = path + "/" + resource - } - if name != "" { - path = path + "/" + name - } - return path -} - -// ResourcePath returns the appropriate path for the given resource, namespace and name. -// For example, this is of the form: -// /api/v1/namespaces/foo/pods/pod0 for v1. -func (g TestGroup) ResourcePath(resource, namespace, name string) string { - return g.ResourcePathWithPrefix("", resource, namespace, name) -} - -// SubResourcePath returns the appropriate path for the given resource, namespace, -// name and subresource. -func (g TestGroup) SubResourcePath(resource, namespace, name, sub string) string { - path := g.ResourcePathWithPrefix("", resource, namespace, name) - if sub != "" { - path = path + "/" + sub - } - - return path -} diff --git a/pkg/scheduler/testing/util_test.go b/pkg/scheduler/testing/util_test.go deleted file mode 100644 index e6545b00559..00000000000 --- a/pkg/scheduler/testing/util_test.go +++ /dev/null @@ -1,214 +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 testing - -import ( - "encoding/json" - "reflect" - "testing" - - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime" -) - -func TestResourcePathWithPrefix(t *testing.T) { - testCases := []struct { - prefix string - resource string - namespace string - name string - expected string - }{ - {"prefix", "resource", "mynamespace", "myresource", "/api/" + Test.externalGroupVersion.Version + "/prefix/namespaces/mynamespace/resource/myresource"}, - {"prefix", "resource", "", "myresource", "/api/" + Test.externalGroupVersion.Version + "/prefix/resource/myresource"}, - {"prefix", "resource", "mynamespace", "", "/api/" + Test.externalGroupVersion.Version + "/prefix/namespaces/mynamespace/resource"}, - {"prefix", "resource", "", "", "/api/" + Test.externalGroupVersion.Version + "/prefix/resource"}, - {"", "resource", "mynamespace", "myresource", "/api/" + Test.externalGroupVersion.Version + "/namespaces/mynamespace/resource/myresource"}, - } - for _, item := range testCases { - if actual := Test.ResourcePathWithPrefix(item.prefix, item.resource, item.namespace, item.name); actual != item.expected { - t.Errorf("Expected: %s, got: %s for prefix: %s, resource: %s, namespace: %s and name: %s", item.expected, actual, item.prefix, item.resource, item.namespace, item.name) - } - } - - TestGroup := Test - TestGroup.externalGroupVersion.Group = "TestGroup" - - testGroupCases := []struct { - prefix string - resource string - namespace string - name string - expected string - }{ - {"prefix", "resource", "mynamespace", "myresource", "/apis/" + TestGroup.externalGroupVersion.Group + "/" + TestGroup.externalGroupVersion.Version + "/prefix/namespaces/mynamespace/resource/myresource"}, - {"prefix", "resource", "", "myresource", "/apis/" + TestGroup.externalGroupVersion.Group + "/" + TestGroup.externalGroupVersion.Version + "/prefix/resource/myresource"}, - {"prefix", "resource", "mynamespace", "", "/apis/" + TestGroup.externalGroupVersion.Group + "/" + TestGroup.externalGroupVersion.Version + "/prefix/namespaces/mynamespace/resource"}, - {"prefix", "resource", "", "", "/apis/" + TestGroup.externalGroupVersion.Group + "/" + TestGroup.externalGroupVersion.Version + "/prefix/resource"}, - {"", "resource", "mynamespace", "myresource", "/apis/" + TestGroup.externalGroupVersion.Group + "/" + TestGroup.externalGroupVersion.Version + "/namespaces/mynamespace/resource/myresource"}, - } - for _, item := range testGroupCases { - if actual := TestGroup.ResourcePathWithPrefix(item.prefix, item.resource, item.namespace, item.name); actual != item.expected { - t.Errorf("Expected: %s, got: %s for prefix: %s, resource: %s, namespace: %s and name: %s", item.expected, actual, item.prefix, item.resource, item.namespace, item.name) - } - } - -} - -func TestResourcePath(t *testing.T) { - testCases := []struct { - resource string - namespace string - name string - expected string - }{ - {"resource", "mynamespace", "myresource", "/api/" + Test.externalGroupVersion.Version + "/namespaces/mynamespace/resource/myresource"}, - {"resource", "", "myresource", "/api/" + Test.externalGroupVersion.Version + "/resource/myresource"}, - {"resource", "mynamespace", "", "/api/" + Test.externalGroupVersion.Version + "/namespaces/mynamespace/resource"}, - {"resource", "", "", "/api/" + Test.externalGroupVersion.Version + "/resource"}, - } - for _, item := range testCases { - if actual := Test.ResourcePath(item.resource, item.namespace, item.name); actual != item.expected { - t.Errorf("Expected: %s, got: %s for resource: %s, namespace: %s and name: %s", item.expected, actual, item.resource, item.namespace, item.name) - } - } - - TestGroup := Test - TestGroup.externalGroupVersion.Group = "TestGroup" - - testGroupCases := []struct { - resource string - namespace string - name string - expected string - }{ - {"resource", "mynamespace", "myresource", "/apis/" + TestGroup.externalGroupVersion.Group + "/" + TestGroup.externalGroupVersion.Version + "/namespaces/mynamespace/resource/myresource"}, - {"resource", "", "myresource", "/apis/" + TestGroup.externalGroupVersion.Group + "/" + TestGroup.externalGroupVersion.Version + "/resource/myresource"}, - {"resource", "mynamespace", "", "/apis/" + TestGroup.externalGroupVersion.Group + "/" + TestGroup.externalGroupVersion.Version + "/namespaces/mynamespace/resource"}, - {"resource", "", "", "/apis/" + TestGroup.externalGroupVersion.Group + "/" + TestGroup.externalGroupVersion.Version + "/resource"}, - } - for _, item := range testGroupCases { - if actual := TestGroup.ResourcePath(item.resource, item.namespace, item.name); actual != item.expected { - t.Errorf("Expected: %s, got: %s for resource: %s, namespace: %s and name: %s", item.expected, actual, item.resource, item.namespace, item.name) - } - } - -} - -func TestSubResourcePath(t *testing.T) { - testCases := []struct { - resource string - namespace string - name string - sub string - expected string - }{ - {"resource", "mynamespace", "myresource", "subresource", "/api/" + Test.externalGroupVersion.Version + "/namespaces/mynamespace/resource/myresource/subresource"}, - {"resource", "mynamespace", "myresource", "", "/api/" + Test.externalGroupVersion.Version + "/namespaces/mynamespace/resource/myresource"}, - } - for _, item := range testCases { - if actual := Test.SubResourcePath(item.resource, item.namespace, item.name, item.sub); actual != item.expected { - t.Errorf("Expected: %s, got: %s for resource: %s, namespace: %s, name: %s and sub: %s", item.expected, actual, item.resource, item.namespace, item.name, item.sub) - } - } - - TestGroup := Test - TestGroup.externalGroupVersion.Group = "TestGroup" - - testGroupCases := []struct { - resource string - namespace string - name string - sub string - expected string - }{ - {"resource", "mynamespace", "myresource", "subresource", "/apis/" + TestGroup.externalGroupVersion.Group + "/" + TestGroup.externalGroupVersion.Version + "/namespaces/mynamespace/resource/myresource/subresource"}, - {"resource", "mynamespace", "myresource", "", "/apis/" + TestGroup.externalGroupVersion.Group + "/" + TestGroup.externalGroupVersion.Version + "/namespaces/mynamespace/resource/myresource"}, - } - for _, item := range testGroupCases { - if actual := TestGroup.SubResourcePath(item.resource, item.namespace, item.name, item.sub); actual != item.expected { - t.Errorf("Expected: %s, got: %s for resource: %s, namespace: %s, name: %s and sub: %s", item.expected, actual, item.resource, item.namespace, item.name, item.sub) - } - } - -} - -func TestSelfLink(t *testing.T) { - testCases := []struct { - resource string - name string - expected string - }{ - {"resource", "name", "/api/" + Test.externalGroupVersion.Version + "/resource/name"}, - {"resource", "", "/api/" + Test.externalGroupVersion.Version + "/resource"}, - } - for _, item := range testCases { - if actual := Test.SelfLink(item.resource, item.name); actual != item.expected { - t.Errorf("Expected: %s, got: %s for resource: %s and name: %s", item.expected, actual, item.resource, item.name) - } - } - - TestGroup := Test - TestGroup.externalGroupVersion.Group = "TestGroup" - - testGroupCases := []struct { - resource string - name string - expected string - }{ - {"resource", "name", "/apis/" + TestGroup.externalGroupVersion.Group + "/" + TestGroup.externalGroupVersion.Version + "/resource/name"}, - {"resource", "", "/apis/" + TestGroup.externalGroupVersion.Group + "/" + TestGroup.externalGroupVersion.Version + "/resource"}, - } - for _, item := range testGroupCases { - if actual := TestGroup.SelfLink(item.resource, item.name); actual != item.expected { - t.Errorf("Expected: %s, got: %s for resource: %s and name: %s", item.expected, actual, item.resource, item.name) - } - } -} - -var status = &metav1.Status{ - Status: metav1.StatusFailure, - Code: 200, - Reason: metav1.StatusReasonUnknown, - Message: "", -} - -func TestV1EncodeDecodeStatus(t *testing.T) { - v1Codec := Test.Codec() - - encoded, err := runtime.Encode(v1Codec, status) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - typeMeta := metav1.TypeMeta{} - if err := json.Unmarshal(encoded, &typeMeta); err != nil { - t.Errorf("unexpected error: %v", err) - } - if typeMeta.Kind != "Status" { - t.Errorf("Kind is not set to \"Status\". Got %v", string(encoded)) - } - if typeMeta.APIVersion != "v1" { - t.Errorf("APIVersion is not set to \"v1\". Got %v", string(encoded)) - } - decoded, err := runtime.Decode(v1Codec, encoded) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - if !reflect.DeepEqual(status, decoded) { - t.Errorf("expected: %#v, got: %#v", status, decoded) - } -} diff --git a/pkg/scheduler/testutil.go b/pkg/scheduler/testutil.go index 0c101a54573..641bf88cf5a 100644 --- a/pkg/scheduler/testutil.go +++ b/pkg/scheduler/testutil.go @@ -24,9 +24,11 @@ import ( clientset "k8s.io/client-go/kubernetes" corelisters "k8s.io/client-go/listers/core/v1" "k8s.io/kubernetes/pkg/scheduler/algorithm" + "k8s.io/kubernetes/pkg/scheduler/algorithm/predicates" schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" "k8s.io/kubernetes/pkg/scheduler/factory" internalqueue "k8s.io/kubernetes/pkg/scheduler/internal/queue" + plugins "k8s.io/kubernetes/pkg/scheduler/plugins/v1alpha1" "k8s.io/kubernetes/pkg/scheduler/util" ) @@ -36,12 +38,12 @@ type FakeConfigurator struct { } // GetPredicateMetadataProducer is not implemented yet. -func (fc *FakeConfigurator) GetPredicateMetadataProducer() (algorithm.PredicateMetadataProducer, error) { +func (fc *FakeConfigurator) GetPredicateMetadataProducer() (predicates.PredicateMetadataProducer, error) { return nil, fmt.Errorf("not implemented") } // GetPredicates is not implemented yet. -func (fc *FakeConfigurator) GetPredicates(predicateKeys sets.String) (map[string]algorithm.FitPredicate, error) { +func (fc *FakeConfigurator) GetPredicates(predicateKeys sets.String) (map[string]predicates.FitPredicate, error) { return nil, fmt.Errorf("not implemented") } @@ -89,3 +91,26 @@ func (fc *FakeConfigurator) CreateFromConfig(policy schedulerapi.Policy) (*facto func (fc *FakeConfigurator) CreateFromKeys(predicateKeys, priorityKeys sets.String, extenders []algorithm.SchedulerExtender) (*factory.Config, error) { return fc.Config, nil } + +// EmptyPluginSet is the default plugin restirar used by the default scheduler. +type EmptyPluginSet struct{} + +var _ = plugins.PluginSet(EmptyPluginSet{}) + +// ReservePlugins returns a slice of default reserve plugins. +func (r EmptyPluginSet) ReservePlugins() []plugins.ReservePlugin { + return []plugins.ReservePlugin{} +} + +// PrebindPlugins returns a slice of default prebind plugins. +func (r EmptyPluginSet) PrebindPlugins() []plugins.PrebindPlugin { + return []plugins.PrebindPlugin{} +} + +// Data returns a pointer to PluginData. +func (r EmptyPluginSet) Data() *plugins.PluginData { + return &plugins.PluginData{ + Ctx: nil, + SchedulerCache: nil, + } +} diff --git a/pkg/scheduler/util/BUILD b/pkg/scheduler/util/BUILD index 810d2c5cb0a..53649692f2a 100644 --- a/pkg/scheduler/util/BUILD +++ b/pkg/scheduler/util/BUILD @@ -10,6 +10,7 @@ go_test( name = "go_default_test", srcs = [ "backoff_utils_test.go", + "heap_test.go", "utils_test.go", ], embed = [":go_default_library"], @@ -25,6 +26,8 @@ go_library( name = "go_default_library", srcs = [ "backoff_utils.go", + "clock.go", + "heap.go", "utils.go", ], importpath = "k8s.io/kubernetes/pkg/scheduler/util", @@ -34,6 +37,7 @@ go_library( "//staging/src/k8s.io/api/core/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/types:go_default_library", "//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library", + "//staging/src/k8s.io/client-go/tools/cache:go_default_library", "//vendor/k8s.io/klog:go_default_library", ], ) diff --git a/pkg/scheduler/util/backoff_utils.go b/pkg/scheduler/util/backoff_utils.go index 506cd1270ac..618f93772f9 100644 --- a/pkg/scheduler/util/backoff_utils.go +++ b/pkg/scheduler/util/backoff_utils.go @@ -37,10 +37,11 @@ func (realClock) Now() time.Time { return time.Now() } -// BackoffEntry is single threaded. in particular, it only allows a single action to be waiting on backoff at a time. -// It is expected that all users will only use the public TryWait(...) method +// backoffEntry is single threaded. in particular, it only allows a single action to be waiting on backoff at a time. // It is also not safe to copy this object. -type BackoffEntry struct { +type backoffEntry struct { + initialized bool + podName ktypes.NamespacedName backoff time.Duration lastUpdate time.Time reqInFlight int32 @@ -48,45 +49,41 @@ type BackoffEntry struct { // tryLock attempts to acquire a lock via atomic compare and swap. // returns true if the lock was acquired, false otherwise -func (b *BackoffEntry) tryLock() bool { +func (b *backoffEntry) tryLock() bool { return atomic.CompareAndSwapInt32(&b.reqInFlight, 0, 1) } // unlock returns the lock. panics if the lock isn't held -func (b *BackoffEntry) unlock() { +func (b *backoffEntry) unlock() { if !atomic.CompareAndSwapInt32(&b.reqInFlight, 1, 0) { panic(fmt.Sprintf("unexpected state on unlocking: %+v", b)) } } -// TryWait tries to acquire the backoff lock, maxDuration is the maximum allowed period to wait for. -func (b *BackoffEntry) TryWait(maxDuration time.Duration) bool { - if !b.tryLock() { - return false - } - defer b.unlock() - b.wait(maxDuration) - return true +// backoffTime returns the Time when a backoffEntry completes backoff +func (b *backoffEntry) backoffTime() time.Time { + return b.lastUpdate.Add(b.backoff) } -func (b *BackoffEntry) getBackoff(maxDuration time.Duration) time.Duration { - duration := b.backoff - newDuration := time.Duration(duration) * 2 +// getBackoff returns the duration until this entry completes backoff +func (b *backoffEntry) getBackoff(maxDuration time.Duration) time.Duration { + if !b.initialized { + b.initialized = true + return b.backoff + } + newDuration := b.backoff * 2 if newDuration > maxDuration { newDuration = maxDuration } b.backoff = newDuration - klog.V(4).Infof("Backing off %s", duration.String()) - return duration -} - -func (b *BackoffEntry) wait(maxDuration time.Duration) { - time.Sleep(b.getBackoff(maxDuration)) + klog.V(4).Infof("Backing off %s", newDuration.String()) + return newDuration } // PodBackoff is used to restart a pod with back-off delay. type PodBackoff struct { - perPodBackoff map[ktypes.NamespacedName]*BackoffEntry + // expiryQ stores backoffEntry orderedy by lastUpdate until they reach maxDuration and are GC'd + expiryQ *Heap lock sync.Mutex clock clock defaultDuration time.Duration @@ -111,24 +108,58 @@ func CreatePodBackoff(defaultDuration, maxDuration time.Duration) *PodBackoff { // CreatePodBackoffWithClock creates a pod back-off object by default duration, max duration and clock. func CreatePodBackoffWithClock(defaultDuration, maxDuration time.Duration, clock clock) *PodBackoff { return &PodBackoff{ - perPodBackoff: map[ktypes.NamespacedName]*BackoffEntry{}, + expiryQ: NewHeap(backoffEntryKeyFunc, backoffEntryCompareUpdate), clock: clock, defaultDuration: defaultDuration, maxDuration: maxDuration, } } -// GetEntry returns a back-off entry by Pod ID. -func (p *PodBackoff) GetEntry(podID ktypes.NamespacedName) *BackoffEntry { +// getEntry returns the backoffEntry for a given podID +func (p *PodBackoff) getEntry(podID ktypes.NamespacedName) *backoffEntry { + entry, exists, _ := p.expiryQ.GetByKey(podID.String()) + var be *backoffEntry + if !exists { + be = &backoffEntry{ + initialized: false, + podName: podID, + backoff: p.defaultDuration, + } + p.expiryQ.Update(be) + } else { + be = entry.(*backoffEntry) + } + return be +} + +// BackoffPod updates the backoff for a podId and returns the duration until backoff completion +func (p *PodBackoff) BackoffPod(podID ktypes.NamespacedName) time.Duration { p.lock.Lock() defer p.lock.Unlock() - entry, ok := p.perPodBackoff[podID] - if !ok { - entry = &BackoffEntry{backoff: p.defaultDuration} - p.perPodBackoff[podID] = entry - } + entry := p.getEntry(podID) entry.lastUpdate = p.clock.Now() - return entry + p.expiryQ.Update(entry) + return entry.getBackoff(p.maxDuration) +} + +// TryBackoffAndWait tries to acquire the backoff lock +func (p *PodBackoff) TryBackoffAndWait(podID ktypes.NamespacedName, stop <-chan struct{}) bool { + p.lock.Lock() + entry := p.getEntry(podID) + + if !entry.tryLock() { + p.lock.Unlock() + return false + } + defer entry.unlock() + duration := entry.getBackoff(p.maxDuration) + p.lock.Unlock() + select { + case <-time.After(duration): + return true + case <-stop: + return false + } } // Gc execute garbage collection on the pod back-off. @@ -136,9 +167,54 @@ func (p *PodBackoff) Gc() { p.lock.Lock() defer p.lock.Unlock() now := p.clock.Now() - for podID, entry := range p.perPodBackoff { - if now.Sub(entry.lastUpdate) > p.maxDuration { - delete(p.perPodBackoff, podID) + var be *backoffEntry + for { + entry := p.expiryQ.Peek() + if entry == nil { + break + } + be = entry.(*backoffEntry) + if now.Sub(be.lastUpdate) > p.maxDuration { + p.expiryQ.Pop() + } else { + break } } } + +// GetBackoffTime returns the time that podID completes backoff +func (p *PodBackoff) GetBackoffTime(podID ktypes.NamespacedName) (time.Time, bool) { + p.lock.Lock() + defer p.lock.Unlock() + rawBe, exists, _ := p.expiryQ.GetByKey(podID.String()) + if !exists { + return time.Time{}, false + } + be := rawBe.(*backoffEntry) + return be.lastUpdate.Add(be.backoff), true +} + +// ClearPodBackoff removes all tracking information for podID (clears expiry) +func (p *PodBackoff) ClearPodBackoff(podID ktypes.NamespacedName) bool { + p.lock.Lock() + defer p.lock.Unlock() + entry, exists, _ := p.expiryQ.GetByKey(podID.String()) + if exists { + err := p.expiryQ.Delete(entry) + return err == nil + } + return false +} + +// backoffEntryKeyFunc is the keying function used for mapping a backoffEntry to string for heap +func backoffEntryKeyFunc(b interface{}) (string, error) { + be := b.(*backoffEntry) + return be.podName.String(), nil +} + +// backoffEntryCompareUpdate returns true when b1's backoff time is before b2's +func backoffEntryCompareUpdate(b1, b2 interface{}) bool { + be1 := b1.(*backoffEntry) + be2 := b2.(*backoffEntry) + return be1.lastUpdate.Before(be2.lastUpdate) +} diff --git a/pkg/scheduler/util/backoff_utils_test.go b/pkg/scheduler/util/backoff_utils_test.go index 8f61b637e7d..b99c9498f58 100644 --- a/pkg/scheduler/util/backoff_utils_test.go +++ b/pkg/scheduler/util/backoff_utils_test.go @@ -31,7 +31,7 @@ func (f *fakeClock) Now() time.Time { return f.t } -func TestBackoff(t *testing.T) { +func TestBackoffPod(t *testing.T) { clock := fakeClock{} backoff := CreatePodBackoffWithClock(1*time.Second, 60*time.Second, &clock) tests := []struct { @@ -64,23 +64,75 @@ func TestBackoff(t *testing.T) { } for _, test := range tests { - duration := backoff.GetEntry(test.podID).getBackoff(backoff.maxDuration) + duration := backoff.BackoffPod(test.podID) if duration != test.expectedDuration { - t.Errorf("expected: %s, got %s for %s", test.expectedDuration.String(), duration.String(), test.podID) + t.Errorf("expected: %s, got %s for pod %s", test.expectedDuration.String(), duration.String(), test.podID) + } + if boTime, _ := backoff.GetBackoffTime(test.podID); boTime != clock.Now().Add(test.expectedDuration) { + t.Errorf("expected GetBackoffTime %s, got %s for pod %s", test.expectedDuration.String(), boTime.String(), test.podID) } clock.t = clock.t.Add(test.advanceClock) backoff.Gc() } fooID := ktypes.NamespacedName{Namespace: "default", Name: "foo"} - backoff.perPodBackoff[fooID].backoff = 60 * time.Second - duration := backoff.GetEntry(fooID).getBackoff(backoff.maxDuration) + be := backoff.getEntry(fooID) + be.backoff = 60 * time.Second + duration := backoff.BackoffPod(fooID) if duration != 60*time.Second { t.Errorf("expected: 60, got %s", duration.String()) } // Verify that we split on namespaces correctly, same name, different namespace fooID.Namespace = "other" - duration = backoff.GetEntry(fooID).getBackoff(backoff.maxDuration) + duration = backoff.BackoffPod(fooID) if duration != 1*time.Second { t.Errorf("expected: 1, got %s", duration.String()) } } + +func TestClearPodBackoff(t *testing.T) { + clock := fakeClock{} + backoff := CreatePodBackoffWithClock(1*time.Second, 60*time.Second, &clock) + + if backoff.ClearPodBackoff(ktypes.NamespacedName{Namespace: "ns", Name: "nonexist"}) { + t.Error("Expected ClearPodBackoff failure for unknown pod, got success.") + } + + podID := ktypes.NamespacedName{Namespace: "ns", Name: "foo"} + if dur := backoff.BackoffPod(podID); dur != 1*time.Second { + t.Errorf("Expected backoff of 1s for pod %s, got %s", podID, dur.String()) + } + + if !backoff.ClearPodBackoff(podID) { + t.Errorf("Failed to clear backoff for pod %v", podID) + } + + expectBoTime := clock.Now() + if boTime, _ := backoff.GetBackoffTime(podID); boTime != expectBoTime { + t.Errorf("Expected backoff time for pod %s of %s, got %s", podID, expectBoTime, boTime) + } +} + +func TestTryBackoffAndWait(t *testing.T) { + clock := fakeClock{} + backoff := CreatePodBackoffWithClock(1*time.Second, 60*time.Second, &clock) + + stopCh := make(chan struct{}) + podID := ktypes.NamespacedName{Namespace: "ns", Name: "pod"} + if !backoff.TryBackoffAndWait(podID, stopCh) { + t.Error("Expected TryBackoffAndWait success for new pod, got failure.") + } + + be := backoff.getEntry(podID) + if !be.tryLock() { + t.Error("Failed to acquire lock for backoffentry") + } + + if backoff.TryBackoffAndWait(podID, stopCh) { + t.Error("Expected TryBackoffAndWait failure with lock acquired, got success.") + } + + close(stopCh) + if backoff.TryBackoffAndWait(podID, stopCh) { + t.Error("Expected TryBackoffAndWait failure with closed stopCh, got success.") + } +} diff --git a/pkg/scheduler/util/clock.go b/pkg/scheduler/util/clock.go new file mode 100644 index 00000000000..e17c759dbac --- /dev/null +++ b/pkg/scheduler/util/clock.go @@ -0,0 +1,34 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package util + +import ( + "time" +) + +// Clock provides an interface for getting the current time +type Clock interface { + Now() time.Time +} + +// RealClock implements a clock using time +type RealClock struct{} + +// Now returns the current time with time.Now +func (RealClock) Now() time.Time { + return time.Now() +} diff --git a/pkg/scheduler/util/heap.go b/pkg/scheduler/util/heap.go new file mode 100644 index 00000000000..0f15652c654 --- /dev/null +++ b/pkg/scheduler/util/heap.go @@ -0,0 +1,236 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Below is the implementation of the a heap. The logic is pretty much the same +// as cache.heap, however, this heap does not perform synchronization. It leaves +// synchronization to the SchedulingQueue. + +package util + +import ( + "container/heap" + "fmt" + + "k8s.io/client-go/tools/cache" +) + +// KeyFunc is a function type to get the key from an object. +type KeyFunc func(obj interface{}) (string, error) + +type heapItem struct { + obj interface{} // The object which is stored in the heap. + index int // The index of the object's key in the Heap.queue. +} + +type itemKeyValue struct { + key string + obj interface{} +} + +// heapData is an internal struct that implements the standard heap interface +// and keeps the data stored in the heap. +type heapData struct { + // items is a map from key of the objects to the objects and their index. + // We depend on the property that items in the map are in the queue and vice versa. + items map[string]*heapItem + // queue implements a heap data structure and keeps the order of elements + // according to the heap invariant. The queue keeps the keys of objects stored + // in "items". + queue []string + + // keyFunc is used to make the key used for queued item insertion and retrieval, and + // should be deterministic. + keyFunc KeyFunc + // lessFunc is used to compare two objects in the heap. + lessFunc LessFunc +} + +var ( + _ = heap.Interface(&heapData{}) // heapData is a standard heap +) + +// Less compares two objects and returns true if the first one should go +// in front of the second one in the heap. +func (h *heapData) Less(i, j int) bool { + if i > len(h.queue) || j > len(h.queue) { + return false + } + itemi, ok := h.items[h.queue[i]] + if !ok { + return false + } + itemj, ok := h.items[h.queue[j]] + if !ok { + return false + } + return h.lessFunc(itemi.obj, itemj.obj) +} + +// Len returns the number of items in the Heap. +func (h *heapData) Len() int { return len(h.queue) } + +// Swap implements swapping of two elements in the heap. This is a part of standard +// heap interface and should never be called directly. +func (h *heapData) Swap(i, j int) { + h.queue[i], h.queue[j] = h.queue[j], h.queue[i] + item := h.items[h.queue[i]] + item.index = i + item = h.items[h.queue[j]] + item.index = j +} + +// Push is supposed to be called by heap.Push only. +func (h *heapData) Push(kv interface{}) { + keyValue := kv.(*itemKeyValue) + n := len(h.queue) + h.items[keyValue.key] = &heapItem{keyValue.obj, n} + h.queue = append(h.queue, keyValue.key) +} + +// Pop is supposed to be called by heap.Pop only. +func (h *heapData) Pop() interface{} { + key := h.queue[len(h.queue)-1] + h.queue = h.queue[0 : len(h.queue)-1] + item, ok := h.items[key] + if !ok { + // This is an error + return nil + } + delete(h.items, key) + return item.obj +} + +// Peek is supposed to be called by heap.Peek only. +func (h *heapData) Peek() interface{} { + if len(h.queue) > 0 { + return h.items[h.queue[0]].obj + } + return nil +} + +// Heap is a producer/consumer queue that implements a heap data structure. +// It can be used to implement priority queues and similar data structures. +type Heap struct { + // data stores objects and has a queue that keeps their ordering according + // to the heap invariant. + data *heapData +} + +// Add inserts an item, and puts it in the queue. The item is updated if it +// already exists. +func (h *Heap) Add(obj interface{}) error { + key, err := h.data.keyFunc(obj) + if err != nil { + return cache.KeyError{Obj: obj, Err: err} + } + if _, exists := h.data.items[key]; exists { + h.data.items[key].obj = obj + heap.Fix(h.data, h.data.items[key].index) + } else { + heap.Push(h.data, &itemKeyValue{key, obj}) + } + return nil +} + +// AddIfNotPresent inserts an item, and puts it in the queue. If an item with +// the key is present in the map, no changes is made to the item. +func (h *Heap) AddIfNotPresent(obj interface{}) error { + key, err := h.data.keyFunc(obj) + if err != nil { + return cache.KeyError{Obj: obj, Err: err} + } + if _, exists := h.data.items[key]; !exists { + heap.Push(h.data, &itemKeyValue{key, obj}) + } + return nil +} + +// Update is the same as Add in this implementation. When the item does not +// exist, it is added. +func (h *Heap) Update(obj interface{}) error { + return h.Add(obj) +} + +// Delete removes an item. +func (h *Heap) Delete(obj interface{}) error { + key, err := h.data.keyFunc(obj) + if err != nil { + return cache.KeyError{Obj: obj, Err: err} + } + if item, ok := h.data.items[key]; ok { + heap.Remove(h.data, item.index) + return nil + } + return fmt.Errorf("object not found") +} + +// Peek returns the head of the heap without removing it. +func (h *Heap) Peek() interface{} { + return h.data.Peek() +} + +// Pop returns the head of the heap and removes it. +func (h *Heap) Pop() (interface{}, error) { + obj := heap.Pop(h.data) + if obj != nil { + return obj, nil + } + return nil, fmt.Errorf("object was removed from heap data") +} + +// Get returns the requested item, or sets exists=false. +func (h *Heap) Get(obj interface{}) (interface{}, bool, error) { + key, err := h.data.keyFunc(obj) + if err != nil { + return nil, false, cache.KeyError{Obj: obj, Err: err} + } + return h.GetByKey(key) +} + +// GetByKey returns the requested item, or sets exists=false. +func (h *Heap) GetByKey(key string) (interface{}, bool, error) { + item, exists := h.data.items[key] + if !exists { + return nil, false, nil + } + return item.obj, true, nil +} + +// List returns a list of all the items. +func (h *Heap) List() []interface{} { + list := make([]interface{}, 0, len(h.data.items)) + for _, item := range h.data.items { + list = append(list, item.obj) + } + return list +} + +// Len returns the number of items in the heap. +func (h *Heap) Len() int { + return len(h.data.queue) +} + +// NewHeap returns a Heap which can be used to queue up items to process. +func NewHeap(keyFn KeyFunc, lessFn LessFunc) *Heap { + return &Heap{ + data: &heapData{ + items: map[string]*heapItem{}, + queue: []string{}, + keyFunc: keyFn, + lessFunc: lessFn, + }, + } +} diff --git a/pkg/scheduler/util/heap_test.go b/pkg/scheduler/util/heap_test.go new file mode 100644 index 00000000000..62812ec4c91 --- /dev/null +++ b/pkg/scheduler/util/heap_test.go @@ -0,0 +1,271 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// This file was copied from client-go/tools/cache/heap.go and modified +// for our non thread-safe heap + +package util + +import ( + "testing" +) + +func testHeapObjectKeyFunc(obj interface{}) (string, error) { + return obj.(testHeapObject).name, nil +} + +type testHeapObject struct { + name string + val interface{} +} + +func mkHeapObj(name string, val interface{}) testHeapObject { + return testHeapObject{name: name, val: val} +} + +func compareInts(val1 interface{}, val2 interface{}) bool { + first := val1.(testHeapObject).val.(int) + second := val2.(testHeapObject).val.(int) + return first < second +} + +// TestHeapBasic tests Heap invariant +func TestHeapBasic(t *testing.T) { + h := NewHeap(testHeapObjectKeyFunc, compareInts) + const amount = 500 + var i int + + for i = amount; i > 0; i-- { + h.Add(mkHeapObj(string([]rune{'a', rune(i)}), i)) + } + + // Make sure that the numbers are popped in ascending order. + prevNum := 0 + for i := 0; i < amount; i++ { + obj, err := h.Pop() + num := obj.(testHeapObject).val.(int) + // All the items must be sorted. + if err != nil || prevNum > num { + t.Errorf("got %v out of order, last was %v", obj, prevNum) + } + prevNum = num + } +} + +// Tests Heap.Add and ensures that heap invariant is preserved after adding items. +func TestHeap_Add(t *testing.T) { + h := NewHeap(testHeapObjectKeyFunc, compareInts) + h.Add(mkHeapObj("foo", 10)) + h.Add(mkHeapObj("bar", 1)) + h.Add(mkHeapObj("baz", 11)) + h.Add(mkHeapObj("zab", 30)) + h.Add(mkHeapObj("foo", 13)) // This updates "foo". + + item, err := h.Pop() + if e, a := 1, item.(testHeapObject).val; err != nil || a != e { + t.Fatalf("expected %d, got %d", e, a) + } + item, err = h.Pop() + if e, a := 11, item.(testHeapObject).val; err != nil || a != e { + t.Fatalf("expected %d, got %d", e, a) + } + h.Delete(mkHeapObj("baz", 11)) // Nothing is deleted. + h.Add(mkHeapObj("foo", 14)) // foo is updated. + item, err = h.Pop() + if e, a := 14, item.(testHeapObject).val; err != nil || a != e { + t.Fatalf("expected %d, got %d", e, a) + } + item, err = h.Pop() + if e, a := 30, item.(testHeapObject).val; err != nil || a != e { + t.Fatalf("expected %d, got %d", e, a) + } +} + +// TestHeap_AddIfNotPresent tests Heap.AddIfNotPresent and ensures that heap +// invariant is preserved after adding items. +func TestHeap_AddIfNotPresent(t *testing.T) { + h := NewHeap(testHeapObjectKeyFunc, compareInts) + h.AddIfNotPresent(mkHeapObj("foo", 10)) + h.AddIfNotPresent(mkHeapObj("bar", 1)) + h.AddIfNotPresent(mkHeapObj("baz", 11)) + h.AddIfNotPresent(mkHeapObj("zab", 30)) + h.AddIfNotPresent(mkHeapObj("foo", 13)) // This is not added. + + if len := len(h.data.items); len != 4 { + t.Errorf("unexpected number of items: %d", len) + } + if val := h.data.items["foo"].obj.(testHeapObject).val; val != 10 { + t.Errorf("unexpected value: %d", val) + } + item, err := h.Pop() + if e, a := 1, item.(testHeapObject).val; err != nil || a != e { + t.Fatalf("expected %d, got %d", e, a) + } + item, err = h.Pop() + if e, a := 10, item.(testHeapObject).val; err != nil || a != e { + t.Fatalf("expected %d, got %d", e, a) + } + // bar is already popped. Let's add another one. + h.AddIfNotPresent(mkHeapObj("bar", 14)) + item, err = h.Pop() + if e, a := 11, item.(testHeapObject).val; err != nil || a != e { + t.Fatalf("expected %d, got %d", e, a) + } + item, err = h.Pop() + if e, a := 14, item.(testHeapObject).val; err != nil || a != e { + t.Fatalf("expected %d, got %d", e, a) + } +} + +// TestHeap_Delete tests Heap.Delete and ensures that heap invariant is +// preserved after deleting items. +func TestHeap_Delete(t *testing.T) { + h := NewHeap(testHeapObjectKeyFunc, compareInts) + h.Add(mkHeapObj("foo", 10)) + h.Add(mkHeapObj("bar", 1)) + h.Add(mkHeapObj("bal", 31)) + h.Add(mkHeapObj("baz", 11)) + + // Delete head. Delete should work with "key" and doesn't care about the value. + if err := h.Delete(mkHeapObj("bar", 200)); err != nil { + t.Fatalf("Failed to delete head.") + } + item, err := h.Pop() + if e, a := 10, item.(testHeapObject).val; err != nil || a != e { + t.Fatalf("expected %d, got %d", e, a) + } + h.Add(mkHeapObj("zab", 30)) + h.Add(mkHeapObj("faz", 30)) + len := h.data.Len() + // Delete non-existing item. + if err = h.Delete(mkHeapObj("non-existent", 10)); err == nil || len != h.data.Len() { + t.Fatalf("Didn't expect any item removal") + } + // Delete tail. + if err = h.Delete(mkHeapObj("bal", 31)); err != nil { + t.Fatalf("Failed to delete tail.") + } + // Delete one of the items with value 30. + if err = h.Delete(mkHeapObj("zab", 30)); err != nil { + t.Fatalf("Failed to delete item.") + } + item, err = h.Pop() + if e, a := 11, item.(testHeapObject).val; err != nil || a != e { + t.Fatalf("expected %d, got %d", e, a) + } + item, err = h.Pop() + if e, a := 30, item.(testHeapObject).val; err != nil || a != e { + t.Fatalf("expected %d, got %d", e, a) + } + if h.data.Len() != 0 { + t.Fatalf("expected an empty heap.") + } +} + +// TestHeap_Update tests Heap.Update and ensures that heap invariant is +// preserved after adding items. +func TestHeap_Update(t *testing.T) { + h := NewHeap(testHeapObjectKeyFunc, compareInts) + h.Add(mkHeapObj("foo", 10)) + h.Add(mkHeapObj("bar", 1)) + h.Add(mkHeapObj("bal", 31)) + h.Add(mkHeapObj("baz", 11)) + + // Update an item to a value that should push it to the head. + h.Update(mkHeapObj("baz", 0)) + if h.data.queue[0] != "baz" || h.data.items["baz"].index != 0 { + t.Fatalf("expected baz to be at the head") + } + item, err := h.Pop() + if e, a := 0, item.(testHeapObject).val; err != nil || a != e { + t.Fatalf("expected %d, got %d", e, a) + } + // Update bar to push it farther back in the queue. + h.Update(mkHeapObj("bar", 100)) + if h.data.queue[0] != "foo" || h.data.items["foo"].index != 0 { + t.Fatalf("expected foo to be at the head") + } +} + +// TestHeap_Get tests Heap.Get. +func TestHeap_Get(t *testing.T) { + h := NewHeap(testHeapObjectKeyFunc, compareInts) + h.Add(mkHeapObj("foo", 10)) + h.Add(mkHeapObj("bar", 1)) + h.Add(mkHeapObj("bal", 31)) + h.Add(mkHeapObj("baz", 11)) + + // Get works with the key. + obj, exists, err := h.Get(mkHeapObj("baz", 0)) + if err != nil || exists == false || obj.(testHeapObject).val != 11 { + t.Fatalf("unexpected error in getting element") + } + // Get non-existing object. + _, exists, err = h.Get(mkHeapObj("non-existing", 0)) + if err != nil || exists == true { + t.Fatalf("didn't expect to get any object") + } +} + +// TestHeap_GetByKey tests Heap.GetByKey and is very similar to TestHeap_Get. +func TestHeap_GetByKey(t *testing.T) { + h := NewHeap(testHeapObjectKeyFunc, compareInts) + h.Add(mkHeapObj("foo", 10)) + h.Add(mkHeapObj("bar", 1)) + h.Add(mkHeapObj("bal", 31)) + h.Add(mkHeapObj("baz", 11)) + + obj, exists, err := h.GetByKey("baz") + if err != nil || exists == false || obj.(testHeapObject).val != 11 { + t.Fatalf("unexpected error in getting element") + } + // Get non-existing object. + _, exists, err = h.GetByKey("non-existing") + if err != nil || exists == true { + t.Fatalf("didn't expect to get any object") + } +} + +// TestHeap_List tests Heap.List function. +func TestHeap_List(t *testing.T) { + h := NewHeap(testHeapObjectKeyFunc, compareInts) + list := h.List() + if len(list) != 0 { + t.Errorf("expected an empty list") + } + + items := map[string]int{ + "foo": 10, + "bar": 1, + "bal": 30, + "baz": 11, + "faz": 30, + } + for k, v := range items { + h.Add(mkHeapObj(k, v)) + } + list = h.List() + if len(list) != len(items) { + t.Errorf("expected %d items, got %d", len(items), len(list)) + } + for _, obj := range list { + heapObj := obj.(testHeapObject) + v, ok := items[heapObj.name] + if !ok || v != heapObj.val { + t.Errorf("unexpected item in the list: %v", heapObj) + } + } +} diff --git a/pkg/scheduler/volumebinder/volume_binder.go b/pkg/scheduler/volumebinder/volume_binder.go index 4a0089a479d..53e3488a8c1 100644 --- a/pkg/scheduler/volumebinder/volume_binder.go +++ b/pkg/scheduler/volumebinder/volume_binder.go @@ -34,13 +34,14 @@ type VolumeBinder struct { // NewVolumeBinder sets up the volume binding library and binding queue func NewVolumeBinder( client clientset.Interface, + nodeInformer coreinformers.NodeInformer, pvcInformer coreinformers.PersistentVolumeClaimInformer, pvInformer coreinformers.PersistentVolumeInformer, storageClassInformer storageinformers.StorageClassInformer, bindTimeout time.Duration) *VolumeBinder { return &VolumeBinder{ - Binder: persistentvolume.NewVolumeBinder(client, pvcInformer, pvInformer, storageClassInformer, bindTimeout), + Binder: persistentvolume.NewVolumeBinder(client, nodeInformer, pvcInformer, pvInformer, storageClassInformer, bindTimeout), } } diff --git a/pkg/securitycontext/fake.go b/pkg/securitycontext/fake.go index 3303db2126c..a0a4ae193a5 100644 --- a/pkg/securitycontext/fake.go +++ b/pkg/securitycontext/fake.go @@ -25,9 +25,11 @@ import ( // empty container defaults. Used for testing. func ValidSecurityContextWithContainerDefaults() *v1.SecurityContext { priv := false + defProcMount := v1.DefaultProcMount return &v1.SecurityContext{ Capabilities: &v1.Capabilities{}, Privileged: &priv, + ProcMount: &defProcMount, } } diff --git a/pkg/serviceaccount/BUILD b/pkg/serviceaccount/BUILD index d0ad133b626..5639e80f197 100644 --- a/pkg/serviceaccount/BUILD +++ b/pkg/serviceaccount/BUILD @@ -57,6 +57,8 @@ go_test( "//staging/src/k8s.io/apiserver/pkg/authentication/authenticator:go_default_library", "//staging/src/k8s.io/client-go/kubernetes:go_default_library", "//staging/src/k8s.io/client-go/kubernetes/fake:go_default_library", + "//staging/src/k8s.io/client-go/listers/core/v1:go_default_library", + "//staging/src/k8s.io/client-go/tools/cache:go_default_library", "//staging/src/k8s.io/client-go/util/cert:go_default_library", "//vendor/gopkg.in/square/go-jose.v2/jwt:go_default_library", ], diff --git a/pkg/serviceaccount/jwt_test.go b/pkg/serviceaccount/jwt_test.go index 36be027c09d..6a74099ce2b 100644 --- a/pkg/serviceaccount/jwt_test.go +++ b/pkg/serviceaccount/jwt_test.go @@ -19,6 +19,7 @@ package serviceaccount_test import ( "context" "reflect" + "strings" "testing" "k8s.io/api/core/v1" @@ -26,6 +27,8 @@ import ( "k8s.io/apiserver/pkg/authentication/authenticator" clientset "k8s.io/client-go/kubernetes" "k8s.io/client-go/kubernetes/fake" + v1listers "k8s.io/client-go/listers/core/v1" + "k8s.io/client-go/tools/cache" certutil "k8s.io/client-go/util/cert" serviceaccountcontroller "k8s.io/kubernetes/pkg/controller/serviceaccount" "k8s.io/kubernetes/pkg/serviceaccount" @@ -277,7 +280,18 @@ func TestTokenGenerateAndValidate(t *testing.T) { for k, tc := range testCases { auds := authenticator.Audiences{"api"} - getter := serviceaccountcontroller.NewGetterFromClient(tc.Client) + getter := serviceaccountcontroller.NewGetterFromClient( + tc.Client, + v1listers.NewSecretLister(newIndexer(func(namespace, name string) (interface{}, error) { + return tc.Client.CoreV1().Secrets(namespace).Get(name, metav1.GetOptions{}) + })), + v1listers.NewServiceAccountLister(newIndexer(func(namespace, name string) (interface{}, error) { + return tc.Client.CoreV1().ServiceAccounts(namespace).Get(name, metav1.GetOptions{}) + })), + v1listers.NewPodLister(newIndexer(func(namespace, name string) (interface{}, error) { + return tc.Client.CoreV1().Pods(namespace).Get(name, metav1.GetOptions{}) + })), + ) authn := serviceaccount.JWTTokenAuthenticator(serviceaccount.LegacyIssuer, tc.Keys, auds, serviceaccount.NewLegacyValidator(tc.Client != nil, getter)) // An invalid, non-JWT token should always fail @@ -316,3 +330,23 @@ func TestTokenGenerateAndValidate(t *testing.T) { } } } + +func newIndexer(get func(namespace, name string) (interface{}, error)) cache.Indexer { + return &fakeIndexer{get: get} +} + +type fakeIndexer struct { + cache.Indexer + get func(namespace, name string) (interface{}, error) +} + +func (f *fakeIndexer) GetByKey(key string) (interface{}, bool, error) { + parts := strings.SplitN(key, "/", 2) + namespace := parts[0] + name := "" + if len(parts) == 2 { + name = parts[1] + } + obj, err := f.get(namespace, name) + return obj, err == nil, err +} diff --git a/pkg/ssh/ssh.go b/pkg/ssh/ssh.go index bee21f6ee5a..5b6cb4e1509 100644 --- a/pkg/ssh/ssh.go +++ b/pkg/ssh/ssh.go @@ -26,7 +26,6 @@ import ( "encoding/pem" "errors" "fmt" - "io" "io/ioutil" mathrand "math/rand" "net" @@ -39,11 +38,11 @@ import ( "github.com/prometheus/client_golang/prometheus" "golang.org/x/crypto/ssh" - "k8s.io/klog" utilnet "k8s.io/apimachinery/pkg/util/net" "k8s.io/apimachinery/pkg/util/runtime" "k8s.io/apimachinery/pkg/util/wait" + "k8s.io/klog" ) var ( @@ -68,51 +67,27 @@ func init() { // TODO: Unit tests for this code, we can spin up a test SSH server with instructions here: // https://godoc.org/golang.org/x/crypto/ssh#ServerConn -type SSHTunnel struct { +type sshTunnel struct { Config *ssh.ClientConfig Host string SSHPort string - running bool - sock net.Listener client *ssh.Client } -func (s *SSHTunnel) copyBytes(out io.Writer, in io.Reader) { - if _, err := io.Copy(out, in); err != nil { - klog.Errorf("Error in SSH tunnel: %v", err) - } -} - -func NewSSHTunnel(user, keyfile, host string) (*SSHTunnel, error) { - signer, err := MakePrivateKeySignerFromFile(keyfile) - if err != nil { - return nil, err - } - return makeSSHTunnel(user, signer, host) -} - -func NewSSHTunnelFromBytes(user string, privateKey []byte, host string) (*SSHTunnel, error) { - signer, err := MakePrivateKeySignerFromBytes(privateKey) - if err != nil { - return nil, err - } - return makeSSHTunnel(user, signer, host) -} - -func makeSSHTunnel(user string, signer ssh.Signer, host string) (*SSHTunnel, error) { +func makeSSHTunnel(user string, signer ssh.Signer, host string) (*sshTunnel, error) { config := ssh.ClientConfig{ User: user, Auth: []ssh.AuthMethod{ssh.PublicKeys(signer)}, HostKeyCallback: ssh.InsecureIgnoreHostKey(), } - return &SSHTunnel{ + return &sshTunnel{ Config: &config, Host: host, SSHPort: "22", }, nil } -func (s *SSHTunnel) Open() error { +func (s *sshTunnel) Open() error { var err error s.client, err = realTimeoutDialer.Dial("tcp", net.JoinHostPort(s.Host, s.SSHPort), s.Config) tunnelOpenCounter.Inc() @@ -122,7 +97,7 @@ func (s *SSHTunnel) Open() error { return err } -func (s *SSHTunnel) Dial(ctx context.Context, network, address string) (net.Conn, error) { +func (s *sshTunnel) Dial(ctx context.Context, network, address string) (net.Conn, error) { if s.client == nil { return nil, errors.New("tunnel is not opened.") } @@ -130,20 +105,7 @@ func (s *SSHTunnel) Dial(ctx context.Context, network, address string) (net.Conn return s.client.Dial(network, address) } -func (s *SSHTunnel) tunnel(conn net.Conn, remoteHost, remotePort string) error { - if s.client == nil { - return errors.New("tunnel is not opened.") - } - tunnel, err := s.client.Dial("tcp", net.JoinHostPort(remoteHost, remotePort)) - if err != nil { - return err - } - go s.copyBytes(tunnel, conn) - go s.copyBytes(conn, tunnel) - return nil -} - -func (s *SSHTunnel) Close() error { +func (s *sshTunnel) Close() error { if s.client == nil { return errors.New("Cannot close tunnel. Tunnel was not opened.") } @@ -305,13 +267,17 @@ type sshTunnelEntry struct { } type sshTunnelCreator interface { - NewSSHTunnel(user, keyFile, healthCheckURL string) (tunnel, error) + newSSHTunnel(user, keyFile, host string) (tunnel, error) } type realTunnelCreator struct{} -func (*realTunnelCreator) NewSSHTunnel(user, keyFile, healthCheckURL string) (tunnel, error) { - return NewSSHTunnel(user, keyFile, healthCheckURL) +func (*realTunnelCreator) newSSHTunnel(user, keyFile, host string) (tunnel, error) { + signer, err := MakePrivateKeySignerFromFile(keyFile) + if err != nil { + return nil, err + } + return makeSSHTunnel(user, signer, host) } type SSHTunnelList struct { @@ -481,7 +447,7 @@ func (l *SSHTunnelList) Update(addrs []string) { func (l *SSHTunnelList) createAndAddTunnel(addr string) { klog.Infof("Trying to add tunnel to %q", addr) - tunnel, err := l.tunnelCreator.NewSSHTunnel(l.user, l.keyfile, addr) + tunnel, err := l.tunnelCreator.newSSHTunnel(l.user, l.keyfile, addr) if err != nil { klog.Errorf("Failed to create tunnel for %q: %v", addr, err) return diff --git a/pkg/ssh/ssh_test.go b/pkg/ssh/ssh_test.go index 6148233f7ec..d0278016f45 100644 --- a/pkg/ssh/ssh_test.go +++ b/pkg/ssh/ssh_test.go @@ -27,9 +27,9 @@ import ( "testing" "time" - "k8s.io/apimachinery/pkg/util/wait" - "golang.org/x/crypto/ssh" + + "k8s.io/apimachinery/pkg/util/wait" "k8s.io/klog" ) @@ -134,7 +134,7 @@ func TestSSHTunnel(t *testing.T) { } privateData := EncodePrivateKey(private) - tunnel, err := NewSSHTunnelFromBytes("foo", privateData, server.Host) + tunnel, err := newSSHTunnelFromBytes("foo", privateData, server.Host) if err != nil { t.Errorf("unexpected error: %v", err) t.FailNow() @@ -183,7 +183,7 @@ func (*fakeTunnel) Dial(ctx context.Context, network, address string) (net.Conn, type fakeTunnelCreator struct{} -func (*fakeTunnelCreator) NewSSHTunnel(string, string, string) (tunnel, error) { +func (*fakeTunnelCreator) newSSHTunnel(string, string, string) (tunnel, error) { return &fakeTunnel{}, nil } @@ -355,3 +355,11 @@ func TestTimeoutDialer(t *testing.T) { listener.Close() } + +func newSSHTunnelFromBytes(user string, privateKey []byte, host string) (*sshTunnel, error) { + signer, err := MakePrivateKeySignerFromBytes(privateKey) + if err != nil { + return nil, err + } + return makeSSHTunnel(user, signer, host) +} diff --git a/pkg/util/configz/configz.go b/pkg/util/configz/configz.go index 99413d5e7fd..5bb192637e3 100644 --- a/pkg/util/configz/configz.go +++ b/pkg/util/configz/configz.go @@ -14,6 +14,29 @@ See the License for the specific language governing permissions and limitations under the License. */ +// Package configz serves ComponentConfig objects from running components. +// +// Each component that wants to serve its ComponentConfig creates a Config +// object, and the program should call InstallHandler once. e.g., +// func main() { +// boatConfig := getBoatConfig() +// planeConfig := getPlaneConfig() +// +// bcz, err := configz.New("boat") +// if err != nil { +// panic(err) +// } +// bcz.Set(boatConfig) +// +// pcz, err := configz.New("plane") +// if err != nil { +// panic(err) +// } +// pcz.Set(planeConfig) +// +// configz.InstallHandler(http.DefaultServeMux) +// http.ListenAndServe(":8080", http.DefaultServeMux) +// } package configz import ( @@ -28,10 +51,14 @@ var ( configs = map[string]*Config{} ) +// Config is a handle to a ComponentConfig object. Don't create these directly; +// use New() instead. type Config struct { val interface{} } +// InstallHandler adds an HTTP handler on the given mux for the "/configz" +// endpoint which serves all registered ComponentConfigs in JSON format. func InstallHandler(m mux) { m.Handle("/configz", http.HandlerFunc(handle)) } @@ -40,6 +67,8 @@ type mux interface { Handle(string, http.Handler) } +// New creates a Config object with the given name. Each Config is registered +// with this package's "/configz" handler. func New(name string) (*Config, error) { configsGuard.Lock() defer configsGuard.Unlock() @@ -51,18 +80,22 @@ func New(name string) (*Config, error) { return &newConfig, nil } +// Delete removes the named ComponentConfig from this package's "/configz" +// handler. func Delete(name string) { configsGuard.Lock() defer configsGuard.Unlock() delete(configs, name) } +// Set sets the ComponentConfig for this Config. func (v *Config) Set(val interface{}) { configsGuard.Lock() defer configsGuard.Unlock() v.val = val } +// MarshalJSON marshals the ComponentConfig as JSON data. func (v *Config) MarshalJSON() ([]byte, error) { return json.Marshal(v.val) } diff --git a/pkg/util/conntrack/conntrack.go b/pkg/util/conntrack/conntrack.go index 353bc0d0c25..5569b411dc1 100644 --- a/pkg/util/conntrack/conntrack.go +++ b/pkg/util/conntrack/conntrack.go @@ -107,3 +107,19 @@ func ClearEntriesForNAT(execer exec.Interface, origin, dest string, protocol v1. } return nil } + +// ClearEntriesForPortNAT uses the conntrack tool to delete the contrack entries +// for connections specified by the {dest IP, port} pair. +// Known issue: +// https://github.com/kubernetes/kubernetes/issues/59368 +func ClearEntriesForPortNAT(execer exec.Interface, dest string, port int, protocol v1.Protocol) error { + if port <= 0 { + return fmt.Errorf("Wrong port number. The port number must be greater then zero") + } + parameters := parametersWithFamily(utilnet.IsIPv6String(dest), "-D", "-p", protoStr(protocol), "--dport", strconv.Itoa(port), "--dst-nat", dest) + err := Exec(execer, parameters...) + if err != nil && !strings.Contains(err.Error(), NoConnectionToDelete) { + return fmt.Errorf("error deleting conntrack entries for UDP port: %d, error: %v", port, err) + } + return nil +} diff --git a/pkg/util/conntrack/conntrack_test.go b/pkg/util/conntrack/conntrack_test.go index 6e1c18735fb..af05a65e12a 100644 --- a/pkg/util/conntrack/conntrack_test.go +++ b/pkg/util/conntrack/conntrack_test.go @@ -234,3 +234,50 @@ func TestDeleteUDPConnections(t *testing.T) { t.Errorf("Expect command executed %d times, but got %d", svcCount, fexec.CommandCalls) } } + +func TestClearUDPConntrackForPortNAT(t *testing.T) { + fcmd := fakeexec.FakeCmd{ + CombinedOutputScript: []fakeexec.FakeCombinedOutputAction{ + func() ([]byte, error) { return []byte("1 flow entries have been deleted"), nil }, + func() ([]byte, error) { + return []byte(""), fmt.Errorf("conntrack v1.4.2 (conntrack-tools): 0 flow entries have been deleted") + }, + func() ([]byte, error) { return []byte("1 flow entries have been deleted"), nil }, + }, + } + fexec := fakeexec.FakeExec{ + CommandScript: []fakeexec.FakeCommandAction{ + func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) }, + func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) }, + func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) }, + }, + LookPathFunc: func(cmd string) (string, error) { return cmd, nil }, + } + testCases := []struct { + name string + port int + dest string + }{ + { + name: "IPv4 success", + port: 30211, + dest: "1.2.3.4", + }, + } + svcCount := 0 + for i, tc := range testCases { + err := ClearEntriesForPortNAT(&fexec, tc.dest, tc.port, v1.ProtocolUDP) + if err != nil { + t.Errorf("%s test case: unexpected error: %v", tc.name, err) + } + expectCommand := fmt.Sprintf("conntrack -D -p udp --dport %d --dst-nat %s", tc.port, tc.dest) + familyParamStr(utilnet.IsIPv6String(tc.dest)) + execCommand := strings.Join(fcmd.CombinedOutputLog[i], " ") + if expectCommand != execCommand { + t.Errorf("%s test case: Expect command: %s, but executed %s", tc.name, expectCommand, execCommand) + } + svcCount++ + } + if svcCount != fexec.CommandCalls { + t.Errorf("Expect command executed %d times, but got %d", svcCount, fexec.CommandCalls) + } +} diff --git a/pkg/util/ipvs/ipvs_linux.go b/pkg/util/ipvs/ipvs_linux.go index b4f53be6fdb..54dac294262 100644 --- a/pkg/util/ipvs/ipvs_linux.go +++ b/pkg/util/ipvs/ipvs_linux.go @@ -23,6 +23,7 @@ import ( "fmt" "net" "strings" + "sync" "syscall" libipvs "github.com/docker/libnetwork/ipvs" @@ -34,6 +35,7 @@ import ( type runner struct { exec utilexec.Interface ipvsHandle *libipvs.Handle + mu sync.Mutex // Protect Netlink calls } // Protocol is the IPVS service protocol type @@ -58,6 +60,8 @@ func (runner *runner) AddVirtualServer(vs *VirtualServer) error { if err != nil { return err } + runner.mu.Lock() + defer runner.mu.Unlock() return runner.ipvsHandle.NewService(svc) } @@ -67,6 +71,8 @@ func (runner *runner) UpdateVirtualServer(vs *VirtualServer) error { if err != nil { return err } + runner.mu.Lock() + defer runner.mu.Unlock() return runner.ipvsHandle.UpdateService(svc) } @@ -76,6 +82,8 @@ func (runner *runner) DeleteVirtualServer(vs *VirtualServer) error { if err != nil { return err } + runner.mu.Lock() + defer runner.mu.Unlock() return runner.ipvsHandle.DelService(svc) } @@ -85,7 +93,10 @@ func (runner *runner) GetVirtualServer(vs *VirtualServer) (*VirtualServer, error if err != nil { return nil, err } + runner.mu.Lock() ipvsSvc, err := runner.ipvsHandle.GetService(svc) + runner.mu.Unlock() + if err != nil { return nil, err } @@ -98,7 +109,9 @@ func (runner *runner) GetVirtualServer(vs *VirtualServer) (*VirtualServer, error // GetVirtualServers is part of ipvs.Interface. func (runner *runner) GetVirtualServers() ([]*VirtualServer, error) { + runner.mu.Lock() ipvsSvcs, err := runner.ipvsHandle.GetServices() + runner.mu.Unlock() if err != nil { return nil, err } @@ -115,6 +128,8 @@ func (runner *runner) GetVirtualServers() ([]*VirtualServer, error) { // Flush is part of ipvs.Interface. Currently we delete IPVS services one by one func (runner *runner) Flush() error { + runner.mu.Lock() + defer runner.mu.Unlock() return runner.ipvsHandle.Flush() } @@ -128,6 +143,8 @@ func (runner *runner) AddRealServer(vs *VirtualServer, rs *RealServer) error { if err != nil { return err } + runner.mu.Lock() + defer runner.mu.Unlock() return runner.ipvsHandle.NewDestination(svc, dst) } @@ -141,6 +158,8 @@ func (runner *runner) DeleteRealServer(vs *VirtualServer, rs *RealServer) error if err != nil { return err } + runner.mu.Lock() + defer runner.mu.Unlock() return runner.ipvsHandle.DelDestination(svc, dst) } @@ -153,6 +172,8 @@ func (runner *runner) UpdateRealServer(vs *VirtualServer, rs *RealServer) error if err != nil { return err } + runner.mu.Lock() + defer runner.mu.Unlock() return runner.ipvsHandle.UpdateDestination(svc, dst) } @@ -162,7 +183,9 @@ func (runner *runner) GetRealServers(vs *VirtualServer) ([]*RealServer, error) { if err != nil { return nil, err } + runner.mu.Lock() dsts, err := runner.ipvsHandle.GetDestinations(svc) + runner.mu.Unlock() if err != nil { return nil, err } diff --git a/pkg/util/mount/BUILD b/pkg/util/mount/BUILD index 221afb7a9c6..c9b9ce8a47e 100644 --- a/pkg/util/mount/BUILD +++ b/pkg/util/mount/BUILD @@ -9,6 +9,7 @@ go_library( "exec_mount_unsupported.go", "fake.go", "mount.go", + "mount_helper.go", "mount_linux.go", "mount_unsupported.go", "mount_windows.go", @@ -67,6 +68,7 @@ go_test( name = "go_default_test", srcs = [ "exec_mount_test.go", + "mount_helper_test.go", "mount_linux_test.go", "mount_test.go", "mount_windows_test.go", diff --git a/pkg/util/mount/fake.go b/pkg/util/mount/fake.go index 06e0fcccdc1..0e2952f3e02 100644 --- a/pkg/util/mount/fake.go +++ b/pkg/util/mount/fake.go @@ -30,6 +30,8 @@ type FakeMounter struct { MountPoints []MountPoint Log []FakeAction Filesystem map[string]FileType + // Error to return for a path when calling IsLikelyNotMountPoint + MountCheckErrors map[string]error // Some tests run things in parallel, make sure the mounter does not produce // any golang's DATA RACE warnings. mutex sync.Mutex @@ -119,6 +121,7 @@ func (f *FakeMounter) Unmount(target string) error { } f.MountPoints = newMountpoints f.Log = append(f.Log, FakeAction{Action: FakeActionUnmount, Target: absTarget}) + delete(f.MountCheckErrors, target) return nil } @@ -141,7 +144,12 @@ func (f *FakeMounter) IsLikelyNotMountPoint(file string) (bool, error) { f.mutex.Lock() defer f.mutex.Unlock() - _, err := os.Stat(file) + err := f.MountCheckErrors[file] + if err != nil { + return false, err + } + + _, err = os.Stat(file) if err != nil { return true, err } diff --git a/pkg/util/mount/mount_helper.go b/pkg/util/mount/mount_helper.go new file mode 100644 index 00000000000..a06871e4789 --- /dev/null +++ b/pkg/util/mount/mount_helper.go @@ -0,0 +1,124 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package mount + +import ( + "fmt" + "os" + "syscall" + + "k8s.io/klog" +) + +// CleanupMountPoint unmounts the given path and +// deletes the remaining directory if successful. +// if extensiveMountPointCheck is true +// IsNotMountPoint will be called instead of IsLikelyNotMountPoint. +// IsNotMountPoint is more expensive but properly handles bind mounts within the same fs. +func CleanupMountPoint(mountPath string, mounter Interface, extensiveMountPointCheck bool) error { + // mounter.ExistsPath cannot be used because for containerized kubelet, we need to check + // the path in the kubelet container, not on the host. + pathExists, pathErr := PathExists(mountPath) + if !pathExists { + klog.Warningf("Warning: Unmount skipped because path does not exist: %v", mountPath) + return nil + } + corruptedMnt := IsCorruptedMnt(pathErr) + if pathErr != nil && !corruptedMnt { + return fmt.Errorf("Error checking path: %v", pathErr) + } + return doCleanupMountPoint(mountPath, mounter, extensiveMountPointCheck, corruptedMnt) +} + +// doCleanupMountPoint unmounts the given path and +// deletes the remaining directory if successful. +// if extensiveMountPointCheck is true +// IsNotMountPoint will be called instead of IsLikelyNotMountPoint. +// IsNotMountPoint is more expensive but properly handles bind mounts within the same fs. +// if corruptedMnt is true, it means that the mountPath is a corrupted mountpoint, and the mount point check +// will be skipped +func doCleanupMountPoint(mountPath string, mounter Interface, extensiveMountPointCheck bool, corruptedMnt bool) error { + if !corruptedMnt { + var notMnt bool + var err error + if extensiveMountPointCheck { + notMnt, err = IsNotMountPoint(mounter, mountPath) + } else { + notMnt, err = mounter.IsLikelyNotMountPoint(mountPath) + } + + if err != nil { + return err + } + + if notMnt { + klog.Warningf("Warning: %q is not a mountpoint, deleting", mountPath) + return os.Remove(mountPath) + } + } + + // Unmount the mount path + klog.V(4).Infof("%q is a mountpoint, unmounting", mountPath) + if err := mounter.Unmount(mountPath); err != nil { + return err + } + + notMnt, mntErr := mounter.IsLikelyNotMountPoint(mountPath) + if mntErr != nil { + return mntErr + } + if notMnt { + klog.V(4).Infof("%q is unmounted, deleting the directory", mountPath) + return os.Remove(mountPath) + } + return fmt.Errorf("Failed to unmount path %v", mountPath) +} + +// TODO: clean this up to use pkg/util/file/FileExists +// PathExists returns true if the specified path exists. +func PathExists(path string) (bool, error) { + _, err := os.Stat(path) + if err == nil { + return true, nil + } else if os.IsNotExist(err) { + return false, nil + } else if IsCorruptedMnt(err) { + return true, err + } else { + return false, err + } +} + +// IsCorruptedMnt return true if err is about corrupted mount point +func IsCorruptedMnt(err error) bool { + if err == nil { + return false + } + var underlyingError error + switch pe := err.(type) { + case nil: + return false + case *os.PathError: + underlyingError = pe.Err + case *os.LinkError: + underlyingError = pe.Err + case *os.SyscallError: + underlyingError = pe.Err + } + + return underlyingError == syscall.ENOTCONN || underlyingError == syscall.ESTALE || underlyingError == syscall.EIO +} diff --git a/pkg/util/mount/mount_helper_test.go b/pkg/util/mount/mount_helper_test.go new file mode 100644 index 00000000000..3afcca37986 --- /dev/null +++ b/pkg/util/mount/mount_helper_test.go @@ -0,0 +1,152 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package mount + +import ( + "fmt" + "io/ioutil" + "os" + "path/filepath" + "syscall" + "testing" +) + +func TestDoCleanupMountPoint(t *testing.T) { + const testMount = "test-mount" + const defaultPerm = 0750 + + tests := map[string]struct { + corruptedMnt bool + // Function that prepares the directory structure for the test under + // the given base directory. + // Returns a fake MountPoint, a fake error for the mount point, + // and error if the prepare function encountered a fatal error. + prepare func(base string) (MountPoint, error, error) + expectErr bool + }{ + "mount-ok": { + prepare: func(base string) (MountPoint, error, error) { + path := filepath.Join(base, testMount) + if err := os.MkdirAll(path, defaultPerm); err != nil { + return MountPoint{}, nil, err + } + return MountPoint{Device: "/dev/sdb", Path: path}, nil, nil + }, + }, + "mount-corrupted": { + prepare: func(base string) (MountPoint, error, error) { + path := filepath.Join(base, testMount) + if err := os.MkdirAll(path, defaultPerm); err != nil { + return MountPoint{}, nil, err + } + return MountPoint{Device: "/dev/sdb", Path: path}, os.NewSyscallError("fake", syscall.ESTALE), nil + }, + corruptedMnt: true, + }, + "mount-err-not-corrupted": { + prepare: func(base string) (MountPoint, error, error) { + path := filepath.Join(base, testMount) + if err := os.MkdirAll(path, defaultPerm); err != nil { + return MountPoint{}, nil, err + } + return MountPoint{Device: "/dev/sdb", Path: path}, os.NewSyscallError("fake", syscall.ETIMEDOUT), nil + }, + expectErr: true, + }, + } + + for name, tt := range tests { + t.Run(name, func(t *testing.T) { + + tmpDir, err := ioutil.TempDir("", "unmount-mount-point-test") + if err != nil { + t.Fatalf("failed to create tmpdir: %v", err) + } + defer os.RemoveAll(tmpDir) + + if tt.prepare == nil { + t.Fatalf("prepare function required") + } + + mountPoint, mountError, err := tt.prepare(tmpDir) + if err != nil { + t.Fatalf("failed to prepare test: %v", err) + } + + fake := &FakeMounter{ + MountPoints: []MountPoint{mountPoint}, + MountCheckErrors: map[string]error{mountPoint.Path: mountError}, + } + + err = doCleanupMountPoint(mountPoint.Path, fake, true, tt.corruptedMnt) + if tt.expectErr { + if err == nil { + t.Errorf("test %s failed, expected error, got none", name) + } + if err := validateDirExists(mountPoint.Path); err != nil { + t.Errorf("test %s failed, mount path doesn't exist: %v", name, err) + } + } + if !tt.expectErr { + if err != nil { + t.Errorf("test %s failed: %v", name, err) + } + if err := validateDirNotExists(mountPoint.Path); err != nil { + t.Errorf("test %s failed, mount path still exists: %v", name, err) + } + } + }) + } +} + +func validateDirEmpty(dir string) error { + files, err := ioutil.ReadDir(dir) + if err != nil { + return err + } + + if len(files) != 0 { + return fmt.Errorf("Directory %q is not empty", dir) + } + return nil +} + +func validateDirExists(dir string) error { + _, err := ioutil.ReadDir(dir) + if err != nil { + return err + } + return nil +} + +func validateDirNotExists(dir string) error { + _, err := ioutil.ReadDir(dir) + if os.IsNotExist(err) { + return nil + } + if err != nil { + return err + } + return fmt.Errorf("dir %q still exists", dir) +} + +func validateFileExists(file string) error { + if _, err := os.Stat(file); err != nil { + return err + } + return nil +} diff --git a/pkg/util/mount/mount_linux.go b/pkg/util/mount/mount_linux.go index 6ebeff053b5..85a90169687 100644 --- a/pkg/util/mount/mount_linux.go +++ b/pkg/util/mount/mount_linux.go @@ -55,6 +55,7 @@ const ( fsckErrorsUncorrected = 4 // place for subpath mounts + // TODO: pass in directory using kubelet_getters instead containerSubPathDirectoryName = "volume-subpaths" // syscall.Openat flags used to traverse directories not following symlinks nofollowFlags = unix.O_RDONLY | unix.O_NOFOLLOW @@ -890,15 +891,22 @@ func doCleanSubPaths(mounter Interface, podDir string, volumeName string) error // scan /var/lib/kubelet/pods//volume-subpaths///* fullContainerDirPath := filepath.Join(subPathDir, containerDir.Name()) - subPaths, err := ioutil.ReadDir(fullContainerDirPath) - if err != nil { - return fmt.Errorf("error reading %s: %s", fullContainerDirPath, err) - } - for _, subPath := range subPaths { - if err = doCleanSubPath(mounter, fullContainerDirPath, subPath.Name()); err != nil { + err = filepath.Walk(fullContainerDirPath, func(path string, info os.FileInfo, err error) error { + if path == fullContainerDirPath { + // Skip top level directory + return nil + } + + // pass through errors and let doCleanSubPath handle them + if err = doCleanSubPath(mounter, fullContainerDirPath, filepath.Base(path)); err != nil { return err } + return nil + }) + if err != nil { + return fmt.Errorf("error processing %s: %s", fullContainerDirPath, err) } + // Whole container has been processed, remove its directory. if err := os.Remove(fullContainerDirPath); err != nil { return fmt.Errorf("error deleting %s: %s", fullContainerDirPath, err) @@ -925,22 +933,12 @@ func doCleanSubPath(mounter Interface, fullContainerDirPath, subPathIndex string // process /var/lib/kubelet/pods//volume-subpaths/// klog.V(4).Infof("Cleaning up subpath mounts for subpath %v", subPathIndex) fullSubPath := filepath.Join(fullContainerDirPath, subPathIndex) - notMnt, err := IsNotMountPoint(mounter, fullSubPath) - if err != nil { - return fmt.Errorf("error checking %s for mount: %s", fullSubPath, err) + + if err := CleanupMountPoint(fullSubPath, mounter, true); err != nil { + return fmt.Errorf("error cleaning subpath mount %s: %s", fullSubPath, err) } - // Unmount it - if !notMnt { - if err = mounter.Unmount(fullSubPath); err != nil { - return fmt.Errorf("error unmounting %s: %s", fullSubPath, err) - } - klog.V(5).Infof("Unmounted %s", fullSubPath) - } - // Remove it *non*-recursively, just in case there were some hiccups. - if err = os.Remove(fullSubPath); err != nil { - return fmt.Errorf("error deleting %s: %s", fullSubPath, err) - } - klog.V(5).Infof("Removed %s", fullSubPath) + + klog.V(4).Infof("Successfully cleaned subpath directory %s", fullSubPath) return nil } diff --git a/pkg/util/mount/mount_linux_test.go b/pkg/util/mount/mount_linux_test.go index 89dbfdf041c..cbd0276322a 100644 --- a/pkg/util/mount/mount_linux_test.go +++ b/pkg/util/mount/mount_linux_test.go @@ -666,44 +666,6 @@ func TestSafeMakeDir(t *testing.T) { } } -func validateDirEmpty(dir string) error { - files, err := ioutil.ReadDir(dir) - if err != nil { - return err - } - - if len(files) != 0 { - return fmt.Errorf("Directory %q is not empty", dir) - } - return nil -} - -func validateDirExists(dir string) error { - _, err := ioutil.ReadDir(dir) - if err != nil { - return err - } - return nil -} - -func validateDirNotExists(dir string) error { - _, err := ioutil.ReadDir(dir) - if os.IsNotExist(err) { - return nil - } - if err != nil { - return err - } - return fmt.Errorf("dir %q still exists", dir) -} - -func validateFileExists(file string) error { - if _, err := os.Stat(file); err != nil { - return err - } - return nil -} - func TestRemoveEmptyDirs(t *testing.T) { defaultPerm := os.FileMode(0750) tests := []struct { diff --git a/pkg/util/node/node.go b/pkg/util/node/node.go index ff503855150..ce9ce636a9d 100644 --- a/pkg/util/node/node.go +++ b/pkg/util/node/node.go @@ -64,6 +64,17 @@ func GetHostname(hostnameOverride string) (string, error) { return strings.ToLower(hostName), nil } +// NoMatchError is a typed implementation of the error interface. It indicates a failure to get a matching Node. +type NoMatchError struct { + addresses []v1.NodeAddress +} + +// Error is the implementation of the conventional interface for +// representing an error condition, with the nil value representing no error. +func (e *NoMatchError) Error() string { + return fmt.Sprintf("no preferred addresses found; known addresses: %v", e.addresses) +} + // GetPreferredNodeAddress returns the address of the provided node, using the provided preference order. // If none of the preferred address types are found, an error is returned. func GetPreferredNodeAddress(node *v1.Node, preferredAddressTypes []v1.NodeAddressType) (string, error) { @@ -74,7 +85,7 @@ func GetPreferredNodeAddress(node *v1.Node, preferredAddressTypes []v1.NodeAddre } } } - return "", fmt.Errorf("no preferred addresses found; known addresses: %v", node.Status.Addresses) + return "", &NoMatchError{addresses: node.Status.Addresses} } // GetNodeHostIP returns the provided node's IP, based on the priority: diff --git a/pkg/util/nsenter/OWNERS b/pkg/util/nsenter/OWNERS index c4f27cb4381..273520d2c73 100644 --- a/pkg/util/nsenter/OWNERS +++ b/pkg/util/nsenter/OWNERS @@ -2,7 +2,9 @@ reviewers: - jsafrane - msau42 - cofyc + - dixudx approvers: - jsafrane - msau42 - cofyc + - dixudx diff --git a/pkg/util/workqueue/prometheus/prometheus.go b/pkg/util/workqueue/prometheus/prometheus.go index 6f5cf38f09d..c0abca6b18f 100644 --- a/pkg/util/workqueue/prometheus/prometheus.go +++ b/pkg/util/workqueue/prometheus/prometheus.go @@ -25,6 +25,18 @@ import ( // Package prometheus sets the workqueue DefaultMetricsFactory to produce // prometheus metrics. To use this package, you just have to import it. +// Metrics subsystem and keys used by the workqueue. +const ( + WorkQueueSubsystem = "workqueue" + DepthKey = "depth" + AddsKey = "adds_total" + QueueLatencyKey = "queue_latency_seconds" + WorkDurationKey = "work_duration_seconds" + UnfinishedWorkKey = "unfinished_work_seconds" + LongestRunningProcessorKey = "longest_running_processor_seconds" + RetriesKey = "retries_total" +) + func init() { workqueue.SetProvider(prometheusMetricsProvider{}) } @@ -32,6 +44,90 @@ func init() { type prometheusMetricsProvider struct{} func (prometheusMetricsProvider) NewDepthMetric(name string) workqueue.GaugeMetric { + depth := prometheus.NewGauge(prometheus.GaugeOpts{ + Subsystem: WorkQueueSubsystem, + Name: DepthKey, + Help: "Current depth of workqueue", + ConstLabels: prometheus.Labels{"name": name}, + }) + prometheus.Register(depth) + return depth +} + +func (prometheusMetricsProvider) NewAddsMetric(name string) workqueue.CounterMetric { + adds := prometheus.NewCounter(prometheus.CounterOpts{ + Subsystem: WorkQueueSubsystem, + Name: AddsKey, + Help: "Total number of adds handled by workqueue", + ConstLabels: prometheus.Labels{"name": name}, + }) + prometheus.Register(adds) + return adds +} + +func (prometheusMetricsProvider) NewLatencyMetric(name string) workqueue.HistogramMetric { + latency := prometheus.NewHistogram(prometheus.HistogramOpts{ + Subsystem: WorkQueueSubsystem, + Name: QueueLatencyKey, + Help: "How long in seconds an item stays in workqueue before being requested.", + ConstLabels: prometheus.Labels{"name": name}, + Buckets: prometheus.ExponentialBuckets(10e-9, 10, 10), + }) + prometheus.Register(latency) + return latency +} + +func (prometheusMetricsProvider) NewWorkDurationMetric(name string) workqueue.HistogramMetric { + workDuration := prometheus.NewHistogram(prometheus.HistogramOpts{ + Subsystem: WorkQueueSubsystem, + Name: WorkDurationKey, + Help: "How long in seconds processing an item from workqueue takes.", + ConstLabels: prometheus.Labels{"name": name}, + Buckets: prometheus.ExponentialBuckets(10e-9, 10, 10), + }) + prometheus.Register(workDuration) + return workDuration +} + +func (prometheusMetricsProvider) NewUnfinishedWorkSecondsMetric(name string) workqueue.SettableGaugeMetric { + unfinished := prometheus.NewGauge(prometheus.GaugeOpts{ + Subsystem: WorkQueueSubsystem, + Name: UnfinishedWorkKey, + Help: "How many seconds of work has done that " + + "is in progress and hasn't been observed by work_duration. Large " + + "values indicate stuck threads. One can deduce the number of stuck " + + "threads by observing the rate at which this increases.", + ConstLabels: prometheus.Labels{"name": name}, + }) + prometheus.Register(unfinished) + return unfinished +} + +func (prometheusMetricsProvider) NewLongestRunningProcessorSecondsMetric(name string) workqueue.SettableGaugeMetric { + unfinished := prometheus.NewGauge(prometheus.GaugeOpts{ + Subsystem: WorkQueueSubsystem, + Name: LongestRunningProcessorKey, + Help: "How many seconds has the longest running " + + "processor for workqueue been running.", + ConstLabels: prometheus.Labels{"name": name}, + }) + prometheus.Register(unfinished) + return unfinished +} + +func (prometheusMetricsProvider) NewRetriesMetric(name string) workqueue.CounterMetric { + retries := prometheus.NewCounter(prometheus.CounterOpts{ + Subsystem: WorkQueueSubsystem, + Name: RetriesKey, + Help: "Total number of retries handled by workqueue", + ConstLabels: prometheus.Labels{"name": name}, + }) + prometheus.Register(retries) + return retries +} + +// TODO(danielqsj): Remove the following metrics, they are deprecated +func (prometheusMetricsProvider) NewDeprecatedDepthMetric(name string) workqueue.GaugeMetric { depth := prometheus.NewGauge(prometheus.GaugeOpts{ Subsystem: name, Name: "depth", @@ -41,7 +137,7 @@ func (prometheusMetricsProvider) NewDepthMetric(name string) workqueue.GaugeMetr return depth } -func (prometheusMetricsProvider) NewAddsMetric(name string) workqueue.CounterMetric { +func (prometheusMetricsProvider) NewDeprecatedAddsMetric(name string) workqueue.CounterMetric { adds := prometheus.NewCounter(prometheus.CounterOpts{ Subsystem: name, Name: "adds", @@ -51,7 +147,7 @@ func (prometheusMetricsProvider) NewAddsMetric(name string) workqueue.CounterMet return adds } -func (prometheusMetricsProvider) NewLatencyMetric(name string) workqueue.SummaryMetric { +func (prometheusMetricsProvider) NewDeprecatedLatencyMetric(name string) workqueue.SummaryMetric { latency := prometheus.NewSummary(prometheus.SummaryOpts{ Subsystem: name, Name: "queue_latency", @@ -61,7 +157,7 @@ func (prometheusMetricsProvider) NewLatencyMetric(name string) workqueue.Summary return latency } -func (prometheusMetricsProvider) NewWorkDurationMetric(name string) workqueue.SummaryMetric { +func (prometheusMetricsProvider) NewDeprecatedWorkDurationMetric(name string) workqueue.SummaryMetric { workDuration := prometheus.NewSummary(prometheus.SummaryOpts{ Subsystem: name, Name: "work_duration", @@ -71,7 +167,7 @@ func (prometheusMetricsProvider) NewWorkDurationMetric(name string) workqueue.Su return workDuration } -func (prometheusMetricsProvider) NewUnfinishedWorkSecondsMetric(name string) workqueue.SettableGaugeMetric { +func (prometheusMetricsProvider) NewDeprecatedUnfinishedWorkSecondsMetric(name string) workqueue.SettableGaugeMetric { unfinished := prometheus.NewGauge(prometheus.GaugeOpts{ Subsystem: name, Name: "unfinished_work_seconds", @@ -84,7 +180,7 @@ func (prometheusMetricsProvider) NewUnfinishedWorkSecondsMetric(name string) wor return unfinished } -func (prometheusMetricsProvider) NewLongestRunningProcessorMicrosecondsMetric(name string) workqueue.SettableGaugeMetric { +func (prometheusMetricsProvider) NewDeprecatedLongestRunningProcessorMicrosecondsMetric(name string) workqueue.SettableGaugeMetric { unfinished := prometheus.NewGauge(prometheus.GaugeOpts{ Subsystem: name, Name: "longest_running_processor_microseconds", @@ -95,7 +191,7 @@ func (prometheusMetricsProvider) NewLongestRunningProcessorMicrosecondsMetric(na return unfinished } -func (prometheusMetricsProvider) NewRetriesMetric(name string) workqueue.CounterMetric { +func (prometheusMetricsProvider) NewDeprecatedRetriesMetric(name string) workqueue.CounterMetric { retries := prometheus.NewCounter(prometheus.CounterOpts{ Subsystem: name, Name: "retries", diff --git a/pkg/volume/OWNERS b/pkg/volume/OWNERS index fb4e6f00e39..4045407d487 100644 --- a/pkg/volume/OWNERS +++ b/pkg/volume/OWNERS @@ -2,10 +2,10 @@ approvers: - saad-ali - thockin - jsafrane -- matchstick - rootfs - gnufied - childsb +- msau42 reviewers: - saad-ali - jsafrane diff --git a/pkg/volume/awsebs/aws_ebs.go b/pkg/volume/awsebs/aws_ebs.go index c6270c1752a..ac934eccafe 100644 --- a/pkg/volume/awsebs/aws_ebs.go +++ b/pkg/volume/awsebs/aws_ebs.go @@ -576,12 +576,10 @@ func (c *awsElasticBlockStoreProvisioner) Provision(selectedNode *v1.Node, allow } } - if utilfeature.DefaultFeatureGate.Enabled(features.VolumeScheduling) { - pv.Spec.NodeAffinity = new(v1.VolumeNodeAffinity) - pv.Spec.NodeAffinity.Required = new(v1.NodeSelector) - pv.Spec.NodeAffinity.Required.NodeSelectorTerms = make([]v1.NodeSelectorTerm, 1) - pv.Spec.NodeAffinity.Required.NodeSelectorTerms[0].MatchExpressions = requirements - } + pv.Spec.NodeAffinity = new(v1.VolumeNodeAffinity) + pv.Spec.NodeAffinity.Required = new(v1.NodeSelector) + pv.Spec.NodeAffinity.Required.NodeSelectorTerms = make([]v1.NodeSelectorTerm, 1) + pv.Spec.NodeAffinity.Required.NodeSelectorTerms[0].MatchExpressions = requirements return pv, nil } diff --git a/pkg/volume/azure_dd/azure_common.go b/pkg/volume/azure_dd/azure_common.go index 9de53fe3368..174510c5d1b 100644 --- a/pkg/volume/azure_dd/azure_common.go +++ b/pkg/volume/azure_dd/azure_common.go @@ -40,7 +40,7 @@ import ( const ( defaultStorageAccountType = compute.StandardLRS defaultAzureDiskKind = v1.AzureManagedDisk - defaultAzureDataDiskCachingMode = v1.AzureDataDiskCachingNone + defaultAzureDataDiskCachingMode = v1.AzureDataDiskCachingReadOnly ) type dataDisk struct { diff --git a/pkg/volume/azure_dd/azure_dd.go b/pkg/volume/azure_dd/azure_dd.go index 961d5a35714..4a082addf1b 100644 --- a/pkg/volume/azure_dd/azure_dd.go +++ b/pkg/volume/azure_dd/azure_dd.go @@ -187,7 +187,7 @@ func getMaxDataDiskCount(instanceType string, sizeList *[]compute.VirtualMachine continue } if strings.ToUpper(*size.Name) == vmsize { - klog.V(2).Infof("got a matching size in getMaxDataDiskCount, Name: %s, MaxDataDiskCount: %d", *size.Name, *size.MaxDataDiskCount) + klog.V(12).Infof("got a matching size in getMaxDataDiskCount, Name: %s, MaxDataDiskCount: %d", *size.Name, *size.MaxDataDiskCount) return int64(*size.MaxDataDiskCount) } } diff --git a/pkg/volume/azure_dd/azure_provision.go b/pkg/volume/azure_dd/azure_provision.go index ca49550a5c4..c915f7b47c9 100644 --- a/pkg/volume/azure_dd/azure_provision.go +++ b/pkg/volume/azure_dd/azure_provision.go @@ -311,51 +311,49 @@ func (p *azureDiskProvisioner) Provision(selectedNode *v1.Node, allowedTopologie }, } - if utilfeature.DefaultFeatureGate.Enabled(features.VolumeScheduling) { - nodeSelectorTerms := make([]v1.NodeSelectorTerm, 0) + nodeSelectorTerms := make([]v1.NodeSelectorTerm, 0) - if zoned { - // Set node affinity labels based on availability zone labels. - if len(labels) > 0 { - requirements := make([]v1.NodeSelectorRequirement, 0) - for k, v := range labels { - requirements = append(requirements, v1.NodeSelectorRequirement{Key: k, Operator: v1.NodeSelectorOpIn, Values: []string{v}}) - } + if zoned { + // Set node affinity labels based on availability zone labels. + if len(labels) > 0 { + requirements := make([]v1.NodeSelectorRequirement, 0) + for k, v := range labels { + requirements = append(requirements, v1.NodeSelectorRequirement{Key: k, Operator: v1.NodeSelectorOpIn, Values: []string{v}}) + } - nodeSelectorTerms = append(nodeSelectorTerms, v1.NodeSelectorTerm{ - MatchExpressions: requirements, - }) - } - } else { - // Set node affinity labels based on fault domains. - // This is required because unzoned AzureDisk can't be attached to zoned nodes. - // There are at most 3 fault domains available in each region. - // Refer https://docs.microsoft.com/en-us/azure/virtual-machines/windows/manage-availability. - for i := 0; i < 3; i++ { - requirements := []v1.NodeSelectorRequirement{ - { - Key: kubeletapis.LabelZoneRegion, - Operator: v1.NodeSelectorOpIn, - Values: []string{diskController.GetLocation()}, - }, - { - Key: kubeletapis.LabelZoneFailureDomain, - Operator: v1.NodeSelectorOpIn, - Values: []string{strconv.Itoa(i)}, - }, - } - nodeSelectorTerms = append(nodeSelectorTerms, v1.NodeSelectorTerm{ - MatchExpressions: requirements, - }) - } + nodeSelectorTerms = append(nodeSelectorTerms, v1.NodeSelectorTerm{ + MatchExpressions: requirements, + }) } - - if len(nodeSelectorTerms) > 0 { - pv.Spec.NodeAffinity = &v1.VolumeNodeAffinity{ - Required: &v1.NodeSelector{ - NodeSelectorTerms: nodeSelectorTerms, + } else { + // Set node affinity labels based on fault domains. + // This is required because unzoned AzureDisk can't be attached to zoned nodes. + // There are at most 3 fault domains available in each region. + // Refer https://docs.microsoft.com/en-us/azure/virtual-machines/windows/manage-availability. + for i := 0; i < 3; i++ { + requirements := []v1.NodeSelectorRequirement{ + { + Key: kubeletapis.LabelZoneRegion, + Operator: v1.NodeSelectorOpIn, + Values: []string{diskController.GetLocation()}, + }, + { + Key: kubeletapis.LabelZoneFailureDomain, + Operator: v1.NodeSelectorOpIn, + Values: []string{strconv.Itoa(i)}, }, } + nodeSelectorTerms = append(nodeSelectorTerms, v1.NodeSelectorTerm{ + MatchExpressions: requirements, + }) + } + } + + if len(nodeSelectorTerms) > 0 { + pv.Spec.NodeAffinity = &v1.VolumeNodeAffinity{ + Required: &v1.NodeSelector{ + NodeSelectorTerms: nodeSelectorTerms, + }, } } diff --git a/pkg/volume/cinder/cinder.go b/pkg/volume/cinder/cinder.go index 953c4660f45..e4e488b8d2e 100644 --- a/pkg/volume/cinder/cinder.go +++ b/pkg/volume/cinder/cinder.go @@ -561,20 +561,18 @@ func (c *cinderVolumeProvisioner) Provision(selectedNode *v1.Node, allowedTopolo pv.Spec.AccessModes = c.plugin.GetAccessModes() } - if utilfeature.DefaultFeatureGate.Enabled(features.VolumeScheduling) { - requirements := make([]v1.NodeSelectorRequirement, 0) - for k, v := range labels { - if v != "" { - requirements = append(requirements, v1.NodeSelectorRequirement{Key: k, Operator: v1.NodeSelectorOpIn, Values: []string{v}}) - } - } - if len(requirements) > 0 { - pv.Spec.NodeAffinity = new(v1.VolumeNodeAffinity) - pv.Spec.NodeAffinity.Required = new(v1.NodeSelector) - pv.Spec.NodeAffinity.Required.NodeSelectorTerms = make([]v1.NodeSelectorTerm, 1) - pv.Spec.NodeAffinity.Required.NodeSelectorTerms[0].MatchExpressions = requirements + requirements := make([]v1.NodeSelectorRequirement, 0) + for k, v := range labels { + if v != "" { + requirements = append(requirements, v1.NodeSelectorRequirement{Key: k, Operator: v1.NodeSelectorOpIn, Values: []string{v}}) } } + if len(requirements) > 0 { + pv.Spec.NodeAffinity = new(v1.VolumeNodeAffinity) + pv.Spec.NodeAffinity.Required = new(v1.NodeSelector) + pv.Spec.NodeAffinity.Required.NodeSelectorTerms = make([]v1.NodeSelectorTerm, 1) + pv.Spec.NodeAffinity.Required.NodeSelectorTerms[0].MatchExpressions = requirements + } return pv, nil } diff --git a/pkg/volume/configmap/configmap.go b/pkg/volume/configmap/configmap.go index 823ce53d4b3..bd35aa50552 100644 --- a/pkg/volume/configmap/configmap.go +++ b/pkg/volume/configmap/configmap.go @@ -47,6 +47,10 @@ type configMapPlugin struct { var _ volume.VolumePlugin = &configMapPlugin{} +func getPath(uid types.UID, volName string, host volume.VolumeHost) string { + return host.GetPodVolumeDir(uid, strings.EscapeQualifiedNameForDisk(configMapPluginName), volName) +} + func (plugin *configMapPlugin) Init(host volume.VolumeHost) error { plugin.host = host plugin.getConfigMap = host.GetConfigMapFunc() @@ -92,7 +96,7 @@ func (plugin *configMapPlugin) NewMounter(spec *volume.Spec, pod *v1.Pod, opts v pod.UID, plugin, plugin.host.GetMounter(plugin.GetPluginName()), - volume.MetricsNil{}, + volume.NewCachedMetrics(volume.NewMetricsDu(getPath(pod.UID, spec.Name(), plugin.host))), }, source: *spec.Volume.ConfigMap, pod: *pod, @@ -108,7 +112,7 @@ func (plugin *configMapPlugin) NewUnmounter(volName string, podUID types.UID) (v podUID, plugin, plugin.host.GetMounter(plugin.GetPluginName()), - volume.MetricsNil{}, + volume.NewCachedMetrics(volume.NewMetricsDu(getPath(podUID, volName, plugin.host))), }, }, nil } @@ -128,7 +132,7 @@ type configMapVolume struct { podUID types.UID plugin *configMapPlugin mounter mount.Interface - volume.MetricsNil + volume.MetricsProvider } var _ volume.Volume = &configMapVolume{} diff --git a/pkg/volume/downwardapi/downwardapi.go b/pkg/volume/downwardapi/downwardapi.go index 391198ad9dd..9616f335738 100644 --- a/pkg/volume/downwardapi/downwardapi.go +++ b/pkg/volume/downwardapi/downwardapi.go @@ -48,6 +48,10 @@ type downwardAPIPlugin struct { var _ volume.VolumePlugin = &downwardAPIPlugin{} +func getPath(uid types.UID, volName string, host volume.VolumeHost) string { + return host.GetPodVolumeDir(uid, utilstrings.EscapeQualifiedNameForDisk(downwardAPIPluginName), volName) +} + func wrappedVolumeSpec() volume.Spec { return volume.Spec{ Volume: &v1.Volume{VolumeSource: v1.VolumeSource{EmptyDir: &v1.EmptyDirVolumeSource{Medium: v1.StorageMediumMemory}}}, @@ -91,11 +95,12 @@ func (plugin *downwardAPIPlugin) SupportsBulkVolumeVerification() bool { func (plugin *downwardAPIPlugin) NewMounter(spec *volume.Spec, pod *v1.Pod, opts volume.VolumeOptions) (volume.Mounter, error) { v := &downwardAPIVolume{ - volName: spec.Name(), - items: spec.Volume.DownwardAPI.Items, - pod: pod, - podUID: pod.UID, - plugin: plugin, + volName: spec.Name(), + items: spec.Volume.DownwardAPI.Items, + pod: pod, + podUID: pod.UID, + plugin: plugin, + MetricsProvider: volume.NewCachedMetrics(volume.NewMetricsDu(getPath(pod.UID, spec.Name(), plugin.host))), } return &downwardAPIVolumeMounter{ downwardAPIVolume: v, @@ -107,9 +112,10 @@ func (plugin *downwardAPIPlugin) NewMounter(spec *volume.Spec, pod *v1.Pod, opts func (plugin *downwardAPIPlugin) NewUnmounter(volName string, podUID types.UID) (volume.Unmounter, error) { return &downwardAPIVolumeUnmounter{ &downwardAPIVolume{ - volName: volName, - podUID: podUID, - plugin: plugin, + volName: volName, + podUID: podUID, + plugin: plugin, + MetricsProvider: volume.NewCachedMetrics(volume.NewMetricsDu(getPath(podUID, volName, plugin.host))), }, }, nil } @@ -131,7 +137,7 @@ type downwardAPIVolume struct { pod *v1.Pod podUID types.UID // TODO: remove this redundancy as soon NewUnmounter func will have *v1.POD and not only types.UID plugin *downwardAPIPlugin - volume.MetricsNil + volume.MetricsProvider } // downwardAPIVolumeMounter fetches info from downward API from the pod diff --git a/pkg/volume/gcepd/gce_pd.go b/pkg/volume/gcepd/gce_pd.go index 45572203320..74cf74ce627 100644 --- a/pkg/volume/gcepd/gce_pd.go +++ b/pkg/volume/gcepd/gce_pd.go @@ -551,7 +551,7 @@ func (c *gcePersistentDiskProvisioner) Provision(selectedNode *v1.Node, allowedT } } - if utilfeature.DefaultFeatureGate.Enabled(features.VolumeScheduling) && len(requirements) > 0 { + if len(requirements) > 0 { pv.Spec.NodeAffinity = new(v1.VolumeNodeAffinity) pv.Spec.NodeAffinity.Required = new(v1.NodeSelector) pv.Spec.NodeAffinity.Required.NodeSelectorTerms = make([]v1.NodeSelectorTerm, 1) diff --git a/pkg/volume/projected/projected.go b/pkg/volume/projected/projected.go index e93588ce676..06ea997292d 100644 --- a/pkg/volume/projected/projected.go +++ b/pkg/volume/projected/projected.go @@ -111,10 +111,11 @@ func (plugin *projectedPlugin) SupportsBulkVolumeVerification() bool { func (plugin *projectedPlugin) NewMounter(spec *volume.Spec, pod *v1.Pod, opts volume.VolumeOptions) (volume.Mounter, error) { return &projectedVolumeMounter{ projectedVolume: &projectedVolume{ - volName: spec.Name(), - sources: spec.Volume.Projected.Sources, - podUID: pod.UID, - plugin: plugin, + volName: spec.Name(), + sources: spec.Volume.Projected.Sources, + podUID: pod.UID, + plugin: plugin, + MetricsProvider: volume.NewCachedMetrics(volume.NewMetricsDu(getPath(pod.UID, spec.Name(), plugin.host))), }, source: *spec.Volume.Projected, pod: pod, @@ -125,9 +126,10 @@ func (plugin *projectedPlugin) NewMounter(spec *volume.Spec, pod *v1.Pod, opts v func (plugin *projectedPlugin) NewUnmounter(volName string, podUID types.UID) (volume.Unmounter, error) { return &projectedVolumeUnmounter{ &projectedVolume{ - volName: volName, - podUID: podUID, - plugin: plugin, + volName: volName, + podUID: podUID, + plugin: plugin, + MetricsProvider: volume.NewCachedMetrics(volume.NewMetricsDu(getPath(podUID, volName, plugin.host))), }, }, nil } @@ -148,7 +150,7 @@ type projectedVolume struct { sources []v1.VolumeProjection podUID types.UID plugin *projectedPlugin - volume.MetricsNil + volume.MetricsProvider } var _ volume.Volume = &projectedVolume{} diff --git a/pkg/volume/rbd/rbd_test.go b/pkg/volume/rbd/rbd_test.go index 46f56b9345e..799194c0760 100644 --- a/pkg/volume/rbd/rbd_test.go +++ b/pkg/volume/rbd/rbd_test.go @@ -682,3 +682,28 @@ func TestRequiresRemount(t *testing.T) { t.Errorf("Exepcted RequiresRemount to be false, got %t", has) } } + +func TestGetRbdImageSize(t *testing.T) { + for i, c := range []struct { + Output string + TargetSize int + }{ + { + Output: `{"name":"kubernetes-dynamic-pvc-18e7a4d9-050d-11e9-b905-548998f3478f","size":10737418240,"objects":2560,"order":22,"object_size":4194304,"block_name_prefix":"rbd_data.9f4ff7238e1f29","format":2}`, + TargetSize: 10240, + }, + { + Output: `{"name":"kubernetes-dynamic-pvc-070635bf-e33f-11e8-aab7-548998f3478f","size":1073741824,"objects":256,"order":22,"object_size":4194304,"block_name_prefix":"rbd_data.670ac4238e1f29","format":2}`, + TargetSize: 1024, + }, + } { + size, err := getRbdImageSize([]byte(c.Output)) + if err != nil { + t.Errorf("Case %d: getRbdImageSize failed: %v", i, err) + continue + } + if size != c.TargetSize { + t.Errorf("Case %d: unexpected size, wanted %d, got %d", i, c.TargetSize, size) + } + } +} diff --git a/pkg/volume/rbd/rbd_util.go b/pkg/volume/rbd/rbd_util.go index 2e3de226442..ec0dd7f2ebb 100644 --- a/pkg/volume/rbd/rbd_util.go +++ b/pkg/volume/rbd/rbd_util.go @@ -47,13 +47,13 @@ import ( const ( imageWatcherStr = "watcher=" imageSizeStr = "size " - sizeDivStr = " MB in" kubeLockMagic = "kubelet_lock_magic_" // The following three values are used for 30 seconds timeout // while waiting for RBD Watcher to expire. rbdImageWatcherInitDelay = 1 * time.Second rbdImageWatcherFactor = 1.4 rbdImageWatcherSteps = 10 + rbdImageSizeUnitMiB = 1024 * 1024 ) func getDevFromImageAndPool(pool, image string) (string, bool) { @@ -672,8 +672,7 @@ func (util *RBDUtil) ExpandImage(rbdExpander *rbdVolumeExpander, oldSize resourc // rbdInfo runs `rbd info` command to get the current image size in MB. func (util *RBDUtil) rbdInfo(b *rbdMounter) (int, error) { var err error - var output string - var cmd []byte + var output []byte // If we don't have admin id/secret (e.g. attaching), fallback to user id/secret. id := b.adminId @@ -702,9 +701,8 @@ func (util *RBDUtil) rbdInfo(b *rbdMounter) (int, error) { // rbd: error opening image 1234: (2) No such file or directory // klog.V(4).Infof("rbd: info %s using mon %s, pool %s id %s key %s", b.Image, mon, b.Pool, id, secret) - cmd, err = b.exec.Run("rbd", - "info", b.Image, "--pool", b.Pool, "-m", mon, "--id", id, "--key="+secret) - output = string(cmd) + output, err = b.exec.Run("rbd", + "info", b.Image, "--pool", b.Pool, "-m", mon, "--id", id, "--key="+secret, "--format=json") if err, ok := err.(*exec.Error); ok { if err.Err == exec.ErrNotFound { @@ -720,22 +718,20 @@ func (util *RBDUtil) rbdInfo(b *rbdMounter) (int, error) { } if len(output) == 0 { - return 0, fmt.Errorf("can not get image size info %s: %s", b.Image, output) + return 0, fmt.Errorf("can not get image size info %s: %s", b.Image, string(output)) } - // Get the size value string, just between `size ` and ` MB in`, such as `size 1024 MB in 256 objects`. - sizeIndex := strings.Index(output, imageSizeStr) - divIndex := strings.Index(output, sizeDivStr) - if sizeIndex == -1 || divIndex == -1 || divIndex <= sizeIndex+5 { - return 0, fmt.Errorf("can not get image size info %s: %s", b.Image, output) - } - rbdSizeStr := output[sizeIndex+5 : divIndex] - rbdSize, err := strconv.Atoi(rbdSizeStr) - if err != nil { - return 0, fmt.Errorf("can not convert size str: %s to int", rbdSizeStr) - } + return getRbdImageSize(output) +} - return rbdSize, nil +func getRbdImageSize(output []byte) (int, error) { + info := struct { + Size int64 `json:"size"` + }{} + if err := json.Unmarshal(output, &info); err != nil { + return 0, fmt.Errorf("parse rbd info output failed: %s, %v", string(output), err) + } + return int(info.Size / rbdImageSizeUnitMiB), nil } // rbdStatus runs `rbd status` command to check if there is watcher on the image. diff --git a/pkg/volume/testing/testing.go b/pkg/volume/testing/testing.go index 4c116aa5934..2791d9bd910 100644 --- a/pkg/volume/testing/testing.go +++ b/pkg/volume/testing/testing.go @@ -504,6 +504,94 @@ func (plugin *FakeVolumePlugin) VolumeLimitKey(spec *Spec) string { return plugin.LimitKey } +// FakeBasicVolumePlugin implements a basic volume plugin. It wrappers on +// FakeVolumePlugin but implements VolumePlugin interface only. +// It is useful to test logic involving plugin interfaces. +type FakeBasicVolumePlugin struct { + Plugin FakeVolumePlugin +} + +func (f *FakeBasicVolumePlugin) GetPluginName() string { + return f.Plugin.GetPluginName() +} + +func (f *FakeBasicVolumePlugin) GetVolumeName(spec *Spec) (string, error) { + return f.Plugin.GetVolumeName(spec) +} + +// CanSupport tests whether the plugin supports a given volume specification by +// testing volume spec name begins with plugin name or not. +// This is useful to choose plugin by volume in testing. +func (f *FakeBasicVolumePlugin) CanSupport(spec *Spec) bool { + return strings.HasPrefix(spec.Name(), f.GetPluginName()) +} + +func (f *FakeBasicVolumePlugin) ConstructVolumeSpec(ame, mountPath string) (*Spec, error) { + return f.Plugin.ConstructVolumeSpec(ame, mountPath) +} + +func (f *FakeBasicVolumePlugin) Init(ost VolumeHost) error { + return f.Plugin.Init(ost) +} + +func (f *FakeBasicVolumePlugin) NewMounter(spec *Spec, pod *v1.Pod, opts VolumeOptions) (Mounter, error) { + return f.Plugin.NewMounter(spec, pod, opts) +} + +func (f *FakeBasicVolumePlugin) NewUnmounter(volName string, podUID types.UID) (Unmounter, error) { + return f.Plugin.NewUnmounter(volName, podUID) +} + +func (f *FakeBasicVolumePlugin) RequiresRemount() bool { + return f.Plugin.RequiresRemount() +} + +func (f *FakeBasicVolumePlugin) SupportsBulkVolumeVerification() bool { + return f.Plugin.SupportsBulkVolumeVerification() +} + +func (f *FakeBasicVolumePlugin) SupportsMountOption() bool { + return f.Plugin.SupportsMountOption() +} + +var _ VolumePlugin = &FakeBasicVolumePlugin{} + +// FakeDeviceMountableVolumePlugin implements an device mountable plugin based on FakeBasicVolumePlugin. +type FakeDeviceMountableVolumePlugin struct { + FakeBasicVolumePlugin +} + +func (f *FakeDeviceMountableVolumePlugin) NewDeviceMounter() (DeviceMounter, error) { + return f.Plugin.NewDeviceMounter() +} + +func (f *FakeDeviceMountableVolumePlugin) NewDeviceUnmounter() (DeviceUnmounter, error) { + return f.Plugin.NewDeviceUnmounter() +} + +func (f *FakeDeviceMountableVolumePlugin) GetDeviceMountRefs(deviceMountPath string) ([]string, error) { + return f.Plugin.GetDeviceMountRefs(deviceMountPath) +} + +var _ VolumePlugin = &FakeDeviceMountableVolumePlugin{} +var _ DeviceMountableVolumePlugin = &FakeDeviceMountableVolumePlugin{} + +// FakeAttachableVolumePlugin implements an attachable plugin based on FakeDeviceMountableVolumePlugin. +type FakeAttachableVolumePlugin struct { + FakeDeviceMountableVolumePlugin +} + +func (f *FakeAttachableVolumePlugin) NewAttacher() (Attacher, error) { + return f.Plugin.NewAttacher() +} + +func (f *FakeAttachableVolumePlugin) NewDetacher() (Detacher, error) { + return f.Plugin.NewDetacher() +} + +var _ VolumePlugin = &FakeAttachableVolumePlugin{} +var _ AttachableVolumePlugin = &FakeAttachableVolumePlugin{} + type FakeFileVolumePlugin struct { } diff --git a/pkg/volume/util/BUILD b/pkg/volume/util/BUILD index ffd1d032151..d2bcab775ee 100644 --- a/pkg/volume/util/BUILD +++ b/pkg/volume/util/BUILD @@ -60,9 +60,7 @@ go_test( deps = [ "//pkg/apis/core/install:go_default_library", "//pkg/apis/core/v1/helper:go_default_library", - "//pkg/features:go_default_library", "//pkg/kubelet/apis:go_default_library", - "//pkg/util/mount:go_default_library", "//pkg/util/slice:go_default_library", "//pkg/volume:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library", @@ -70,10 +68,12 @@ go_test( "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/types:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library", - "//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library", - "//staging/src/k8s.io/apiserver/pkg/util/feature/testing:go_default_library", - "//staging/src/k8s.io/client-go/util/testing:go_default_library", - ], + ] + select({ + "@io_bazel_rules_go//go/platform:linux": [ + "//staging/src/k8s.io/client-go/util/testing:go_default_library", + ], + "//conditions:default": [], + }), ) filegroup( diff --git a/pkg/volume/util/operationexecutor/operation_executor.go b/pkg/volume/util/operationexecutor/operation_executor.go index 745910dc220..cfcc249f8bd 100644 --- a/pkg/volume/util/operationexecutor/operation_executor.go +++ b/pkg/volume/util/operationexecutor/operation_executor.go @@ -725,7 +725,7 @@ func (oe *operationExecutor) MountVolume( if fsVolume { // Filesystem volume case // Mount/remount a volume when a volume is attached - generatedOperations, err = oe.operationGenerator.GenerateMountVolumeFunc( + generatedOperations = oe.operationGenerator.GenerateMountVolumeFunc( waitForAttachTimeout, volumeToMount, actualStateOfWorld, isRemount) } else { diff --git a/pkg/volume/util/operationexecutor/operation_executor_test.go b/pkg/volume/util/operationexecutor/operation_executor_test.go index c7d0c9c8097..00816341cd6 100644 --- a/pkg/volume/util/operationexecutor/operation_executor_test.go +++ b/pkg/volume/util/operationexecutor/operation_executor_test.go @@ -389,14 +389,14 @@ func newFakeOperationGenerator(ch chan interface{}, quit chan interface{}) Opera } } -func (fopg *fakeOperationGenerator) GenerateMountVolumeFunc(waitForAttachTimeout time.Duration, volumeToMount VolumeToMount, actualStateOfWorldMounterUpdater ActualStateOfWorldMounterUpdater, isRemount bool) (volumetypes.GeneratedOperations, error) { +func (fopg *fakeOperationGenerator) GenerateMountVolumeFunc(waitForAttachTimeout time.Duration, volumeToMount VolumeToMount, actualStateOfWorldMounterUpdater ActualStateOfWorldMounterUpdater, isRemount bool) volumetypes.GeneratedOperations { opFunc := func() (error, error) { startOperationAndBlock(fopg.ch, fopg.quit) return nil, nil } return volumetypes.GeneratedOperations{ OperationFunc: opFunc, - }, nil + } } func (fopg *fakeOperationGenerator) GenerateUnmountVolumeFunc(volumeToUnmount MountedVolume, actualStateOfWorld ActualStateOfWorldMounterUpdater, podsDir string) (volumetypes.GeneratedOperations, error) { opFunc := func() (error, error) { diff --git a/pkg/volume/util/operationexecutor/operation_generator.go b/pkg/volume/util/operationexecutor/operation_generator.go index b4311e134e9..a185a5f33f8 100644 --- a/pkg/volume/util/operationexecutor/operation_generator.go +++ b/pkg/volume/util/operationexecutor/operation_generator.go @@ -40,6 +40,10 @@ import ( "k8s.io/kubernetes/pkg/volume/util/volumepathhandler" ) +const ( + unknownVolumePlugin string = "UnknownVolumePlugin" +) + var _ OperationGenerator = &operationGenerator{} type operationGenerator struct { @@ -82,7 +86,7 @@ func NewOperationGenerator(kubeClient clientset.Interface, // OperationGenerator interface that extracts out the functions from operation_executor to make it dependency injectable type OperationGenerator interface { // Generates the MountVolume function needed to perform the mount of a volume plugin - GenerateMountVolumeFunc(waitForAttachTimeout time.Duration, volumeToMount VolumeToMount, actualStateOfWorldMounterUpdater ActualStateOfWorldMounterUpdater, isRemount bool) (volumetypes.GeneratedOperations, error) + GenerateMountVolumeFunc(waitForAttachTimeout time.Duration, volumeToMount VolumeToMount, actualStateOfWorldMounterUpdater ActualStateOfWorldMounterUpdater, isRemount bool) volumetypes.GeneratedOperations // Generates the UnmountVolume function needed to perform the unmount of a volume plugin GenerateUnmountVolumeFunc(volumeToUnmount MountedVolume, actualStateOfWorld ActualStateOfWorldMounterUpdater, podsDir string) (volumetypes.GeneratedOperations, error) @@ -436,61 +440,61 @@ func (og *operationGenerator) GenerateMountVolumeFunc( waitForAttachTimeout time.Duration, volumeToMount VolumeToMount, actualStateOfWorld ActualStateOfWorldMounterUpdater, - isRemount bool) (volumetypes.GeneratedOperations, error) { + isRemount bool) volumetypes.GeneratedOperations { // Get mounter plugin + volumePluginName := unknownVolumePlugin volumePlugin, err := og.volumePluginMgr.FindPluginBySpec(volumeToMount.VolumeSpec) - if err != nil || volumePlugin == nil { - return volumetypes.GeneratedOperations{}, volumeToMount.GenerateErrorDetailed("MountVolume.FindPluginBySpec failed", err) - } - - affinityErr := checkNodeAffinity(og, volumeToMount, volumePlugin) - if affinityErr != nil { - eventErr, detailedErr := volumeToMount.GenerateError("MountVolume.NodeAffinity check failed", affinityErr) - og.recorder.Eventf(volumeToMount.Pod, v1.EventTypeWarning, kevents.FailedMountVolume, eventErr.Error()) - return volumetypes.GeneratedOperations{}, detailedErr - } - - volumeMounter, newMounterErr := volumePlugin.NewMounter( - volumeToMount.VolumeSpec, - volumeToMount.Pod, - volume.VolumeOptions{}) - if newMounterErr != nil { - eventErr, detailedErr := volumeToMount.GenerateError("MountVolume.NewMounter initialization failed", newMounterErr) - og.recorder.Eventf(volumeToMount.Pod, v1.EventTypeWarning, kevents.FailedMountVolume, eventErr.Error()) - return volumetypes.GeneratedOperations{}, detailedErr - } - - mountCheckError := checkMountOptionSupport(og, volumeToMount, volumePlugin) - - if mountCheckError != nil { - eventErr, detailedErr := volumeToMount.GenerateError("MountVolume.MountOptionSupport check failed", mountCheckError) - og.recorder.Eventf(volumeToMount.Pod, v1.EventTypeWarning, kevents.UnsupportedMountOption, eventErr.Error()) - return volumetypes.GeneratedOperations{}, detailedErr - } - - // Get attacher, if possible - attachableVolumePlugin, _ := - og.volumePluginMgr.FindAttachablePluginBySpec(volumeToMount.VolumeSpec) - var volumeAttacher volume.Attacher - if attachableVolumePlugin != nil { - volumeAttacher, _ = attachableVolumePlugin.NewAttacher() - } - - // get deviceMounter, if possible - deviceMountableVolumePlugin, _ := og.volumePluginMgr.FindDeviceMountablePluginBySpec(volumeToMount.VolumeSpec) - var volumeDeviceMounter volume.DeviceMounter - if deviceMountableVolumePlugin != nil { - volumeDeviceMounter, _ = deviceMountableVolumePlugin.NewDeviceMounter() - } - - var fsGroup *int64 - if volumeToMount.Pod.Spec.SecurityContext != nil && - volumeToMount.Pod.Spec.SecurityContext.FSGroup != nil { - fsGroup = volumeToMount.Pod.Spec.SecurityContext.FSGroup + if err == nil && volumePlugin != nil { + volumePluginName = volumePlugin.GetPluginName() } mountVolumeFunc := func() (error, error) { + if err != nil || volumePlugin == nil { + return volumeToMount.GenerateError("MountVolume.FindPluginBySpec failed", err) + } + + affinityErr := checkNodeAffinity(og, volumeToMount, volumePlugin) + if affinityErr != nil { + return volumeToMount.GenerateError("MountVolume.NodeAffinity check failed", affinityErr) + } + + volumeMounter, newMounterErr := volumePlugin.NewMounter( + volumeToMount.VolumeSpec, + volumeToMount.Pod, + volume.VolumeOptions{}) + if newMounterErr != nil { + return volumeToMount.GenerateError("MountVolume.NewMounter initialization failed", newMounterErr) + + } + + mountCheckError := checkMountOptionSupport(og, volumeToMount, volumePlugin) + + if mountCheckError != nil { + return volumeToMount.GenerateError("MountVolume.MountOptionSupport check failed", mountCheckError) + } + + // Get attacher, if possible + attachableVolumePlugin, _ := + og.volumePluginMgr.FindAttachablePluginBySpec(volumeToMount.VolumeSpec) + var volumeAttacher volume.Attacher + if attachableVolumePlugin != nil { + volumeAttacher, _ = attachableVolumePlugin.NewAttacher() + } + + // get deviceMounter, if possible + deviceMountableVolumePlugin, _ := og.volumePluginMgr.FindDeviceMountablePluginBySpec(volumeToMount.VolumeSpec) + var volumeDeviceMounter volume.DeviceMounter + if deviceMountableVolumePlugin != nil { + volumeDeviceMounter, _ = deviceMountableVolumePlugin.NewDeviceMounter() + } + + var fsGroup *int64 + if volumeToMount.Pod.Spec.SecurityContext != nil && + volumeToMount.Pod.Spec.SecurityContext.FSGroup != nil { + fsGroup = volumeToMount.Pod.Spec.SecurityContext.FSGroup + } + devicePath := volumeToMount.DevicePath if volumeAttacher != nil { // Wait for attachable volumes to finish attaching @@ -536,7 +540,7 @@ func (og *operationGenerator) GenerateMountVolumeFunc( // resizeFileSystem will resize the file system if user has requested a resize of // underlying persistent volume and is allowed to do so. - resizeSimpleError, resizeDetailedError := og.resizeFileSystem(volumeToMount, devicePath, deviceMountPath, volumePlugin.GetPluginName()) + resizeSimpleError, resizeDetailedError := og.resizeFileSystem(volumeToMount, devicePath, deviceMountPath, volumePluginName) if resizeSimpleError != nil || resizeDetailedError != nil { return resizeSimpleError, resizeDetailedError @@ -593,8 +597,8 @@ func (og *operationGenerator) GenerateMountVolumeFunc( return volumetypes.GeneratedOperations{ OperationFunc: mountVolumeFunc, EventRecorderFunc: eventRecorderFunc, - CompleteFunc: util.OperationCompleteHook(util.GetFullQualifiedPluginNameForVolume(volumePlugin.GetPluginName(), volumeToMount.VolumeSpec), "volume_mount"), - }, nil + CompleteFunc: util.OperationCompleteHook(util.GetFullQualifiedPluginNameForVolume(volumePluginName, volumeToMount.VolumeSpec), "volume_mount"), + } } func (og *operationGenerator) resizeFileSystem(volumeToMount VolumeToMount, devicePath, deviceMountPath, pluginName string) (simpleErr, detailedErr error) { diff --git a/pkg/volume/util/util.go b/pkg/volume/util/util.go index 8f5f4f6ff65..18e24d69f05 100644 --- a/pkg/volume/util/util.go +++ b/pkg/volume/util/util.go @@ -23,9 +23,8 @@ import ( "path" "path/filepath" "strings" - "syscall" - "k8s.io/api/core/v1" + v1 "k8s.io/api/core/v1" storage "k8s.io/api/storage/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" @@ -128,8 +127,9 @@ func SetReady(dir string) { // UnmountPath is a common unmount routine that unmounts the given path and // deletes the remaining directory if successful. +// TODO: Remove this function and change callers to call mount pkg directly func UnmountPath(mountPath string, mounter mount.Interface) error { - return UnmountMountPoint(mountPath, mounter, false /* extensiveMountPointCheck */) + return mount.CleanupMountPoint(mountPath, mounter, false /* extensiveMountPointCheck */) } // UnmountMountPoint is a common unmount routine that unmounts the given path and @@ -137,93 +137,21 @@ func UnmountPath(mountPath string, mounter mount.Interface) error { // if extensiveMountPointCheck is true // IsNotMountPoint will be called instead of IsLikelyNotMountPoint. // IsNotMountPoint is more expensive but properly handles bind mounts. +// TODO: Change callers to call mount pkg directly func UnmountMountPoint(mountPath string, mounter mount.Interface, extensiveMountPointCheck bool) error { - pathExists, pathErr := PathExists(mountPath) - if !pathExists { - klog.Warningf("Warning: Unmount skipped because path does not exist: %v", mountPath) - return nil - } - corruptedMnt := IsCorruptedMnt(pathErr) - if pathErr != nil && !corruptedMnt { - return fmt.Errorf("Error checking path: %v", pathErr) - } - return doUnmountMountPoint(mountPath, mounter, extensiveMountPointCheck, corruptedMnt) -} - -// doUnmountMountPoint is a common unmount routine that unmounts the given path and -// deletes the remaining directory if successful. -// if extensiveMountPointCheck is true -// IsNotMountPoint will be called instead of IsLikelyNotMountPoint. -// IsNotMountPoint is more expensive but properly handles bind mounts. -// if corruptedMnt is true, it means that the mountPath is a corrupted mountpoint, Take it as an argument for convenience of testing -func doUnmountMountPoint(mountPath string, mounter mount.Interface, extensiveMountPointCheck bool, corruptedMnt bool) error { - if !corruptedMnt { - var notMnt bool - var err error - if extensiveMountPointCheck { - notMnt, err = mount.IsNotMountPoint(mounter, mountPath) - } else { - notMnt, err = mounter.IsLikelyNotMountPoint(mountPath) - } - - if err != nil { - return err - } - - if notMnt { - klog.Warningf("Warning: %q is not a mountpoint, deleting", mountPath) - return os.Remove(mountPath) - } - } - - // Unmount the mount path - klog.V(4).Infof("%q is a mountpoint, unmounting", mountPath) - if err := mounter.Unmount(mountPath); err != nil { - return err - } - notMnt, mntErr := mounter.IsLikelyNotMountPoint(mountPath) - if mntErr != nil { - return mntErr - } - if notMnt { - klog.V(4).Infof("%q is unmounted, deleting the directory", mountPath) - return os.Remove(mountPath) - } - return fmt.Errorf("Failed to unmount path %v", mountPath) + return mount.CleanupMountPoint(mountPath, mounter, extensiveMountPointCheck) } // PathExists returns true if the specified path exists. +// TODO: Change callers to call mount pkg directly func PathExists(path string) (bool, error) { - _, err := os.Stat(path) - if err == nil { - return true, nil - } else if os.IsNotExist(err) { - return false, nil - } else if IsCorruptedMnt(err) { - return true, err - } - - return false, err + return mount.PathExists(path) } // IsCorruptedMnt return true if err is about corrupted mount point +// TODO: Change callers to call mount pkg directly func IsCorruptedMnt(err error) bool { - if err == nil { - return false - } - var underlyingError error - switch pe := err.(type) { - case nil: - return false - case *os.PathError: - underlyingError = pe.Err - case *os.LinkError: - underlyingError = pe.Err - case *os.SyscallError: - underlyingError = pe.Err - } - - return underlyingError == syscall.ENOTCONN || underlyingError == syscall.ESTALE || underlyingError == syscall.EIO + return mount.IsCorruptedMnt(err) } // GetSecretForPod locates secret by name in the pod's namespace and returns secret map @@ -825,9 +753,10 @@ func GetUniqueVolumeName(pluginName, volumeName string) v1.UniqueVolumeName { return v1.UniqueVolumeName(fmt.Sprintf("%s/%s", pluginName, volumeName)) } -// GetUniqueVolumeNameForNonAttachableVolume returns the unique volume name -// for a non-attachable volume. -func GetUniqueVolumeNameForNonAttachableVolume( +// GetUniqueVolumeNameFromSpecWithPod returns a unique volume name with pod +// name included. This is useful to generate different names for different pods +// on same volume. +func GetUniqueVolumeNameFromSpecWithPod( podName types.UniquePodName, volumePlugin volume.VolumePlugin, volumeSpec *volume.Spec) v1.UniqueVolumeName { return v1.UniqueVolumeName( fmt.Sprintf("%s/%v-%s", volumePlugin.GetPluginName(), podName, volumeSpec.Name())) diff --git a/pkg/volume/util/util_test.go b/pkg/volume/util/util_test.go index 8f376a3adb3..257410e226f 100644 --- a/pkg/volume/util/util_test.go +++ b/pkg/volume/util/util_test.go @@ -22,25 +22,20 @@ import ( "runtime" "testing" - "k8s.io/api/core/v1" + v1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/util/sets" - utilfeaturetesting "k8s.io/apiserver/pkg/util/feature/testing" - utiltesting "k8s.io/client-go/util/testing" // util.go uses api.Codecs.LegacyCodec so import this package to do some // resource initialization. "hash/fnv" _ "k8s.io/kubernetes/pkg/apis/core/install" - "k8s.io/kubernetes/pkg/features" - "k8s.io/kubernetes/pkg/util/mount" "reflect" "strings" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - utilfeature "k8s.io/apiserver/pkg/util/feature" kubeletapis "k8s.io/kubernetes/pkg/kubelet/apis" "k8s.io/kubernetes/pkg/util/slice" @@ -357,45 +352,6 @@ func TestZonesToSet(t *testing.T) { } } -func TestDoUnmountMountPoint(t *testing.T) { - - tmpDir1, err1 := utiltesting.MkTmpdir("umount_test1") - if err1 != nil { - t.Fatalf("error creating temp dir: %v", err1) - } - defer os.RemoveAll(tmpDir1) - - tmpDir2, err2 := utiltesting.MkTmpdir("umount_test2") - if err2 != nil { - t.Fatalf("error creating temp dir: %v", err2) - } - defer os.RemoveAll(tmpDir2) - - // Second part: want no error - tests := []struct { - mountPath string - corruptedMnt bool - }{ - { - mountPath: tmpDir1, - corruptedMnt: true, - }, - { - mountPath: tmpDir2, - corruptedMnt: false, - }, - } - - fake := &mount.FakeMounter{} - - for _, tt := range tests { - err := doUnmountMountPoint(tt.mountPath, fake, false, tt.corruptedMnt) - if err != nil { - t.Errorf("err Expected nil, but got: %v", err) - } - } -} - func TestCalculateTimeoutForVolume(t *testing.T) { pv := &v1.PersistentVolume{ Spec: v1.PersistentVolumeSpec{ @@ -1065,7 +1021,6 @@ func TestSelectZoneForVolume(t *testing.T) { ZonesWithNodes string Node *v1.Node AllowedTopologies []v1.TopologySelectorTerm - VolumeScheduling bool // Expectations around returned zone from SelectZoneForVolume Reject bool // expect error due to validation failing ExpectSpecificZone bool // expect returned zone to specifically match a single zone (rather than one from a set) @@ -1078,7 +1033,6 @@ func TestSelectZoneForVolume(t *testing.T) { // [1] Node irrelevant // [2] Zone and Zones parameters presents // [3] AllowedTopologies irrelevant - // [4] VolumeScheduling irrelevant { Name: "Nil_Node_with_Zone_Zones_parameters_present", ZonePresent: true, @@ -1092,53 +1046,45 @@ func TestSelectZoneForVolume(t *testing.T) { // [1] Node with no zone labels // [2] Zone/Zones parameter irrelevant // [3] AllowedTopologies irrelevant - // [4] VolumeScheduling enabled { - Name: "Node_with_no_Zone_labels", - Node: nodeWithNoLabels, - VolumeScheduling: true, - Reject: true, + Name: "Node_with_no_Zone_labels", + Node: nodeWithNoLabels, + Reject: true, }, // Node with Zone labels as well as Zone parameter specified [Fail] // [1] Node with zone labels // [2] Zone parameter specified // [3] AllowedTopologies irrelevant - // [4] VolumeScheduling enabled { - Name: "Node_with_Zone_labels_and_Zone_parameter_present", - Node: nodeWithZoneLabels, - ZonePresent: true, - Zone: "zoneX", - VolumeScheduling: true, - Reject: true, + Name: "Node_with_Zone_labels_and_Zone_parameter_present", + Node: nodeWithZoneLabels, + ZonePresent: true, + Zone: "zoneX", + Reject: true, }, // Node with Zone labels as well as Zones parameter specified [Fail] // [1] Node with zone labels // [2] Zones parameter specified // [3] AllowedTopologies irrelevant - // [4] VolumeScheduling enabled { - Name: "Node_with_Zone_labels_and_Zones_parameter_present", - Node: nodeWithZoneLabels, - ZonesPresent: true, - Zones: "zoneX,zoneY", - VolumeScheduling: true, - Reject: true, + Name: "Node_with_Zone_labels_and_Zones_parameter_present", + Node: nodeWithZoneLabels, + ZonesPresent: true, + Zones: "zoneX,zoneY", + Reject: true, }, // Zone parameter as well as AllowedTopologies specified [Fail] // [1] nil Node // [2] Zone parameter specified // [3] AllowedTopologies specified - // [4] VolumeScheduling enabled { - Name: "Nil_Node_and_Zone_parameter_and_Allowed_Topology_term", - Node: nil, - ZonePresent: true, - Zone: "zoneX", - VolumeScheduling: true, + Name: "Nil_Node_and_Zone_parameter_and_Allowed_Topology_term", + Node: nil, + ZonePresent: true, + Zone: "zoneX", AllowedTopologies: []v1.TopologySelectorTerm{ { MatchLabelExpressions: []v1.TopologySelectorLabelRequirement{ @@ -1156,13 +1102,11 @@ func TestSelectZoneForVolume(t *testing.T) { // [1] nil Node // [2] Zones parameter specified // [3] AllowedTopologies specified - // [4] VolumeScheduling enabled { - Name: "Nil_Node_and_Zones_parameter_and_Allowed_Topology_term", - Node: nil, - ZonesPresent: true, - Zones: "zoneX,zoneY", - VolumeScheduling: true, + Name: "Nil_Node_and_Zones_parameter_and_Allowed_Topology_term", + Node: nil, + ZonesPresent: true, + Zones: "zoneX,zoneY", AllowedTopologies: []v1.TopologySelectorTerm{ { MatchLabelExpressions: []v1.TopologySelectorLabelRequirement{ @@ -1180,11 +1124,9 @@ func TestSelectZoneForVolume(t *testing.T) { // [1] nil Node // [2] no Zone/Zones parameter // [3] AllowedTopologies with invalid key specified - // [4] VolumeScheduling enabled { - Name: "Nil_Node_and_Invalid_Allowed_Topology_Key", - Node: nil, - VolumeScheduling: true, + Name: "Nil_Node_and_Invalid_Allowed_Topology_Key", + Node: nil, AllowedTopologies: []v1.TopologySelectorTerm{ { MatchLabelExpressions: []v1.TopologySelectorLabelRequirement{ @@ -1206,11 +1148,9 @@ func TestSelectZoneForVolume(t *testing.T) { // [1] nil Node // [2] no Zone/Zones parameter // [3] Invalid AllowedTopologies - // [4] VolumeScheduling enabled { - Name: "Nil_Node_and_Invalid_AllowedTopologies", - Node: nil, - VolumeScheduling: true, + Name: "Nil_Node_and_Invalid_AllowedTopologies", + Node: nil, AllowedTopologies: []v1.TopologySelectorTerm{ { MatchLabelExpressions: []v1.TopologySelectorLabelRequirement{}, @@ -1219,77 +1159,29 @@ func TestSelectZoneForVolume(t *testing.T) { Reject: true, }, - // POSITIVE TESTS WITH VolumeScheduling DISABLED - - // Select zone from active zones [Pass] - // [1] nil Node (Node irrelevant) - // [2] no Zone parameter - // [3] no AllowedTopologies - // [4] VolumeScheduling disabled - { - Name: "No_Zone_Zones_parameter_and_VolumeScheduling_disabled", - ZonesWithNodes: "zoneX,zoneY", - VolumeScheduling: false, - Reject: false, - ExpectedZones: "zoneX,zoneY", - }, - - // Select zone from single zone parameter [Pass] - // [1] nil Node (Node irrelevant) - // [2] Zone parameter specified - // [3] no AllowedTopologies - // [4] VolumeScheduling disabled - { - Name: "Zone_parameter_present_and_VolumeScheduling_disabled", - ZonePresent: true, - Zone: "zoneX", - VolumeScheduling: false, - Reject: false, - ExpectSpecificZone: true, - ExpectedZone: "zoneX", - }, - - // Select zone from zones parameter [Pass] - // [1] nil Node (Node irrelevant) - // [2] Zones parameter specified - // [3] no AllowedTopologies - // [4] VolumeScheduling disabled - { - Name: "Zones_parameter_present_and_VolumeScheduling_disabled", - ZonesPresent: true, - Zones: "zoneX,zoneY", - VolumeScheduling: false, - Reject: false, - ExpectedZones: "zoneX,zoneY", - }, - // POSITIVE TESTS WITH VolumeScheduling ENABLED // Select zone from active zones [Pass] // [1] nil Node // [2] no Zone parameter specified // [3] no AllowedTopologies - // [4] VolumeScheduling enabled { - Name: "Nil_Node_and_No_Zone_Zones_parameter_and_no_Allowed_topologies_and_VolumeScheduling_enabled", - Node: nil, - ZonesWithNodes: "zoneX,zoneY", - VolumeScheduling: true, - Reject: false, - ExpectedZones: "zoneX,zoneY", + Name: "Nil_Node_and_No_Zone_Zones_parameter_and_no_Allowed_topologies_and_VolumeScheduling_enabled", + Node: nil, + ZonesWithNodes: "zoneX,zoneY", + Reject: false, + ExpectedZones: "zoneX,zoneY", }, // Select zone from single zone parameter [Pass] // [1] nil Node // [2] Zone parameter specified // [3] no AllowedTopology specified - // [4] VolumeScheduling enabled { Name: "Nil_Node_and_Zone_parameter_present_and_VolumeScheduling_enabled", ZonePresent: true, Zone: "zoneX", Node: nil, - VolumeScheduling: true, Reject: false, ExpectSpecificZone: true, ExpectedZone: "zoneX", @@ -1299,26 +1191,22 @@ func TestSelectZoneForVolume(t *testing.T) { // [1] nil Node // [2] Zones parameter specified // [3] no AllowedTopology - // [4] VolumeScheduling enabled { - Name: "Nil_Node_and_Zones_parameter_present_and_VolumeScheduling_enabled", - ZonesPresent: true, - Zones: "zoneX,zoneY", - Node: nil, - VolumeScheduling: true, - Reject: false, - ExpectedZones: "zoneX,zoneY", + Name: "Nil_Node_and_Zones_parameter_present_and_VolumeScheduling_enabled", + ZonesPresent: true, + Zones: "zoneX,zoneY", + Node: nil, + Reject: false, + ExpectedZones: "zoneX,zoneY", }, // Select zone from node label [Pass] // [1] Node with zone labels // [2] no zone/zones parameters // [3] no AllowedTopology - // [4] VolumeScheduling enabled { Name: "Node_with_Zone_labels_and_VolumeScheduling_enabled", Node: nodeWithZoneLabels, - VolumeScheduling: true, Reject: false, ExpectSpecificZone: true, ExpectedZone: "zoneX", @@ -1328,11 +1216,9 @@ func TestSelectZoneForVolume(t *testing.T) { // [1] Node with zone labels // [2] no Zone/Zones parameters // [3] AllowedTopology with single term with multiple values specified (ignored) - // [4] VolumeScheduling enabled { - Name: "Node_with_Zone_labels_and_Multiple_Allowed_Topology_values_and_VolumeScheduling_enabled", - Node: nodeWithZoneLabels, - VolumeScheduling: true, + Name: "Node_with_Zone_labels_and_Multiple_Allowed_Topology_values_and_VolumeScheduling_enabled", + Node: nodeWithZoneLabels, AllowedTopologies: []v1.TopologySelectorTerm{ { MatchLabelExpressions: []v1.TopologySelectorLabelRequirement{ @@ -1352,11 +1238,9 @@ func TestSelectZoneForVolume(t *testing.T) { // [1] nil Node // [2] no Zone/Zones parametes specified // [3] AllowedTopologies with single term with multiple values specified - // [4] VolumeScheduling enabled { - Name: "Nil_Node_with_Multiple_Allowed_Topology_values_and_VolumeScheduling_enabled", - Node: nil, - VolumeScheduling: true, + Name: "Nil_Node_with_Multiple_Allowed_Topology_values_and_VolumeScheduling_enabled", + Node: nil, AllowedTopologies: []v1.TopologySelectorTerm{ { MatchLabelExpressions: []v1.TopologySelectorLabelRequirement{ @@ -1375,11 +1259,9 @@ func TestSelectZoneForVolume(t *testing.T) { // [1] nil Node // [2] no Zone/Zones parametes specified // [3] AllowedTopologies with multiple terms specified - // [4] VolumeScheduling enabled { - Name: "Nil_Node_and_Multiple_Allowed_Topology_terms_and_VolumeScheduling_enabled", - Node: nil, - VolumeScheduling: true, + Name: "Nil_Node_and_Multiple_Allowed_Topology_terms_and_VolumeScheduling_enabled", + Node: nil, AllowedTopologies: []v1.TopologySelectorTerm{ { MatchLabelExpressions: []v1.TopologySelectorLabelRequirement{ @@ -1407,11 +1289,9 @@ func TestSelectZoneForVolume(t *testing.T) { // [1] nil Node // [2] no Zone/Zones parametes specified // [3] AllowedTopologies with single term and value specified - // [4] VolumeScheduling enabled { - Name: "Nil_Node_and_Single_Allowed_Topology_term_value_and_VolumeScheduling_enabled", - Node: nil, - VolumeScheduling: true, + Name: "Nil_Node_and_Single_Allowed_Topology_term_value_and_VolumeScheduling_enabled", + Node: nil, AllowedTopologies: []v1.TopologySelectorTerm{ { MatchLabelExpressions: []v1.TopologySelectorLabelRequirement{ @@ -1430,8 +1310,6 @@ func TestSelectZoneForVolume(t *testing.T) { for _, test := range tests { t.Run(test.Name, func(t *testing.T) { - defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.VolumeScheduling, test.VolumeScheduling)() - var zonesParameter, zonesWithNodes sets.String var err error diff --git a/plugin/pkg/admission/gc/BUILD b/plugin/pkg/admission/gc/BUILD index 354e386505b..842479b5a9a 100644 --- a/plugin/pkg/admission/gc/BUILD +++ b/plugin/pkg/admission/gc/BUILD @@ -29,8 +29,8 @@ go_test( deps = [ "//pkg/apis/core:go_default_library", "//pkg/kubeapiserver/admission:go_default_library", + "//staging/src/k8s.io/api/apps/v1:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library", - "//staging/src/k8s.io/api/extensions/v1beta1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", diff --git a/plugin/pkg/admission/gc/gc_admission_test.go b/plugin/pkg/admission/gc/gc_admission_test.go index 034e5179e45..a7d51cd0ef1 100644 --- a/plugin/pkg/admission/gc/gc_admission_test.go +++ b/plugin/pkg/admission/gc/gc_admission_test.go @@ -21,8 +21,8 @@ import ( "strings" "testing" + appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" - extensionv1beta1 "k8s.io/api/extensions/v1beta1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" @@ -112,7 +112,7 @@ func newGCPermissionsEnforcement() (*gcPermissionsEnforcement, error) { }, }, { - GroupVersion: extensionv1beta1.SchemeGroupVersion.String(), + GroupVersion: appsv1.SchemeGroupVersion.String(), APIResources: []metav1.APIResource{ {Name: "daemonsets", Namespaced: true, Kind: "DaemonSet"}, }, @@ -372,13 +372,13 @@ func TestBlockOwnerDeletionAdmission(t *testing.T) { Name: "rc2", } blockDS1 := metav1.OwnerReference{ - APIVersion: "extensions/v1beta1", + APIVersion: "apps/v1", Kind: "DaemonSet", Name: "ds1", BlockOwnerDeletion: getTrueVar(), } notBlockDS1 := metav1.OwnerReference{ - APIVersion: "extensions/v1beta1", + APIVersion: "apps/v1", Kind: "DaemonSet", Name: "ds1", BlockOwnerDeletion: getFalseVar(), diff --git a/plugin/pkg/admission/storage/persistentvolume/label/BUILD b/plugin/pkg/admission/storage/persistentvolume/label/BUILD index d93e3e75c1f..74fe386c138 100644 --- a/plugin/pkg/admission/storage/persistentvolume/label/BUILD +++ b/plugin/pkg/admission/storage/persistentvolume/label/BUILD @@ -18,13 +18,11 @@ go_library( "//pkg/cloudprovider/providers/aws:go_default_library", "//pkg/cloudprovider/providers/azure:go_default_library", "//pkg/cloudprovider/providers/gce:go_default_library", - "//pkg/features:go_default_library", "//pkg/kubeapiserver/admission:go_default_library", "//pkg/kubelet/apis:go_default_library", "//pkg/volume:go_default_library", "//pkg/volume/util:go_default_library", "//staging/src/k8s.io/apiserver/pkg/admission:go_default_library", - "//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library", "//staging/src/k8s.io/cloud-provider:go_default_library", "//vendor/k8s.io/klog:go_default_library", ], @@ -37,15 +35,12 @@ go_test( deps = [ "//pkg/apis/core:go_default_library", "//pkg/cloudprovider/providers/aws:go_default_library", - "//pkg/features:go_default_library", "//pkg/kubelet/apis:go_default_library", "//pkg/volume/util:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/resource:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/types:go_default_library", "//staging/src/k8s.io/apiserver/pkg/admission:go_default_library", - "//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library", - "//staging/src/k8s.io/apiserver/pkg/util/feature/testing:go_default_library", ], ) diff --git a/plugin/pkg/admission/storage/persistentvolume/label/admission.go b/plugin/pkg/admission/storage/persistentvolume/label/admission.go index db291c86f44..4125dd52c35 100644 --- a/plugin/pkg/admission/storage/persistentvolume/label/admission.go +++ b/plugin/pkg/admission/storage/persistentvolume/label/admission.go @@ -23,14 +23,12 @@ import ( "sync" "k8s.io/apiserver/pkg/admission" - utilfeature "k8s.io/apiserver/pkg/util/feature" cloudprovider "k8s.io/cloud-provider" "k8s.io/klog" api "k8s.io/kubernetes/pkg/apis/core" "k8s.io/kubernetes/pkg/cloudprovider/providers/aws" "k8s.io/kubernetes/pkg/cloudprovider/providers/azure" "k8s.io/kubernetes/pkg/cloudprovider/providers/gce" - "k8s.io/kubernetes/pkg/features" kubeapiserveradmission "k8s.io/kubernetes/pkg/kubeapiserver/admission" kubeletapis "k8s.io/kubernetes/pkg/kubelet/apis" vol "k8s.io/kubernetes/pkg/volume" @@ -158,25 +156,23 @@ func (l *persistentVolumeLabel) Admit(a admission.Attributes) (err error) { requirements = append(requirements, api.NodeSelectorRequirement{Key: k, Operator: api.NodeSelectorOpIn, Values: values}) } - if utilfeature.DefaultFeatureGate.Enabled(features.VolumeScheduling) { - if volume.Spec.NodeAffinity == nil { - volume.Spec.NodeAffinity = new(api.VolumeNodeAffinity) - } - if volume.Spec.NodeAffinity.Required == nil { - volume.Spec.NodeAffinity.Required = new(api.NodeSelector) - } - if len(volume.Spec.NodeAffinity.Required.NodeSelectorTerms) == 0 { - // Need at least one term pre-allocated whose MatchExpressions can be appended to - volume.Spec.NodeAffinity.Required.NodeSelectorTerms = make([]api.NodeSelectorTerm, 1) - } - if nodeSelectorRequirementKeysExistInNodeSelectorTerms(requirements, volume.Spec.NodeAffinity.Required.NodeSelectorTerms) { - klog.V(4).Infof("NodeSelectorRequirements for cloud labels %v conflict with existing NodeAffinity %v. Skipping addition of NodeSelectorRequirements for cloud labels.", - requirements, volume.Spec.NodeAffinity) - } else { - for _, req := range requirements { - for i := range volume.Spec.NodeAffinity.Required.NodeSelectorTerms { - volume.Spec.NodeAffinity.Required.NodeSelectorTerms[i].MatchExpressions = append(volume.Spec.NodeAffinity.Required.NodeSelectorTerms[i].MatchExpressions, req) - } + if volume.Spec.NodeAffinity == nil { + volume.Spec.NodeAffinity = new(api.VolumeNodeAffinity) + } + if volume.Spec.NodeAffinity.Required == nil { + volume.Spec.NodeAffinity.Required = new(api.NodeSelector) + } + if len(volume.Spec.NodeAffinity.Required.NodeSelectorTerms) == 0 { + // Need at least one term pre-allocated whose MatchExpressions can be appended to + volume.Spec.NodeAffinity.Required.NodeSelectorTerms = make([]api.NodeSelectorTerm, 1) + } + if nodeSelectorRequirementKeysExistInNodeSelectorTerms(requirements, volume.Spec.NodeAffinity.Required.NodeSelectorTerms) { + klog.V(4).Infof("NodeSelectorRequirements for cloud labels %v conflict with existing NodeAffinity %v. Skipping addition of NodeSelectorRequirements for cloud labels.", + requirements, volume.Spec.NodeAffinity) + } else { + for _, req := range requirements { + for i := range volume.Spec.NodeAffinity.Required.NodeSelectorTerms { + volume.Spec.NodeAffinity.Required.NodeSelectorTerms[i].MatchExpressions = append(volume.Spec.NodeAffinity.Required.NodeSelectorTerms[i].MatchExpressions, req) } } } diff --git a/plugin/pkg/admission/storage/persistentvolume/label/admission_test.go b/plugin/pkg/admission/storage/persistentvolume/label/admission_test.go index 5b6dc02041d..99c1843f1b5 100644 --- a/plugin/pkg/admission/storage/persistentvolume/label/admission_test.go +++ b/plugin/pkg/admission/storage/persistentvolume/label/admission_test.go @@ -27,11 +27,8 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" "k8s.io/apiserver/pkg/admission" - utilfeature "k8s.io/apiserver/pkg/util/feature" - utilfeaturetesting "k8s.io/apiserver/pkg/util/feature/testing" api "k8s.io/kubernetes/pkg/apis/core" "k8s.io/kubernetes/pkg/cloudprovider/providers/aws" - "k8s.io/kubernetes/pkg/features" kubeletapis "k8s.io/kubernetes/pkg/kubelet/apis" volumeutil "k8s.io/kubernetes/pkg/volume/util" ) @@ -125,8 +122,6 @@ func TestAdmission(t *testing.T) { }, } - defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.VolumeScheduling, true)() - // Non-cloud PVs are ignored err := handler.Admit(admission.NewAttributesRecord(&ignoredPV, nil, api.Kind("PersistentVolume").WithVersion("version"), ignoredPV.Namespace, ignoredPV.Name, api.Resource("persistentvolumes").WithVersion("version"), "", admission.Create, false, nil)) if err != nil { diff --git a/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/policy.go b/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/policy.go index 1972220c25e..e3aaef39a8c 100644 --- a/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/policy.go +++ b/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/policy.go @@ -489,17 +489,14 @@ func ClusterRoles() []rbacv1.ClusterRole { rbacv1helpers.NewRule("create").Groups(certificatesGroup).Resources("certificatesigningrequests/selfnodeclient").RuleOrDie(), }, }, - } - - if utilfeature.DefaultFeatureGate.Enabled(features.VolumeScheduling) { - roles = append(roles, rbacv1.ClusterRole{ + { ObjectMeta: metav1.ObjectMeta{Name: "system:volume-scheduler"}, Rules: []rbacv1.PolicyRule{ rbacv1helpers.NewRule(ReadUpdate...).Groups(legacyGroup).Resources("persistentvolumes").RuleOrDie(), rbacv1helpers.NewRule(Read...).Groups(storageGroup).Resources("storageclasses").RuleOrDie(), rbacv1helpers.NewRule(ReadUpdate...).Groups(legacyGroup).Resources("persistentvolumeclaims").RuleOrDie(), }, - }) + }, } externalProvisionerRules := []rbacv1.PolicyRule{ @@ -535,6 +532,7 @@ func ClusterRoleBindings() []rbacv1.ClusterRoleBinding { rbacv1helpers.NewClusterBinding("system:kube-dns").SAs("kube-system", "kube-dns").BindingOrDie(), rbacv1helpers.NewClusterBinding("system:kube-scheduler").Users(user.KubeScheduler).BindingOrDie(), rbacv1helpers.NewClusterBinding("system:aws-cloud-provider").SAs("kube-system", "aws-cloud-provider").BindingOrDie(), + rbacv1helpers.NewClusterBinding("system:volume-scheduler").Users(user.KubeScheduler).BindingOrDie(), // This default binding of the system:node role to the system:nodes group is deprecated in 1.7 with the availability of the Node authorizer. // This leaves the binding, but with an empty set of subjects, so that tightening reconciliation can remove the subject. @@ -544,10 +542,6 @@ func ClusterRoleBindings() []rbacv1.ClusterRoleBinding { }, } - if utilfeature.DefaultFeatureGate.Enabled(features.VolumeScheduling) { - rolebindings = append(rolebindings, rbacv1helpers.NewClusterBinding("system:volume-scheduler").Users(user.KubeScheduler).BindingOrDie()) - } - addClusterRoleBindingLabel(rolebindings) return rolebindings diff --git a/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/testdata/cluster-roles.yaml b/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/testdata/cluster-roles.yaml index 5f97d6d8308..543025b37f8 100644 --- a/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/testdata/cluster-roles.yaml +++ b/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/testdata/cluster-roles.yaml @@ -971,6 +971,16 @@ items: - volumeattachments verbs: - get + - apiGroups: + - coordination.k8s.io + resources: + - leases + verbs: + - create + - delete + - get + - patch + - update - apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: diff --git a/staging/README.md b/staging/README.md index 34ff9884b07..c33acbcfa90 100644 --- a/staging/README.md +++ b/staging/README.md @@ -22,6 +22,7 @@ Repositories currently staged here: - [`k8s.io/kube-scheduler`](https://github.com/kubernetes/kube-scheduler) - [`k8s.io/kubelet`](https://github.com/kubernetes/kubelet) - [`k8s.io/metrics`](https://github.com/kubernetes/metrics) +- [`k8s.io/node-api`](https://github.com/kubernetes/node-api) - [`k8s.io/sample-apiserver`](https://github.com/kubernetes/sample-apiserver) - [`k8s.io/sample-cli-plugin`](https://github.com/kubernetes/sample-cli-plugin) - [`k8s.io/sample-controller`](https://github.com/kubernetes/sample-controller) diff --git a/staging/src/BUILD b/staging/src/BUILD index 38232323052..5af24ec250e 100644 --- a/staging/src/BUILD +++ b/staging/src/BUILD @@ -115,6 +115,7 @@ filegroup( "//staging/src/k8s.io/apiserver/plugin/pkg/authorizer/webhook:all-srcs", "//staging/src/k8s.io/cli-runtime/artifacts:all-srcs", "//staging/src/k8s.io/cli-runtime/pkg/genericclioptions:all-srcs", + "//staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps:all-srcs", "//staging/src/k8s.io/client-go/deprecated-dynamic:all-srcs", "//staging/src/k8s.io/client-go/discovery:all-srcs", "//staging/src/k8s.io/client-go/dynamic:all-srcs", @@ -143,6 +144,7 @@ filegroup( "//staging/src/k8s.io/client-go/listers/batch/v1beta1:all-srcs", "//staging/src/k8s.io/client-go/listers/batch/v2alpha1:all-srcs", "//staging/src/k8s.io/client-go/listers/certificates/v1beta1:all-srcs", + "//staging/src/k8s.io/client-go/listers/coordination/v1:all-srcs", "//staging/src/k8s.io/client-go/listers/coordination/v1beta1:all-srcs", "//staging/src/k8s.io/client-go/listers/core/v1:all-srcs", "//staging/src/k8s.io/client-go/listers/events/v1beta1:all-srcs", @@ -205,6 +207,7 @@ filegroup( "//staging/src/k8s.io/code-generator/cmd/register-gen:all-srcs", "//staging/src/k8s.io/code-generator/cmd/set-gen:all-srcs", "//staging/src/k8s.io/code-generator/hack:all-srcs", + "//staging/src/k8s.io/code-generator/pkg/namer:all-srcs", "//staging/src/k8s.io/code-generator/pkg/util:all-srcs", "//staging/src/k8s.io/code-generator/third_party/forked/golang/reflect:all-srcs", "//staging/src/k8s.io/csi-api/pkg/apis/csi/v1alpha1:all-srcs", @@ -223,6 +226,10 @@ filegroup( "//staging/src/k8s.io/metrics/pkg/client/clientset/versioned:all-srcs", "//staging/src/k8s.io/metrics/pkg/client/custom_metrics:all-srcs", "//staging/src/k8s.io/metrics/pkg/client/external_metrics:all-srcs", + "//staging/src/k8s.io/node-api/pkg/apis/node/v1alpha1:all-srcs", + "//staging/src/k8s.io/node-api/pkg/client/clientset/versioned:all-srcs", + "//staging/src/k8s.io/node-api/pkg/client/informers/externalversions:all-srcs", + "//staging/src/k8s.io/node-api/pkg/client/listers/node/v1alpha1:all-srcs", "//staging/src/k8s.io/sample-apiserver:all-srcs", "//staging/src/k8s.io/sample-cli-plugin/cmd:all-srcs", "//staging/src/k8s.io/sample-cli-plugin/pkg/cmd:all-srcs", diff --git a/staging/src/k8s.io/api/BUILD b/staging/src/k8s.io/api/BUILD index fe6ca1e4e1b..1a651e7d7fb 100644 --- a/staging/src/k8s.io/api/BUILD +++ b/staging/src/k8s.io/api/BUILD @@ -75,6 +75,7 @@ filegroup( "//staging/src/k8s.io/api/batch/v1beta1:all-srcs", "//staging/src/k8s.io/api/batch/v2alpha1:all-srcs", "//staging/src/k8s.io/api/certificates/v1beta1:all-srcs", + "//staging/src/k8s.io/api/coordination/v1:all-srcs", "//staging/src/k8s.io/api/coordination/v1beta1:all-srcs", "//staging/src/k8s.io/api/core/v1:all-srcs", "//staging/src/k8s.io/api/events/v1beta1:all-srcs", diff --git a/staging/src/k8s.io/api/coordination/v1/BUILD b/staging/src/k8s.io/api/coordination/v1/BUILD new file mode 100644 index 00000000000..4dd8cf4be13 --- /dev/null +++ b/staging/src/k8s.io/api/coordination/v1/BUILD @@ -0,0 +1,36 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = [ + "doc.go", + "generated.pb.go", + "register.go", + "types.go", + "types_swagger_doc_generated.go", + "zz_generated.deepcopy.go", + ], + importmap = "k8s.io/kubernetes/vendor/k8s.io/api/coordination/v1", + importpath = "k8s.io/api/coordination/v1", + visibility = ["//visibility:public"], + deps = [ + "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + "//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library", + "//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", + "//vendor/github.com/gogo/protobuf/proto:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/staging/src/k8s.io/api/coordination/v1/doc.go b/staging/src/k8s.io/api/coordination/v1/doc.go new file mode 100644 index 00000000000..6d554c2a5be --- /dev/null +++ b/staging/src/k8s.io/api/coordination/v1/doc.go @@ -0,0 +1,22 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// +k8s:deepcopy-gen=package +// +k8s:openapi-gen=true + +// +groupName=coordination.k8s.io + +package v1 // import "k8s.io/api/coordination/v1" diff --git a/staging/src/k8s.io/api/coordination/v1/generated.pb.go b/staging/src/k8s.io/api/coordination/v1/generated.pb.go new file mode 100644 index 00000000000..349c68574af --- /dev/null +++ b/staging/src/k8s.io/api/coordination/v1/generated.pb.go @@ -0,0 +1,864 @@ +/* +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 protoc-gen-gogo. DO NOT EDIT. +// source: k8s.io/kubernetes/vendor/k8s.io/api/coordination/v1/generated.proto + +/* + Package v1 is a generated protocol buffer package. + + It is generated from these files: + k8s.io/kubernetes/vendor/k8s.io/api/coordination/v1/generated.proto + + It has these top-level messages: + Lease + LeaseList + LeaseSpec +*/ +package v1 + +import proto "github.com/gogo/protobuf/proto" +import fmt "fmt" +import math "math" + +import k8s_io_apimachinery_pkg_apis_meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + +import strings "strings" +import reflect "reflect" + +import io "io" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package + +func (m *Lease) Reset() { *m = Lease{} } +func (*Lease) ProtoMessage() {} +func (*Lease) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{0} } + +func (m *LeaseList) Reset() { *m = LeaseList{} } +func (*LeaseList) ProtoMessage() {} +func (*LeaseList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{1} } + +func (m *LeaseSpec) Reset() { *m = LeaseSpec{} } +func (*LeaseSpec) ProtoMessage() {} +func (*LeaseSpec) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{2} } + +func init() { + proto.RegisterType((*Lease)(nil), "k8s.io.api.coordination.v1.Lease") + proto.RegisterType((*LeaseList)(nil), "k8s.io.api.coordination.v1.LeaseList") + proto.RegisterType((*LeaseSpec)(nil), "k8s.io.api.coordination.v1.LeaseSpec") +} +func (m *Lease) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *Lease) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + dAtA[i] = 0xa + i++ + i = encodeVarintGenerated(dAtA, i, uint64(m.ObjectMeta.Size())) + n1, err := m.ObjectMeta.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n1 + dAtA[i] = 0x12 + i++ + i = encodeVarintGenerated(dAtA, i, uint64(m.Spec.Size())) + n2, err := m.Spec.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n2 + return i, nil +} + +func (m *LeaseList) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *LeaseList) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + dAtA[i] = 0xa + i++ + i = encodeVarintGenerated(dAtA, i, uint64(m.ListMeta.Size())) + n3, err := m.ListMeta.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n3 + if len(m.Items) > 0 { + for _, msg := range m.Items { + dAtA[i] = 0x12 + i++ + i = encodeVarintGenerated(dAtA, i, uint64(msg.Size())) + n, err := msg.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n + } + } + return i, nil +} + +func (m *LeaseSpec) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *LeaseSpec) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if m.HolderIdentity != nil { + dAtA[i] = 0xa + i++ + i = encodeVarintGenerated(dAtA, i, uint64(len(*m.HolderIdentity))) + i += copy(dAtA[i:], *m.HolderIdentity) + } + if m.LeaseDurationSeconds != nil { + dAtA[i] = 0x10 + i++ + i = encodeVarintGenerated(dAtA, i, uint64(*m.LeaseDurationSeconds)) + } + if m.AcquireTime != nil { + dAtA[i] = 0x1a + i++ + i = encodeVarintGenerated(dAtA, i, uint64(m.AcquireTime.Size())) + n4, err := m.AcquireTime.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n4 + } + if m.RenewTime != nil { + dAtA[i] = 0x22 + i++ + i = encodeVarintGenerated(dAtA, i, uint64(m.RenewTime.Size())) + n5, err := m.RenewTime.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n5 + } + if m.LeaseTransitions != nil { + dAtA[i] = 0x28 + i++ + i = encodeVarintGenerated(dAtA, i, uint64(*m.LeaseTransitions)) + } + return i, nil +} + +func encodeVarintGenerated(dAtA []byte, offset int, v uint64) int { + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return offset + 1 +} +func (m *Lease) Size() (n int) { + var l int + _ = l + l = m.ObjectMeta.Size() + n += 1 + l + sovGenerated(uint64(l)) + l = m.Spec.Size() + n += 1 + l + sovGenerated(uint64(l)) + return n +} + +func (m *LeaseList) Size() (n int) { + var l int + _ = l + l = m.ListMeta.Size() + n += 1 + l + sovGenerated(uint64(l)) + if len(m.Items) > 0 { + for _, e := range m.Items { + l = e.Size() + n += 1 + l + sovGenerated(uint64(l)) + } + } + return n +} + +func (m *LeaseSpec) Size() (n int) { + var l int + _ = l + if m.HolderIdentity != nil { + l = len(*m.HolderIdentity) + n += 1 + l + sovGenerated(uint64(l)) + } + if m.LeaseDurationSeconds != nil { + n += 1 + sovGenerated(uint64(*m.LeaseDurationSeconds)) + } + if m.AcquireTime != nil { + l = m.AcquireTime.Size() + n += 1 + l + sovGenerated(uint64(l)) + } + if m.RenewTime != nil { + l = m.RenewTime.Size() + n += 1 + l + sovGenerated(uint64(l)) + } + if m.LeaseTransitions != nil { + n += 1 + sovGenerated(uint64(*m.LeaseTransitions)) + } + return n +} + +func sovGenerated(x uint64) (n int) { + for { + n++ + x >>= 7 + if x == 0 { + break + } + } + return n +} +func sozGenerated(x uint64) (n int) { + return sovGenerated(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (this *Lease) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&Lease{`, + `ObjectMeta:` + strings.Replace(strings.Replace(this.ObjectMeta.String(), "ObjectMeta", "k8s_io_apimachinery_pkg_apis_meta_v1.ObjectMeta", 1), `&`, ``, 1) + `,`, + `Spec:` + strings.Replace(strings.Replace(this.Spec.String(), "LeaseSpec", "LeaseSpec", 1), `&`, ``, 1) + `,`, + `}`, + }, "") + return s +} +func (this *LeaseList) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&LeaseList{`, + `ListMeta:` + strings.Replace(strings.Replace(this.ListMeta.String(), "ListMeta", "k8s_io_apimachinery_pkg_apis_meta_v1.ListMeta", 1), `&`, ``, 1) + `,`, + `Items:` + strings.Replace(strings.Replace(fmt.Sprintf("%v", this.Items), "Lease", "Lease", 1), `&`, ``, 1) + `,`, + `}`, + }, "") + return s +} +func (this *LeaseSpec) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&LeaseSpec{`, + `HolderIdentity:` + valueToStringGenerated(this.HolderIdentity) + `,`, + `LeaseDurationSeconds:` + valueToStringGenerated(this.LeaseDurationSeconds) + `,`, + `AcquireTime:` + strings.Replace(fmt.Sprintf("%v", this.AcquireTime), "MicroTime", "k8s_io_apimachinery_pkg_apis_meta_v1.MicroTime", 1) + `,`, + `RenewTime:` + strings.Replace(fmt.Sprintf("%v", this.RenewTime), "MicroTime", "k8s_io_apimachinery_pkg_apis_meta_v1.MicroTime", 1) + `,`, + `LeaseTransitions:` + valueToStringGenerated(this.LeaseTransitions) + `,`, + `}`, + }, "") + return s +} +func valueToStringGenerated(v interface{}) string { + rv := reflect.ValueOf(v) + if rv.IsNil() { + return "nil" + } + pv := reflect.Indirect(rv).Interface() + return fmt.Sprintf("*%v", pv) +} +func (m *Lease) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: Lease: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Lease: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ObjectMeta", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.ObjectMeta.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Spec", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Spec.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenerated(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *LeaseList) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: LeaseList: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: LeaseList: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ListMeta", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.ListMeta.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Items", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Items = append(m.Items, Lease{}) + if err := m.Items[len(m.Items)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenerated(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *LeaseSpec) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: LeaseSpec: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: LeaseSpec: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field HolderIdentity", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + s := string(dAtA[iNdEx:postIndex]) + m.HolderIdentity = &s + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field LeaseDurationSeconds", wireType) + } + var v int32 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= (int32(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + m.LeaseDurationSeconds = &v + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AcquireTime", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.AcquireTime == nil { + m.AcquireTime = &k8s_io_apimachinery_pkg_apis_meta_v1.MicroTime{} + } + if err := m.AcquireTime.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field RenewTime", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.RenewTime == nil { + m.RenewTime = &k8s_io_apimachinery_pkg_apis_meta_v1.MicroTime{} + } + if err := m.RenewTime.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 5: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field LeaseTransitions", wireType) + } + var v int32 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= (int32(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + m.LeaseTransitions = &v + default: + iNdEx = preIndex + skippy, err := skipGenerated(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipGenerated(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowGenerated + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowGenerated + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + return iNdEx, nil + case 1: + iNdEx += 8 + return iNdEx, nil + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowGenerated + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + iNdEx += length + if length < 0 { + return 0, ErrInvalidLengthGenerated + } + return iNdEx, nil + case 3: + for { + var innerWire uint64 + var start int = iNdEx + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowGenerated + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + innerWire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + innerWireType := int(innerWire & 0x7) + if innerWireType == 4 { + break + } + next, err := skipGenerated(dAtA[start:]) + if err != nil { + return 0, err + } + iNdEx = start + next + } + return iNdEx, nil + case 4: + return iNdEx, nil + case 5: + iNdEx += 4 + return iNdEx, nil + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + } + panic("unreachable") +} + +var ( + ErrInvalidLengthGenerated = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowGenerated = fmt.Errorf("proto: integer overflow") +) + +func init() { + proto.RegisterFile("k8s.io/kubernetes/vendor/k8s.io/api/coordination/v1/generated.proto", fileDescriptorGenerated) +} + +var fileDescriptorGenerated = []byte{ + // 535 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x90, 0xc1, 0x6e, 0xd3, 0x40, + 0x10, 0x86, 0xe3, 0x36, 0x91, 0x9a, 0x0d, 0x2d, 0x91, 0x95, 0x83, 0x95, 0x83, 0x5d, 0x22, 0x21, + 0xe5, 0xc2, 0x2e, 0xa9, 0x10, 0x42, 0x9c, 0xc0, 0x20, 0xa0, 0x52, 0x2a, 0x24, 0xb7, 0x27, 0xd4, + 0x03, 0x1b, 0x7b, 0x70, 0x96, 0xd4, 0x5e, 0xb3, 0xbb, 0x0e, 0xea, 0x8d, 0x47, 0xe0, 0xca, 0x63, + 0xc0, 0x53, 0xe4, 0xd8, 0x63, 0x4f, 0x16, 0x31, 0x2f, 0x82, 0x76, 0x93, 0x36, 0x21, 0x49, 0xd5, + 0x8a, 0xdb, 0xee, 0xcc, 0xfc, 0xdf, 0xfc, 0xf3, 0xa3, 0x57, 0xa3, 0x67, 0x12, 0x33, 0x4e, 0x46, + 0xf9, 0x00, 0x44, 0x0a, 0x0a, 0x24, 0x19, 0x43, 0x1a, 0x71, 0x41, 0xe6, 0x0d, 0x9a, 0x31, 0x12, + 0x72, 0x2e, 0x22, 0x96, 0x52, 0xc5, 0x78, 0x4a, 0xc6, 0x3d, 0x12, 0x43, 0x0a, 0x82, 0x2a, 0x88, + 0x70, 0x26, 0xb8, 0xe2, 0x76, 0x7b, 0x36, 0x8b, 0x69, 0xc6, 0xf0, 0xf2, 0x2c, 0x1e, 0xf7, 0xda, + 0x8f, 0x62, 0xa6, 0x86, 0xf9, 0x00, 0x87, 0x3c, 0x21, 0x31, 0x8f, 0x39, 0x31, 0x92, 0x41, 0xfe, + 0xc9, 0xfc, 0xcc, 0xc7, 0xbc, 0x66, 0xa8, 0xf6, 0x93, 0xc5, 0xda, 0x84, 0x86, 0x43, 0x96, 0x82, + 0x38, 0x27, 0xd9, 0x28, 0xd6, 0x05, 0x49, 0x12, 0x50, 0x74, 0x83, 0x81, 0x36, 0xb9, 0x49, 0x25, + 0xf2, 0x54, 0xb1, 0x04, 0xd6, 0x04, 0x4f, 0x6f, 0x13, 0xc8, 0x70, 0x08, 0x09, 0x5d, 0xd5, 0x75, + 0x7e, 0x59, 0xa8, 0xd6, 0x07, 0x2a, 0xc1, 0xfe, 0x88, 0x76, 0xb4, 0x9b, 0x88, 0x2a, 0xea, 0x58, + 0xfb, 0x56, 0xb7, 0x71, 0xf0, 0x18, 0x2f, 0x62, 0xb8, 0x86, 0xe2, 0x6c, 0x14, 0xeb, 0x82, 0xc4, + 0x7a, 0x1a, 0x8f, 0x7b, 0xf8, 0xfd, 0xe0, 0x33, 0x84, 0xea, 0x08, 0x14, 0xf5, 0xed, 0x49, 0xe1, + 0x55, 0xca, 0xc2, 0x43, 0x8b, 0x5a, 0x70, 0x4d, 0xb5, 0xdf, 0xa2, 0xaa, 0xcc, 0x20, 0x74, 0xb6, + 0x0c, 0xfd, 0x21, 0xbe, 0x39, 0x64, 0x6c, 0x2c, 0x1d, 0x67, 0x10, 0xfa, 0xf7, 0xe6, 0xc8, 0xaa, + 0xfe, 0x05, 0x06, 0xd0, 0xf9, 0x69, 0xa1, 0xba, 0x99, 0xe8, 0x33, 0xa9, 0xec, 0xd3, 0x35, 0xe3, + 0xf8, 0x6e, 0xc6, 0xb5, 0xda, 0xd8, 0x6e, 0xce, 0x77, 0xec, 0x5c, 0x55, 0x96, 0x4c, 0xbf, 0x41, + 0x35, 0xa6, 0x20, 0x91, 0xce, 0xd6, 0xfe, 0x76, 0xb7, 0x71, 0xf0, 0xe0, 0x56, 0xd7, 0xfe, 0xee, + 0x9c, 0x56, 0x3b, 0xd4, 0xba, 0x60, 0x26, 0xef, 0xfc, 0xd8, 0x9e, 0x7b, 0xd6, 0x77, 0xd8, 0xcf, + 0xd1, 0xde, 0x90, 0x9f, 0x45, 0x20, 0x0e, 0x23, 0x48, 0x15, 0x53, 0xe7, 0xc6, 0x79, 0xdd, 0xb7, + 0xcb, 0xc2, 0xdb, 0x7b, 0xf7, 0x4f, 0x27, 0x58, 0x99, 0xb4, 0xfb, 0xa8, 0x75, 0xa6, 0x41, 0xaf, + 0x73, 0x61, 0x36, 0x1f, 0x43, 0xc8, 0xd3, 0x48, 0x9a, 0x58, 0x6b, 0xbe, 0x53, 0x16, 0x5e, 0xab, + 0xbf, 0xa1, 0x1f, 0x6c, 0x54, 0xd9, 0x03, 0xd4, 0xa0, 0xe1, 0x97, 0x9c, 0x09, 0x38, 0x61, 0x09, + 0x38, 0xdb, 0x26, 0x40, 0x72, 0xb7, 0x00, 0x8f, 0x58, 0x28, 0xb8, 0x96, 0xf9, 0xf7, 0xcb, 0xc2, + 0x6b, 0xbc, 0x5c, 0x70, 0x82, 0x65, 0xa8, 0x7d, 0x8a, 0xea, 0x02, 0x52, 0xf8, 0x6a, 0x36, 0x54, + 0xff, 0x6f, 0xc3, 0x6e, 0x59, 0x78, 0xf5, 0xe0, 0x8a, 0x12, 0x2c, 0x80, 0xf6, 0x0b, 0xd4, 0x34, + 0x97, 0x9d, 0x08, 0x9a, 0x4a, 0xa6, 0x6f, 0x93, 0x4e, 0xcd, 0x64, 0xd1, 0x2a, 0x0b, 0xaf, 0xd9, + 0x5f, 0xe9, 0x05, 0x6b, 0xd3, 0x7e, 0x77, 0x32, 0x75, 0x2b, 0x17, 0x53, 0xb7, 0x72, 0x39, 0x75, + 0x2b, 0xdf, 0x4a, 0xd7, 0x9a, 0x94, 0xae, 0x75, 0x51, 0xba, 0xd6, 0x65, 0xe9, 0x5a, 0xbf, 0x4b, + 0xd7, 0xfa, 0xfe, 0xc7, 0xad, 0x7c, 0xd8, 0x1a, 0xf7, 0xfe, 0x06, 0x00, 0x00, 0xff, 0xff, 0x41, + 0x5e, 0x94, 0x96, 0x5e, 0x04, 0x00, 0x00, +} diff --git a/staging/src/k8s.io/api/coordination/v1/generated.proto b/staging/src/k8s.io/api/coordination/v1/generated.proto new file mode 100644 index 00000000000..99692e958d6 --- /dev/null +++ b/staging/src/k8s.io/api/coordination/v1/generated.proto @@ -0,0 +1,80 @@ +/* +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. +*/ + + +// This file was autogenerated by go-to-protobuf. Do not edit it manually! + +syntax = 'proto2'; + +package k8s.io.api.coordination.v1; + +import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; +import "k8s.io/apimachinery/pkg/runtime/generated.proto"; +import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; + +// Package-wide variables from generator "generated". +option go_package = "v1"; + +// Lease defines a lease concept. +message Lease { + // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata + // +optional + optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; + + // Specification of the Lease. + // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status + // +optional + optional LeaseSpec spec = 2; +} + +// LeaseList is a list of Lease objects. +message LeaseList { + // Standard list metadata. + // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata + // +optional + optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; + + // Items is a list of schema objects. + repeated Lease items = 2; +} + +// LeaseSpec is a specification of a Lease. +message LeaseSpec { + // holderIdentity contains the identity of the holder of a current lease. + // +optional + optional string holderIdentity = 1; + + // leaseDurationSeconds is a duration that candidates for a lease need + // to wait to force acquire it. This is measure against time of last + // observed RenewTime. + // +optional + optional int32 leaseDurationSeconds = 2; + + // acquireTime is a time when the current lease was acquired. + // +optional + optional k8s.io.apimachinery.pkg.apis.meta.v1.MicroTime acquireTime = 3; + + // renewTime is a time when the current holder of a lease has last + // updated the lease. + // +optional + optional k8s.io.apimachinery.pkg.apis.meta.v1.MicroTime renewTime = 4; + + // leaseTransitions is the number of transitions of a lease between + // holders. + // +optional + optional int32 leaseTransitions = 5; +} + diff --git a/staging/src/k8s.io/api/coordination/v1/register.go b/staging/src/k8s.io/api/coordination/v1/register.go new file mode 100644 index 00000000000..95b987b98b6 --- /dev/null +++ b/staging/src/k8s.io/api/coordination/v1/register.go @@ -0,0 +1,53 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" +) + +// GroupName is the group name use in this package +const GroupName = "coordination.k8s.io" + +// SchemeGroupVersion is group version used to register these objects +var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1"} + +// Resource takes an unqualified resource and returns a Group qualified GroupResource +func Resource(resource string) schema.GroupResource { + return SchemeGroupVersion.WithResource(resource).GroupResource() +} + +var ( + // TODO: move SchemeBuilder with zz_generated.deepcopy.go to k8s.io/api. + // localSchemeBuilder and AddToScheme will stay in k8s.io/kubernetes. + SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes) + localSchemeBuilder = &SchemeBuilder + AddToScheme = localSchemeBuilder.AddToScheme +) + +// Adds the list of known types to api.Scheme. +func addKnownTypes(scheme *runtime.Scheme) error { + scheme.AddKnownTypes(SchemeGroupVersion, + &Lease{}, + &LeaseList{}, + ) + + metav1.AddToGroupVersion(scheme, SchemeGroupVersion) + return nil +} diff --git a/staging/src/k8s.io/api/coordination/v1/types.go b/staging/src/k8s.io/api/coordination/v1/types.go new file mode 100644 index 00000000000..8f9f24d04eb --- /dev/null +++ b/staging/src/k8s.io/api/coordination/v1/types.go @@ -0,0 +1,74 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// +genclient +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// Lease defines a lease concept. +type Lease struct { + metav1.TypeMeta `json:",inline"` + // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata + // +optional + metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` + + // Specification of the Lease. + // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status + // +optional + Spec LeaseSpec `json:"spec,omitempty" protobuf:"bytes,2,opt,name=spec"` +} + +// LeaseSpec is a specification of a Lease. +type LeaseSpec struct { + // holderIdentity contains the identity of the holder of a current lease. + // +optional + HolderIdentity *string `json:"holderIdentity,omitempty" protobuf:"bytes,1,opt,name=holderIdentity"` + // leaseDurationSeconds is a duration that candidates for a lease need + // to wait to force acquire it. This is measure against time of last + // observed RenewTime. + // +optional + LeaseDurationSeconds *int32 `json:"leaseDurationSeconds,omitempty" protobuf:"varint,2,opt,name=leaseDurationSeconds"` + // acquireTime is a time when the current lease was acquired. + // +optional + AcquireTime *metav1.MicroTime `json:"acquireTime,omitempty" protobuf:"bytes,3,opt,name=acquireTime"` + // renewTime is a time when the current holder of a lease has last + // updated the lease. + // +optional + RenewTime *metav1.MicroTime `json:"renewTime,omitempty" protobuf:"bytes,4,opt,name=renewTime"` + // leaseTransitions is the number of transitions of a lease between + // holders. + // +optional + LeaseTransitions *int32 `json:"leaseTransitions,omitempty" protobuf:"varint,5,opt,name=leaseTransitions"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// LeaseList is a list of Lease objects. +type LeaseList struct { + metav1.TypeMeta `json:",inline"` + // Standard list metadata. + // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata + // +optional + metav1.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` + + // Items is a list of schema objects. + Items []Lease `json:"items" protobuf:"bytes,2,rep,name=items"` +} diff --git a/staging/src/k8s.io/api/coordination/v1/types_swagger_doc_generated.go b/staging/src/k8s.io/api/coordination/v1/types_swagger_doc_generated.go new file mode 100644 index 00000000000..bd02ad5daa6 --- /dev/null +++ b/staging/src/k8s.io/api/coordination/v1/types_swagger_doc_generated.go @@ -0,0 +1,63 @@ +/* +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. +*/ + +package v1 + +// This file contains a collection of methods that can be used from go-restful to +// generate Swagger API documentation for its models. Please read this PR for more +// information on the implementation: https://github.com/emicklei/go-restful/pull/215 +// +// TODOs are ignored from the parser (e.g. TODO(andronat):... || TODO:...) if and only if +// they are on one line! For multiple line or blocks that you want to ignore use ---. +// Any context after a --- is ignored. +// +// Those methods can be generated by using hack/update-generated-swagger-docs.sh + +// AUTO-GENERATED FUNCTIONS START HERE. DO NOT EDIT. +var map_Lease = map[string]string{ + "": "Lease defines a lease concept.", + "metadata": "More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", + "spec": "Specification of the Lease. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status", +} + +func (Lease) SwaggerDoc() map[string]string { + return map_Lease +} + +var map_LeaseList = map[string]string{ + "": "LeaseList is a list of Lease objects.", + "metadata": "Standard list metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", + "items": "Items is a list of schema objects.", +} + +func (LeaseList) SwaggerDoc() map[string]string { + return map_LeaseList +} + +var map_LeaseSpec = map[string]string{ + "": "LeaseSpec is a specification of a Lease.", + "holderIdentity": "holderIdentity contains the identity of the holder of a current lease.", + "leaseDurationSeconds": "leaseDurationSeconds is a duration that candidates for a lease need to wait to force acquire it. This is measure against time of last observed RenewTime.", + "acquireTime": "acquireTime is a time when the current lease was acquired.", + "renewTime": "renewTime is a time when the current holder of a lease has last updated the lease.", + "leaseTransitions": "leaseTransitions is the number of transitions of a lease between holders.", +} + +func (LeaseSpec) SwaggerDoc() map[string]string { + return map_LeaseSpec +} + +// AUTO-GENERATED FUNCTIONS END HERE diff --git a/staging/src/k8s.io/api/coordination/v1/zz_generated.deepcopy.go b/staging/src/k8s.io/api/coordination/v1/zz_generated.deepcopy.go new file mode 100644 index 00000000000..0f534055f65 --- /dev/null +++ b/staging/src/k8s.io/api/coordination/v1/zz_generated.deepcopy.go @@ -0,0 +1,124 @@ +// +build !ignore_autogenerated + +/* +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 deepcopy-gen. DO NOT EDIT. + +package v1 + +import ( + runtime "k8s.io/apimachinery/pkg/runtime" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Lease) DeepCopyInto(out *Lease) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Lease. +func (in *Lease) DeepCopy() *Lease { + if in == nil { + return nil + } + out := new(Lease) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *Lease) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *LeaseList) DeepCopyInto(out *LeaseList) { + *out = *in + out.TypeMeta = in.TypeMeta + out.ListMeta = in.ListMeta + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]Lease, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LeaseList. +func (in *LeaseList) DeepCopy() *LeaseList { + if in == nil { + return nil + } + out := new(LeaseList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *LeaseList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *LeaseSpec) DeepCopyInto(out *LeaseSpec) { + *out = *in + if in.HolderIdentity != nil { + in, out := &in.HolderIdentity, &out.HolderIdentity + *out = new(string) + **out = **in + } + if in.LeaseDurationSeconds != nil { + in, out := &in.LeaseDurationSeconds, &out.LeaseDurationSeconds + *out = new(int32) + **out = **in + } + if in.AcquireTime != nil { + in, out := &in.AcquireTime, &out.AcquireTime + *out = (*in).DeepCopy() + } + if in.RenewTime != nil { + in, out := &in.RenewTime, &out.RenewTime + *out = (*in).DeepCopy() + } + if in.LeaseTransitions != nil { + in, out := &in.LeaseTransitions, &out.LeaseTransitions + *out = new(int32) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LeaseSpec. +func (in *LeaseSpec) DeepCopy() *LeaseSpec { + if in == nil { + return nil + } + out := new(LeaseSpec) + in.DeepCopyInto(out) + return out +} diff --git a/staging/src/k8s.io/apiextensions-apiserver/Godeps/Godeps.json b/staging/src/k8s.io/apiextensions-apiserver/Godeps/Godeps.json index a2c48314a39..b0f4f493475 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/Godeps/Godeps.json +++ b/staging/src/k8s.io/apiextensions-apiserver/Godeps/Godeps.json @@ -608,11 +608,15 @@ }, { "ImportPath": "github.com/prometheus/client_golang/prometheus", - "Rev": "e7e903064f5e9eb5da98208bae10b475d4db0f8c" + "Rev": "abad2d1bd44235a26707c172eab6bca5bf2dbad3" + }, + { + "ImportPath": "github.com/prometheus/client_golang/prometheus/internal", + "Rev": "abad2d1bd44235a26707c172eab6bca5bf2dbad3" }, { "ImportPath": "github.com/prometheus/client_golang/prometheus/promhttp", - "Rev": "e7e903064f5e9eb5da98208bae10b475d4db0f8c" + "Rev": "abad2d1bd44235a26707c172eab6bca5bf2dbad3" }, { "ImportPath": "github.com/prometheus/client_model/go", @@ -1010,6 +1014,10 @@ "ImportPath": "k8s.io/api/certificates/v1beta1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/api/coordination/v1", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/api/coordination/v1beta1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" @@ -1782,6 +1790,10 @@ "ImportPath": "k8s.io/client-go/informers/coordination", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/client-go/informers/coordination/v1", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/client-go/informers/coordination/v1beta1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" @@ -1958,6 +1970,10 @@ "ImportPath": "k8s.io/client-go/kubernetes/typed/certificates/v1beta1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/client-go/kubernetes/typed/coordination/v1", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/client-go/kubernetes/typed/coordination/v1beta1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" @@ -2070,6 +2086,10 @@ "ImportPath": "k8s.io/client-go/listers/certificates/v1beta1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/client-go/listers/coordination/v1", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/client-go/listers/coordination/v1beta1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" diff --git a/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/validation/validation.go b/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/validation/validation.go index 4f16ccce878..4f3c27e66cc 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/validation/validation.go +++ b/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/validation/validation.go @@ -196,18 +196,8 @@ func ValidateCustomResourceDefinitionSpec(spec *apiextensions.CustomResourceDefi } allErrs = append(allErrs, ValidateCustomResourceDefinitionNames(&spec.Names, fldPath.Child("names"))...) - - if utilfeature.DefaultFeatureGate.Enabled(apiextensionsfeatures.CustomResourceValidation) { - allErrs = append(allErrs, ValidateCustomResourceDefinitionValidation(spec.Validation, hasAnyStatusEnabled(spec), fldPath.Child("validation"))...) - } else if spec.Validation != nil { - allErrs = append(allErrs, field.Forbidden(fldPath.Child("validation"), "disabled by feature-gate CustomResourceValidation")) - } - - if utilfeature.DefaultFeatureGate.Enabled(apiextensionsfeatures.CustomResourceSubresources) { - allErrs = append(allErrs, ValidateCustomResourceDefinitionSubresources(spec.Subresources, fldPath.Child("subresources"))...) - } else if spec.Subresources != nil { - allErrs = append(allErrs, field.Forbidden(fldPath.Child("subresources"), "disabled by feature-gate CustomResourceSubresources")) - } + allErrs = append(allErrs, ValidateCustomResourceDefinitionValidation(spec.Validation, hasAnyStatusEnabled(spec), fldPath.Child("validation"))...) + allErrs = append(allErrs, ValidateCustomResourceDefinitionSubresources(spec.Subresources, fldPath.Child("subresources"))...) for i := range spec.AdditionalPrinterColumns { if errs := ValidateCustomResourceColumnDefinition(&spec.AdditionalPrinterColumns[i], fldPath.Child("additionalPrinterColumns").Index(i)); len(errs) > 0 { @@ -481,7 +471,7 @@ func ValidateCustomResourceDefinitionValidation(customResourceValidation *apiext if schema := customResourceValidation.OpenAPIV3Schema; schema != nil { // if the status subresource is enabled, only certain fields are allowed inside the root schema. // these fields are chosen such that, if status is extracted as properties["status"], it's validation is not lost. - if utilfeature.DefaultFeatureGate.Enabled(apiextensionsfeatures.CustomResourceSubresources) && statusSubresourceEnabled { + if statusSubresourceEnabled { v := reflect.ValueOf(schema).Elem() for i := 0; i < v.NumField(); i++ { // skip zero values diff --git a/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/customresource_handler.go b/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/customresource_handler.go index 2ad59dfe937..264a794b364 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/customresource_handler.go +++ b/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/customresource_handler.go @@ -248,7 +248,7 @@ func (r *crdHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) { } if handler != nil { - handler = metrics.InstrumentHandlerFunc(verb, resource, subresource, scope, handler) + handler = metrics.InstrumentHandlerFunc(verb, requestInfo.APIGroup, requestInfo.APIVersion, resource, subresource, scope, metrics.APIServerComponent, handler) handler(w, req) return } diff --git a/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresourcedefinition/BUILD b/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresourcedefinition/BUILD index 153b889eacf..c51e800e1b4 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresourcedefinition/BUILD +++ b/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresourcedefinition/BUILD @@ -1,9 +1,6 @@ package(default_visibility = ["//visibility:public"]) -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) +load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") go_library( name = "go_default_library", @@ -47,3 +44,16 @@ filegroup( srcs = [":package-srcs"], tags = ["automanaged"], ) + +go_test( + name = "go_default_test", + srcs = ["strategy_test.go"], + embed = [":go_default_library"], + deps = [ + "//staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions:go_default_library", + "//staging/src/k8s.io/apiextensions-apiserver/pkg/features:go_default_library", + "//staging/src/k8s.io/apimachinery/pkg/util/diff:go_default_library", + "//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library", + "//staging/src/k8s.io/apiserver/pkg/util/feature/testing:go_default_library", + ], +) diff --git a/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresourcedefinition/strategy.go b/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresourcedefinition/strategy.go index ee3d8eaf042..0fbad281757 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresourcedefinition/strategy.go +++ b/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresourcedefinition/strategy.go @@ -54,32 +54,7 @@ func (strategy) PrepareForCreate(ctx context.Context, obj runtime.Object) { crd.Status = apiextensions.CustomResourceDefinitionStatus{} crd.Generation = 1 - // if the feature gate is disabled, drop the feature. - if !utilfeature.DefaultFeatureGate.Enabled(apiextensionsfeatures.CustomResourceValidation) { - crd.Spec.Validation = nil - for i := range crd.Spec.Versions { - crd.Spec.Versions[i].Schema = nil - } - } - if !utilfeature.DefaultFeatureGate.Enabled(apiextensionsfeatures.CustomResourceSubresources) { - crd.Spec.Subresources = nil - for i := range crd.Spec.Versions { - crd.Spec.Versions[i].Subresources = nil - } - } - // On CREATE, if the CustomResourceWebhookConversion feature gate is off, we auto-clear - // the per-version fields. This is to be consistent with the other built-in types, as the - // apiserver drops unknown fields. - if !utilfeature.DefaultFeatureGate.Enabled(apiextensionsfeatures.CustomResourceWebhookConversion) { - for i := range crd.Spec.Versions { - crd.Spec.Versions[i].Schema = nil - crd.Spec.Versions[i].Subresources = nil - crd.Spec.Versions[i].AdditionalPrinterColumns = nil - } - } - if !utilfeature.DefaultFeatureGate.Enabled(apiextensionsfeatures.CustomResourceWebhookConversion) && crd.Spec.Conversion != nil { - crd.Spec.Conversion.WebhookClientConfig = nil - } + dropDisabledFields(&crd.Spec, nil) for _, v := range crd.Spec.Versions { if v.Storage { @@ -109,45 +84,7 @@ func (strategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) { newCRD.Generation = oldCRD.Generation + 1 } - if !utilfeature.DefaultFeatureGate.Enabled(apiextensionsfeatures.CustomResourceValidation) { - newCRD.Spec.Validation = nil - oldCRD.Spec.Validation = nil - for i := range newCRD.Spec.Versions { - newCRD.Spec.Versions[i].Schema = nil - } - for i := range oldCRD.Spec.Versions { - oldCRD.Spec.Versions[i].Schema = nil - } - } - if !utilfeature.DefaultFeatureGate.Enabled(apiextensionsfeatures.CustomResourceSubresources) { - newCRD.Spec.Subresources = nil - oldCRD.Spec.Subresources = nil - for i := range newCRD.Spec.Versions { - newCRD.Spec.Versions[i].Subresources = nil - } - for i := range oldCRD.Spec.Versions { - oldCRD.Spec.Versions[i].Subresources = nil - } - } - - // On UPDATE, if the CustomResourceWebhookConversion feature gate is off, we auto-clear - // the per-version fields if the old CRD doesn't use per-version fields already. - // This is to be consistent with the other built-in types, as the apiserver drops unknown - // fields. If the old CRD already uses per-version fields, the CRD is allowed to continue - // use per-version fields. - if !utilfeature.DefaultFeatureGate.Enabled(apiextensionsfeatures.CustomResourceWebhookConversion) && - !hasPerVersionField(oldCRD.Spec.Versions) { - for i := range newCRD.Spec.Versions { - newCRD.Spec.Versions[i].Schema = nil - newCRD.Spec.Versions[i].Subresources = nil - newCRD.Spec.Versions[i].AdditionalPrinterColumns = nil - } - } - if !utilfeature.DefaultFeatureGate.Enabled(apiextensionsfeatures.CustomResourceWebhookConversion) && newCRD.Spec.Conversion != nil { - if oldCRD.Spec.Conversion == nil || newCRD.Spec.Conversion.WebhookClientConfig == nil { - newCRD.Spec.Conversion.WebhookClientConfig = nil - } - } + dropDisabledFields(&newCRD.Spec, &oldCRD.Spec) for _, v := range newCRD.Spec.Versions { if v.Storage { @@ -159,16 +96,6 @@ func (strategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) { } } -// hasPerVersionField returns true if a CRD uses per-version schema/subresources/columns fields. -func hasPerVersionField(versions []apiextensions.CustomResourceDefinitionVersion) bool { - for _, v := range versions { - if v.Schema != nil || v.Subresources != nil || len(v.AdditionalPrinterColumns) > 0 { - return true - } - } - return false -} - // Validate validates a new CustomResourceDefinition. func (strategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList { return validation.ValidateCustomResourceDefinition(obj.(*apiextensions.CustomResourceDefinition)) @@ -259,3 +186,102 @@ func MatchCustomResourceDefinition(label labels.Selector, field fields.Selector) func CustomResourceDefinitionToSelectableFields(obj *apiextensions.CustomResourceDefinition) fields.Set { return generic.ObjectMetaFieldsSet(&obj.ObjectMeta, true) } + +func dropDisabledFields(crdSpec, oldCrdSpec *apiextensions.CustomResourceDefinitionSpec) { + // if the feature gate is disabled, drop the feature. + if !utilfeature.DefaultFeatureGate.Enabled(apiextensionsfeatures.CustomResourceValidation) && + !validationInUse(oldCrdSpec) { + crdSpec.Validation = nil + for i := range crdSpec.Versions { + crdSpec.Versions[i].Schema = nil + } + } + if !utilfeature.DefaultFeatureGate.Enabled(apiextensionsfeatures.CustomResourceSubresources) && + !subresourceInUse(oldCrdSpec) { + crdSpec.Subresources = nil + for i := range crdSpec.Versions { + crdSpec.Versions[i].Subresources = nil + } + } + + // 1. On CREATE (in which case the old CRD spec is nil), if the CustomResourceWebhookConversion feature gate is off, we auto-clear + // the per-version fields. This is to be consistent with the other built-in types, as the + // apiserver drops unknown fields. + // 2. On UPDATE, if the CustomResourceWebhookConversion feature gate is off, we auto-clear + // the per-version fields if the old CRD doesn't use per-version fields already. + // This is to be consistent with the other built-in types, as the apiserver drops unknown + // fields. If the old CRD already uses per-version fields, the CRD is allowed to continue + // use per-version fields. + if !utilfeature.DefaultFeatureGate.Enabled(apiextensionsfeatures.CustomResourceWebhookConversion) && + !hasPerVersionField(oldCrdSpec) { + for i := range crdSpec.Versions { + crdSpec.Versions[i].Schema = nil + crdSpec.Versions[i].Subresources = nil + crdSpec.Versions[i].AdditionalPrinterColumns = nil + } + } + + if !utilfeature.DefaultFeatureGate.Enabled(apiextensionsfeatures.CustomResourceWebhookConversion) && + !conversionWebhookInUse(oldCrdSpec) { + if crdSpec.Conversion != nil { + crdSpec.Conversion.WebhookClientConfig = nil + } + } + +} + +func validationInUse(crdSpec *apiextensions.CustomResourceDefinitionSpec) bool { + if crdSpec == nil { + return false + } + if crdSpec.Validation != nil { + return true + } + + for i := range crdSpec.Versions { + if crdSpec.Versions[i].Schema != nil { + return true + } + } + return false +} + +func subresourceInUse(crdSpec *apiextensions.CustomResourceDefinitionSpec) bool { + if crdSpec == nil { + return false + } + if crdSpec.Subresources != nil { + return true + } + + for i := range crdSpec.Versions { + if crdSpec.Versions[i].Subresources != nil { + return true + } + } + return false +} + +// hasPerVersionField returns true if a CRD uses per-version schema/subresources/columns fields. +//func hasPerVersionField(versions []apiextensions.CustomResourceDefinitionVersion) bool { +func hasPerVersionField(crdSpec *apiextensions.CustomResourceDefinitionSpec) bool { + if crdSpec == nil { + return false + } + for _, v := range crdSpec.Versions { + if v.Schema != nil || v.Subresources != nil || len(v.AdditionalPrinterColumns) > 0 { + return true + } + } + return false +} + +func conversionWebhookInUse(crdSpec *apiextensions.CustomResourceDefinitionSpec) bool { + if crdSpec == nil { + return false + } + if crdSpec.Conversion == nil { + return false + } + return crdSpec.Conversion.WebhookClientConfig != nil +} diff --git a/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresourcedefinition/strategy_test.go b/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresourcedefinition/strategy_test.go new file mode 100644 index 00000000000..c67c94721e9 --- /dev/null +++ b/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresourcedefinition/strategy_test.go @@ -0,0 +1,472 @@ +/* +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 customresourcedefinition + +import ( + "fmt" + "reflect" + "testing" + + "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions" + apiextensionsfeatures "k8s.io/apiextensions-apiserver/pkg/features" + "k8s.io/apimachinery/pkg/util/diff" + utilfeature "k8s.io/apiserver/pkg/util/feature" + utilfeaturetesting "k8s.io/apiserver/pkg/util/feature/testing" +) + +func TestDropDisableFieldsCustomResourceDefinition(t *testing.T) { + t.Log("testing unversioned validation..") + for _, validationEnabled := range []bool{true, false} { + crdWithUnversionedValidation := func() *apiextensions.CustomResourceDefinition { + // crd with non-versioned validation + return &apiextensions.CustomResourceDefinition{ + Spec: apiextensions.CustomResourceDefinitionSpec{ + Validation: &apiextensions.CustomResourceValidation{ + OpenAPIV3Schema: &apiextensions.JSONSchemaProps{}, + }, + }, + } + } + crdWithoutUnversionedValidation := func() *apiextensions.CustomResourceDefinition { + // crd with non-versioned validation + return &apiextensions.CustomResourceDefinition{ + Spec: apiextensions.CustomResourceDefinitionSpec{}, + } + } + crdInfos := []struct { + name string + hasCRValidation bool + crd func() *apiextensions.CustomResourceDefinition + }{ + { + name: "has unversioned validation", + hasCRValidation: true, + crd: crdWithUnversionedValidation, + }, + { + name: "doesn't have unversioned validation", + hasCRValidation: false, + crd: crdWithoutUnversionedValidation, + }, + { + name: "nil", + hasCRValidation: false, + crd: func() *apiextensions.CustomResourceDefinition { return nil }, + }, + } + for _, oldCRDInfo := range crdInfos { + for _, newCRDInfo := range crdInfos { + oldCRDHasValidation, oldCRD := oldCRDInfo.hasCRValidation, oldCRDInfo.crd() + newCRDHasValidation, newCRD := newCRDInfo.hasCRValidation, newCRDInfo.crd() + if newCRD == nil { + continue + } + t.Run(fmt.Sprintf("validation feature enabled=%v, old CRD %v, new CRD %v", validationEnabled, oldCRDInfo.name, newCRDInfo.name), + func(t *testing.T) { + defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, apiextensionsfeatures.CustomResourceValidation, validationEnabled)() + var oldCRDSpec *apiextensions.CustomResourceDefinitionSpec + if oldCRD != nil { + oldCRDSpec = &oldCRD.Spec + } + dropDisabledFields(&newCRD.Spec, oldCRDSpec) + // old CRD should never be changed + if !reflect.DeepEqual(oldCRD, oldCRDInfo.crd()) { + t.Errorf("old crd changed: %v", diff.ObjectReflectDiff(oldCRD, oldCRDInfo.crd())) + } + switch { + case validationEnabled || oldCRDHasValidation: + if !reflect.DeepEqual(newCRD, newCRDInfo.crd()) { + t.Errorf("new crd changed: %v", diff.ObjectReflectDiff(newCRD, newCRDInfo.crd())) + } + case newCRDHasValidation: + if reflect.DeepEqual(newCRD, newCRDInfo.crd()) { + t.Errorf("new crd was not changed") + } + if !reflect.DeepEqual(newCRD, crdWithoutUnversionedValidation()) { + t.Errorf("new crd had unversioned validation: %v", diff.ObjectReflectDiff(newCRD, crdWithoutUnversionedValidation())) + } + default: + if !reflect.DeepEqual(newCRD, newCRDInfo.crd()) { + t.Errorf("new crd changed: %v", diff.ObjectReflectDiff(newCRD, newCRDInfo.crd())) + } + } + }, + ) + } + } + } + + t.Log("testing unversioned subresources...") + for _, validationEnabled := range []bool{true, false} { + crdWithUnversionedSubresources := func() *apiextensions.CustomResourceDefinition { + // crd with unversioned subresources + return &apiextensions.CustomResourceDefinition{ + Spec: apiextensions.CustomResourceDefinitionSpec{ + Subresources: &apiextensions.CustomResourceSubresources{}, + }, + } + } + crdWithoutUnversionedSubresources := func() *apiextensions.CustomResourceDefinition { + // crd without unversioned subresources + return &apiextensions.CustomResourceDefinition{ + Spec: apiextensions.CustomResourceDefinitionSpec{}, + } + } + crdInfos := []struct { + name string + hasCRSubresources bool + crd func() *apiextensions.CustomResourceDefinition + }{ + { + name: "has unversioned subresources", + hasCRSubresources: true, + crd: crdWithUnversionedSubresources, + }, + { + name: "doesn't have unversioned subresources", + hasCRSubresources: false, + crd: crdWithoutUnversionedSubresources, + }, + { + name: "nil", + hasCRSubresources: false, + crd: func() *apiextensions.CustomResourceDefinition { return nil }, + }, + } + for _, oldCRDInfo := range crdInfos { + for _, newCRDInfo := range crdInfos { + oldCRDHasSubresources, oldCRD := oldCRDInfo.hasCRSubresources, oldCRDInfo.crd() + newCRDHasSubresources, newCRD := newCRDInfo.hasCRSubresources, newCRDInfo.crd() + if newCRD == nil { + continue + } + t.Run(fmt.Sprintf("subresources feature enabled=%v, old CRD %v, new CRD %v", validationEnabled, oldCRDInfo.name, newCRDInfo.name), + func(t *testing.T) { + defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, apiextensionsfeatures.CustomResourceSubresources, validationEnabled)() + defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, apiextensionsfeatures.CustomResourceWebhookConversion, true)() + var oldCRDSpec *apiextensions.CustomResourceDefinitionSpec + if oldCRD != nil { + oldCRDSpec = &oldCRD.Spec + } + dropDisabledFields(&newCRD.Spec, oldCRDSpec) + // old CRD should never be changed + if !reflect.DeepEqual(oldCRD, oldCRDInfo.crd()) { + t.Errorf("old crd changed: %v", diff.ObjectReflectDiff(oldCRD, oldCRDInfo.crd())) + } + switch { + case validationEnabled || oldCRDHasSubresources: + if !reflect.DeepEqual(newCRD, newCRDInfo.crd()) { + t.Errorf("new crd changed: %v", diff.ObjectReflectDiff(newCRD, newCRDInfo.crd())) + } + case newCRDHasSubresources: + if reflect.DeepEqual(newCRD, newCRDInfo.crd()) { + t.Errorf("new crd was not changed") + } + if !reflect.DeepEqual(newCRD, crdWithoutUnversionedSubresources()) { + t.Errorf("new crd had unversioned subresources: %v", diff.ObjectReflectDiff(newCRD, crdWithoutUnversionedSubresources())) + } + default: + if !reflect.DeepEqual(newCRD, newCRDInfo.crd()) { + t.Errorf("new crd changed: %v", diff.ObjectReflectDiff(newCRD, newCRDInfo.crd())) + } + } + }, + ) + } + } + } + + t.Log("testing versioned validation..") + for _, conversionEnabled := range []bool{true, false} { + for _, validationEnabled := range []bool{true, false} { + crdWithVersionedValidation := func() *apiextensions.CustomResourceDefinition { + // crd with versioned validation + return &apiextensions.CustomResourceDefinition{ + Spec: apiextensions.CustomResourceDefinitionSpec{ + Versions: []apiextensions.CustomResourceDefinitionVersion{ + { + Name: "v1", + Schema: &apiextensions.CustomResourceValidation{ + OpenAPIV3Schema: &apiextensions.JSONSchemaProps{}, + }, + }, + }, + }, + } + } + crdWithoutVersionedValidation := func() *apiextensions.CustomResourceDefinition { + // crd with versioned validation + return &apiextensions.CustomResourceDefinition{ + Spec: apiextensions.CustomResourceDefinitionSpec{ + Versions: []apiextensions.CustomResourceDefinitionVersion{ + { + Name: "v1", + }, + }, + }, + } + } + crdInfos := []struct { + name string + hasCRValidation bool + crd func() *apiextensions.CustomResourceDefinition + }{ + { + name: "has versioned validation", + hasCRValidation: true, + crd: crdWithVersionedValidation, + }, + { + name: "doesn't have versioned validation", + hasCRValidation: false, + crd: crdWithoutVersionedValidation, + }, + { + name: "nil", + hasCRValidation: false, + crd: func() *apiextensions.CustomResourceDefinition { return nil }, + }, + } + for _, oldCRDInfo := range crdInfos { + for _, newCRDInfo := range crdInfos { + oldCRDHasValidation, oldCRD := oldCRDInfo.hasCRValidation, oldCRDInfo.crd() + newCRDHasValidation, newCRD := newCRDInfo.hasCRValidation, newCRDInfo.crd() + if newCRD == nil { + continue + } + t.Run(fmt.Sprintf("validation feature enabled=%v, old CRD %v, new CRD %v", validationEnabled, oldCRDInfo.name, newCRDInfo.name), + func(t *testing.T) { + defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, apiextensionsfeatures.CustomResourceValidation, validationEnabled)() + defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, apiextensionsfeatures.CustomResourceWebhookConversion, conversionEnabled)() + var oldCRDSpec *apiextensions.CustomResourceDefinitionSpec + if oldCRD != nil { + oldCRDSpec = &oldCRD.Spec + } + dropDisabledFields(&newCRD.Spec, oldCRDSpec) + // old CRD should never be changed + if !reflect.DeepEqual(oldCRD, oldCRDInfo.crd()) { + t.Errorf("old crd changed: %v", diff.ObjectReflectDiff(oldCRD, oldCRDInfo.crd())) + } + switch { + case (conversionEnabled && validationEnabled) || oldCRDHasValidation: + if !reflect.DeepEqual(newCRD, newCRDInfo.crd()) { + t.Errorf("new crd changed: %v", diff.ObjectReflectDiff(newCRD, newCRDInfo.crd())) + } + case !conversionEnabled && !oldCRDHasValidation: + if !reflect.DeepEqual(newCRD, crdWithoutVersionedValidation()) { + t.Errorf("new crd was not changed") + } + case newCRDHasValidation: + if reflect.DeepEqual(newCRD, newCRDInfo.crd()) { + t.Errorf("new crd was not changed") + } + if !reflect.DeepEqual(newCRD, crdWithoutVersionedValidation()) { + t.Errorf("new crd had unversioned validation: %v", diff.ObjectReflectDiff(newCRD, crdWithoutVersionedValidation())) + } + default: + if !reflect.DeepEqual(newCRD, newCRDInfo.crd()) { + t.Errorf("new crd changed: %v", diff.ObjectReflectDiff(newCRD, newCRDInfo.crd())) + } + } + }, + ) + } + } + } + } + + t.Log("testing versioned subresources w/ conversion enabled..") + for _, conversionEnabled := range []bool{true, false} { + for _, validationEnabled := range []bool{true, false} { + crdWithVersionedSubresources := func() *apiextensions.CustomResourceDefinition { + // crd with versioned subresources + return &apiextensions.CustomResourceDefinition{ + Spec: apiextensions.CustomResourceDefinitionSpec{ + Versions: []apiextensions.CustomResourceDefinitionVersion{ + { + Name: "v1", + Subresources: &apiextensions.CustomResourceSubresources{}, + }, + }, + }, + } + } + crdWithoutVersionedSubresources := func() *apiextensions.CustomResourceDefinition { + // crd without versioned subresources + return &apiextensions.CustomResourceDefinition{ + Spec: apiextensions.CustomResourceDefinitionSpec{ + Versions: []apiextensions.CustomResourceDefinitionVersion{ + { + Name: "v1", + }, + }, + }, + } + } + crdInfos := []struct { + name string + hasCRSubresources bool + crd func() *apiextensions.CustomResourceDefinition + }{ + { + name: "has versioned subresources", + hasCRSubresources: true, + crd: crdWithVersionedSubresources, + }, + { + name: "doesn't have versioned subresources", + hasCRSubresources: false, + crd: crdWithoutVersionedSubresources, + }, + { + name: "nil", + hasCRSubresources: false, + crd: func() *apiextensions.CustomResourceDefinition { return nil }, + }, + } + for _, oldCRDInfo := range crdInfos { + for _, newCRDInfo := range crdInfos { + oldCRDHasSubresources, oldCRD := oldCRDInfo.hasCRSubresources, oldCRDInfo.crd() + newCRDHasSubresources, newCRD := newCRDInfo.hasCRSubresources, newCRDInfo.crd() + if newCRD == nil { + continue + } + t.Run(fmt.Sprintf("subresources feature enabled=%v, old CRD %v, new CRD %v", validationEnabled, oldCRDInfo.name, newCRDInfo.name), + func(t *testing.T) { + defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, apiextensionsfeatures.CustomResourceSubresources, validationEnabled)() + defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, apiextensionsfeatures.CustomResourceWebhookConversion, conversionEnabled)() + var oldCRDSpec *apiextensions.CustomResourceDefinitionSpec + if oldCRD != nil { + oldCRDSpec = &oldCRD.Spec + } + dropDisabledFields(&newCRD.Spec, oldCRDSpec) + // old CRD should never be changed + if !reflect.DeepEqual(oldCRD, oldCRDInfo.crd()) { + t.Errorf("old crd changed: %v", diff.ObjectReflectDiff(oldCRD, oldCRDInfo.crd())) + } + switch { + case (conversionEnabled && validationEnabled) || oldCRDHasSubresources: + if !reflect.DeepEqual(newCRD, newCRDInfo.crd()) { + t.Errorf("new crd changed: %v", diff.ObjectReflectDiff(newCRD, newCRDInfo.crd())) + } + case !conversionEnabled && !oldCRDHasSubresources: + if !reflect.DeepEqual(newCRD, crdWithoutVersionedSubresources()) { + t.Errorf("new crd was not changed") + } + case newCRDHasSubresources: + if reflect.DeepEqual(newCRD, newCRDInfo.crd()) { + t.Errorf("new crd was not changed") + } + if !reflect.DeepEqual(newCRD, crdWithoutVersionedSubresources()) { + t.Errorf("new crd had versioned subresources: %v", diff.ObjectReflectDiff(newCRD, crdWithoutVersionedSubresources())) + } + default: + if !reflect.DeepEqual(newCRD, newCRDInfo.crd()) { + t.Errorf("new crd changed: %v", diff.ObjectReflectDiff(newCRD, newCRDInfo.crd())) + } + } + }, + ) + } + } + } + } + + t.Log("testing conversion webhook..") + for _, validationEnabled := range []bool{true, false} { + crdWithUnversionedConversionWebhook := func() *apiextensions.CustomResourceDefinition { + // crd with conversion webhook + return &apiextensions.CustomResourceDefinition{ + Spec: apiextensions.CustomResourceDefinitionSpec{ + Conversion: &apiextensions.CustomResourceConversion{ + WebhookClientConfig: &apiextensions.WebhookClientConfig{}, + }, + }, + } + } + crdWithoutUnversionedConversionWebhook := func() *apiextensions.CustomResourceDefinition { + // crd with conversion webhook + return &apiextensions.CustomResourceDefinition{ + Spec: apiextensions.CustomResourceDefinitionSpec{ + Conversion: &apiextensions.CustomResourceConversion{}, + }, + } + } + crdInfos := []struct { + name string + hasCRConversionWebhook bool + crd func() *apiextensions.CustomResourceDefinition + }{ + { + name: "has conversion webhook", + hasCRConversionWebhook: true, + crd: crdWithUnversionedConversionWebhook, + }, + { + name: "doesn't have conversion webhook", + hasCRConversionWebhook: false, + crd: crdWithoutUnversionedConversionWebhook, + }, + { + name: "nil", + hasCRConversionWebhook: false, + crd: func() *apiextensions.CustomResourceDefinition { return nil }, + }, + } + for _, oldCRDInfo := range crdInfos { + for _, newCRDInfo := range crdInfos { + oldCRDHasConversionWebhook, oldCRD := oldCRDInfo.hasCRConversionWebhook, oldCRDInfo.crd() + newCRDHasConversionWebhook, newCRD := newCRDInfo.hasCRConversionWebhook, newCRDInfo.crd() + if newCRD == nil { + continue + } + t.Run(fmt.Sprintf("subresources feature enabled=%v, old CRD %v, new CRD %v", validationEnabled, oldCRDInfo.name, newCRDInfo.name), + func(t *testing.T) { + defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, apiextensionsfeatures.CustomResourceWebhookConversion, validationEnabled)() + var oldCRDSpec *apiextensions.CustomResourceDefinitionSpec + if oldCRD != nil { + oldCRDSpec = &oldCRD.Spec + } + dropDisabledFields(&newCRD.Spec, oldCRDSpec) + // old CRD should never be changed + if !reflect.DeepEqual(oldCRD, oldCRDInfo.crd()) { + t.Errorf("old crd changed: %v", diff.ObjectReflectDiff(oldCRD, oldCRDInfo.crd())) + } + switch { + case validationEnabled || oldCRDHasConversionWebhook: + if !reflect.DeepEqual(newCRD, newCRDInfo.crd()) { + t.Errorf("new crd changed: %v", diff.ObjectReflectDiff(newCRD, newCRDInfo.crd())) + } + case newCRDHasConversionWebhook: + if reflect.DeepEqual(newCRD, newCRDInfo.crd()) { + t.Errorf("new crd was not changed") + } + if !reflect.DeepEqual(newCRD, crdWithoutUnversionedConversionWebhook()) { + t.Errorf("new crd had webhook conversion: %v", diff.ObjectReflectDiff(newCRD, crdWithoutUnversionedConversionWebhook())) + } + default: + if !reflect.DeepEqual(newCRD, newCRDInfo.crd()) { + t.Errorf("new crd changed: %v", diff.ObjectReflectDiff(newCRD, newCRDInfo.crd())) + } + } + }, + ) + } + } + } + +} diff --git a/staging/src/k8s.io/apiextensions-apiserver/test/integration/objectmeta_test.go b/staging/src/k8s.io/apiextensions-apiserver/test/integration/objectmeta_test.go index 1ce637aa702..123543be8db 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/test/integration/objectmeta_test.go +++ b/staging/src/k8s.io/apiextensions-apiserver/test/integration/objectmeta_test.go @@ -110,16 +110,16 @@ func TestInvalidObjectMetaInStorage(t *testing.T) { t.Fatal(err) } tlsInfo := transport.TLSInfo{ - CertFile: restOptions.StorageConfig.CertFile, - KeyFile: restOptions.StorageConfig.KeyFile, - CAFile: restOptions.StorageConfig.CAFile, + CertFile: restOptions.StorageConfig.Transport.CertFile, + KeyFile: restOptions.StorageConfig.Transport.KeyFile, + CAFile: restOptions.StorageConfig.Transport.CAFile, } tlsConfig, err := tlsInfo.ClientConfig() if err != nil { t.Fatal(err) } etcdConfig := clientv3.Config{ - Endpoints: restOptions.StorageConfig.ServerList, + Endpoints: restOptions.StorageConfig.Transport.ServerList, TLS: tlsConfig, } etcdclient, err := clientv3.New(etcdConfig) diff --git a/staging/src/k8s.io/apimachinery/OWNERS b/staging/src/k8s.io/apimachinery/OWNERS index 3449af97672..028d1e50016 100644 --- a/staging/src/k8s.io/apimachinery/OWNERS +++ b/staging/src/k8s.io/apimachinery/OWNERS @@ -13,6 +13,7 @@ reviewers: - deads2k - derekwaynecarr - caesarxuchao +- cheftako - mikedanese - liggitt - gmarek diff --git a/staging/src/k8s.io/apimachinery/pkg/api/meta/help.go b/staging/src/k8s.io/apimachinery/pkg/api/meta/help.go index c70b3d2b6c7..3425055f6ec 100644 --- a/staging/src/k8s.io/apimachinery/pkg/api/meta/help.go +++ b/staging/src/k8s.io/apimachinery/pkg/api/meta/help.go @@ -158,6 +158,19 @@ func ExtractList(obj runtime.Object) ([]runtime.Object, error) { // objectSliceType is the type of a slice of Objects var objectSliceType = reflect.TypeOf([]runtime.Object{}) +// LenList returns the length of this list or 0 if it is not a list. +func LenList(list runtime.Object) int { + itemsPtr, err := GetItemsPtr(list) + if err != nil { + return 0 + } + items, err := conversion.EnforcePtr(itemsPtr) + if err != nil { + return 0 + } + return items.Len() +} + // SetList sets the given list object's Items member have the elements given in // objects. // Returns an error if list is not a List type (does not have an Items member), diff --git a/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/duration.go b/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/duration.go index 2eaabf0794f..babe8a8b53b 100644 --- a/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/duration.go +++ b/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/duration.go @@ -48,3 +48,13 @@ func (d *Duration) UnmarshalJSON(b []byte) error { func (d Duration) MarshalJSON() ([]byte, error) { return json.Marshal(d.Duration.String()) } + +// OpenAPISchemaType is used by the kube-openapi generator when constructing +// the OpenAPI spec of this type. +// +// See: https://github.com/kubernetes/kube-openapi/tree/master/pkg/generators +func (_ Duration) OpenAPISchemaType() []string { return []string{"string"} } + +// OpenAPISchemaFormat is used by the kube-openapi generator when constructing +// the OpenAPI spec of this type. +func (_ Duration) OpenAPISchemaFormat() string { return "" } diff --git a/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/group_version_test.go b/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/group_version_test.go index 5250e33cba6..d0b1bc2ac4c 100644 --- a/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/group_version_test.go +++ b/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/group_version_test.go @@ -34,7 +34,7 @@ func TestGroupVersionUnmarshalJSON(t *testing.T) { expect GroupVersion }{ {[]byte(`{"val": "v1"}`), GroupVersion{"", "v1"}}, - {[]byte(`{"val": "extensions/v1beta1"}`), GroupVersion{"extensions", "v1beta1"}}, + {[]byte(`{"val": "apps/v1"}`), GroupVersion{"apps", "v1"}}, } for _, c := range cases { @@ -63,7 +63,7 @@ func TestGroupVersionMarshalJSON(t *testing.T) { expect []byte }{ {GroupVersion{"", "v1"}, []byte(`{"val":"v1"}`)}, - {GroupVersion{"extensions", "v1beta1"}, []byte(`{"val":"extensions/v1beta1"}`)}, + {GroupVersion{"apps", "v1"}, []byte(`{"val":"apps/v1"}`)}, } for _, c := range cases { diff --git a/staging/src/k8s.io/apimachinery/pkg/apply/strategy/merge_conflict_test.go b/staging/src/k8s.io/apimachinery/pkg/apply/strategy/merge_conflict_test.go index ecde484eb28..d1d2aa4c5b9 100644 --- a/staging/src/k8s.io/apimachinery/pkg/apply/strategy/merge_conflict_test.go +++ b/staging/src/k8s.io/apimachinery/pkg/apply/strategy/merge_conflict_test.go @@ -26,19 +26,19 @@ var _ = Describe("Comparing fields of remote and recorded ", func() { Context("Test conflict in map fields of remote and recorded", func() { It("If conflicts found, expected return error", func() { recorded := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: foo1: "key1" `) local := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: foo2: "baz2-1" `) remote := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: foo1: "baz1-0" @@ -53,7 +53,7 @@ spec: Context("Test conflict in list fields of remote and recorded ", func() { It("If conflicts found, expected return false", func() { recorded := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment metadata: finalizers: @@ -62,7 +62,7 @@ metadata: - "d" `) local := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment metadata: finalizers: @@ -70,7 +70,7 @@ metadata: - "b" `) remote := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment metadata: finalizers: @@ -87,7 +87,7 @@ metadata: Context("Test conflict in Map-List fields of remote and recorded ", func() { It("should leave the item", func() { recorded := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: template: @@ -97,7 +97,7 @@ spec: image: image1 `) local := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: template: @@ -107,7 +107,7 @@ spec: image: image2 `) remote := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: template: @@ -125,21 +125,21 @@ spec: Context("Test conflicts in nested map field", func() { It("If conflicts found, expected return error", func() { recorded := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: foo1: name: "key1" `) local := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: foo1: name: "baz1-0" `) remote := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: foo1: @@ -154,7 +154,7 @@ spec: Context("Test conflicts in complicated map, list", func() { It("Should catch conflict in key-value in map element", func() { recorded := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: template: @@ -170,7 +170,7 @@ spec: hostPort: 2022 `) local := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: template: @@ -183,7 +183,7 @@ spec: hostPort: 2020 `) remote := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: template: diff --git a/staging/src/k8s.io/apimachinery/pkg/apply/strategy/merge_map_list_test.go b/staging/src/k8s.io/apimachinery/pkg/apply/strategy/merge_map_list_test.go index a4c0da96531..1f0fdfabef8 100644 --- a/staging/src/k8s.io/apimachinery/pkg/apply/strategy/merge_map_list_test.go +++ b/staging/src/k8s.io/apimachinery/pkg/apply/strategy/merge_map_list_test.go @@ -29,7 +29,7 @@ var _ = Describe("Merging fields of type list-of-map with openapi", func() { Context("where one of the items has been deleted resulting in the containers being empty", func() { It("should set the containers field to null", func() { recorded := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: template: @@ -39,7 +39,7 @@ spec: image: image `) local := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: template: @@ -47,7 +47,7 @@ spec: containers: `) remote := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: template: @@ -59,7 +59,7 @@ spec: image: image2 `) expected := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: template: @@ -72,7 +72,7 @@ spec: Context("where one of the items has been deleted", func() { It("should be deleted from the result", func() { recorded := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: template: @@ -84,7 +84,7 @@ spec: image: image-delete `) local := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: template: @@ -94,7 +94,7 @@ spec: image: image-keep `) remote := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: template: @@ -106,7 +106,7 @@ spec: image: image-delete `) expected := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: template: @@ -123,7 +123,7 @@ spec: Context("where one of the items is only in the remote", func() { It("should leave the item", func() { recorded := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: template: @@ -133,7 +133,7 @@ spec: image: image2 `) local := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: template: @@ -143,7 +143,7 @@ spec: image: image2 `) remote := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: template: @@ -153,7 +153,7 @@ spec: image: image `) expected := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: template: @@ -171,7 +171,7 @@ spec: Context("where one of the items differs from the remote value and is missing from the recorded", func() { It("should update the item", func() { recorded := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: template: @@ -179,7 +179,7 @@ spec: containers: `) local := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: template: @@ -189,7 +189,7 @@ spec: image: image:2 `) remote := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: template: @@ -199,7 +199,7 @@ spec: image: image:1 `) expected := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: template: @@ -215,7 +215,7 @@ spec: Context("where one of the items differs from the remote value but matches the recorded", func() { It("should update the item", func() { recorded := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: template: @@ -225,7 +225,7 @@ spec: image: image:2 `) local := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: template: @@ -235,7 +235,7 @@ spec: image: image:2 `) remote := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: template: @@ -245,7 +245,7 @@ spec: image: image:1 `) expected := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: template: @@ -261,7 +261,7 @@ spec: Context("where one of the items is missing from the remote but matches the recorded", func() { It("should add the item", func() { recorded := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: template: @@ -271,7 +271,7 @@ spec: image: image:2 `) local := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: template: @@ -281,7 +281,7 @@ spec: image: image:2 `) remote := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: template: @@ -289,7 +289,7 @@ spec: containers: `) expected := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: template: @@ -305,7 +305,7 @@ spec: Context("where one of the items is missing from the remote and missing from the recorded ", func() { It("should add the item", func() { recorded := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: template: @@ -314,7 +314,7 @@ spec: `) local := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: template: @@ -324,7 +324,7 @@ spec: image: image:2 `) remote := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: template: @@ -332,7 +332,7 @@ spec: containers: `) expected := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: template: @@ -348,7 +348,7 @@ spec: Context("where the order of the resolved, local and remote lists differs", func() { It("should keep the order specified in local and append items appears only in remote", func() { recorded := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: template: @@ -365,7 +365,7 @@ spec: timeoutSeconds: 4 `) local := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: template: @@ -385,7 +385,7 @@ spec: initialDelaySeconds: 18 `) remote := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: template: @@ -405,7 +405,7 @@ spec: imagePullPolicy: Always `) expected := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: template: @@ -448,7 +448,7 @@ var _ = Describe("Merging fields of type list-of-map with openapi containing a m Context("where one of the items has been deleted", func() { It("should delete the item", func() { recorded := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: template: @@ -464,7 +464,7 @@ spec: hostPort: 2022 `) local := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: template: @@ -477,7 +477,7 @@ spec: hostPort: 2020 `) remote := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: template: @@ -494,7 +494,7 @@ spec: hostIP: "127.0.0.1" `) expected := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: template: @@ -513,7 +513,7 @@ spec: Context("where one of the items has been updated", func() { It("should merge updates to the item", func() { recorded := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: template: @@ -529,7 +529,7 @@ spec: hostPort: 2021 `) local := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: template: @@ -545,7 +545,7 @@ spec: hostPort: 2022 `) remote := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: template: @@ -562,7 +562,7 @@ spec: hostIP: "127.0.0.1" `) expected := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: template: @@ -585,7 +585,7 @@ spec: Context("where one of the items has been added", func() { It("should add the item", func() { recorded := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: template: @@ -598,7 +598,7 @@ spec: hostPort: 2020 `) local := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: template: @@ -614,7 +614,7 @@ spec: hostPort: 2022 `) remote := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: template: @@ -628,7 +628,7 @@ spec: hostIP: "127.0.0.1" `) expected := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: template: diff --git a/staging/src/k8s.io/apimachinery/pkg/apply/strategy/merge_map_test.go b/staging/src/k8s.io/apimachinery/pkg/apply/strategy/merge_map_test.go index 6b6a5d5a33a..146500f25c4 100644 --- a/staging/src/k8s.io/apimachinery/pkg/apply/strategy/merge_map_test.go +++ b/staging/src/k8s.io/apimachinery/pkg/apply/strategy/merge_map_test.go @@ -26,7 +26,7 @@ var _ = Describe("Merging fields of type map with openapi for some fields", func Context("where a field has been deleted", func() { It("should delete the field", func() { recorded := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: replicas: 3 @@ -35,14 +35,14 @@ spec: image: "1" `) local := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: replicas: 3 foo2: null `) remote := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: replicas: 3 @@ -57,7 +57,7 @@ spec: image: "3" `) expected := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: replicas: 3 @@ -72,7 +72,7 @@ spec: Context("where a field is has been added", func() { It("should add the field", func() { recorded := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: foo1: @@ -80,7 +80,7 @@ spec: image: "1" `) local := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: replicas: 3 @@ -92,12 +92,12 @@ spec: image: "2" `) remote := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: `) expected := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: replicas: 3 @@ -115,7 +115,7 @@ spec: Context("where a field is has been updated", func() { It("should update the field", func() { recorded := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: foo1: @@ -123,7 +123,7 @@ spec: image: "1-1" `) local := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: replicas: 3 @@ -135,7 +135,7 @@ spec: image: "2-1" `) remote := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: replicas: 2 @@ -147,7 +147,7 @@ spec: image: "2-0" `) expected := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: replicas: 3 diff --git a/staging/src/k8s.io/apimachinery/pkg/apply/strategy/merge_primitive_list_test.go b/staging/src/k8s.io/apimachinery/pkg/apply/strategy/merge_primitive_list_test.go index 7f3383ae264..59c35348834 100644 --- a/staging/src/k8s.io/apimachinery/pkg/apply/strategy/merge_primitive_list_test.go +++ b/staging/src/k8s.io/apimachinery/pkg/apply/strategy/merge_primitive_list_test.go @@ -26,7 +26,7 @@ var _ = Describe("Merging fields of type list-of-primitive with openapi", func() Context("where one of the items has been deleted", func() { It("should delete the deleted item", func() { recorded := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment metadata: finalizers: @@ -35,7 +35,7 @@ metadata: - "c" `) local := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment metadata: finalizers: @@ -43,7 +43,7 @@ metadata: - "c" `) remote := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment metadata: finalizers: @@ -52,7 +52,7 @@ metadata: - "c" `) expected := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment metadata: finalizers: @@ -66,7 +66,7 @@ metadata: Context("where one of the items is only on the remote", func() { It("should move the remote-only item to the end but keep it", func() { recorded := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment metadata: finalizers: @@ -74,7 +74,7 @@ metadata: - "b" `) local := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment metadata: finalizers: @@ -82,7 +82,7 @@ metadata: - "b" `) remote := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment metadata: finalizers: @@ -91,7 +91,7 @@ metadata: - "a" `) expected := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment metadata: finalizers: @@ -106,7 +106,7 @@ metadata: Context("where one of the items is repeated", func() { It("should de-duplicate the repeated items", func() { recorded := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment metadata: finalizers: @@ -114,7 +114,7 @@ metadata: - "b" `) local := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment metadata: finalizers: @@ -123,7 +123,7 @@ metadata: - "a" `) remote := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment metadata: finalizers: @@ -131,7 +131,7 @@ metadata: - "b" `) expected := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment metadata: finalizers: @@ -145,7 +145,7 @@ metadata: Context("where some items are deleted and others are on remote only", func() { It("should retain the correct items in the correct order", func() { recorded := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment metadata: finalizers: @@ -154,7 +154,7 @@ metadata: - "c" `) local := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment metadata: finalizers: @@ -163,7 +163,7 @@ metadata: - "a" `) remote := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment metadata: finalizers: @@ -174,7 +174,7 @@ metadata: - "e" `) expected := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment metadata: finalizers: diff --git a/staging/src/k8s.io/apimachinery/pkg/apply/strategy/merge_primitive_test.go b/staging/src/k8s.io/apimachinery/pkg/apply/strategy/merge_primitive_test.go index 51e7a7dedb1..a6c4ab50459 100644 --- a/staging/src/k8s.io/apimachinery/pkg/apply/strategy/merge_primitive_test.go +++ b/staging/src/k8s.io/apimachinery/pkg/apply/strategy/merge_primitive_test.go @@ -26,7 +26,7 @@ var _ = Describe("Merging fields of type map with openapi", func() { Context("where a field has been deleted", func() { It("should delete the field when it is the only field in the map", func() { recorded := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: # delete - recorded/remote match @@ -35,14 +35,14 @@ spec: progressDeadlineSeconds: 1 `) local := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: # delete - not present in recorded replicas: null `) remote := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: replicas: 3 @@ -51,7 +51,7 @@ spec: `) expected := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: `) @@ -60,7 +60,7 @@ spec: It("should delete the field when there are other fields in the map", func() { recorded := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: # delete - recorded/remote match @@ -69,7 +69,7 @@ spec: progressDeadlineSeconds: 1 `) local := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: # delete - not present in recorded @@ -78,7 +78,7 @@ spec: revisionHistoryLimit: 1 `) remote := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: replicas: 3 @@ -88,7 +88,7 @@ spec: `) expected := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: revisionHistoryLimit: 1 @@ -100,14 +100,14 @@ spec: Context("where a field is has been added", func() { It("should add the field", func() { recorded := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: paused: true progressDeadlineSeconds: 1 `) local := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: # Add this - it is missing from recorded and remote @@ -118,12 +118,12 @@ spec: progressDeadlineSeconds: 2 `) remote := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: `) expected := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: replicas: 3 @@ -137,14 +137,14 @@ spec: Context("where a field is has been updated", func() { It("should add the field", func() { recorded := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: paused: true progressDeadlineSeconds: 1 `) local := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: # Missing from recorded @@ -155,7 +155,7 @@ spec: progressDeadlineSeconds: 2 `) remote := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: replicas: 2 @@ -163,7 +163,7 @@ spec: progressDeadlineSeconds: 3 `) expected := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: replicas: 3 @@ -175,26 +175,26 @@ spec: It("should update the field", func() { recorded := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: replicas: 2 `) local := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: replicas: 3 `) remote := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: replicas: 2 `) expected := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: replicas: 3 @@ -208,7 +208,7 @@ var _ = Describe("Merging fields of type map without openapi", func() { Context("where a field has been deleted", func() { It("should delete the field when it is the only field in the map", func() { recorded := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Foo spec: # delete - recorded/remote match @@ -217,14 +217,14 @@ spec: progressDeadlineSeconds: 1 `) local := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Foo spec: # delete - not present in recorded replicas: null `) remote := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Foo spec: replicas: 3 @@ -233,7 +233,7 @@ spec: `) expected := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Foo spec: `) @@ -242,7 +242,7 @@ spec: It("should delete the field when there are other fields in the map", func() { recorded := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Foo spec: # delete - recorded/remote match @@ -251,7 +251,7 @@ spec: progressDeadlineSeconds: 1 `) local := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Foo spec: # delete - not present in recorded @@ -260,7 +260,7 @@ spec: revisionHistoryLimit: 1 `) remote := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Foo spec: replicas: 3 @@ -270,7 +270,7 @@ spec: `) expected := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Foo spec: revisionHistoryLimit: 1 @@ -282,14 +282,14 @@ spec: Context("where a field is has been added", func() { It("should add the field", func() { recorded := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Foo spec: paused: true progressDeadlineSeconds: 1 `) local := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Foo spec: # Add this - it is missing from recorded and remote @@ -300,12 +300,12 @@ spec: progressDeadlineSeconds: 2 `) remote := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Foo spec: `) expected := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Foo spec: replicas: 3 @@ -319,14 +319,14 @@ spec: Context("where a field is has been updated", func() { It("should add the field", func() { recorded := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Foo spec: paused: true progressDeadlineSeconds: 1 `) local := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Foo spec: # Matches recorded @@ -337,7 +337,7 @@ spec: progressDeadlineSeconds: 2 `) remote := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Foo spec: replicas: 2 @@ -345,7 +345,7 @@ spec: progressDeadlineSeconds: 3 `) expected := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Foo spec: replicas: 3 @@ -357,26 +357,26 @@ spec: It("should update the field", func() { recorded := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Foo spec: replicas: 2 `) local := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Foo spec: replicas: 3 `) remote := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Foo spec: replicas: 2 `) expected := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Foo spec: replicas: 3 @@ -390,7 +390,7 @@ var _ = Describe("Merging fields of type map with openapi", func() { Context("where a field has been deleted", func() { It("should delete the field when it is the only field in the map", func() { recorded := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: # delete - recorded/remote match @@ -399,14 +399,14 @@ spec: bar: 1 `) local := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: # delete - not present in recorded baz: null `) remote := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: baz: 3 @@ -415,7 +415,7 @@ spec: `) expected := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: `) @@ -424,7 +424,7 @@ spec: It("should delete the field when there are other fields in the map", func() { recorded := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: # delete - recorded/remote match @@ -433,7 +433,7 @@ spec: bar: 1 `) local := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: # delete - not present in recorded @@ -442,7 +442,7 @@ spec: biz: 1 `) remote := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: bar: 3 @@ -452,7 +452,7 @@ spec: `) expected := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: biz: 1 @@ -464,14 +464,14 @@ spec: Context("where a field is has been added", func() { It("should add the field", func() { recorded := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: foo: true biz: 1 `) local := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: # Add this - it is missing from recorded and remote @@ -482,12 +482,12 @@ spec: biz: 2 `) remote := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: `) expected := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: baz: 3 @@ -501,14 +501,14 @@ spec: Context("where a field is has been updated", func() { It("should add the field", func() { recorded := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: foo: true baz: 1 `) local := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: # Missing from recorded @@ -519,7 +519,7 @@ spec: baz: 2 `) remote := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: bar: 2 @@ -527,7 +527,7 @@ spec: baz: 3 `) expected := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: bar: 3 diff --git a/staging/src/k8s.io/apimachinery/pkg/apply/strategy/replace_map_list_test.go b/staging/src/k8s.io/apimachinery/pkg/apply/strategy/replace_map_list_test.go index 18ca89ae332..2144b812868 100644 --- a/staging/src/k8s.io/apimachinery/pkg/apply/strategy/replace_map_list_test.go +++ b/staging/src/k8s.io/apimachinery/pkg/apply/strategy/replace_map_list_test.go @@ -26,7 +26,7 @@ var _ = Describe("Replacing fields of type list without openapi", func() { Context("where a field is has been updated", func() { It("should replace the field", func() { recorded := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Foo spec: bar: @@ -36,7 +36,7 @@ spec: value: 2 `) local := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Foo spec: bar: @@ -46,7 +46,7 @@ spec: value: 2 `) remote := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Foo spec: bar: @@ -58,7 +58,7 @@ spec: value: 4 `) expected := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Foo spec: bar: diff --git a/staging/src/k8s.io/apimachinery/pkg/apply/strategy/replace_map_test.go b/staging/src/k8s.io/apimachinery/pkg/apply/strategy/replace_map_test.go index c0ea7b2aef1..049ca013b05 100644 --- a/staging/src/k8s.io/apimachinery/pkg/apply/strategy/replace_map_test.go +++ b/staging/src/k8s.io/apimachinery/pkg/apply/strategy/replace_map_test.go @@ -32,7 +32,7 @@ var _ = Describe("Replacing fields of type map with openapi for some fields", fu Context("where a field is has been updated", func() { It("should update the field", func() { recorded := create(` -apiVersion: extensions/v1beta1 +apiVersion: apps/v1 kind: ReplicaSet spec: template: @@ -41,7 +41,7 @@ spec: image: image1 `) local := create(` -apiVersion: extensions/v1beta1 +apiVersion: apps/v1 kind: ReplicaSet spec: template: @@ -50,7 +50,7 @@ spec: image: image1 `) remote := create(` -apiVersion: extensions/v1beta1 +apiVersion: apps/v1 kind: ReplicaSet spec: template: @@ -63,7 +63,7 @@ spec: image: image3 `) expected := create(` -apiVersion: extensions/v1beta1 +apiVersion: apps/v1 kind: ReplicaSet spec: template: diff --git a/staging/src/k8s.io/apimachinery/pkg/apply/strategy/replace_primitive_list_test.go b/staging/src/k8s.io/apimachinery/pkg/apply/strategy/replace_primitive_list_test.go index 12cd1deec4b..ddb02df88bf 100644 --- a/staging/src/k8s.io/apimachinery/pkg/apply/strategy/replace_primitive_list_test.go +++ b/staging/src/k8s.io/apimachinery/pkg/apply/strategy/replace_primitive_list_test.go @@ -26,7 +26,7 @@ var _ = Describe("Replacing fields of type list with openapi", func() { Context("where the field has been deleted", func() { It("should delete the field if present in recorded and missing from local.", func() { recorded := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: template: @@ -38,7 +38,7 @@ spec: - b `) local := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: template: @@ -47,7 +47,7 @@ spec: - name: container `) remote := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: template: @@ -62,7 +62,7 @@ spec: `) expected := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: template: @@ -75,7 +75,7 @@ spec: It("should delete the field if missing in recorded and set to null in local.", func() { recorded := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: template: @@ -84,7 +84,7 @@ spec: - name: container `) local := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: template: @@ -95,7 +95,7 @@ spec: `) remote := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: template: @@ -109,7 +109,7 @@ spec: - "y" `) expected := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: template: @@ -124,14 +124,14 @@ spec: Context("where the field is has been added", func() { It("should add the field when missing from recorded", func() { recorded := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: template: spec: `) local := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: template: @@ -144,14 +144,14 @@ spec: - c `) remote := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: template: spec: `) expected := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: template: @@ -168,7 +168,7 @@ spec: It("should add the field when even when present in recorded", func() { recorded := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: template: @@ -181,7 +181,7 @@ spec: - c `) local := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: template: @@ -194,14 +194,14 @@ spec: - c `) remote := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: template: spec: `) expected := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: template: @@ -218,12 +218,12 @@ spec: It("should add the field when the parent field is missing as well", func() { recorded := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: `) local := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: template: @@ -236,12 +236,12 @@ spec: - c `) remote := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: `) expected := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: template: @@ -260,7 +260,7 @@ spec: Context("where a field is has been updated", func() { It("should replace the field", func() { recorded := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: template: @@ -273,7 +273,7 @@ spec: - c `) local := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: template: @@ -286,7 +286,7 @@ spec: - f `) remote := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: spec: @@ -302,7 +302,7 @@ spec: - "y" `) expected := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: template: @@ -319,7 +319,7 @@ spec: It("should replace the field even if recorded matches", func() { recorded := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: template: @@ -332,7 +332,7 @@ spec: - f `) local := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: template: @@ -345,7 +345,7 @@ spec: - f `) remote := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: spec: @@ -361,7 +361,7 @@ spec: - "y" `) expected := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: template: @@ -378,7 +378,7 @@ spec: It("should replace the field even if the only change is ordering", func() { recorded := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: template: @@ -391,7 +391,7 @@ spec: - f `) local := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: template: @@ -404,7 +404,7 @@ spec: - f `) remote := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: spec: @@ -418,7 +418,7 @@ spec: - c `) expected := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: template: @@ -439,7 +439,7 @@ var _ = Describe("Replacing fields of type list with openapi for the type, but n Context("where a field is has been updated", func() { It("should replace the field", func() { recorded := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: template: @@ -452,7 +452,7 @@ spec: - c `) local := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: template: @@ -471,7 +471,7 @@ spec: - g `) remote := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: spec: @@ -503,7 +503,7 @@ spec: - m `) expected := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: template: @@ -530,7 +530,7 @@ var _ = Describe("Replacing fields of type list without openapi", func() { Context("where the field has been deleted", func() { It("should delete the field.", func() { recorded := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Foo spec: template: @@ -539,14 +539,14 @@ spec: - b `) local := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Foo spec: template: arguments: `) remote := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Foo spec: template: @@ -570,7 +570,7 @@ spec: `) expected := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Foo spec: template: @@ -587,7 +587,7 @@ spec: Context("where the field is has been added", func() { It("should add the field", func() { recorded := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Foo spec: template: @@ -598,7 +598,7 @@ spec: - "y" `) local := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Foo spec: template: @@ -616,12 +616,12 @@ spec: - w `) remote := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Foo spec: `) expected := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Foo spec: template: @@ -643,7 +643,7 @@ spec: Context("where a field is has been updated", func() { It("should replace field", func() { recorded := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Foo spec: template: @@ -657,7 +657,7 @@ spec: - u `) local := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Foo spec: template: @@ -677,7 +677,7 @@ spec: - u `) remote := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Foo spec: spec: @@ -698,7 +698,7 @@ spec: - "t" `) expected := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Foo spec: template: diff --git a/staging/src/k8s.io/apimachinery/pkg/apply/strategy/retain_keys_test.go b/staging/src/k8s.io/apimachinery/pkg/apply/strategy/retain_keys_test.go index 7c68b7ec1ff..469069d629b 100644 --- a/staging/src/k8s.io/apimachinery/pkg/apply/strategy/retain_keys_test.go +++ b/staging/src/k8s.io/apimachinery/pkg/apply/strategy/retain_keys_test.go @@ -26,20 +26,20 @@ var _ = Describe("Merging fields with the retainkeys strategy", func() { Context("where some fields are only defined remotely", func() { It("should drop those fields ", func() { recorded := create(` -apiVersion: extensions/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: strategy: `) local := create(` -apiVersion: extensions/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: strategy: type: Recreate `) remote := create(` -apiVersion: extensions/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: strategy: @@ -49,7 +49,7 @@ spec: maxSurge: 1 `) expected := create(` -apiVersion: extensions/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: strategy: @@ -62,13 +62,13 @@ spec: Context("where some fields are defined both locally and remotely", func() { It("should merge those fields", func() { recorded := create(` -apiVersion: extensions/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: strategy: `) local := create(` -apiVersion: extensions/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: strategy: @@ -77,7 +77,7 @@ spec: maxUnavailable: 2 `) remote := create(` -apiVersion: extensions/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: strategy: @@ -86,7 +86,7 @@ spec: maxSurge: 1 `) expected := create(` -apiVersion: extensions/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: strategy: @@ -102,14 +102,14 @@ spec: Context("where the elements are in a list and some fields are only defined remotely", func() { It("should drop those fields ", func() { recorded := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: template: spec: `) local := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: template: @@ -119,7 +119,7 @@ spec: emptyDir: `) remote := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: template: @@ -130,7 +130,7 @@ spec: path: /tmp/cache-volume `) expected := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: template: @@ -146,14 +146,14 @@ spec: Context("where the elements are in a list", func() { It("the fields defined both locally and remotely should be merged", func() { recorded := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: template: spec: `) local := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: template: @@ -165,7 +165,7 @@ spec: emptyDir: `) remote := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: template: @@ -177,7 +177,7 @@ spec: type: Directory `) expected := create(` -apiVersion: apps/v1beta1 +apiVersion: apps/v1 kind: Deployment spec: template: diff --git a/staging/src/k8s.io/apimachinery/pkg/apply/strategy/test_swagger.json b/staging/src/k8s.io/apimachinery/pkg/apply/strategy/test_swagger.json index 57f69314d60..57c014f6ab6 100644 --- a/staging/src/k8s.io/apimachinery/pkg/apply/strategy/test_swagger.json +++ b/staging/src/k8s.io/apimachinery/pkg/apply/strategy/test_swagger.json @@ -1,11 +1,10 @@ { "swagger": "2.0", "info": { - "title": "Kubernetes", - "version": "v1.9.0" - }, - "paths": { + "title": "Kubernetes", + "version": "v1.9.0" }, + "paths": {}, "definitions": { "io.k8s.api.core.v1.Container": { "description": "A single application container that you want to run within a pod.", @@ -63,8 +62,8 @@ } } }, - "io.k8s.api.apps.v1beta1.Deployment": { - "description": "DEPRECATED - This group version of Deployment is deprecated by apps/v1beta2/Deployment. See the release notes for more information. Deployment enables declarative updates for Pods and ReplicaSets.", + "io.k8s.api.apps.v1.Deployment": { + "description": "Deployment enables declarative updates for Pods and ReplicaSets.", "properties": { "apiVersion": { "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", @@ -80,20 +79,21 @@ }, "spec": { "description": "Specification of the desired behavior of the Deployment.", - "$ref": "#/definitions/io.k8s.api.apps.v1beta1.DeploymentSpec" + "$ref": "#/definitions/io.k8s.api.apps.v1.DeploymentSpec" } }, "x-kubernetes-group-version-kind": [ { "group": "apps", "kind": "Deployment", - "version": "v1beta1" + "version": "v1" } ] }, - "io.k8s.api.apps.v1beta1.DeploymentSpec": { + "io.k8s.api.apps.v1.DeploymentSpec": { "description": "DeploymentSpec is the specification of the desired behavior of the Deployment.", "required": [ + "selector", "template" ], "properties": { @@ -107,7 +107,7 @@ "type": "boolean" }, "progressDeadlineSeconds": { - "description": "The maximum time in seconds for a deployment to make progress before it is considered to be failed. The deployment controller will continue to process failed deployments and a condition with a ProgressDeadlineExceeded reason will be surfaced in the deployment status. Once autoRollback is implemented, the deployment controller will automatically rollback failed deployments. Note that progress will not be estimated during the time a deployment is paused. Defaults to 600s.", + "description": "The maximum time in seconds for a deployment to make progress before it is considered to be failed. The deployment controller will continue to process failed deployments and a condition with a ProgressDeadlineExceeded reason will be surfaced in the deployment status. Note that progress will not be estimated during the time a deployment is paused. Defaults to 600s.", "type": "integer", "format": "int32" }, @@ -117,16 +117,56 @@ "format": "int32" }, "revisionHistoryLimit": { - "description": "The number of old ReplicaSets to retain to allow rollback. This is a pointer to distinguish between explicit zero and not specified. Defaults to 2.", + "description": "The number of old ReplicaSets to retain to allow rollback. This is a pointer to distinguish between explicit zero and not specified. Defaults to 10.", "type": "integer", "format": "int32" }, + "selector": { + "description": "Label selector for pods. Existing ReplicaSets whose pods are selected by this will be the ones affected by this deployment. It must match the pod template's labels.", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector" + }, + "strategy": { + "description": "The deployment strategy to use to replace existing pods with new ones.", + "x-kubernetes-patch-strategy": "retainKeys", + "$ref": "#/definitions/io.k8s.api.apps.v1.DeploymentStrategy" + }, "template": { "description": "Template describes the pods that will be created.", "$ref": "#/definitions/io.k8s.api.core.v1.PodTemplateSpec" } } }, + "io.k8s.api.apps.v1.DeploymentStrategy": { + "description": "DeploymentStrategy describes how to replace existing pods with new ones.", + "properties": { + "rollingUpdate": { + "description": "Rolling update config params. Present only if DeploymentStrategyType = RollingUpdate.", + "$ref": "#/definitions/io.k8s.api.apps.v1.RollingUpdateDeployment" + }, + "type": { + "description": "Type of deployment. Can be \"Recreate\" or \"RollingUpdate\". Default is RollingUpdate.", + "type": "string" + } + } + }, + "io.k8s.api.apps.v1.RollingUpdateDeployment": { + "description": "Spec to control the desired behavior of rolling update.", + "properties": { + "maxSurge": { + "description": "The maximum number of pods that can be scheduled above the desired number of pods. Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). This can not be 0 if MaxUnavailable is 0. Absolute number is calculated from percentage by rounding up. Defaults to 25%. Example: when this is set to 30%, the new ReplicaSet can be scaled up immediately when the rolling update starts, such that the total number of old and new pods do not exceed 130% of desired pods. Once old pods have been killed, new ReplicaSet can be scaled up further, ensuring that total number of pods running at any time during the update is at most 130% of desired pods.", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.util.intstr.IntOrString" + }, + "maxUnavailable": { + "description": "The maximum number of pods that can be unavailable during the update. Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). Absolute number is calculated from percentage by rounding down. This can not be 0 if MaxSurge is 0. Defaults to 25%. Example: when this is set to 30%, the old ReplicaSet can be scaled down to 70% of desired pods immediately when the rolling update starts. Once new pods are ready, old ReplicaSet can be scaled down further, followed by scaling up the new ReplicaSet, ensuring that the total number of pods available at all times during the update is at least 70% of desired pods.", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.util.intstr.IntOrString" + } + } + }, + "io.k8s.apimachinery.pkg.util.intstr.IntOrString": { + "description": "IntOrString is a type that can hold an int32 or a string. When used in JSON or YAML marshalling and unmarshalling, it produces or consumes the inner type. This allows you to have, for example, a JSON field that can accept a name or number.", + "type": "string", + "format": "int-or-string" + }, "io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta": { "description": "ObjectMeta is metadata that all persisted resources must have, which includes all objects users must create.", "properties": { @@ -184,8 +224,8 @@ } } }, - "io.k8s.api.extensions.v1beta1.ReplicaSet": { - "description": "DEPRECATED - This group version of ReplicaSet is deprecated by apps/v1beta2/ReplicaSet. See the release notes for more information. ReplicaSet represents the configuration of a ReplicaSet.", + "io.k8s.api.apps.v1.ReplicaSet": { + "description": "ReplicaSet ensures that a specified number of pod replicas are running at any given time.", "properties": { "apiVersion": { "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", @@ -201,21 +241,22 @@ }, "spec": { "description": "Spec defines the specification of the desired behavior of the ReplicaSet. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status", - "$ref": "#/definitions/io.k8s.api.extensions.v1beta1.ReplicaSetSpec", - "x-kubernetes-patch-strategy": "replace" - + "$ref": "#/definitions/io.k8s.api.apps.v1.ReplicaSetSpec" } }, "x-kubernetes-group-version-kind": [ { - "group": "extensions", + "group": "apps", "kind": "ReplicaSet", - "version": "v1beta1" + "version": "v1" } ] }, - "io.k8s.api.extensions.v1beta1.ReplicaSetSpec": { + "io.k8s.api.apps.v1.ReplicaSetSpec": { "description": "ReplicaSetSpec is the specification of a ReplicaSet.", + "required": [ + "selector" + ], "properties": { "minReadySeconds": { "description": "Minimum number of seconds for which a newly created pod should be ready without any of its container crashing, for it to be considered available. Defaults to 0 (pod will be considered available as soon as it is ready)", @@ -227,24 +268,73 @@ "type": "integer", "format": "int32" }, + "selector": { + "description": "Selector is a label query over pods that should match the replica count. Label keys and values that must match in order to be controlled by this replica set. It must match the pod template's labels. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#label-selectors", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector" + }, "template": { "description": "Template is the object that describes the pod that will be created if insufficient replicas are detected. More info: https://kubernetes.io/docs/concepts/workloads/controllers/replicationcontroller#pod-template", "$ref": "#/definitions/io.k8s.api.core.v1.PodTemplateSpec" } } + }, + "io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector": { + "description": "A label selector is a label query over a set of resources. The result of matchLabels and matchExpressions are ANDed. An empty label selector matches all objects. A null label selector matches no objects.", + "properties": { + "matchExpressions": { + "description": "matchExpressions is a list of label selector requirements. The requirements are ANDed.", + "type": "array", + "items": { + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelectorRequirement" + } + }, + "matchLabels": { + "description": "matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is \"key\", the operator is \"In\", and the values array contains only \"value\". The requirements are ANDed.", + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + }, + "io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelectorRequirement": { + "description": "A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values.", + "required": [ + "key", + "operator" + ], + "properties": { + "key": { + "description": "key is the label key that the selector applies to.", + "type": "string", + "x-kubernetes-patch-merge-key": "key", + "x-kubernetes-patch-strategy": "merge" + }, + "operator": { + "description": "operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist.", + "type": "string" + }, + "values": { + "description": "values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch.", + "type": "array", + "items": { + "type": "string" + } + } + } } }, "securityDefinitions": { - "BearerToken": { - "description": "Bearer Token authentication", - "type": "apiKey", - "name": "authorization", - "in": "header" - } + "BearerToken": { + "description": "Bearer Token authentication", + "type": "apiKey", + "name": "authorization", + "in": "header" + } }, "security": [ - { - "BearerToken": [] - } + { + "BearerToken": [] + } ] - } +} \ No newline at end of file diff --git a/staging/src/k8s.io/apimachinery/pkg/runtime/serializer/streaming/streaming.go b/staging/src/k8s.io/apimachinery/pkg/runtime/serializer/streaming/streaming.go index 91fd4ed4f0b..a60a7c04156 100644 --- a/staging/src/k8s.io/apimachinery/pkg/runtime/serializer/streaming/streaming.go +++ b/staging/src/k8s.io/apimachinery/pkg/runtime/serializer/streaming/streaming.go @@ -64,7 +64,7 @@ func NewDecoder(r io.ReadCloser, d runtime.Decoder) Decoder { reader: r, decoder: d, buf: make([]byte, 1024), - maxBytes: 1024 * 1024, + maxBytes: 16 * 1024 * 1024, } } diff --git a/staging/src/k8s.io/apimachinery/pkg/runtime/serializer/streaming/streaming_test.go b/staging/src/k8s.io/apimachinery/pkg/runtime/serializer/streaming/streaming_test.go index 9cae6a32c43..1721423accc 100644 --- a/staging/src/k8s.io/apimachinery/pkg/runtime/serializer/streaming/streaming_test.go +++ b/staging/src/k8s.io/apimachinery/pkg/runtime/serializer/streaming/streaming_test.go @@ -51,7 +51,7 @@ func TestDecoder(t *testing.T) { frames := [][]byte{ make([]byte, 1025), make([]byte, 1024*5), - make([]byte, 1024*1024*5), + make([]byte, 1024*1024*17), make([]byte, 1025), } pr, pw := io.Pipe() diff --git a/staging/src/k8s.io/apimachinery/pkg/runtime/serializer/versioning/BUILD b/staging/src/k8s.io/apimachinery/pkg/runtime/serializer/versioning/BUILD index 785dc5fcfe4..9ba9d16f5a4 100644 --- a/staging/src/k8s.io/apimachinery/pkg/runtime/serializer/versioning/BUILD +++ b/staging/src/k8s.io/apimachinery/pkg/runtime/serializer/versioning/BUILD @@ -8,12 +8,17 @@ load( go_test( name = "go_default_test", - srcs = ["versioning_test.go"], + srcs = [ + "versioning_test.go", + "versioning_unstructured_test.go", + ], embed = [":go_default_library"], deps = [ + "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/diff:go_default_library", + "//vendor/github.com/stretchr/testify/assert:go_default_library", ], ) diff --git a/staging/src/k8s.io/apimachinery/pkg/runtime/serializer/versioning/versioning_unstructured_test.go b/staging/src/k8s.io/apimachinery/pkg/runtime/serializer/versioning/versioning_unstructured_test.go new file mode 100644 index 00000000000..e47a259f69d --- /dev/null +++ b/staging/src/k8s.io/apimachinery/pkg/runtime/serializer/versioning/versioning_unstructured_test.go @@ -0,0 +1,338 @@ +/* +Copyright 2015 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 versioning + +import ( + "fmt" + "io/ioutil" + "testing" + + "github.com/stretchr/testify/assert" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" +) + +func buildUnstructuredDecodable(gvk schema.GroupVersionKind) runtime.Object { + obj := &unstructured.Unstructured{} + obj.SetGroupVersionKind(gvk) + return obj +} + +func buildUnstructuredListDecodable(gvk schema.GroupVersionKind) runtime.Object { + obj := &unstructured.UnstructuredList{} + obj.SetGroupVersionKind(gvk) + return obj +} + +func TestEncodeUnstructured(t *testing.T) { + v1GVK := schema.GroupVersionKind{ + Group: "crispy", + Version: "v1", + Kind: "Noxu", + } + v2GVK := schema.GroupVersionKind{ + Group: "crispy", + Version: "v2", + Kind: "Noxu", + } + elseGVK := schema.GroupVersionKind{ + Group: "crispy2", + Version: "else", + Kind: "Noxu", + } + elseUnstructuredDecodable := buildUnstructuredDecodable(elseGVK) + elseUnstructuredDecodableList := buildUnstructuredListDecodable(elseGVK) + v1UnstructuredDecodable := buildUnstructuredDecodable(v1GVK) + v1UnstructuredDecodableList := buildUnstructuredListDecodable(v1GVK) + v2UnstructuredDecodable := buildUnstructuredDecodable(v2GVK) + + testCases := []struct { + name string + convertor runtime.ObjectConvertor + targetVersion runtime.GroupVersioner + outObj runtime.Object + typer runtime.ObjectTyper + + errFunc func(error) bool + expectedObj runtime.Object + }{ + { + name: "encode v1 unstructured with v2 encode version", + typer: &mockTyper{ + gvks: []schema.GroupVersionKind{v1GVK}, + }, + outObj: v1UnstructuredDecodable, + targetVersion: v2GVK.GroupVersion(), + convertor: &checkConvertor{ + obj: v2UnstructuredDecodable, + groupVersion: v2GVK.GroupVersion(), + }, + expectedObj: v2UnstructuredDecodable, + }, + { + name: "both typer and conversion are bypassed when unstructured gvk matches encode gvk", + typer: &mockTyper{ + err: fmt.Errorf("unexpected typer call"), + }, + outObj: v1UnstructuredDecodable, + targetVersion: v1GVK.GroupVersion(), + convertor: &checkConvertor{ + err: fmt.Errorf("unexpected conversion happened"), + }, + expectedObj: v1UnstructuredDecodable, + }, + { + name: "encode will fail when unstructured object's gvk and encode gvk mismatches", + outObj: elseUnstructuredDecodable, + targetVersion: v1GVK.GroupVersion(), + errFunc: func(err error) bool { + return assert.Equal(t, runtime.NewNotRegisteredGVKErrForTarget("noxu-scheme", elseGVK, v1GVK.GroupVersion()), err) + }, + }, + { + name: "encode with unstructured list's gvk regardless of its elements' gvk", + outObj: elseUnstructuredDecodableList, + targetVersion: elseGVK.GroupVersion(), + }, + { + name: "typer fail to recognize unstructured object gvk will fail the encoding", + outObj: elseUnstructuredDecodable, + targetVersion: v1GVK.GroupVersion(), + typer: &mockTyper{ + err: fmt.Errorf("invalid obj gvk"), + }, + }, + { + name: "encoding unstructured object without encode version will fallback to typer suggested version", + targetVersion: v1GVK.GroupVersion(), + convertor: &checkConvertor{ + obj: v1UnstructuredDecodableList, + groupVersion: v1GVK.GroupVersion(), + }, + outObj: elseUnstructuredDecodable, + typer: &mockTyper{ + gvks: []schema.GroupVersionKind{v1GVK}, + }, + }, + } + for _, testCase := range testCases { + serializer := &mockSerializer{} + codec := NewCodec(serializer, serializer, testCase.convertor, nil, testCase.typer, nil, testCase.targetVersion, nil, "noxu-scheme") + err := codec.Encode(testCase.outObj, ioutil.Discard) + if testCase.errFunc != nil { + if !testCase.errFunc(err) { + t.Errorf("%v: failed: %v", testCase.name, err) + } + return + } + assert.NoError(t, err) + assert.Equal(t, testCase.expectedObj, serializer.obj) + } +} + +type errNotRecognizedGVK struct { + failedGVK schema.GroupVersionKind + claimingGVKs []schema.GroupVersionKind +} + +func (e errNotRecognizedGVK) Error() string { + return fmt.Sprintf("unrecognized gvk %v, should be one of %v", e.failedGVK, e.claimingGVKs) +} + +type mockUnstructuredNopConvertor struct { + claimingGVKs []schema.GroupVersionKind +} + +func (c *mockUnstructuredNopConvertor) recognizeGVK(gvkToCheck schema.GroupVersionKind) error { + matched := false + for _, gvk := range c.claimingGVKs { + if gvk == gvkToCheck { + matched = true + } + } + if !matched { + return errNotRecognizedGVK{ + failedGVK: gvkToCheck, + claimingGVKs: c.claimingGVKs, + } + } + return nil +} + +func (c *mockUnstructuredNopConvertor) Convert(in, out, context interface{}) error { + inObj := in.(*unstructured.Unstructured) + outObj := out.(*unstructured.Unstructured) + if err := c.recognizeGVK(outObj.GroupVersionKind()); err != nil { + return err + } + outGVK := outObj.GetObjectKind().GroupVersionKind() + *outObj = *inObj.DeepCopy() + outObj.GetObjectKind().SetGroupVersionKind(outGVK) + return nil +} + +func (c *mockUnstructuredNopConvertor) ConvertToVersion(in runtime.Object, outVersion runtime.GroupVersioner) (runtime.Object, error) { + out := in.DeepCopyObject() + targetGVK, matched := outVersion.KindForGroupVersionKinds([]schema.GroupVersionKind{in.GetObjectKind().GroupVersionKind()}) + if !matched { + return nil, fmt.Errorf("attempt to convert to mismatched gv %v", outVersion) + } + if err := c.recognizeGVK(out.GetObjectKind().GroupVersionKind()); err != nil { + return nil, err + } + out.GetObjectKind().SetGroupVersionKind(targetGVK) + return out, nil +} + +func (c *mockUnstructuredNopConvertor) ConvertFieldLabel(gvk schema.GroupVersionKind, label, value string) (string, string, error) { + return "", "", fmt.Errorf("unexpected call to ConvertFieldLabel") +} + +func TestDecodeUnstructured(t *testing.T) { + internalGVK := schema.GroupVersionKind{ + Group: "crispy", + Version: runtime.APIVersionInternal, + Kind: "Noxu", + } + v1GVK := schema.GroupVersionKind{ + Group: "crispy", + Version: "v1", + Kind: "Noxu", + } + v2GVK := schema.GroupVersionKind{ + Group: "crispy", + Version: "v2", + Kind: "Noxu", + } + internalUnstructuredDecodable := buildUnstructuredDecodable(internalGVK) + v1UnstructuredDecodable := buildUnstructuredDecodable(v1GVK) + v2UnstructuredDecodable := buildUnstructuredDecodable(v2GVK) + + testCases := []struct { + name string + serializer runtime.Serializer + convertor runtime.ObjectConvertor + suggestedConvertVersion runtime.GroupVersioner + defaultGVK *schema.GroupVersionKind + intoObj runtime.Object + + errFunc func(error) bool + expectedGVKOfSerializedData *schema.GroupVersionKind + expectedOut runtime.Object + }{ + { + name: "decode v1 unstructured into non-nil v2 unstructured", + serializer: &mockSerializer{actual: &v1GVK, obj: v1UnstructuredDecodable}, + convertor: &mockUnstructuredNopConvertor{ + claimingGVKs: []schema.GroupVersionKind{ + v1GVK, v2GVK, + }, + }, + suggestedConvertVersion: v2GVK.GroupVersion(), + intoObj: v2UnstructuredDecodable, + expectedGVKOfSerializedData: &v1GVK, + expectedOut: v2UnstructuredDecodable, + }, + { + name: "decode v1 unstructured into nil object with v2 version", + serializer: &mockSerializer{actual: &v1GVK, obj: v1UnstructuredDecodable}, + convertor: &mockUnstructuredNopConvertor{ + claimingGVKs: []schema.GroupVersionKind{ + v1GVK, v2GVK, + }, + }, + suggestedConvertVersion: v2GVK.GroupVersion(), + intoObj: nil, + expectedGVKOfSerializedData: &v1GVK, + expectedOut: v2UnstructuredDecodable, + }, + { + name: "decode v1 unstructured into non-nil internal unstructured", + serializer: &mockSerializer{actual: &v1GVK, obj: v1UnstructuredDecodable}, + convertor: &mockUnstructuredNopConvertor{ + claimingGVKs: []schema.GroupVersionKind{ + v1GVK, v2GVK, + }, + }, + suggestedConvertVersion: internalGVK.GroupVersion(), + intoObj: internalUnstructuredDecodable, + errFunc: func(err error) bool { + notRecognized, ok := err.(errNotRecognizedGVK) + if !ok { + return false + } + return assert.Equal(t, notRecognized.failedGVK, internalGVK) + }, + }, + { + name: "decode v1 unstructured into nil object with internal version", + serializer: &mockSerializer{actual: &v1GVK, obj: v1UnstructuredDecodable}, + convertor: &mockUnstructuredNopConvertor{ + claimingGVKs: []schema.GroupVersionKind{ + v1GVK, v2GVK, + }, + }, + suggestedConvertVersion: internalGVK.GroupVersion(), + intoObj: nil, + errFunc: func(err error) bool { + notRecognized, ok := err.(errNotRecognizedGVK) + if !ok { + return false + } + return assert.Equal(t, notRecognized.failedGVK, internalGVK) + }, + }, + { + name: "skip conversion if serializer returns the same unstructured as into", + serializer: &mockSerializer{actual: &v1GVK, obj: v1UnstructuredDecodable}, + convertor: &checkConvertor{ + err: fmt.Errorf("unexpected conversion happened"), + }, + suggestedConvertVersion: internalGVK.GroupVersion(), + intoObj: v1UnstructuredDecodable, + expectedGVKOfSerializedData: &v1GVK, + expectedOut: v1UnstructuredDecodable, + }, + { + name: "invalid convert version makes decoding unstructured fail", + serializer: &mockSerializer{actual: &v1GVK, obj: v1UnstructuredDecodable}, + convertor: &checkConvertor{ + in: v1UnstructuredDecodable, + groupVersion: internalGVK.GroupVersion(), + err: fmt.Errorf("no matching decode version"), + }, + suggestedConvertVersion: internalGVK.GroupVersion(), + errFunc: func(err error) bool { + return assert.Equal(t, err, fmt.Errorf("no matching decode version")) + }, + }, + } + for _, testCase := range testCases { + codec := NewCodec(testCase.serializer, testCase.serializer, testCase.convertor, nil, nil, nil, nil, testCase.suggestedConvertVersion, "noxu-scheme") + actualObj, actualSerializedGVK, err := codec.Decode([]byte(`{}`), testCase.defaultGVK, testCase.intoObj) + if testCase.errFunc != nil { + if !testCase.errFunc(err) { + t.Errorf("%v: failed: %v", testCase.name, err) + } + return + } + assert.NoError(t, err) + assert.Equal(t, testCase.expectedOut, actualObj, "%v failed", testCase.name) + assert.Equal(t, testCase.expectedGVKOfSerializedData, actualSerializedGVK, "%v failed", testCase.name) + } +} diff --git a/staging/src/k8s.io/apimachinery/pkg/util/proxy/upgradeaware_test.go b/staging/src/k8s.io/apimachinery/pkg/util/proxy/upgradeaware_test.go index c5dfde90d93..e85c6e5e9fd 100644 --- a/staging/src/k8s.io/apimachinery/pkg/util/proxy/upgradeaware_test.go +++ b/staging/src/k8s.io/apimachinery/pkg/util/proxy/upgradeaware_test.go @@ -17,6 +17,7 @@ limitations under the License. package proxy import ( + "bufio" "bytes" "compress/gzip" "context" @@ -538,6 +539,68 @@ func TestProxyUpgradeErrorResponse(t *testing.T) { assert.Contains(t, string(msg), expectedErr.Error()) } +func TestProxyUpgradeErrorResponseTerminates(t *testing.T) { + for _, intercept := range []bool{true, false} { + for _, code := range []int{200, 400, 500} { + t.Run(fmt.Sprintf("intercept=%v,code=%v", intercept, code), func(t *testing.T) { + // Set up a backend server + backend := http.NewServeMux() + backend.Handle("/hello", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(code) + w.Write([]byte(`some data`)) + })) + backend.Handle("/there", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + t.Error("request to /there") + })) + backendServer := httptest.NewServer(backend) + defer backendServer.Close() + backendServerURL, _ := url.Parse(backendServer.URL) + backendServerURL.Path = "/hello" + + // Set up a proxy pointing to a specific path on the backend + proxyHandler := NewUpgradeAwareHandler(backendServerURL, nil, false, false, &noErrorsAllowed{t: t}) + proxyHandler.InterceptRedirects = intercept + proxy := httptest.NewServer(proxyHandler) + defer proxy.Close() + proxyURL, _ := url.Parse(proxy.URL) + + conn, err := net.Dial("tcp", proxyURL.Host) + require.NoError(t, err) + bufferedReader := bufio.NewReader(conn) + + // Send upgrade request resulting in a non-101 response from the backend + req, _ := http.NewRequest("GET", "/", nil) + req.Header.Set(httpstream.HeaderConnection, httpstream.HeaderUpgrade) + require.NoError(t, req.Write(conn)) + // Verify we get the correct response and full message body content + resp, err := http.ReadResponse(bufferedReader, nil) + require.NoError(t, err) + data, err := ioutil.ReadAll(resp.Body) + require.NoError(t, err) + require.Equal(t, resp.StatusCode, code) + require.Equal(t, data, []byte(`some data`)) + resp.Body.Close() + + // try to read from the connection to verify it was closed + b := make([]byte, 1) + conn.SetReadDeadline(time.Now().Add(time.Second)) + if _, err := conn.Read(b); err != io.EOF { + t.Errorf("expected EOF, got %v", err) + } + + // Send another request to another endpoint to verify it is not received + req, _ = http.NewRequest("GET", "/there", nil) + req.Write(conn) + // wait to ensure the handler does not receive the request + time.Sleep(time.Second) + + // clean up + conn.Close() + }) + } + } +} + func TestDefaultProxyTransport(t *testing.T) { tests := []struct { name, diff --git a/staging/src/k8s.io/apimachinery/pkg/util/strategicpatch/patch_test.go b/staging/src/k8s.io/apimachinery/pkg/util/strategicpatch/patch_test.go index 6a0166e57d2..06814273da6 100644 --- a/staging/src/k8s.io/apimachinery/pkg/util/strategicpatch/patch_test.go +++ b/staging/src/k8s.io/apimachinery/pkg/util/strategicpatch/patch_test.go @@ -282,7 +282,7 @@ testCases: func TestSortMergeLists(t *testing.T) { mergeItemOpenapiSchema := PatchMetaFromOpenAPI{ - Schema: sptest.GetSchemaOrDie(fakeMergeItemSchema, "mergeItem"), + Schema: sptest.GetSchemaOrDie(&fakeMergeItemSchema, "mergeItem"), } schemas := []LookupPatchMeta{ mergeItemStructSchema, @@ -673,7 +673,7 @@ mergingList: func TestCustomStrategicMergePatch(t *testing.T) { mergeItemOpenapiSchema := PatchMetaFromOpenAPI{ - Schema: sptest.GetSchemaOrDie(fakeMergeItemSchema, "mergeItem"), + Schema: sptest.GetSchemaOrDie(&fakeMergeItemSchema, "mergeItem"), } schemas := []LookupPatchMeta{ mergeItemStructSchema, @@ -6029,7 +6029,7 @@ func TestStrategicMergePatch(t *testing.T) { "{}", "{}", []byte(""), mergepatch.ErrBadArgKind(struct{}{}, []byte{})) mergeItemOpenapiSchema := PatchMetaFromOpenAPI{ - Schema: sptest.GetSchemaOrDie(fakeMergeItemSchema, "mergeItem"), + Schema: sptest.GetSchemaOrDie(&fakeMergeItemSchema, "mergeItem"), } schemas := []LookupPatchMeta{ mergeItemStructSchema, @@ -6413,7 +6413,7 @@ func TestNumberConversion(t *testing.T) { } precisionItemOpenapiSchema := PatchMetaFromOpenAPI{ - Schema: sptest.GetSchemaOrDie(fakePrecisionItemSchema, "precisionItem"), + Schema: sptest.GetSchemaOrDie(&fakePrecisionItemSchema, "precisionItem"), } precisionItemSchemas := []LookupPatchMeta{ precisionItemStructSchema, @@ -6623,7 +6623,7 @@ replacingItem: func TestReplaceWithRawExtension(t *testing.T) { mergeItemOpenapiSchema := PatchMetaFromOpenAPI{ - Schema: sptest.GetSchemaOrDie(fakeMergeItemSchema, "mergeItem"), + Schema: sptest.GetSchemaOrDie(&fakeMergeItemSchema, "mergeItem"), } schemas := []LookupPatchMeta{ mergeItemStructSchema, @@ -6695,7 +6695,7 @@ func TestUnknownField(t *testing.T) { } mergeItemOpenapiSchema := PatchMetaFromOpenAPI{ - Schema: sptest.GetSchemaOrDie(fakeMergeItemSchema, "mergeItem"), + Schema: sptest.GetSchemaOrDie(&fakeMergeItemSchema, "mergeItem"), } schemas := []LookupPatchMeta{ mergeItemStructSchema, diff --git a/staging/src/k8s.io/apimachinery/pkg/util/strategicpatch/testing/openapi.go b/staging/src/k8s.io/apimachinery/pkg/util/strategicpatch/testing/openapi.go index 68b5e196bcb..0aafc2c479d 100644 --- a/staging/src/k8s.io/apimachinery/pkg/util/strategicpatch/testing/openapi.go +++ b/staging/src/k8s.io/apimachinery/pkg/util/strategicpatch/testing/openapi.go @@ -62,7 +62,7 @@ func (f *Fake) OpenAPISchema() (*openapi_v2.Document, error) { return f.document, f.err } -func getSchema(f Fake, model string) (openapi.Schema, error) { +func getSchema(f *Fake, model string) (openapi.Schema, error) { s, err := f.OpenAPISchema() if err != nil { return nil, err @@ -75,7 +75,7 @@ func getSchema(f Fake, model string) (openapi.Schema, error) { } // GetSchemaOrDie returns the openapi schema. -func GetSchemaOrDie(f Fake, model string) openapi.Schema { +func GetSchemaOrDie(f *Fake, model string) openapi.Schema { s, err := getSchema(f, model) if err != nil { panic(err) diff --git a/staging/src/k8s.io/apimachinery/pkg/util/validation/validation.go b/staging/src/k8s.io/apimachinery/pkg/util/validation/validation.go index e0d1715420e..2dd99992dca 100644 --- a/staging/src/k8s.io/apimachinery/pkg/util/validation/validation.go +++ b/staging/src/k8s.io/apimachinery/pkg/util/validation/validation.go @@ -87,6 +87,8 @@ func IsFullyQualifiedName(fldPath *field.Path, name string) field.ErrorList { const labelValueFmt string = "(" + qualifiedNameFmt + ")?" const labelValueErrMsg string = "a valid label must be an empty string or consist of alphanumeric characters, '-', '_' or '.', and must start and end with an alphanumeric character" + +// LabelValueMaxLength is a label's max length const LabelValueMaxLength int = 63 var labelValueRegexp = regexp.MustCompile("^" + labelValueFmt + "$") @@ -107,6 +109,8 @@ func IsValidLabelValue(value string) []string { const dns1123LabelFmt string = "[a-z0-9]([-a-z0-9]*[a-z0-9])?" const dns1123LabelErrMsg string = "a DNS-1123 label must consist of lower case alphanumeric characters or '-', and must start and end with an alphanumeric character" + +// DNS1123LabelMaxLength is a label's max length in DNS (RFC 1123) const DNS1123LabelMaxLength int = 63 var dns1123LabelRegexp = regexp.MustCompile("^" + dns1123LabelFmt + "$") @@ -126,6 +130,8 @@ func IsDNS1123Label(value string) []string { const dns1123SubdomainFmt string = dns1123LabelFmt + "(\\." + dns1123LabelFmt + ")*" const dns1123SubdomainErrorMsg string = "a DNS-1123 subdomain must consist of lower case alphanumeric characters, '-' or '.', and must start and end with an alphanumeric character" + +// DNS1123SubdomainMaxLength is a subdomain's max length in DNS (RFC 1123) const DNS1123SubdomainMaxLength int = 253 var dns1123SubdomainRegexp = regexp.MustCompile("^" + dns1123SubdomainFmt + "$") @@ -145,6 +151,8 @@ func IsDNS1123Subdomain(value string) []string { const dns1035LabelFmt string = "[a-z]([-a-z0-9]*[a-z0-9])?" const dns1035LabelErrMsg string = "a DNS-1035 label must consist of lower case alphanumeric characters or '-', start with an alphabetic character, and end with an alphanumeric character" + +// DNS1035LabelMaxLength is a label's max length in DNS (RFC 1035) const DNS1035LabelMaxLength int = 63 var dns1035LabelRegexp = regexp.MustCompile("^" + dns1035LabelFmt + "$") @@ -282,6 +290,7 @@ const percentErrMsg string = "a valid percent string must be a numeric string fo var percentRegexp = regexp.MustCompile("^" + percentFmt + "$") +// IsValidPercent checks that string is in the form of a percentage func IsValidPercent(percent string) []string { if !percentRegexp.MatchString(percent) { return []string{RegexError(percentErrMsg, percentFmt, "1%", "93%")} @@ -391,13 +400,13 @@ func hasChDirPrefix(value string) []string { return errs } -// IsSocketAddr checks that a string conforms is a valid socket address +// IsValidSocketAddr checks that string represents a valid socket address // as defined in RFC 789. (e.g 0.0.0.0:10254 or [::]:10254)) func IsValidSocketAddr(value string) []string { var errs []string ip, port, err := net.SplitHostPort(value) if err != nil { - return append(errs, "must be a valid socket address format, (e.g. 0.0.0.0:10254 or [::]:10254)") + errs = append(errs, "must be a valid socket address format, (e.g. 0.0.0.0:10254 or [::]:10254)") return errs } portInt, _ := strconv.Atoi(port) diff --git a/staging/src/k8s.io/apimachinery/pkg/util/version/version.go b/staging/src/k8s.io/apimachinery/pkg/util/version/version.go index 24724e50ac5..9bc928a4e82 100644 --- a/staging/src/k8s.io/apimachinery/pkg/util/version/version.go +++ b/staging/src/k8s.io/apimachinery/pkg/util/version/version.go @@ -154,6 +154,35 @@ func (v *Version) Components() []uint { return v.components } +// WithMajor returns copy of the version object with requested major number +func (v *Version) WithMajor(major uint) *Version { + result := *v + result.components = []uint{major, v.Minor(), v.Patch()} + return &result +} + +// WithMinor returns copy of the version object with requested minor number +func (v *Version) WithMinor(minor uint) *Version { + result := *v + result.components = []uint{v.Major(), minor, v.Patch()} + return &result +} + +// WithPatch returns copy of the version object with requested patch number +func (v *Version) WithPatch(patch uint) *Version { + result := *v + result.components = []uint{v.Major(), v.Minor(), patch} + return &result +} + +// WithPreRelease returns copy of the version object with requested prerelease +func (v *Version) WithPreRelease(preRelease string) *Version { + result := *v + result.components = []uint{v.Major(), v.Minor(), v.Patch()} + result.preRelease = preRelease + return &result +} + // String converts a Version back to a string; note that for versions parsed with // ParseGeneric, this will not include the trailing uninterpreted portion of the version // number. diff --git a/staging/src/k8s.io/apimachinery/pkg/util/wait/wait.go b/staging/src/k8s.io/apimachinery/pkg/util/wait/wait.go index ca61168cd4a..760e17066c5 100644 --- a/staging/src/k8s.io/apimachinery/pkg/util/wait/wait.go +++ b/staging/src/k8s.io/apimachinery/pkg/util/wait/wait.go @@ -173,10 +173,49 @@ type ConditionFunc func() (done bool, err error) // Backoff holds parameters applied to a Backoff function. type Backoff struct { - Duration time.Duration // the base duration - Factor float64 // Duration is multiplied by factor each iteration - Jitter float64 // The amount of jitter applied each iteration - Steps int // Exit with error after this many steps + // The initial duration. + Duration time.Duration + // Duration is multiplied by factor each iteration. Must be greater + // than or equal to zero. + Factor float64 + // The amount of jitter applied each iteration. Jitter is applied after + // cap. + Jitter float64 + // The number of steps before duration stops changing. If zero, initial + // duration is always used. Used for exponential backoff in combination + // with Factor. + Steps int + // The returned duration will never be greater than cap *before* jitter + // is applied. The actual maximum cap is `cap * (1.0 + jitter)`. + Cap time.Duration +} + +// Step returns the next interval in the exponential backoff. This method +// will mutate the provided backoff. +func (b *Backoff) Step() time.Duration { + if b.Steps < 1 { + if b.Jitter > 0 { + return Jitter(b.Duration, b.Jitter) + } + return b.Duration + } + b.Steps-- + + duration := b.Duration + + // calculate the next step + if b.Factor != 0 { + b.Duration = time.Duration(float64(b.Duration) * b.Factor) + if b.Cap > 0 && b.Duration > b.Cap { + b.Duration = b.Cap + b.Steps = 0 + } + } + + if b.Jitter > 0 { + duration = Jitter(duration, b.Jitter) + } + return duration } // ExponentialBackoff repeats a condition check with exponential backoff. @@ -190,19 +229,14 @@ type Backoff struct { // If the condition never returns true, ErrWaitTimeout is returned. All other // errors terminate immediately. func ExponentialBackoff(backoff Backoff, condition ConditionFunc) error { - duration := backoff.Duration - for i := 0; i < backoff.Steps; i++ { - if i != 0 { - adjusted := duration - if backoff.Jitter > 0.0 { - adjusted = Jitter(duration, backoff.Jitter) - } - time.Sleep(adjusted) - duration = time.Duration(float64(duration) * backoff.Factor) - } + for backoff.Steps > 0 { if ok, err := condition(); err != nil || ok { return err } + if backoff.Steps == 1 { + break + } + time.Sleep(backoff.Step()) } return ErrWaitTimeout } @@ -325,18 +359,30 @@ type WaitFunc func(done <-chan struct{}) <-chan struct{} // ErrWaitTimeout will be returned if the channel is closed without fn ever // returning true. func WaitFor(wait WaitFunc, fn ConditionFunc, done <-chan struct{}) error { - c := wait(done) + stopCh := make(chan struct{}) + once := sync.Once{} + closeCh := func() { + once.Do(func() { + close(stopCh) + }) + } + defer closeCh() + c := wait(stopCh) for { - _, open := <-c - ok, err := fn() - if err != nil { - return err - } - if ok { - return nil - } - if !open { - break + select { + case _, open := <-c: + ok, err := fn() + if err != nil { + return err + } + if ok { + return nil + } + if !open { + return ErrWaitTimeout + } + case <-done: + closeCh() } } return ErrWaitTimeout diff --git a/staging/src/k8s.io/apimachinery/pkg/util/wait/wait_test.go b/staging/src/k8s.io/apimachinery/pkg/util/wait/wait_test.go index 2dfd2877756..611fa5a0a0e 100644 --- a/staging/src/k8s.io/apimachinery/pkg/util/wait/wait_test.go +++ b/staging/src/k8s.io/apimachinery/pkg/util/wait/wait_test.go @@ -19,6 +19,7 @@ package wait import ( "errors" "fmt" + "math/rand" "sync" "sync/atomic" "testing" @@ -455,18 +456,46 @@ func TestWaitFor(t *testing.T) { } } -func TestWaitForWithDelay(t *testing.T) { - done := make(chan struct{}) - defer close(done) - WaitFor(poller(time.Millisecond, ForeverTestTimeout), func() (bool, error) { +func TestWaitForWithClosedChannel(t *testing.T) { + stopCh := make(chan struct{}) + close(stopCh) + start := time.Now() + err := WaitFor(poller(ForeverTestTimeout, ForeverTestTimeout), func() (bool, error) { + return false, nil + }, stopCh) + duration := time.Now().Sub(start) + // The WaitFor should return immediately, so the duration is close to 0s. + if duration >= ForeverTestTimeout/2 { + t.Errorf("expected short timeout duration") + } + // The interval of the poller is ForeverTestTimeout, so the WaitFor should always return ErrWaitTimeout. + if err != ErrWaitTimeout { + t.Errorf("expected ErrWaitTimeout from WaitFunc") + } +} + +// TestWaitForClosesStopCh verifies that after the condition func returns true, WaitFor() closes the stop channel it supplies to the WaitFunc. +func TestWaitForClosesStopCh(t *testing.T) { + stopCh := make(chan struct{}) + defer close(stopCh) + waitFunc := poller(time.Millisecond, ForeverTestTimeout) + var doneCh <-chan struct{} + + WaitFor(func(done <-chan struct{}) <-chan struct{} { + doneCh = done + return waitFunc(done) + }, func() (bool, error) { time.Sleep(10 * time.Millisecond) return true, nil - }, done) - // If polling goroutine doesn't see the done signal it will leak timers. + }, stopCh) + // The polling goroutine should be closed after WaitFor returning. select { - case done <- struct{}{}: - case <-time.After(ForeverTestTimeout): - t.Errorf("expected an ack of the done signal.") + case _, ok := <-doneCh: + if ok { + t.Errorf("expected closed channel after WaitFunc returning") + } + default: + t.Errorf("expected an ack of the done signal") } } @@ -499,3 +528,47 @@ func TestPollUntil(t *testing.T) { // make sure we finished the poll <-pollDone } + +func TestBackoff_Step(t *testing.T) { + tests := []struct { + initial *Backoff + want []time.Duration + }{ + {initial: &Backoff{Duration: time.Second, Steps: 0}, want: []time.Duration{time.Second, time.Second, time.Second}}, + {initial: &Backoff{Duration: time.Second, Steps: 1}, want: []time.Duration{time.Second, time.Second, time.Second}}, + {initial: &Backoff{Duration: time.Second, Factor: 1.0, Steps: 1}, want: []time.Duration{time.Second, time.Second, time.Second}}, + {initial: &Backoff{Duration: time.Second, Factor: 2, Steps: 3}, want: []time.Duration{1 * time.Second, 2 * time.Second, 4 * time.Second}}, + {initial: &Backoff{Duration: time.Second, Factor: 2, Steps: 3, Cap: 3 * time.Second}, want: []time.Duration{1 * time.Second, 2 * time.Second, 3 * time.Second}}, + {initial: &Backoff{Duration: time.Second, Factor: 2, Steps: 2, Cap: 3 * time.Second, Jitter: 0.5}, want: []time.Duration{2 * time.Second, 3 * time.Second, 3 * time.Second}}, + {initial: &Backoff{Duration: time.Second, Factor: 2, Steps: 6, Jitter: 4}, want: []time.Duration{1 * time.Second, 2 * time.Second, 4 * time.Second, 8 * time.Second, 16 * time.Second, 32 * time.Second}}, + } + for seed := int64(0); seed < 5; seed++ { + for _, tt := range tests { + initial := *tt.initial + t.Run(fmt.Sprintf("%#v seed=%d", initial, seed), func(t *testing.T) { + rand.Seed(seed) + for i := 0; i < len(tt.want); i++ { + got := initial.Step() + t.Logf("[%d]=%s", i, got) + if initial.Jitter > 0 { + if got == tt.want[i] { + // this is statistically unlikely to happen by chance + t.Errorf("Backoff.Step(%d) = %v, no jitter", i, got) + continue + } + diff := float64(tt.want[i]-got) / float64(tt.want[i]) + if diff > initial.Jitter { + t.Errorf("Backoff.Step(%d) = %v, want %v, outside range", i, got, tt.want) + continue + } + } else { + if got != tt.want[i] { + t.Errorf("Backoff.Step(%d) = %v, want %v", i, got, tt.want) + continue + } + } + } + }) + } + } +} diff --git a/staging/src/k8s.io/apiserver/Godeps/Godeps.json b/staging/src/k8s.io/apiserver/Godeps/Godeps.json index b3a786acb96..c66d975afa9 100644 --- a/staging/src/k8s.io/apiserver/Godeps/Godeps.json +++ b/staging/src/k8s.io/apiserver/Godeps/Godeps.json @@ -572,11 +572,15 @@ }, { "ImportPath": "github.com/prometheus/client_golang/prometheus", - "Rev": "e7e903064f5e9eb5da98208bae10b475d4db0f8c" + "Rev": "abad2d1bd44235a26707c172eab6bca5bf2dbad3" + }, + { + "ImportPath": "github.com/prometheus/client_golang/prometheus/internal", + "Rev": "abad2d1bd44235a26707c172eab6bca5bf2dbad3" }, { "ImportPath": "github.com/prometheus/client_golang/prometheus/promhttp", - "Rev": "e7e903064f5e9eb5da98208bae10b475d4db0f8c" + "Rev": "abad2d1bd44235a26707c172eab6bca5bf2dbad3" }, { "ImportPath": "github.com/prometheus/client_model/go", @@ -1014,6 +1018,10 @@ "ImportPath": "k8s.io/api/certificates/v1beta1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/api/coordination/v1", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/api/coordination/v1beta1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" @@ -1374,6 +1382,10 @@ "ImportPath": "k8s.io/client-go/informers/coordination", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/client-go/informers/coordination/v1", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/client-go/informers/coordination/v1beta1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" @@ -1618,6 +1630,14 @@ "ImportPath": "k8s.io/client-go/kubernetes/typed/certificates/v1beta1/fake", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/client-go/kubernetes/typed/coordination/v1", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/client-go/kubernetes/typed/coordination/v1/fake", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/client-go/kubernetes/typed/coordination/v1beta1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" @@ -1790,6 +1810,10 @@ "ImportPath": "k8s.io/client-go/listers/certificates/v1beta1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/client-go/listers/coordination/v1", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/client-go/listers/coordination/v1beta1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" diff --git a/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/create.go b/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/create.go index b3f8b675236..67ddb0e73d0 100644 --- a/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/create.go +++ b/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/create.go @@ -71,6 +71,11 @@ func createHandler(r rest.NamedCreater, scope RequestScope, admit admission.Inte ctx := req.Context() ctx = request.WithNamespace(ctx, namespace) + outputMediaType, _, err := negotiation.NegotiateOutputMediaType(req, scope.Serializer, &scope) + if err != nil { + scope.err(err, w, req) + return + } gv := scope.Kind.GroupVersion() s, err := negotiation.NegotiateInputSerializer(req, false, scope.Serializer) @@ -78,6 +83,7 @@ func createHandler(r rest.NamedCreater, scope RequestScope, admit admission.Inte scope.err(err, w, req) return } + decoder := scope.Serializer.DecoderToVersion(s.Serializer, scope.HubGroupVersion) body, err := readBody(req) @@ -161,17 +167,6 @@ func createHandler(r rest.NamedCreater, scope RequestScope, admit admission.Inte } trace.Step("Object stored in database") - requestInfo, ok := request.RequestInfoFrom(ctx) - if !ok { - scope.err(fmt.Errorf("missing requestInfo"), w, req) - return - } - if err := setSelfLink(result, requestInfo, scope.Namer); err != nil { - scope.err(err, w, req) - return - } - trace.Step("Self-link added") - // If the object is partially initialized, always indicate it via StatusAccepted code := http.StatusCreated if accessor, err := meta.Accessor(result); err == nil { @@ -185,7 +180,7 @@ func createHandler(r rest.NamedCreater, scope RequestScope, admit admission.Inte } scope.Trace = trace - transformResponseObject(ctx, scope, req, w, code, result) + transformResponseObject(ctx, scope, req, w, code, outputMediaType, result) } } diff --git a/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/delete.go b/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/delete.go index b8b4cdc2315..e38e1c2972c 100644 --- a/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/delete.go +++ b/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/delete.go @@ -64,6 +64,12 @@ func DeleteResource(r rest.GracefulDeleter, allowsOptions bool, scope RequestSco ae := request.AuditEventFrom(ctx) admit = admission.WithAudit(admit, ae) + outputMediaType, _, err := negotiation.NegotiateOutputMediaType(req, scope.Serializer, &scope) + if err != nil { + scope.err(err, w, req) + return + } + options := &metav1.DeleteOptions{} if allowsOptions { body, err := readBody(req) @@ -160,23 +166,10 @@ func DeleteResource(r rest.GracefulDeleter, allowsOptions bool, scope RequestSco Kind: scope.Kind.Kind, }, } - } else { - // when a non-status response is returned, set the self link - requestInfo, ok := request.RequestInfoFrom(ctx) - if !ok { - scope.err(fmt.Errorf("missing requestInfo"), w, req) - return - } - if _, ok := result.(*metav1.Status); !ok { - if err := setSelfLink(result, requestInfo, scope.Namer); err != nil { - scope.err(err, w, req) - return - } - } } scope.Trace = trace - transformResponseObject(ctx, scope, req, w, status, result) + transformResponseObject(ctx, scope, req, w, status, outputMediaType, result) } } @@ -204,6 +197,12 @@ func DeleteCollection(r rest.CollectionDeleter, checkBody bool, scope RequestSco ctx = request.WithNamespace(ctx, namespace) ae := request.AuditEventFrom(ctx) + outputMediaType, _, err := negotiation.NegotiateOutputMediaType(req, scope.Serializer, &scope) + if err != nil { + scope.err(err, w, req) + return + } + listOptions := metainternalversion.ListOptions{} if err := metainternalversion.ParameterCodec.DecodeParameters(req.URL.Query(), scope.MetaGroupVersion, &listOptions); err != nil { err = errors.NewBadRequest(err.Error()) @@ -304,17 +303,9 @@ func DeleteCollection(r rest.CollectionDeleter, checkBody bool, scope RequestSco Kind: scope.Kind.Kind, }, } - } else { - // when a non-status response is returned, set the self link - if _, ok := result.(*metav1.Status); !ok { - if _, err := setListSelfLink(result, ctx, req, scope.Namer); err != nil { - scope.err(err, w, req) - return - } - } } scope.Trace = trace - transformResponseObject(ctx, scope, req, w, http.StatusOK, result) + transformResponseObject(ctx, scope, req, w, http.StatusOK, outputMediaType, result) } } diff --git a/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/get.go b/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/get.go index 0f1c59946a3..1c0950b8d10 100644 --- a/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/get.go +++ b/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/get.go @@ -33,6 +33,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/fields" "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apiserver/pkg/endpoints/handlers/negotiation" "k8s.io/apiserver/pkg/endpoints/metrics" "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/registry/rest" @@ -58,24 +59,21 @@ func getResourceHandler(scope RequestScope, getter getterFunc) http.HandlerFunc ctx := req.Context() ctx = request.WithNamespace(ctx, namespace) - result, err := getter(ctx, name, req, trace) + outputMediaType, _, err := negotiation.NegotiateOutputMediaType(req, scope.Serializer, &scope) if err != nil { scope.err(err, w, req) return } - requestInfo, ok := request.RequestInfoFrom(ctx) - if !ok { - scope.err(fmt.Errorf("missing requestInfo"), w, req) - return - } - if err := setSelfLink(result, requestInfo, scope.Namer); err != nil { + + result, err := getter(ctx, name, req, trace) + if err != nil { scope.err(err, w, req) return } trace.Step("About to write a response") scope.Trace = trace - transformResponseObject(ctx, scope, req, w, http.StatusOK, result) + transformResponseObject(ctx, scope, req, w, http.StatusOK, outputMediaType, result) trace.Step("Transformed response object") } } @@ -187,6 +185,12 @@ func ListResource(r rest.Lister, rw rest.Watcher, scope RequestScope, forceWatch ctx := req.Context() ctx = request.WithNamespace(ctx, namespace) + outputMediaType, _, err := negotiation.NegotiateOutputMediaType(req, scope.Serializer, &scope) + if err != nil { + scope.err(err, w, req) + return + } + opts := metainternalversion.ListOptions{} if err := metainternalversion.ParameterCodec.DecodeParameters(req.URL.Query(), scope.MetaGroupVersion, &opts); err != nil { err = errors.NewBadRequest(err.Error()) @@ -252,7 +256,7 @@ func ListResource(r rest.Lister, rw rest.Watcher, scope RequestScope, forceWatch return } requestInfo, _ := request.RequestInfoFrom(ctx) - metrics.RecordLongRunning(req, requestInfo, func() { + metrics.RecordLongRunning(req, requestInfo, metrics.APIServerComponent, func() { serveWatch(watcher, scope, req, w, timeout) }) return @@ -267,22 +271,9 @@ func ListResource(r rest.Lister, rw rest.Watcher, scope RequestScope, forceWatch return } trace.Step("Listing from storage done") - numberOfItems, err := setListSelfLink(result, ctx, req, scope.Namer) - if err != nil { - scope.err(err, w, req) - return - } - trace.Step("Self-linking done") - // Ensure empty lists return a non-nil items slice - if numberOfItems == 0 && meta.IsListType(result) { - if err := meta.SetList(result, []runtime.Object{}); err != nil { - scope.err(err, w, req) - return - } - } scope.Trace = trace - transformResponseObject(ctx, scope, req, w, http.StatusOK, result) - trace.Step(fmt.Sprintf("Writing http response done (%d items)", numberOfItems)) + transformResponseObject(ctx, scope, req, w, http.StatusOK, outputMediaType, result) + trace.Step(fmt.Sprintf("Writing http response done (%d items)", meta.LenList(result))) } } diff --git a/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/patch.go b/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/patch.go index 6bfd4dbf5e9..6367a6cba10 100644 --- a/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/patch.go +++ b/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/patch.go @@ -91,6 +91,12 @@ func PatchResource(r rest.Patcher, scope RequestScope, admit admission.Interface ctx := req.Context() ctx = request.WithNamespace(ctx, namespace) + outputMediaType, _, err := negotiation.NegotiateOutputMediaType(req, scope.Serializer, &scope) + if err != nil { + scope.err(err, w, req) + return + } + patchBytes, err := readBody(req) if err != nil { scope.err(err, w, req) @@ -223,7 +229,7 @@ func PatchResource(r rest.Patcher, scope RequestScope, admit admission.Interface status = http.StatusCreated } scope.Trace = trace - transformResponseObject(ctx, scope, req, w, status, result) + transformResponseObject(ctx, scope, req, w, status, outputMediaType, result) } } diff --git a/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/response.go b/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/response.go index e140c081746..f9f363840f7 100644 --- a/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/response.go +++ b/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/response.go @@ -27,160 +27,85 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1beta1 "k8s.io/apimachinery/pkg/apis/meta/v1beta1" "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apiserver/pkg/endpoints/handlers/negotiation" "k8s.io/apiserver/pkg/endpoints/handlers/responsewriters" ) // transformResponseObject takes an object loaded from storage and performs any necessary transformations. // Will write the complete response object. -func transformResponseObject(ctx context.Context, scope RequestScope, req *http.Request, w http.ResponseWriter, statusCode int, result runtime.Object) { - // TODO: fetch the media type much earlier in request processing and pass it into this method. - trace := scope.Trace - mediaType, _, err := negotiation.NegotiateOutputMediaType(req, scope.Serializer, &scope) - if err != nil { - status := responsewriters.ErrorToAPIStatus(err) - trace.Step("Writing raw JSON response") - responsewriters.WriteRawJSON(int(status.Code), status, w) +func transformResponseObject(ctx context.Context, scope RequestScope, req *http.Request, w http.ResponseWriter, statusCode int, mediaType negotiation.MediaTypeOptions, result runtime.Object) { + // status objects are ignored for transformation + if _, ok := result.(*metav1.Status); ok { + responsewriters.WriteObject(statusCode, scope.Kind.GroupVersion(), scope.Serializer, result, w, req) return } - // If conversion was allowed by the scope, perform it before writing the response - if target := mediaType.Convert; target != nil { - switch { - - case target.Kind == "PartialObjectMetadata" && target.GroupVersion() == metav1beta1.SchemeGroupVersion: - if meta.IsListType(result) { - // TODO: this should be calculated earlier - err = newNotAcceptableError(fmt.Sprintf("you requested PartialObjectMetadata, but the requested object is a list (%T)", result)) - scope.err(err, w, req) - return - } - m, err := meta.Accessor(result) - if err != nil { - scope.err(err, w, req) - return - } - partial := meta.AsPartialObjectMetadata(m) - partial.GetObjectKind().SetGroupVersionKind(metav1beta1.SchemeGroupVersion.WithKind("PartialObjectMetadata")) - - // renegotiate under the internal version - _, info, err := negotiation.NegotiateOutputMediaType(req, metainternalversion.Codecs, &scope) - if err != nil { - scope.err(err, w, req) - return - } - encoder := metainternalversion.Codecs.EncoderForVersion(info.Serializer, metav1beta1.SchemeGroupVersion) - trace.Step(fmt.Sprintf("Serializing response as type %s", info.MediaType)) - responsewriters.SerializeObject(info.MediaType, encoder, w, req, statusCode, partial) - return - - case target.Kind == "PartialObjectMetadataList" && target.GroupVersion() == metav1beta1.SchemeGroupVersion: - if !meta.IsListType(result) { - // TODO: this should be calculated earlier - err = newNotAcceptableError(fmt.Sprintf("you requested PartialObjectMetadataList, but the requested object is not a list (%T)", result)) - scope.err(err, w, req) - return - } - list := &metav1beta1.PartialObjectMetadataList{} - trace.Step("Processing list items") - err := meta.EachListItem(result, func(obj runtime.Object) error { - m, err := meta.Accessor(obj) - if err != nil { - return err - } - partial := meta.AsPartialObjectMetadata(m) - partial.GetObjectKind().SetGroupVersionKind(metav1beta1.SchemeGroupVersion.WithKind("PartialObjectMetadata")) - list.Items = append(list.Items, partial) - return nil - }) - if err != nil { - scope.err(err, w, req) - return - } - - // renegotiate under the internal version - _, info, err := negotiation.NegotiateOutputMediaType(req, metainternalversion.Codecs, &scope) - if err != nil { - scope.err(err, w, req) - return - } - encoder := metainternalversion.Codecs.EncoderForVersion(info.Serializer, metav1beta1.SchemeGroupVersion) - trace.Step(fmt.Sprintf("Serializing response as type %s", info.MediaType)) - responsewriters.SerializeObject(info.MediaType, encoder, w, req, statusCode, list) - return - - case target.Kind == "Table" && target.GroupVersion() == metav1beta1.SchemeGroupVersion: - // TODO: relax the version abstraction - // TODO: skip if this is a status response (delete without body)? - - opts := &metav1beta1.TableOptions{} - trace.Step("Decoding parameters") - if err := metav1beta1.ParameterCodec.DecodeParameters(req.URL.Query(), metav1beta1.SchemeGroupVersion, opts); err != nil { - scope.err(err, w, req) - return - } - - trace.Step("Converting to table") - table, err := scope.TableConvertor.ConvertToTable(ctx, result, opts) - if err != nil { - scope.err(err, w, req) - return - } - - trace.Step("Processing rows") - for i := range table.Rows { - item := &table.Rows[i] - switch opts.IncludeObject { - case metav1beta1.IncludeObject: - item.Object.Object, err = scope.Convertor.ConvertToVersion(item.Object.Object, scope.Kind.GroupVersion()) - if err != nil { - scope.err(err, w, req) - return - } - // TODO: rely on defaulting for the value here? - case metav1beta1.IncludeMetadata, "": - m, err := meta.Accessor(item.Object.Object) - if err != nil { - scope.err(err, w, req) - return - } - // TODO: turn this into an internal type and do conversion in order to get object kind automatically set? - partial := meta.AsPartialObjectMetadata(m) - partial.GetObjectKind().SetGroupVersionKind(metav1beta1.SchemeGroupVersion.WithKind("PartialObjectMetadata")) - item.Object.Object = partial - case metav1beta1.IncludeNone: - item.Object.Object = nil - default: - // TODO: move this to validation on the table options? - err = errors.NewBadRequest(fmt.Sprintf("unrecognized includeObject value: %q", opts.IncludeObject)) - scope.err(err, w, req) - } - } - - // renegotiate under the internal version - _, info, err := negotiation.NegotiateOutputMediaType(req, metainternalversion.Codecs, &scope) - if err != nil { - scope.err(err, w, req) - return - } - encoder := metainternalversion.Codecs.EncoderForVersion(info.Serializer, metav1beta1.SchemeGroupVersion) - trace.Step(fmt.Sprintf("Serializing response as type %s", info.MediaType)) - responsewriters.SerializeObject(info.MediaType, encoder, w, req, statusCode, table) - return - - default: - // this block should only be hit if scope AllowsConversion is incorrect - accepted, _ := negotiation.MediaTypesForSerializer(metainternalversion.Codecs) - err := negotiation.NewNotAcceptableError(accepted) - status := responsewriters.ErrorToAPIStatus(err) - trace.Step("Writing raw JSON response") - responsewriters.WriteRawJSON(int(status.Code), status, w) - return - } + // ensure the self link and empty list array are set + if err := setObjectSelfLink(ctx, result, req, scope.Namer); err != nil { + scope.err(err, w, req) + return } - trace.Step("Writing response") - responsewriters.WriteObject(statusCode, scope.Kind.GroupVersion(), scope.Serializer, result, w, req) + trace := scope.Trace + + // If conversion was allowed by the scope, perform it before writing the response + switch target := mediaType.Convert; { + + case target == nil: + trace.Step("Writing response") + responsewriters.WriteObject(statusCode, scope.Kind.GroupVersion(), scope.Serializer, result, w, req) + + case target.Kind == "PartialObjectMetadata" && target.GroupVersion() == metav1beta1.SchemeGroupVersion: + partial, err := asV1Beta1PartialObjectMetadata(result) + if err != nil { + scope.err(err, w, req) + return + } + + if err := writeMetaInternalVersion(partial, statusCode, w, req, &scope, target.GroupVersion()); err != nil { + scope.err(err, w, req) + return + } + + case target.Kind == "PartialObjectMetadataList" && target.GroupVersion() == metav1beta1.SchemeGroupVersion: + trace.Step("Processing list items") + partial, err := asV1Beta1PartialObjectMetadataList(result) + if err != nil { + scope.err(err, w, req) + return + } + + if err := writeMetaInternalVersion(partial, statusCode, w, req, &scope, target.GroupVersion()); err != nil { + scope.err(err, w, req) + return + } + + case target.Kind == "Table" && target.GroupVersion() == metav1beta1.SchemeGroupVersion: + opts := &metav1beta1.TableOptions{} + trace.Step("Decoding parameters") + if err := metav1beta1.ParameterCodec.DecodeParameters(req.URL.Query(), metav1beta1.SchemeGroupVersion, opts); err != nil { + scope.err(err, w, req) + return + } + + table, err := asV1Beta1Table(ctx, result, opts, scope) + if err != nil { + scope.err(err, w, req) + return + } + + if err := writeMetaInternalVersion(table, statusCode, w, req, &scope, target.GroupVersion()); err != nil { + scope.err(err, w, req) + return + } + + default: + // this block should only be hit if scope AllowsConversion is incorrect + accepted, _ := negotiation.MediaTypesForSerializer(metainternalversion.Codecs) + err := negotiation.NewNotAcceptableError(accepted) + scope.err(err, w, req) + } } // errNotAcceptable indicates Accept negotiation has failed @@ -204,3 +129,91 @@ func (e errNotAcceptable) Status() metav1.Status { Message: e.Error(), } } + +func asV1Beta1Table(ctx context.Context, result runtime.Object, opts *metav1beta1.TableOptions, scope RequestScope) (runtime.Object, error) { + trace := scope.Trace + + trace.Step("Converting to table") + table, err := scope.TableConvertor.ConvertToTable(ctx, result, opts) + if err != nil { + return nil, err + } + + trace.Step("Processing rows") + for i := range table.Rows { + item := &table.Rows[i] + switch opts.IncludeObject { + case metav1beta1.IncludeObject: + item.Object.Object, err = scope.Convertor.ConvertToVersion(item.Object.Object, scope.Kind.GroupVersion()) + if err != nil { + return nil, err + } + // TODO: rely on defaulting for the value here? + case metav1beta1.IncludeMetadata, "": + m, err := meta.Accessor(item.Object.Object) + if err != nil { + return nil, err + } + // TODO: turn this into an internal type and do conversion in order to get object kind automatically set? + partial := meta.AsPartialObjectMetadata(m) + partial.GetObjectKind().SetGroupVersionKind(metav1beta1.SchemeGroupVersion.WithKind("PartialObjectMetadata")) + item.Object.Object = partial + case metav1beta1.IncludeNone: + item.Object.Object = nil + default: + // TODO: move this to validation on the table options? + err = errors.NewBadRequest(fmt.Sprintf("unrecognized includeObject value: %q", opts.IncludeObject)) + return nil, err + } + } + + return table, nil +} + +func asV1Beta1PartialObjectMetadata(result runtime.Object) (runtime.Object, error) { + if meta.IsListType(result) { + // TODO: this should be calculated earlier + err := newNotAcceptableError(fmt.Sprintf("you requested PartialObjectMetadata, but the requested object is a list (%T)", result)) + return nil, err + } + m, err := meta.Accessor(result) + if err != nil { + return nil, err + } + partial := meta.AsPartialObjectMetadata(m) + partial.GetObjectKind().SetGroupVersionKind(metav1beta1.SchemeGroupVersion.WithKind("PartialObjectMetadata")) + return partial, nil +} + +func asV1Beta1PartialObjectMetadataList(result runtime.Object) (runtime.Object, error) { + if !meta.IsListType(result) { + // TODO: this should be calculated earlier + return nil, newNotAcceptableError(fmt.Sprintf("you requested PartialObjectMetadataList, but the requested object is not a list (%T)", result)) + } + list := &metav1beta1.PartialObjectMetadataList{} + err := meta.EachListItem(result, func(obj runtime.Object) error { + m, err := meta.Accessor(obj) + if err != nil { + return err + } + partial := meta.AsPartialObjectMetadata(m) + partial.GetObjectKind().SetGroupVersionKind(metav1beta1.SchemeGroupVersion.WithKind("PartialObjectMetadata")) + list.Items = append(list.Items, partial) + return nil + }) + if err != nil { + return nil, err + } + return list, nil +} + +func writeMetaInternalVersion(obj runtime.Object, statusCode int, w http.ResponseWriter, req *http.Request, restrictions negotiation.EndpointRestrictions, target schema.GroupVersion) error { + // renegotiate under the internal version + _, info, err := negotiation.NegotiateOutputMediaType(req, metainternalversion.Codecs, restrictions) + if err != nil { + return err + } + encoder := metainternalversion.Codecs.EncoderForVersion(info.Serializer, target) + responsewriters.SerializeObject(info.MediaType, encoder, w, req, statusCode, obj) + return nil +} diff --git a/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/responsewriters/status.go b/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/responsewriters/status.go index 99673077b2b..5a845435033 100755 --- a/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/responsewriters/status.go +++ b/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/responsewriters/status.go @@ -38,11 +38,18 @@ func ErrorToAPIStatus(err error) *metav1.Status { if len(status.Status) == 0 { status.Status = metav1.StatusFailure } - if status.Code == 0 { - switch status.Status { - case metav1.StatusSuccess: + switch status.Status { + case metav1.StatusSuccess: + if status.Code == 0 { status.Code = http.StatusOK - case metav1.StatusFailure: + } + case metav1.StatusFailure: + if status.Code == 0 { + status.Code = http.StatusInternalServerError + } + default: + runtime.HandleError(fmt.Errorf("apiserver received an error with wrong status field : %#+v", err)) + if status.Code == 0 { status.Code = http.StatusInternalServerError } } diff --git a/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/responsewriters/status_test.go b/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/responsewriters/status_test.go index b4a8bf42c78..9e1d37bd2b2 100644 --- a/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/responsewriters/status_test.go +++ b/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/responsewriters/status_test.go @@ -27,6 +27,19 @@ import ( "k8s.io/apimachinery/pkg/runtime/schema" ) +func TestBadStatusErrorToAPIStatus(t *testing.T) { + err := errors.StatusError{} + actual := ErrorToAPIStatus(&err) + expected := &metav1.Status{ + TypeMeta: metav1.TypeMeta{Kind: "Status", APIVersion: "v1"}, + Status: metav1.StatusFailure, + Code: 500, + } + if !reflect.DeepEqual(actual, expected) { + t.Errorf("%s: Expected %#v, Got %#v", actual, expected, actual) + } +} + func TestAPIStatus(t *testing.T) { cases := map[error]metav1.Status{ errors.NewNotFound(schema.GroupResource{Group: "legacy.kubernetes.io", Resource: "foos"}, "bar"): { diff --git a/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/responsewriters/writers.go b/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/responsewriters/writers.go index fd335b5d7e5..5a811401cf3 100644 --- a/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/responsewriters/writers.go +++ b/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/responsewriters/writers.go @@ -64,7 +64,7 @@ func WriteObject(statusCode int, gv schema.GroupVersion, s runtime.NegotiatedSer stream, ok := object.(rest.ResourceStreamer) if ok { requestInfo, _ := request.RequestInfoFrom(req.Context()) - metrics.RecordLongRunning(req, requestInfo, func() { + metrics.RecordLongRunning(req, requestInfo, metrics.APIServerComponent, func() { StreamObject(statusCode, gv, s, stream, w, req) }) return @@ -101,6 +101,10 @@ func StreamObject(statusCode int, gv schema.GroupVersion, s runtime.NegotiatedSe } w.Header().Set("Content-Type", contentType) w.WriteHeader(statusCode) + // Flush headers, if possible + if flusher, ok := w.(http.Flusher); ok { + flusher.Flush() + } writer := w.(io.Writer) if flush { writer = flushwriter.Wrap(w) diff --git a/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/rest.go b/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/rest.go index f058e24dcfb..7e56b164138 100644 --- a/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/rest.go +++ b/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/rest.go @@ -143,7 +143,7 @@ func ConnectResource(connecter rest.Connecter, scope RequestScope, admit admissi } } requestInfo, _ := request.RequestInfoFrom(ctx) - metrics.RecordLongRunning(req, requestInfo, func() { + metrics.RecordLongRunning(req, requestInfo, metrics.APIServerComponent, func() { handler, err := connecter.Connect(ctx, name, opts, &responder{scope: scope, req: req, w: w}) if err != nil { scope.err(err, w, req) @@ -279,23 +279,26 @@ func checkName(obj runtime.Object, name, namespace string, namer ScopeNamer) err return nil } -// setListSelfLink sets the self link of a list to the base URL, then sets the self links -// on all child objects returned. Returns the number of items in the list. -func setListSelfLink(obj runtime.Object, ctx context.Context, req *http.Request, namer ScopeNamer) (int, error) { +// setObjectSelfLink sets the self link of an object as needed. +func setObjectSelfLink(ctx context.Context, obj runtime.Object, req *http.Request, namer ScopeNamer) error { if !meta.IsListType(obj) { - return 0, nil + requestInfo, ok := request.RequestInfoFrom(ctx) + if !ok { + return fmt.Errorf("missing requestInfo") + } + return setSelfLink(obj, requestInfo, namer) } uri, err := namer.GenerateListLink(req) if err != nil { - return 0, err + return err } if err := namer.SetSelfLink(obj, uri); err != nil { klog.V(4).Infof("Unable to set self link on object: %v", err) } requestInfo, ok := request.RequestInfoFrom(ctx) if !ok { - return 0, fmt.Errorf("missing requestInfo") + return fmt.Errorf("missing requestInfo") } count := 0 @@ -303,7 +306,14 @@ func setListSelfLink(obj runtime.Object, ctx context.Context, req *http.Request, count++ return setSelfLink(obj, requestInfo, namer) }) - return count, err + + if count == 0 { + if err := meta.SetList(obj, []runtime.Object{}); err != nil { + return err + } + } + + return err } func summarizeData(data []byte, maxLength int) string { diff --git a/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/rest_test.go b/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/rest_test.go index c157fc3e9b3..3ac685c0409 100644 --- a/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/rest_test.go +++ b/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/rest_test.go @@ -887,7 +887,6 @@ func TestFinishRequest(t *testing.T) { timeout: time.Second, fn: func() (runtime.Object, error) { panic("my panic") - return nil, nil }, expectedObj: nil, expectedErr: nil, @@ -898,7 +897,6 @@ func TestFinishRequest(t *testing.T) { timeout: time.Second, fn: func() (runtime.Object, error) { panic("my panic") - return nil, nil }, expectedObj: nil, expectedErr: nil, diff --git a/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/update.go b/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/update.go index c942b7775cc..328c5e7fe8f 100644 --- a/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/update.go +++ b/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/update.go @@ -65,6 +65,12 @@ func UpdateResource(r rest.Updater, scope RequestScope, admit admission.Interfac ctx := req.Context() ctx = request.WithNamespace(ctx, namespace) + outputMediaType, _, err := negotiation.NegotiateOutputMediaType(req, scope.Serializer, &scope) + if err != nil { + scope.err(err, w, req) + return + } + body, err := readBody(req) if err != nil { scope.err(err, w, req) @@ -185,24 +191,13 @@ func UpdateResource(r rest.Updater, scope RequestScope, admit admission.Interfac } trace.Step("Object stored in database") - requestInfo, ok := request.RequestInfoFrom(ctx) - if !ok { - scope.err(fmt.Errorf("missing requestInfo"), w, req) - return - } - if err := setSelfLink(result, requestInfo, scope.Namer); err != nil { - scope.err(err, w, req) - return - } - trace.Step("Self-link added") - status := http.StatusOK if wasCreated { status = http.StatusCreated } scope.Trace = trace - transformResponseObject(ctx, scope, req, w, status, result) + transformResponseObject(ctx, scope, req, w, status, outputMediaType, result) } } diff --git a/staging/src/k8s.io/apiserver/pkg/endpoints/installer.go b/staging/src/k8s.io/apiserver/pkg/endpoints/installer.go index 0a6c83ad0d1..4b9650b5575 100644 --- a/staging/src/k8s.io/apiserver/pkg/endpoints/installer.go +++ b/staging/src/k8s.io/apiserver/pkg/endpoints/installer.go @@ -178,6 +178,8 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag return nil, err } + group, version := a.group.GroupVersion.Group, a.group.GroupVersion.Version + fqKindToRegister, err := GetResourceKind(a.group.GroupVersion, storage, a.group.Typer) if err != nil { return nil, err @@ -589,9 +591,9 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag if needOverride { // need change the reported verb - handler = metrics.InstrumentRouteFunc(verbOverrider.OverrideMetricsVerb(action.Verb), resource, subresource, requestScope, handler) + handler = metrics.InstrumentRouteFunc(verbOverrider.OverrideMetricsVerb(action.Verb), group, version, resource, subresource, requestScope, metrics.APIServerComponent, handler) } else { - handler = metrics.InstrumentRouteFunc(action.Verb, resource, subresource, requestScope, handler) + handler = metrics.InstrumentRouteFunc(action.Verb, group, version, resource, subresource, requestScope, metrics.APIServerComponent, handler) } if a.enableAPIResponseCompression { @@ -625,7 +627,7 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag if isSubresource { doc = "list " + subresource + " of objects of kind " + kind } - handler := metrics.InstrumentRouteFunc(action.Verb, resource, subresource, requestScope, restfulListResource(lister, watcher, reqScope, false, a.minRequestTimeout)) + handler := metrics.InstrumentRouteFunc(action.Verb, group, version, resource, subresource, requestScope, metrics.APIServerComponent, restfulListResource(lister, watcher, reqScope, false, a.minRequestTimeout)) if a.enableAPIResponseCompression { handler = genericfilters.RestfulWithCompression(handler) } @@ -660,7 +662,7 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag if isSubresource { doc = "replace " + subresource + " of the specified " + kind } - handler := metrics.InstrumentRouteFunc(action.Verb, resource, subresource, requestScope, restfulUpdateResource(updater, reqScope, admit)) + handler := metrics.InstrumentRouteFunc(action.Verb, group, version, resource, subresource, requestScope, metrics.APIServerComponent, restfulUpdateResource(updater, reqScope, admit)) route := ws.PUT(action.Path).To(handler). Doc(doc). Param(ws.QueryParameter("pretty", "If 'true', then the output is pretty printed.")). @@ -690,7 +692,7 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag if utilfeature.DefaultFeatureGate.Enabled(features.ServerSideApply) { supportedTypes = append(supportedTypes, string(types.ApplyPatchType)) } - handler := metrics.InstrumentRouteFunc(action.Verb, resource, subresource, requestScope, restfulPatchResource(patcher, reqScope, admit, supportedTypes)) + handler := metrics.InstrumentRouteFunc(action.Verb, group, version, resource, subresource, requestScope, metrics.APIServerComponent, restfulPatchResource(patcher, reqScope, admit, supportedTypes)) route := ws.PATCH(action.Path).To(handler). Doc(doc). Param(ws.QueryParameter("pretty", "If 'true', then the output is pretty printed.")). @@ -712,7 +714,7 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag } else { handler = restfulCreateResource(creater, reqScope, admit) } - handler = metrics.InstrumentRouteFunc(action.Verb, resource, subresource, requestScope, handler) + handler = metrics.InstrumentRouteFunc(action.Verb, group, version, resource, subresource, requestScope, metrics.APIServerComponent, handler) article := getArticleForNoun(kind, " ") doc := "create" + article + kind if isSubresource { @@ -741,7 +743,7 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag if isSubresource { doc = "delete " + subresource + " of" + article + kind } - handler := metrics.InstrumentRouteFunc(action.Verb, resource, subresource, requestScope, restfulDeleteResource(gracefulDeleter, isGracefulDeleter, reqScope, admit)) + handler := metrics.InstrumentRouteFunc(action.Verb, group, version, resource, subresource, requestScope, metrics.APIServerComponent, restfulDeleteResource(gracefulDeleter, isGracefulDeleter, reqScope, admit)) route := ws.DELETE(action.Path).To(handler). Doc(doc). Param(ws.QueryParameter("pretty", "If 'true', then the output is pretty printed.")). @@ -764,7 +766,7 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag if isSubresource { doc = "delete collection of " + subresource + " of a " + kind } - handler := metrics.InstrumentRouteFunc(action.Verb, resource, subresource, requestScope, restfulDeleteCollection(collectionDeleter, isCollectionDeleter, reqScope, admit)) + handler := metrics.InstrumentRouteFunc(action.Verb, group, version, resource, subresource, requestScope, metrics.APIServerComponent, restfulDeleteCollection(collectionDeleter, isCollectionDeleter, reqScope, admit)) route := ws.DELETE(action.Path).To(handler). Doc(doc). Param(ws.QueryParameter("pretty", "If 'true', then the output is pretty printed.")). @@ -784,7 +786,7 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag doc = "watch changes to " + subresource + " of an object of kind " + kind } doc += ". deprecated: use the 'watch' parameter with a list operation instead, filtered to a single item with the 'fieldSelector' parameter." - handler := metrics.InstrumentRouteFunc(action.Verb, resource, subresource, requestScope, restfulListResource(lister, watcher, reqScope, true, a.minRequestTimeout)) + handler := metrics.InstrumentRouteFunc(action.Verb, group, version, resource, subresource, requestScope, metrics.APIServerComponent, restfulListResource(lister, watcher, reqScope, true, a.minRequestTimeout)) route := ws.GET(action.Path).To(handler). Doc(doc). Param(ws.QueryParameter("pretty", "If 'true', then the output is pretty printed.")). @@ -804,7 +806,7 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag doc = "watch individual changes to a list of " + subresource + " of " + kind } doc += ". deprecated: use the 'watch' parameter with a list operation instead." - handler := metrics.InstrumentRouteFunc(action.Verb, resource, subresource, requestScope, restfulListResource(lister, watcher, reqScope, true, a.minRequestTimeout)) + handler := metrics.InstrumentRouteFunc(action.Verb, group, version, resource, subresource, requestScope, metrics.APIServerComponent, restfulListResource(lister, watcher, reqScope, true, a.minRequestTimeout)) route := ws.GET(action.Path).To(handler). Doc(doc). Param(ws.QueryParameter("pretty", "If 'true', then the output is pretty printed.")). @@ -827,7 +829,7 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag if isSubresource { doc = "connect " + method + " requests to " + subresource + " of " + kind } - handler := metrics.InstrumentRouteFunc(action.Verb, resource, subresource, requestScope, restfulConnectResource(connecter, reqScope, admit, path, isSubresource)) + handler := metrics.InstrumentRouteFunc(action.Verb, group, version, resource, subresource, requestScope, metrics.APIServerComponent, restfulConnectResource(connecter, reqScope, admit, path, isSubresource)) route := ws.Method(method).Path(action.Path). To(handler). Doc(doc). diff --git a/staging/src/k8s.io/apiserver/pkg/endpoints/metrics/metrics.go b/staging/src/k8s.io/apiserver/pkg/endpoints/metrics/metrics.go index ae16d43bb1e..e2b3d8d07bb 100644 --- a/staging/src/k8s.io/apiserver/pkg/endpoints/metrics/metrics.go +++ b/staging/src/k8s.io/apiserver/pkg/endpoints/metrics/metrics.go @@ -40,50 +40,54 @@ type resettableCollector interface { Reset() } +const ( + APIServerComponent string = "apiserver" +) + var ( // TODO(a-robinson): Add unit tests for the handling of these metrics once // the upstream library supports it. requestCounter = prometheus.NewCounterVec( prometheus.CounterOpts{ Name: "apiserver_request_count", - Help: "Counter of apiserver requests broken out for each verb, API resource, client, and HTTP response contentType and code.", + Help: "Counter of apiserver requests broken out for each verb, group, version, resource, scope, component, client, and HTTP response contentType and code.", }, - []string{"verb", "resource", "subresource", "scope", "client", "contentType", "code"}, + []string{"verb", "group", "version", "resource", "subresource", "scope", "component", "client", "contentType", "code"}, ) longRunningRequestGauge = prometheus.NewGaugeVec( prometheus.GaugeOpts{ Name: "apiserver_longrunning_gauge", - Help: "Gauge of all active long-running apiserver requests broken out by verb, API resource, and scope. Not all requests are tracked this way.", + Help: "Gauge of all active long-running apiserver requests broken out by verb, group, version, resource, scope and component. Not all requests are tracked this way.", }, - []string{"verb", "resource", "subresource", "scope"}, + []string{"verb", "group", "version", "resource", "subresource", "scope", "component"}, ) requestLatencies = prometheus.NewHistogramVec( prometheus.HistogramOpts{ Name: "apiserver_request_latencies", - Help: "Response latency distribution in microseconds for each verb, resource and subresource.", + Help: "Response latency distribution in microseconds for each verb, group, version, resource, subresource, scope and component.", // Use buckets ranging from 125 ms to 8 seconds. Buckets: prometheus.ExponentialBuckets(125000, 2.0, 7), }, - []string{"verb", "resource", "subresource", "scope"}, + []string{"verb", "group", "version", "resource", "subresource", "scope", "component"}, ) requestLatenciesSummary = prometheus.NewSummaryVec( prometheus.SummaryOpts{ Name: "apiserver_request_latencies_summary", - Help: "Response latency summary in microseconds for each verb, resource and subresource.", + Help: "Response latency summary in microseconds for each verb, group, version, resource, subresource, scope and component.", // Make the sliding window of 5h. // TODO: The value for this should be based on our SLI definition (medium term). MaxAge: 5 * time.Hour, }, - []string{"verb", "resource", "subresource", "scope"}, + []string{"verb", "group", "version", "resource", "subresource", "scope", "component"}, ) responseSizes = prometheus.NewHistogramVec( prometheus.HistogramOpts{ Name: "apiserver_response_sizes", - Help: "Response size distribution in bytes for each verb, resource, subresource and scope (namespace/cluster).", + Help: "Response size distribution in bytes for each group, version, verb, resource, subresource, scope and component.", // Use buckets ranging from 1000 bytes (1KB) to 10^9 bytes (1GB). Buckets: prometheus.ExponentialBuckets(1000, 10.0, 7), }, - []string{"verb", "resource", "subresource", "scope"}, + []string{"verb", "group", "version", "resource", "subresource", "scope", "component"}, ) // DroppedRequests is a number of requests dropped with 'Try again later' response" DroppedRequests = prometheus.NewCounterVec( @@ -106,7 +110,7 @@ var ( currentInflightRequests = prometheus.NewGaugeVec( prometheus.GaugeOpts{ Name: "apiserver_current_inflight_requests", - Help: "Maximal mumber of currently used inflight request limit of this apiserver per request kind in last second.", + Help: "Maximal number of currently used inflight request limit of this apiserver per request kind in last second.", }, []string{"requestKind"}, ) @@ -157,21 +161,21 @@ func UpdateInflightRequestMetrics(nonmutating, mutating int) { // Record records a single request to the standard metrics endpoints. For use by handlers that perform their own // processing. All API paths should use InstrumentRouteFunc implicitly. Use this instead of MonitorRequest if // you already have a RequestInfo object. -func Record(req *http.Request, requestInfo *request.RequestInfo, contentType string, code int, responseSizeInBytes int, elapsed time.Duration) { +func Record(req *http.Request, requestInfo *request.RequestInfo, component, contentType string, code int, responseSizeInBytes int, elapsed time.Duration) { if requestInfo == nil { requestInfo = &request.RequestInfo{Verb: req.Method, Path: req.URL.Path} } scope := CleanScope(requestInfo) if requestInfo.IsResourceRequest { - MonitorRequest(req, strings.ToUpper(requestInfo.Verb), requestInfo.Resource, requestInfo.Subresource, scope, contentType, code, responseSizeInBytes, elapsed) + MonitorRequest(req, strings.ToUpper(requestInfo.Verb), requestInfo.APIGroup, requestInfo.APIVersion, requestInfo.Resource, requestInfo.Subresource, scope, component, contentType, code, responseSizeInBytes, elapsed) } else { - MonitorRequest(req, strings.ToUpper(requestInfo.Verb), "", requestInfo.Path, scope, contentType, code, responseSizeInBytes, elapsed) + MonitorRequest(req, strings.ToUpper(requestInfo.Verb), "", "", "", requestInfo.Path, scope, component, contentType, code, responseSizeInBytes, elapsed) } } // RecordLongRunning tracks the execution of a long running request against the API server. It provides an accurate count // of the total number of open long running requests. requestInfo may be nil if the caller is not in the normal request flow. -func RecordLongRunning(req *http.Request, requestInfo *request.RequestInfo, fn func()) { +func RecordLongRunning(req *http.Request, requestInfo *request.RequestInfo, component string, fn func()) { if requestInfo == nil { requestInfo = &request.RequestInfo{Verb: req.Method, Path: req.URL.Path} } @@ -179,9 +183,9 @@ func RecordLongRunning(req *http.Request, requestInfo *request.RequestInfo, fn f scope := CleanScope(requestInfo) reportedVerb := cleanVerb(strings.ToUpper(requestInfo.Verb), req) if requestInfo.IsResourceRequest { - g = longRunningRequestGauge.WithLabelValues(reportedVerb, requestInfo.Resource, requestInfo.Subresource, scope) + g = longRunningRequestGauge.WithLabelValues(reportedVerb, requestInfo.APIGroup, requestInfo.APIVersion, requestInfo.Resource, requestInfo.Subresource, scope, component) } else { - g = longRunningRequestGauge.WithLabelValues(reportedVerb, "", requestInfo.Path, scope) + g = longRunningRequestGauge.WithLabelValues(reportedVerb, "", "", "", requestInfo.Path, scope, component) } g.Inc() defer g.Dec() @@ -190,22 +194,22 @@ func RecordLongRunning(req *http.Request, requestInfo *request.RequestInfo, fn f // MonitorRequest handles standard transformations for client and the reported verb and then invokes Monitor to record // a request. verb must be uppercase to be backwards compatible with existing monitoring tooling. -func MonitorRequest(req *http.Request, verb, resource, subresource, scope, contentType string, httpCode, respSize int, elapsed time.Duration) { +func MonitorRequest(req *http.Request, verb, group, version, resource, subresource, scope, component, contentType string, httpCode, respSize int, elapsed time.Duration) { reportedVerb := cleanVerb(verb, req) client := cleanUserAgent(utilnet.GetHTTPClient(req)) elapsedMicroseconds := float64(elapsed / time.Microsecond) - requestCounter.WithLabelValues(reportedVerb, resource, subresource, scope, client, contentType, codeToString(httpCode)).Inc() - requestLatencies.WithLabelValues(reportedVerb, resource, subresource, scope).Observe(elapsedMicroseconds) - requestLatenciesSummary.WithLabelValues(reportedVerb, resource, subresource, scope).Observe(elapsedMicroseconds) + requestCounter.WithLabelValues(reportedVerb, group, version, resource, subresource, scope, component, client, contentType, codeToString(httpCode)).Inc() + requestLatencies.WithLabelValues(reportedVerb, group, version, resource, subresource, scope, component).Observe(elapsedMicroseconds) + requestLatenciesSummary.WithLabelValues(reportedVerb, group, version, resource, subresource, scope, component).Observe(elapsedMicroseconds) // We are only interested in response sizes of read requests. if verb == "GET" || verb == "LIST" { - responseSizes.WithLabelValues(reportedVerb, resource, subresource, scope).Observe(float64(respSize)) + responseSizes.WithLabelValues(reportedVerb, group, version, resource, subresource, scope, component).Observe(float64(respSize)) } } // InstrumentRouteFunc works like Prometheus' InstrumentHandlerFunc but wraps // the go-restful RouteFunction instead of a HandlerFunc plus some Kubernetes endpoint specific information. -func InstrumentRouteFunc(verb, resource, subresource, scope string, routeFunc restful.RouteFunction) restful.RouteFunction { +func InstrumentRouteFunc(verb, group, version, resource, subresource, scope, component string, routeFunc restful.RouteFunction) restful.RouteFunction { return restful.RouteFunction(func(request *restful.Request, response *restful.Response) { now := time.Now() @@ -224,12 +228,12 @@ func InstrumentRouteFunc(verb, resource, subresource, scope string, routeFunc re routeFunc(request, response) - MonitorRequest(request.Request, verb, resource, subresource, scope, delegate.Header().Get("Content-Type"), delegate.Status(), delegate.ContentLength(), time.Since(now)) + MonitorRequest(request.Request, verb, group, version, resource, subresource, scope, component, delegate.Header().Get("Content-Type"), delegate.Status(), delegate.ContentLength(), time.Since(now)) }) } // InstrumentHandlerFunc works like Prometheus' InstrumentHandlerFunc but adds some Kubernetes endpoint specific information. -func InstrumentHandlerFunc(verb, resource, subresource, scope string, handler http.HandlerFunc) http.HandlerFunc { +func InstrumentHandlerFunc(verb, group, version, resource, subresource, scope, component string, handler http.HandlerFunc) http.HandlerFunc { return func(w http.ResponseWriter, req *http.Request) { now := time.Now() @@ -246,7 +250,7 @@ func InstrumentHandlerFunc(verb, resource, subresource, scope string, handler ht handler(w, req) - MonitorRequest(req, verb, resource, subresource, scope, delegate.Header().Get("Content-Type"), delegate.Status(), delegate.ContentLength(), time.Since(now)) + MonitorRequest(req, verb, group, version, resource, subresource, scope, component, delegate.Header().Get("Content-Type"), delegate.Status(), delegate.ContentLength(), time.Since(now)) } } diff --git a/staging/src/k8s.io/apiserver/pkg/server/filters/BUILD b/staging/src/k8s.io/apiserver/pkg/server/filters/BUILD index b75b3de9824..44b669deb5a 100644 --- a/staging/src/k8s.io/apiserver/pkg/server/filters/BUILD +++ b/staging/src/k8s.io/apiserver/pkg/server/filters/BUILD @@ -10,6 +10,7 @@ go_test( name = "go_default_test", srcs = [ "compression_test.go", + "content_type_test.go", "cors_test.go", "maxinflight_test.go", "timeout_test.go", @@ -32,6 +33,7 @@ go_library( name = "go_default_library", srcs = [ "compression.go", + "content_type.go", "cors.go", "doc.go", "longrunning.go", diff --git a/staging/src/k8s.io/apiserver/pkg/server/filters/content_type.go b/staging/src/k8s.io/apiserver/pkg/server/filters/content_type.go new file mode 100644 index 00000000000..65c73fcdc46 --- /dev/null +++ b/staging/src/k8s.io/apiserver/pkg/server/filters/content_type.go @@ -0,0 +1,28 @@ +/* +Copyright 2019 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package filters + +import "net/http" + +// WithContentType sets both the Content-Type and the X-Content-Type-Options (nosniff) header +func WithContentType(handler http.Handler, contentType string) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", contentType) + w.Header().Set("X-Content-Type-Options", "nosniff") + handler.ServeHTTP(w, r) + }) +} diff --git a/staging/src/k8s.io/apiserver/pkg/server/filters/content_type_test.go b/staging/src/k8s.io/apiserver/pkg/server/filters/content_type_test.go new file mode 100644 index 00000000000..3fc163f18cf --- /dev/null +++ b/staging/src/k8s.io/apiserver/pkg/server/filters/content_type_test.go @@ -0,0 +1,60 @@ +/* +Copyright 2019 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package filters + +import ( + "net/http" + "net/http/httptest" + "testing" +) + +func noopHandler() http.HandlerFunc { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + // noop + }) +} + +func TestWithContentType(t *testing.T) { + mux := http.NewServeMux() + mux.Handle("/text", WithContentType(noopHandler(), "text/plain")) + mux.Handle("/json", WithContentType(noopHandler(), "application/json")) + tests := []struct { + description string + path string + expectedMimeType string + }{ + {"/text should return a plain text response", "/text", "text/plain"}, + {"/json should return a json response", "/json", "application/json"}, + } + for _, test := range tests { + path := "http://example.com" + test.path + t.Run(path, func(t *testing.T) { + req, err := http.NewRequest("GET", path, nil) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + w := httptest.NewRecorder() + mux.ServeHTTP(w, req) + if nosniffHeader := w.Header().Get("X-Content-Type-Options"); nosniffHeader != "nosniff" { + t.Errorf("expected nosniff header to be set, got %v", nosniffHeader) + } + if mimeTypeHeader := w.Header().Get("Content-Type"); mimeTypeHeader != test.expectedMimeType { + t.Errorf("expected %v, got %v", test.expectedMimeType, mimeTypeHeader) + } + }) + } +} diff --git a/staging/src/k8s.io/apiserver/pkg/server/filters/maxinflight.go b/staging/src/k8s.io/apiserver/pkg/server/filters/maxinflight.go index 8818cb5633f..cc10d0abd8f 100644 --- a/staging/src/k8s.io/apiserver/pkg/server/filters/maxinflight.go +++ b/staging/src/k8s.io/apiserver/pkg/server/filters/maxinflight.go @@ -176,7 +176,7 @@ func WithMaxInFlightLimit( } } } - metrics.Record(r, requestInfo, "", http.StatusTooManyRequests, 0, 0) + metrics.Record(r, requestInfo, metrics.APIServerComponent, "", http.StatusTooManyRequests, 0, 0) tooManyRequests(r, w) } } diff --git a/staging/src/k8s.io/apiserver/pkg/server/filters/timeout.go b/staging/src/k8s.io/apiserver/pkg/server/filters/timeout.go index adb179f8235..56cd8a4ce05 100644 --- a/staging/src/k8s.io/apiserver/pkg/server/filters/timeout.go +++ b/staging/src/k8s.io/apiserver/pkg/server/filters/timeout.go @@ -58,7 +58,7 @@ func WithTimeoutForNonLongRunningRequests(handler http.Handler, longRunning apir postTimeoutFn := func() { cancel() - metrics.Record(req, requestInfo, "", http.StatusGatewayTimeout, 0, 0) + metrics.Record(req, requestInfo, metrics.APIServerComponent, "", http.StatusGatewayTimeout, 0, 0) } return req, time.After(timeout), postTimeoutFn, apierrors.NewTimeoutError(fmt.Sprintf("request did not complete within %s", timeout), 0) } diff --git a/staging/src/k8s.io/apiserver/pkg/server/healthz/healthz.go b/staging/src/k8s.io/apiserver/pkg/server/healthz/healthz.go index 17d85fbe637..8a975b31623 100644 --- a/staging/src/k8s.io/apiserver/pkg/server/healthz/healthz.go +++ b/staging/src/k8s.io/apiserver/pkg/server/healthz/healthz.go @@ -167,7 +167,7 @@ func handleRootHealthz(checks ...HealthzChecker) http.HandlerFunc { if err := check.Check(r); err != nil { // don't include the error since this endpoint is public. If someone wants more detail // they should have explicit permission to the detailed checks. - klog.V(6).Infof("healthz check %v failed: %v", check.Name(), err) + klog.V(4).Infof("healthz check %v failed: %v", check.Name(), err) fmt.Fprintf(&verboseOut, "[-]%v failed: reason withheld\n", check.Name()) failed = true } else { diff --git a/staging/src/k8s.io/apiserver/pkg/server/options/BUILD b/staging/src/k8s.io/apiserver/pkg/server/options/BUILD index 87318a1f053..79c96a13942 100644 --- a/staging/src/k8s.io/apiserver/pkg/server/options/BUILD +++ b/staging/src/k8s.io/apiserver/pkg/server/options/BUILD @@ -123,6 +123,7 @@ go_test( "//vendor/github.com/spf13/pflag:go_default_library", "//vendor/github.com/stretchr/testify/assert:go_default_library", "//vendor/github.com/stretchr/testify/require:go_default_library", + "//vendor/k8s.io/kube-openapi/pkg/common:go_default_library", ], ) diff --git a/staging/src/k8s.io/apiserver/pkg/server/options/authentication.go b/staging/src/k8s.io/apiserver/pkg/server/options/authentication.go index 04331794e54..02fed5f451e 100644 --- a/staging/src/k8s.io/apiserver/pkg/server/options/authentication.go +++ b/staging/src/k8s.io/apiserver/pkg/server/options/authentication.go @@ -117,7 +117,12 @@ type DelegatingAuthenticationOptions struct { ClientCert ClientCertAuthenticationOptions RequestHeader RequestHeaderAuthenticationOptions + // SkipInClusterLookup indicates missing authentication configuration should not be retrieved from the cluster configmap SkipInClusterLookup bool + + // TolerateInClusterLookupFailure indicates failures to look up authentication configuration from the cluster configmap should not be fatal. + // Setting this can result in an authenticator that will reject all requests. + TolerateInClusterLookupFailure bool } func NewDelegatingAuthenticationOptions() *DelegatingAuthenticationOptions { @@ -160,6 +165,9 @@ func (s *DelegatingAuthenticationOptions) AddFlags(fs *pflag.FlagSet) { fs.BoolVar(&s.SkipInClusterLookup, "authentication-skip-lookup", s.SkipInClusterLookup, ""+ "If false, the authentication-kubeconfig will be used to lookup missing authentication "+ "configuration from the cluster.") + fs.BoolVar(&s.TolerateInClusterLookupFailure, "authentication-tolerate-lookup-failure", s.TolerateInClusterLookupFailure, ""+ + "If true, failures to look up missing authentication configuration from the cluster are not considered fatal. "+ + "Note that this can result in authentication that treats all requests as anonymous.") } func (s *DelegatingAuthenticationOptions) ApplyTo(c *server.AuthenticationInfo, servingInfo *server.SecureServingInfo, openAPIConfig *openapicommon.Config) error { @@ -187,7 +195,13 @@ func (s *DelegatingAuthenticationOptions) ApplyTo(c *server.AuthenticationInfo, if !s.SkipInClusterLookup { err := s.lookupMissingConfigInCluster(client) if err != nil { - return err + if s.TolerateInClusterLookupFailure { + klog.Warningf("Error looking up in-cluster authentication configuration: %v", err) + klog.Warningf("Continuing without authentication configuration. This may treat all requests as anonymous.") + klog.Warningf("To require authentication configuration lookup to succeed, set --authentication-tolerate-lookup-failure=false") + } else { + return err + } } } @@ -246,7 +260,7 @@ func (s *DelegatingAuthenticationOptions) lookupMissingConfigInCluster(client ku // ignore, authConfigMap is nil now case errors.IsForbidden(err): klog.Warningf("Unable to get configmap/%s in %s. Usually fixed by "+ - "'kubectl create rolebinding -n %s ROLE_NAME --role=%s --serviceaccount=YOUR_NS:YOUR_SA'", + "'kubectl create rolebinding -n %s ROLEBINDING_NAME --role=%s --serviceaccount=YOUR_NS:YOUR_SA'", authenticationConfigMapName, authenticationConfigMapNamespace, authenticationConfigMapNamespace, authenticationRoleName) return err case err != nil: diff --git a/staging/src/k8s.io/apiserver/pkg/server/options/authentication_test.go b/staging/src/k8s.io/apiserver/pkg/server/options/authentication_test.go index 3b2a581f2cc..a196b1c76da 100644 --- a/staging/src/k8s.io/apiserver/pkg/server/options/authentication_test.go +++ b/staging/src/k8s.io/apiserver/pkg/server/options/authentication_test.go @@ -17,10 +17,15 @@ limitations under the License. package options import ( + "io/ioutil" + "net/http" + "os" "reflect" "testing" "k8s.io/apiserver/pkg/authentication/authenticatorfactory" + "k8s.io/apiserver/pkg/server" + openapicommon "k8s.io/kube-openapi/pkg/common" ) func TestToAuthenticationRequestHeaderConfig(t *testing.T) { @@ -66,3 +71,131 @@ func TestToAuthenticationRequestHeaderConfig(t *testing.T) { }) } } + +func TestApplyToFallback(t *testing.T) { + + f, err := ioutil.TempFile("", "authkubeconfig") + if err != nil { + t.Fatal(err) + } + defer os.Remove(f.Name()) + + if err := ioutil.WriteFile(f.Name(), []byte(` +apiVersion: v1 +kind: Config +clusters: +- cluster: + server: http://localhost:56789 + name: cluster +contexts: +- context: + cluster: cluster + name: cluster +current-context: cluster +`), os.FileMode(0755)); err != nil { + t.Fatal(err) + } + remoteKubeconfig := f.Name() + + testcases := []struct { + name string + options *DelegatingAuthenticationOptions + expectError bool + expectAuthenticator bool + expectTokenAnonymous bool + expectTokenErrors bool + }{ + { + name: "empty", + options: nil, + expectError: false, + expectAuthenticator: false, + }, + { + name: "default", + options: NewDelegatingAuthenticationOptions(), + expectError: true, // in-cluster client building fails, no kubeconfig provided + expectAuthenticator: false, + }, + { + name: "optional kubeconfig", + options: func() *DelegatingAuthenticationOptions { + opts := NewDelegatingAuthenticationOptions() + opts.RemoteKubeConfigFileOptional = true + return opts + }(), + expectError: false, // in-cluster client building fails, no kubeconfig required + expectAuthenticator: true, + expectTokenAnonymous: true, // no token validator available + }, + { + name: "valid client, failed cluster info lookup", + options: func() *DelegatingAuthenticationOptions { + opts := NewDelegatingAuthenticationOptions() + opts.RemoteKubeConfigFile = remoteKubeconfig + return opts + }(), + expectError: true, // client building is valid, remote config lookup fails + expectAuthenticator: false, + }, + { + name: "valid client, skip cluster info lookup", + options: func() *DelegatingAuthenticationOptions { + opts := NewDelegatingAuthenticationOptions() + opts.RemoteKubeConfigFile = remoteKubeconfig + opts.SkipInClusterLookup = true + return opts + }(), + expectError: false, // client building is valid, skipped cluster lookup + expectAuthenticator: true, + expectTokenErrors: true, // client fails making tokenreview calls + }, + { + name: "valid client, tolerate failed cluster info lookup", + options: func() *DelegatingAuthenticationOptions { + opts := NewDelegatingAuthenticationOptions() + opts.RemoteKubeConfigFile = remoteKubeconfig + opts.TolerateInClusterLookupFailure = true + return opts + }(), + expectError: false, // client is valid, skipped cluster lookup + expectAuthenticator: true, // anonymous auth + expectTokenErrors: true, // client fails making tokenreview calls + }, + } + + for _, tc := range testcases { + t.Run(tc.name, func(t *testing.T) { + c := &server.AuthenticationInfo{} + servingInfo := &server.SecureServingInfo{} + openAPIConfig := &openapicommon.Config{} + + err := tc.options.ApplyTo(c, servingInfo, openAPIConfig) + if (err != nil) != tc.expectError { + t.Errorf("expected error=%v, got %v", tc.expectError, err) + } + if (c.Authenticator != nil) != tc.expectAuthenticator { + t.Errorf("expected authenticator=%v, got %#v", tc.expectError, c.Authenticator) + } + if c.Authenticator != nil { + { + result, ok, err := c.Authenticator.AuthenticateRequest(&http.Request{}) + if err != nil || !ok || result == nil || result.User.GetName() != "system:anonymous" { + t.Errorf("expected anonymous, got %#v, %#v, %#v", result, ok, err) + } + } + { + result, ok, err := c.Authenticator.AuthenticateRequest(&http.Request{Header: http.Header{"Authorization": []string{"Bearer foo"}}}) + if tc.expectTokenAnonymous { + if err != nil || !ok || result == nil || result.User.GetName() != "system:anonymous" { + t.Errorf("expected anonymous, got %#v, %#v, %#v", result, ok, err) + } + } + if tc.expectTokenErrors != (err != nil) { + t.Errorf("expected error=%v, got %#v, %#v, %#v", tc.expectTokenErrors, result, ok, err) + } + } + } + }) + } +} diff --git a/staging/src/k8s.io/apiserver/pkg/server/options/deprecated_insecure_serving.go b/staging/src/k8s.io/apiserver/pkg/server/options/deprecated_insecure_serving.go index f1cc4430b8b..804f04bca96 100644 --- a/staging/src/k8s.io/apiserver/pkg/server/options/deprecated_insecure_serving.go +++ b/staging/src/k8s.io/apiserver/pkg/server/options/deprecated_insecure_serving.go @@ -85,11 +85,13 @@ func (s *DeprecatedInsecureServingOptions) AddUnqualifiedFlags(fs *pflag.FlagSet } fs.IPVar(&s.BindAddress, "address", s.BindAddress, - "DEPRECATED: see --bind-address instead.") + "The IP address on which to serve the insecure --port (set to 0.0.0.0 for all IPv4 interfaces and :: for all IPv6 interfaces).") fs.MarkDeprecated("address", "see --bind-address instead.") + fs.Lookup("address").Hidden = false - fs.IntVar(&s.BindPort, "port", s.BindPort, "DEPRECATED: see --secure-port instead.") + fs.IntVar(&s.BindPort, "port", s.BindPort, "The port on which to serve unsecured, unauthenticated access. Set to 0 to disable.") fs.MarkDeprecated("port", "see --secure-port instead.") + fs.Lookup("port").Hidden = false } // ApplyTo adds DeprecatedInsecureServingOptions to the insecureserverinfo amd kube-controller manager configuration. diff --git a/staging/src/k8s.io/apiserver/pkg/server/options/etcd.go b/staging/src/k8s.io/apiserver/pkg/server/options/etcd.go index 26173eb72c4..f1fe2c3b415 100644 --- a/staging/src/k8s.io/apiserver/pkg/server/options/etcd.go +++ b/staging/src/k8s.io/apiserver/pkg/server/options/etcd.go @@ -81,7 +81,7 @@ func (s *EtcdOptions) Validate() []error { } allErrors := []error{} - if len(s.StorageConfig.ServerList) == 0 { + if len(s.StorageConfig.Transport.ServerList) == 0 { allErrors = append(allErrors, fmt.Errorf("--etcd-servers must be specified")) } @@ -148,19 +148,19 @@ func (s *EtcdOptions) AddFlags(fs *pflag.FlagSet) { fs.IntVar(&dummyCacheSize, "deserialization-cache-size", 0, "Number of deserialized json objects to cache in memory.") fs.MarkDeprecated("deserialization-cache-size", "the deserialization cache was dropped in 1.13 with support for etcd2") - fs.StringSliceVar(&s.StorageConfig.ServerList, "etcd-servers", s.StorageConfig.ServerList, + fs.StringSliceVar(&s.StorageConfig.Transport.ServerList, "etcd-servers", s.StorageConfig.Transport.ServerList, "List of etcd servers to connect with (scheme://ip:port), comma separated.") fs.StringVar(&s.StorageConfig.Prefix, "etcd-prefix", s.StorageConfig.Prefix, "The prefix to prepend to all resource paths in etcd.") - fs.StringVar(&s.StorageConfig.KeyFile, "etcd-keyfile", s.StorageConfig.KeyFile, + fs.StringVar(&s.StorageConfig.Transport.KeyFile, "etcd-keyfile", s.StorageConfig.Transport.KeyFile, "SSL key file used to secure etcd communication.") - fs.StringVar(&s.StorageConfig.CertFile, "etcd-certfile", s.StorageConfig.CertFile, + fs.StringVar(&s.StorageConfig.Transport.CertFile, "etcd-certfile", s.StorageConfig.Transport.CertFile, "SSL certification file used to secure etcd communication.") - fs.StringVar(&s.StorageConfig.CAFile, "etcd-cafile", s.StorageConfig.CAFile, + fs.StringVar(&s.StorageConfig.Transport.CAFile, "etcd-cafile", s.StorageConfig.Transport.CAFile, "SSL Certificate Authority file used to secure etcd communication.") fs.StringVar(&s.EncryptionProviderConfigFilepath, "experimental-encryption-provider-config", s.EncryptionProviderConfigFilepath, diff --git a/staging/src/k8s.io/apiserver/pkg/server/options/etcd_test.go b/staging/src/k8s.io/apiserver/pkg/server/options/etcd_test.go index 7f772f5b397..5600d5438a9 100644 --- a/staging/src/k8s.io/apiserver/pkg/server/options/etcd_test.go +++ b/staging/src/k8s.io/apiserver/pkg/server/options/etcd_test.go @@ -36,12 +36,14 @@ func TestEtcdOptionsValidate(t *testing.T) { name: "test when ServerList is not specified", testOptions: &EtcdOptions{ StorageConfig: storagebackend.Config{ - Type: "etcd3", - ServerList: nil, - Prefix: "/registry", - KeyFile: "/var/run/kubernetes/etcd.key", - CAFile: "/var/run/kubernetes/etcdca.crt", - CertFile: "/var/run/kubernetes/etcdce.crt", + Type: "etcd3", + Prefix: "/registry", + Transport: storagebackend.TransportConfig{ + ServerList: nil, + KeyFile: "/var/run/kubernetes/etcd.key", + CAFile: "/var/run/kubernetes/etcdca.crt", + CertFile: "/var/run/kubernetes/etcdce.crt", + }, CompactionInterval: storagebackend.DefaultCompactInterval, CountMetricPollPeriod: time.Minute, }, @@ -58,12 +60,14 @@ func TestEtcdOptionsValidate(t *testing.T) { name: "test when storage-backend is invalid", testOptions: &EtcdOptions{ StorageConfig: storagebackend.Config{ - Type: "etcd4", - ServerList: []string{"http://127.0.0.1"}, - Prefix: "/registry", - KeyFile: "/var/run/kubernetes/etcd.key", - CAFile: "/var/run/kubernetes/etcdca.crt", - CertFile: "/var/run/kubernetes/etcdce.crt", + Type: "etcd4", + Prefix: "/registry", + Transport: storagebackend.TransportConfig{ + ServerList: []string{"http://127.0.0.1"}, + KeyFile: "/var/run/kubernetes/etcd.key", + CAFile: "/var/run/kubernetes/etcdca.crt", + CertFile: "/var/run/kubernetes/etcdce.crt", + }, CompactionInterval: storagebackend.DefaultCompactInterval, CountMetricPollPeriod: time.Minute, }, @@ -80,12 +84,14 @@ func TestEtcdOptionsValidate(t *testing.T) { name: "test when etcd-servers-overrides is invalid", testOptions: &EtcdOptions{ StorageConfig: storagebackend.Config{ - Type: "etcd3", - ServerList: []string{"http://127.0.0.1"}, + Type: "etcd3", + Transport: storagebackend.TransportConfig{ + ServerList: []string{"http://127.0.0.1"}, + KeyFile: "/var/run/kubernetes/etcd.key", + CAFile: "/var/run/kubernetes/etcdca.crt", + CertFile: "/var/run/kubernetes/etcdce.crt", + }, Prefix: "/registry", - KeyFile: "/var/run/kubernetes/etcd.key", - CAFile: "/var/run/kubernetes/etcdca.crt", - CertFile: "/var/run/kubernetes/etcdce.crt", CompactionInterval: storagebackend.DefaultCompactInterval, CountMetricPollPeriod: time.Minute, }, @@ -102,12 +108,14 @@ func TestEtcdOptionsValidate(t *testing.T) { name: "test when EtcdOptions is valid", testOptions: &EtcdOptions{ StorageConfig: storagebackend.Config{ - Type: "etcd3", - ServerList: []string{"http://127.0.0.1"}, - Prefix: "/registry", - KeyFile: "/var/run/kubernetes/etcd.key", - CAFile: "/var/run/kubernetes/etcdca.crt", - CertFile: "/var/run/kubernetes/etcdce.crt", + Type: "etcd3", + Prefix: "/registry", + Transport: storagebackend.TransportConfig{ + ServerList: []string{"http://127.0.0.1"}, + KeyFile: "/var/run/kubernetes/etcd.key", + CAFile: "/var/run/kubernetes/etcdca.crt", + CertFile: "/var/run/kubernetes/etcdce.crt", + }, CompactionInterval: storagebackend.DefaultCompactInterval, CountMetricPollPeriod: time.Minute, }, diff --git a/staging/src/k8s.io/apiserver/pkg/server/resourceconfig/BUILD b/staging/src/k8s.io/apiserver/pkg/server/resourceconfig/BUILD index bc889d28c7a..c971b6f07a9 100644 --- a/staging/src/k8s.io/apiserver/pkg/server/resourceconfig/BUILD +++ b/staging/src/k8s.io/apiserver/pkg/server/resourceconfig/BUILD @@ -14,6 +14,7 @@ go_library( "//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", "//staging/src/k8s.io/apiserver/pkg/server/storage:go_default_library", "//staging/src/k8s.io/apiserver/pkg/util/flag:go_default_library", + "//vendor/k8s.io/klog:go_default_library", ], ) diff --git a/staging/src/k8s.io/apiserver/pkg/server/resourceconfig/helpers.go b/staging/src/k8s.io/apiserver/pkg/server/resourceconfig/helpers.go index cb1c54e3f0b..ad0d5f5784f 100644 --- a/staging/src/k8s.io/apiserver/pkg/server/resourceconfig/helpers.go +++ b/staging/src/k8s.io/apiserver/pkg/server/resourceconfig/helpers.go @@ -25,6 +25,7 @@ import ( "k8s.io/apimachinery/pkg/runtime/schema" serverstore "k8s.io/apiserver/pkg/server/storage" utilflag "k8s.io/apiserver/pkg/util/flag" + "k8s.io/klog" ) // GroupVersionRegistry provides access to registered group versions. @@ -94,7 +95,7 @@ func MergeAPIResourceConfigs( } tokens := strings.Split(key, "/") - if len(tokens) != 2 { + if len(tokens) < 2 { continue } groupVersionString := tokens[0] + "/" + tokens[1] @@ -103,6 +104,13 @@ func MergeAPIResourceConfigs( return nil, fmt.Errorf("invalid key %s", key) } + // individual resource enablement/disablement is only supported in the extensions/v1beta1 API group for legacy reasons. + // all other API groups are expected to contain coherent sets of resources that are enabled/disabled together. + if len(tokens) > 2 && (groupVersion != schema.GroupVersion{Group: "extensions", Version: "v1beta1"}) { + klog.Warningf("ignoring invalid key %s, individual resource enablement/disablement is not supported in %s, and will prevent starting in future releases", key, groupVersion.String()) + continue + } + // Exclude group not registered into the registry. if !registry.IsGroupRegistered(groupVersion.Group) { continue @@ -117,10 +125,22 @@ func MergeAPIResourceConfigs( return nil, err } if enabled { + // enable the groupVersion for "group/version=true" and "group/version/resource=true" resourceConfig.EnableVersions(groupVersion) - } else { + } else if len(tokens) == 2 { + // disable the groupVersion only for "group/version=false", not "group/version/resource=false" resourceConfig.DisableVersions(groupVersion) } + + if len(tokens) < 3 { + continue + } + groupVersionResource := groupVersion.WithResource(tokens[2]) + if enabled { + resourceConfig.EnableResources(groupVersionResource) + } else { + resourceConfig.DisableResources(groupVersionResource) + } } return resourceConfig, nil diff --git a/staging/src/k8s.io/apiserver/pkg/server/resourceconfig/helpers_test.go b/staging/src/k8s.io/apiserver/pkg/server/resourceconfig/helpers_test.go index 6ae41f7143b..9f905941bfe 100644 --- a/staging/src/k8s.io/apiserver/pkg/server/resourceconfig/helpers_test.go +++ b/staging/src/k8s.io/apiserver/pkg/server/resourceconfig/helpers_test.go @@ -66,7 +66,7 @@ func TestParseRuntimeConfig(t *testing.T) { { // version enabled by runtimeConfig override. runtimeConfig: map[string]string{ - "extensions/v1beta1": "", + "apps/v1": "", }, defaultResourceConfig: func() *serverstore.ResourceConfig { config := newFakeAPIResourceConfigSource() @@ -137,6 +137,64 @@ func TestParseRuntimeConfig(t *testing.T) { }, err: false, }, + { + // enable specific extensions resources + runtimeConfig: map[string]string{ + "extensions/v1beta1/deployments": "true", + }, + defaultResourceConfig: func() *serverstore.ResourceConfig { + return newFakeAPIResourceConfigSource() + }, + expectedAPIConfig: func() *serverstore.ResourceConfig { + config := newFakeAPIResourceConfigSource() + config.EnableResources(extensionsapiv1beta1.SchemeGroupVersion.WithResource("deployments")) + return config + }, + err: false, + }, + { + // disable specific extensions resources + runtimeConfig: map[string]string{ + "extensions/v1beta1/ingresses": "false", + }, + defaultResourceConfig: func() *serverstore.ResourceConfig { + return newFakeAPIResourceConfigSource() + }, + expectedAPIConfig: func() *serverstore.ResourceConfig { + config := newFakeAPIResourceConfigSource() + config.DisableResources(extensionsapiv1beta1.SchemeGroupVersion.WithResource("ingresses")) + return config + }, + err: false, + }, + { + // disable all extensions resources + runtimeConfig: map[string]string{ + "extensions/v1beta1": "false", + }, + defaultResourceConfig: func() *serverstore.ResourceConfig { + return newFakeAPIResourceConfigSource() + }, + expectedAPIConfig: func() *serverstore.ResourceConfig { + config := newFakeAPIResourceConfigSource() + config.DisableVersions(extensionsapiv1beta1.SchemeGroupVersion) + return config + }, + err: false, + }, + { + // disable a non-extensions resource + runtimeConfig: map[string]string{ + "apps/v1/deployments": "false", + }, + defaultResourceConfig: func() *serverstore.ResourceConfig { + return newFakeAPIResourceConfigSource() + }, + expectedAPIConfig: func() *serverstore.ResourceConfig { + return newFakeAPIResourceConfigSource() + }, + err: false, // no error for backwards compatibility + }, } for index, test := range testCases { t.Log(scheme.PrioritizedVersionsAllGroups()) @@ -161,6 +219,14 @@ func newFakeAPIResourceConfigSource() *serverstore.ResourceConfig { apiv1.SchemeGroupVersion, extensionsapiv1beta1.SchemeGroupVersion, ) + ret.EnableResources( + extensionsapiv1beta1.SchemeGroupVersion.WithResource("ingresses"), + ) + ret.DisableResources( + extensionsapiv1beta1.SchemeGroupVersion.WithResource("deployments"), + extensionsapiv1beta1.SchemeGroupVersion.WithResource("replicasets"), + extensionsapiv1beta1.SchemeGroupVersion.WithResource("daemonsets"), + ) return ret } diff --git a/staging/src/k8s.io/apiserver/pkg/server/secure_serving.go b/staging/src/k8s.io/apiserver/pkg/server/secure_serving.go index 08006c96550..663c33bc4ed 100644 --- a/staging/src/k8s.io/apiserver/pkg/server/secure_serving.go +++ b/staging/src/k8s.io/apiserver/pkg/server/secure_serving.go @@ -165,12 +165,12 @@ func RunServer( type NamedTLSCert struct { TLSCert tls.Certificate - // names is a list of domain patterns: fully qualified domain names, possibly prefixed with + // Names is a list of domain patterns: fully qualified domain names, possibly prefixed with // wildcard segments. Names []string } -// getNamedCertificateMap returns a map of *tls.Certificate by name. It's is +// GetNamedCertificateMap returns a map of *tls.Certificate by name. It's // suitable for use in tls.Config#NamedCertificates. Returns an error if any of the certs // cannot be loaded. Returns nil if len(certs) == 0 func GetNamedCertificateMap(certs []NamedTLSCert) (map[string]*tls.Certificate, error) { diff --git a/staging/src/k8s.io/apiserver/pkg/server/storage/resource_config.go b/staging/src/k8s.io/apiserver/pkg/server/storage/resource_config.go index d16be4279a3..eb892b5a5c0 100644 --- a/staging/src/k8s.io/apiserver/pkg/server/storage/resource_config.go +++ b/staging/src/k8s.io/apiserver/pkg/server/storage/resource_config.go @@ -23,6 +23,7 @@ import ( // APIResourceConfigSource is the interface to determine which groups and versions are enabled type APIResourceConfigSource interface { VersionEnabled(version schema.GroupVersion) bool + ResourceEnabled(resource schema.GroupVersionResource) bool AnyVersionForGroupEnabled(group string) bool } @@ -30,18 +31,21 @@ var _ APIResourceConfigSource = &ResourceConfig{} type ResourceConfig struct { GroupVersionConfigs map[schema.GroupVersion]bool + ResourceConfigs map[schema.GroupVersionResource]bool } func NewResourceConfig() *ResourceConfig { - return &ResourceConfig{GroupVersionConfigs: map[schema.GroupVersion]bool{}} + return &ResourceConfig{GroupVersionConfigs: map[schema.GroupVersion]bool{}, ResourceConfigs: map[schema.GroupVersionResource]bool{}} } +// DisableAll disables all group/versions. It does not modify individual resource enablement/disablement. func (o *ResourceConfig) DisableAll() { for k := range o.GroupVersionConfigs { o.GroupVersionConfigs[k] = false } } +// EnableAll enables all group/versions. It does not modify individual resource enablement/disablement. func (o *ResourceConfig) EnableAll() { for k := range o.GroupVersionConfigs { o.GroupVersionConfigs[k] = true @@ -70,6 +74,29 @@ func (o *ResourceConfig) VersionEnabled(version schema.GroupVersion) bool { return false } +func (o *ResourceConfig) DisableResources(resources ...schema.GroupVersionResource) { + for _, resource := range resources { + o.ResourceConfigs[resource] = false + } +} + +func (o *ResourceConfig) EnableResources(resources ...schema.GroupVersionResource) { + for _, resource := range resources { + o.ResourceConfigs[resource] = true + } +} + +func (o *ResourceConfig) ResourceEnabled(resource schema.GroupVersionResource) bool { + if !o.VersionEnabled(resource.GroupVersion()) { + return false + } + resourceEnabled, explicitlySet := o.ResourceConfigs[resource] + if !explicitlySet { + return true + } + return resourceEnabled +} + func (o *ResourceConfig) AnyVersionForGroupEnabled(group string) bool { for version := range o.GroupVersionConfigs { if version.Group == group { diff --git a/staging/src/k8s.io/apiserver/pkg/server/storage/resource_config_test.go b/staging/src/k8s.io/apiserver/pkg/server/storage/resource_config_test.go index a22d6227df6..25a6fb0dc52 100644 --- a/staging/src/k8s.io/apiserver/pkg/server/storage/resource_config_test.go +++ b/staging/src/k8s.io/apiserver/pkg/server/storage/resource_config_test.go @@ -43,6 +43,117 @@ func TestDisabledVersion(t *testing.T) { } } +func TestDisabledResource(t *testing.T) { + g1v1 := schema.GroupVersion{Group: "group1", Version: "version1"} + g1v1rUnspecified := g1v1.WithResource("unspecified") + g1v1rEnabled := g1v1.WithResource("enabled") + g1v1rDisabled := g1v1.WithResource("disabled") + g1v2 := schema.GroupVersion{Group: "group1", Version: "version2"} + g1v2rUnspecified := g1v2.WithResource("unspecified") + g1v2rEnabled := g1v2.WithResource("enabled") + g1v2rDisabled := g1v2.WithResource("disabled") + g2v1 := schema.GroupVersion{Group: "group2", Version: "version1"} + g2v1rUnspecified := g2v1.WithResource("unspecified") + g2v1rEnabled := g2v1.WithResource("enabled") + g2v1rDisabled := g2v1.WithResource("disabled") + + config := NewResourceConfig() + + config.DisableVersions(g1v1) + config.EnableVersions(g1v2, g2v1) + + config.EnableResources(g1v1rEnabled, g1v2rEnabled, g2v1rEnabled) + config.DisableResources(g1v1rDisabled, g1v2rDisabled, g2v1rDisabled) + + // all resources under g1v1 are disabled because the group-version is disabled + if config.ResourceEnabled(g1v1rUnspecified) { + t.Errorf("expected disabled for %v, from %v", g1v1rUnspecified, config) + } + if config.ResourceEnabled(g1v1rEnabled) { + t.Errorf("expected disabled for %v, from %v", g1v1rEnabled, config) + } + if config.ResourceEnabled(g1v1rDisabled) { + t.Errorf("expected disabled for %v, from %v", g1v1rDisabled, config) + } + + // explicitly disabled resources in enabled group-versions are disabled + if config.ResourceEnabled(g1v2rDisabled) { + t.Errorf("expected disabled for %v, from %v", g1v2rDisabled, config) + } + if config.ResourceEnabled(g2v1rDisabled) { + t.Errorf("expected disabled for %v, from %v", g2v1rDisabled, config) + } + + // unspecified and explicitly enabled resources in enabled group-versions are enabled + if !config.ResourceEnabled(g1v2rUnspecified) { + t.Errorf("expected enabled for %v, from %v", g1v2rUnspecified, config) + } + if !config.ResourceEnabled(g1v2rEnabled) { + t.Errorf("expected enabled for %v, from %v", g1v2rEnabled, config) + } + if !config.ResourceEnabled(g2v1rUnspecified) { + t.Errorf("expected enabled for %v, from %v", g2v1rUnspecified, config) + } + if !config.ResourceEnabled(g2v1rEnabled) { + t.Errorf("expected enabled for %v, from %v", g2v1rEnabled, config) + } + + // DisableAll() only disables to the group/version level for compatibility + // corresponds to --runtime-config=api/all=false + config.DisableAll() + if config.ResourceEnabled(g1v1rEnabled) { + t.Errorf("expected disabled for %v, from %v", g1v1rEnabled, config) + } + if config.ResourceEnabled(g1v2rEnabled) { + t.Errorf("expected disabled for %v, from %v", g1v2rEnabled, config) + } + if config.ResourceEnabled(g2v1rEnabled) { + t.Errorf("expected disabled for %v, from %v", g2v1rEnabled, config) + } + + // DisableAll() only disables to the group/version level for compatibility + // corresponds to --runtime-config=api/all=false,g1/v1=true + config.DisableAll() + config.EnableVersions(g1v1) + if !config.ResourceEnabled(g1v1rEnabled) { + t.Errorf("expected enabled for %v, from %v", g1v1rEnabled, config) + } + + // EnableAll() only enables to the group/version level for compatibility + config.EnableAll() + + // all unspecified or enabled resources under all groups now enabled + if !config.ResourceEnabled(g1v1rUnspecified) { + t.Errorf("expected enabled for %v, from %v", g1v1rUnspecified, config) + } + if !config.ResourceEnabled(g1v1rEnabled) { + t.Errorf("expected enabled for %v, from %v", g1v1rEnabled, config) + } + if !config.ResourceEnabled(g1v2rUnspecified) { + t.Errorf("expected enabled for %v, from %v", g1v2rUnspecified, config) + } + if !config.ResourceEnabled(g1v2rEnabled) { + t.Errorf("expected enabled for %v, from %v", g1v2rEnabled, config) + } + if !config.ResourceEnabled(g2v1rUnspecified) { + t.Errorf("expected enabled for %v, from %v", g2v1rUnspecified, config) + } + if !config.ResourceEnabled(g2v1rEnabled) { + t.Errorf("expected enabled for %v, from %v", g2v1rEnabled, config) + } + + // previously disabled resources are still disabled + if config.ResourceEnabled(g1v1rDisabled) { + t.Errorf("expected disabled for %v, from %v", g1v1rDisabled, config) + } + if config.ResourceEnabled(g1v2rDisabled) { + t.Errorf("expected disabled for %v, from %v", g1v2rDisabled, config) + } + if config.ResourceEnabled(g2v1rDisabled) { + t.Errorf("expected disabled for %v, from %v", g2v1rDisabled, config) + } +} + func TestAnyVersionForGroupEnabled(t *testing.T) { tests := []struct { name string diff --git a/staging/src/k8s.io/apiserver/pkg/server/storage/storage_factory.go b/staging/src/k8s.io/apiserver/pkg/server/storage/storage_factory.go index a87ce4a5efb..c3bb6ecd6db 100644 --- a/staging/src/k8s.io/apiserver/pkg/server/storage/storage_factory.go +++ b/staging/src/k8s.io/apiserver/pkg/server/storage/storage_factory.go @@ -121,7 +121,7 @@ type groupResourceOverrides struct { // Apply overrides the provided config and options if the override has a value in that position func (o groupResourceOverrides) Apply(config *storagebackend.Config, options *StorageCodecConfig) { if len(o.etcdLocation) > 0 { - config.ServerList = o.etcdLocation + config.Transport.ServerList = o.etcdLocation } if len(o.etcdPrefix) > 0 { config.Prefix = o.etcdPrefix @@ -290,7 +290,7 @@ func (s *DefaultStorageFactory) NewConfig(groupResource schema.GroupResource) (* // Backends returns all backends for all registered storage destinations. // Used for getting all instances for health validations. func (s *DefaultStorageFactory) Backends() []Backend { - servers := sets.NewString(s.StorageConfig.ServerList...) + servers := sets.NewString(s.StorageConfig.Transport.ServerList...) for _, overrides := range s.Overrides { servers.Insert(overrides.etcdLocation...) @@ -299,16 +299,16 @@ func (s *DefaultStorageFactory) Backends() []Backend { tlsConfig := &tls.Config{ InsecureSkipVerify: true, } - if len(s.StorageConfig.CertFile) > 0 && len(s.StorageConfig.KeyFile) > 0 { - cert, err := tls.LoadX509KeyPair(s.StorageConfig.CertFile, s.StorageConfig.KeyFile) + if len(s.StorageConfig.Transport.CertFile) > 0 && len(s.StorageConfig.Transport.KeyFile) > 0 { + cert, err := tls.LoadX509KeyPair(s.StorageConfig.Transport.CertFile, s.StorageConfig.Transport.KeyFile) if err != nil { klog.Errorf("failed to load key pair while getting backends: %s", err) } else { tlsConfig.Certificates = []tls.Certificate{cert} } } - if len(s.StorageConfig.CAFile) > 0 { - if caCert, err := ioutil.ReadFile(s.StorageConfig.CAFile); err != nil { + if len(s.StorageConfig.Transport.CAFile) > 0 { + if caCert, err := ioutil.ReadFile(s.StorageConfig.Transport.CAFile); err != nil { klog.Errorf("failed to read ca file while getting backends: %s", err) } else { caPool := x509.NewCertPool() diff --git a/staging/src/k8s.io/apiserver/pkg/server/storage/storage_factory_test.go b/staging/src/k8s.io/apiserver/pkg/server/storage/storage_factory_test.go index 197ff6b795e..3c8c1c2d3c6 100644 --- a/staging/src/k8s.io/apiserver/pkg/server/storage/storage_factory_test.go +++ b/staging/src/k8s.io/apiserver/pkg/server/storage/storage_factory_test.go @@ -104,7 +104,7 @@ func TestConfigurableStorageFactory(t *testing.T) { if err != nil { t.Fatal(err) } - if config.Prefix != "/prefix_for_test" || !reflect.DeepEqual(config.ServerList, []string{"/server2"}) { + if config.Prefix != "/prefix_for_test" || !reflect.DeepEqual(config.Transport.ServerList, []string{"/server2"}) { t.Errorf("unexpected config %#v", config) } if !called { @@ -136,8 +136,10 @@ func TestUpdateEtcdOverrides(t *testing.T) { defaultEtcdLocation := []string{"http://127.0.0.1"} for i, test := range testCases { defaultConfig := storagebackend.Config{ - Prefix: "/registry", - ServerList: defaultEtcdLocation, + Prefix: "/registry", + Transport: storagebackend.TransportConfig{ + ServerList: defaultEtcdLocation, + }, } storageFactory := NewDefaultStorageFactory(defaultConfig, "", codecs, NewDefaultResourceEncodingConfig(scheme), NewResourceConfig(), nil) storageFactory.SetEtcdLocation(test.resource, test.servers) @@ -148,8 +150,8 @@ func TestUpdateEtcdOverrides(t *testing.T) { t.Errorf("%d: unexpected error %v", i, err) continue } - if !reflect.DeepEqual(config.ServerList, test.servers) { - t.Errorf("%d: expected %v, got %v", i, test.servers, config.ServerList) + if !reflect.DeepEqual(config.Transport.ServerList, test.servers) { + t.Errorf("%d: expected %v, got %v", i, test.servers, config.Transport.ServerList) continue } @@ -158,8 +160,8 @@ func TestUpdateEtcdOverrides(t *testing.T) { t.Errorf("%d: unexpected error %v", i, err) continue } - if !reflect.DeepEqual(config.ServerList, defaultEtcdLocation) { - t.Errorf("%d: expected %v, got %v", i, defaultEtcdLocation, config.ServerList) + if !reflect.DeepEqual(config.Transport.ServerList, defaultEtcdLocation) { + t.Errorf("%d: expected %v, got %v", i, defaultEtcdLocation, config.Transport.ServerList) continue } diff --git a/staging/src/k8s.io/apiserver/pkg/storage/etcd/testing/utils.go b/staging/src/k8s.io/apiserver/pkg/storage/etcd/testing/utils.go index 493abaa2feb..77a6db4525f 100644 --- a/staging/src/k8s.io/apiserver/pkg/storage/etcd/testing/utils.go +++ b/staging/src/k8s.io/apiserver/pkg/storage/etcd/testing/utils.go @@ -293,10 +293,12 @@ func NewUnsecuredEtcd3TestClientServer(t *testing.T) (*EtcdTestServer, *storageb } server.V3Client = server.v3Cluster.RandClient() config := &storagebackend.Config{ - Type: "etcd3", - Prefix: etcdtest.PathPrefix(), - ServerList: server.V3Client.Endpoints(), - Paging: true, + Type: "etcd3", + Prefix: etcdtest.PathPrefix(), + Transport: storagebackend.TransportConfig{ + ServerList: server.V3Client.Endpoints(), + }, + Paging: true, } return server, config } diff --git a/staging/src/k8s.io/apiserver/pkg/storage/storagebackend/config.go b/staging/src/k8s.io/apiserver/pkg/storage/storagebackend/config.go index f18ac76dd9f..c36a1039424 100644 --- a/staging/src/k8s.io/apiserver/pkg/storage/storagebackend/config.go +++ b/staging/src/k8s.io/apiserver/pkg/storage/storagebackend/config.go @@ -30,18 +30,26 @@ const ( DefaultCompactInterval = 5 * time.Minute ) -// Config is configuration for creating a storage backend. -type Config struct { - // Type defines the type of storage backend. Default ("") is "etcd3". - Type string - // Prefix is the prefix to all keys passed to storage.Interface methods. - Prefix string +// TransportConfig holds all connection related info, i.e. equal TransportConfig means equal servers we talk to. +type TransportConfig struct { // ServerList is the list of storage servers to connect with. ServerList []string // TLS credentials KeyFile string CertFile string CAFile string +} + +// Config is configuration for creating a storage backend. +type Config struct { + // Type defines the type of storage backend. Default ("") is "etcd3". + Type string + // Prefix is the prefix to all keys passed to storage.Interface methods. + Prefix string + // Transport holds all connection related info, i.e. equal TransportConfig means equal servers we talk to. + Transport TransportConfig + // Quorum indicates that whether read operations should be quorum-level consistent. + Quorum bool // Paging indicates whether the server implementation should allow paging (if it is // supported). This is generally configured by feature gating, or by a specific // resource type not wishing to allow paging, and is not intended for end users to @@ -55,7 +63,6 @@ type Config struct { // CompactionInterval is an interval of requesting compaction from apiserver. // If the value is 0, no compaction will be issued. CompactionInterval time.Duration - // CountMetricPollPeriod specifies how often should count metric be updated CountMetricPollPeriod time.Duration } diff --git a/staging/src/k8s.io/apiserver/pkg/storage/storagebackend/factory/etcd3.go b/staging/src/k8s.io/apiserver/pkg/storage/storagebackend/factory/etcd3.go index e18fe9acde7..6bac7424383 100644 --- a/staging/src/k8s.io/apiserver/pkg/storage/storagebackend/factory/etcd3.go +++ b/staging/src/k8s.io/apiserver/pkg/storage/storagebackend/factory/etcd3.go @@ -19,6 +19,7 @@ package factory import ( "context" "fmt" + "sync" "sync/atomic" "time" @@ -54,7 +55,7 @@ func newETCD3HealthCheck(c storagebackend.Config) (func() error, error) { clientErrMsg.Store("etcd client connection not yet established") go wait.PollUntil(time.Second, func() (bool, error) { - client, err := newETCD3Client(c) + client, err := newETCD3Client(c.Transport) if err != nil { clientErrMsg.Store(err.Error()) return false, nil @@ -78,7 +79,7 @@ func newETCD3HealthCheck(c storagebackend.Config) (func() error, error) { }, nil } -func newETCD3Client(c storagebackend.Config) (*clientv3.Client, error) { +func newETCD3Client(c storagebackend.TransportConfig) (*clientv3.Client, error) { tlsInfo := transport.TLSInfo{ CertFile: c.CertFile, KeyFile: c.KeyFile, @@ -108,16 +109,88 @@ func newETCD3Client(c storagebackend.Config) (*clientv3.Client, error) { return clientv3.New(cfg) } +type runningCompactor struct { + interval time.Duration + cancel context.CancelFunc + client *clientv3.Client + refs int +} + +var ( + lock sync.Mutex + compactors = map[string]*runningCompactor{} +) + +// startCompactorOnce start one compactor per transport. If the interval get smaller on repeated calls, the +// compactor is replaced. A destroy func is returned. If all destroy funcs with the same transport are called, +// the compactor is stopped. +func startCompactorOnce(c storagebackend.TransportConfig, interval time.Duration) (func(), error) { + lock.Lock() + defer lock.Unlock() + + key := fmt.Sprintf("%v", c) // gives: {[server1 server2] keyFile certFile caFile} + if compactor, foundBefore := compactors[key]; !foundBefore || compactor.interval > interval { + compactorClient, err := newETCD3Client(c) + if err != nil { + return nil, err + } + + if foundBefore { + // replace compactor + compactor.cancel() + compactor.client.Close() + } else { + // start new compactor + compactor = &runningCompactor{} + compactors[key] = compactor + } + + ctx, cancel := context.WithCancel(context.Background()) + + compactor.interval = interval + compactor.cancel = cancel + compactor.client = compactorClient + + etcd3.StartCompactor(ctx, compactorClient, interval) + } + + compactors[key].refs++ + + return func() { + lock.Lock() + defer lock.Unlock() + + compactor := compactors[key] + compactor.refs-- + if compactor.refs == 0 { + compactor.cancel() + compactor.client.Close() + delete(compactors, key) + } + }, nil +} + func newETCD3Storage(c storagebackend.Config) (storage.Interface, DestroyFunc, error) { - client, err := newETCD3Client(c) + stopCompactor, err := startCompactorOnce(c.Transport, c.CompactionInterval) if err != nil { return nil, nil, err } - ctx, cancel := context.WithCancel(context.Background()) - etcd3.StartCompactor(ctx, client, c.CompactionInterval) + + client, err := newETCD3Client(c.Transport) + if err != nil { + stopCompactor() + return nil, nil, err + } + + var once sync.Once destroyFunc := func() { - cancel() - client.Close() + // we know that storage destroy funcs are called multiple times (due to reuse in subresources). + // Hence, we only destroy once. + // TODO: fix duplicated storage destroy calls higher level + once.Do(func() { + stopCompactor() + client.Close() + }) } transformer := c.Transformer if transformer == nil { diff --git a/staging/src/k8s.io/apiserver/pkg/storage/storagebackend/factory/tls_test.go b/staging/src/k8s.io/apiserver/pkg/storage/storagebackend/factory/tls_test.go index 9286c7bc2cd..0646de89bf9 100644 --- a/staging/src/k8s.io/apiserver/pkg/storage/storagebackend/factory/tls_test.go +++ b/staging/src/k8s.io/apiserver/pkg/storage/storagebackend/factory/tls_test.go @@ -66,12 +66,14 @@ func TestTLSConnection(t *testing.T) { defer cluster.Terminate(t) cfg := storagebackend.Config{ - Type: storagebackend.StorageTypeETCD3, - ServerList: []string{cluster.Members[0].GRPCAddr()}, - CertFile: certFile, - KeyFile: keyFile, - CAFile: caFile, - Codec: codec, + Type: storagebackend.StorageTypeETCD3, + Transport: storagebackend.TransportConfig{ + ServerList: []string{cluster.Members[0].GRPCAddr()}, + CertFile: certFile, + KeyFile: keyFile, + CAFile: caFile, + }, + Codec: codec, } storage, destroyFunc, err := newETCD3Storage(cfg) defer destroyFunc() diff --git a/staging/src/k8s.io/apiserver/pkg/util/feature/feature_gate.go b/staging/src/k8s.io/apiserver/pkg/util/feature/feature_gate.go index a8bce27f3a7..90f8300bd32 100644 --- a/staging/src/k8s.io/apiserver/pkg/util/feature/feature_gate.go +++ b/staging/src/k8s.io/apiserver/pkg/util/feature/feature_gate.go @@ -63,7 +63,11 @@ var ( ) type FeatureSpec struct { - Default bool + // Default is the default enablement state for the feature + Default bool + // LockToDefault indicates that the feature is locked to its default and cannot be changed + LockToDefault bool + // PreRelease indicates the maturity level of the feature PreRelease prerelease } @@ -199,6 +203,9 @@ func (f *featureGate) SetFromMap(m map[string]bool) error { if !ok { return fmt.Errorf("unrecognized feature gate: %s", k) } + if featureSpec.LockToDefault && featureSpec.Default != v { + return fmt.Errorf("cannot set feature gate %v to %v, feature is locked to %v", k, v, featureSpec.Default) + } enabled[k] = v // Handle "special" features like "all alpha gates" if fn, found := f.special[k]; found { diff --git a/staging/src/k8s.io/apiserver/pkg/util/feature/feature_gate_test.go b/staging/src/k8s.io/apiserver/pkg/util/feature/feature_gate_test.go index 194ed1f0723..aa42b3d3e94 100644 --- a/staging/src/k8s.io/apiserver/pkg/util/feature/feature_gate_test.go +++ b/staging/src/k8s.io/apiserver/pkg/util/feature/feature_gate_test.go @@ -221,6 +221,8 @@ func TestFeatureGateSetFromMap(t *testing.T) { // gates for testing const testAlphaGate Feature = "TestAlpha" const testBetaGate Feature = "TestBeta" + const testLockedTrueGate Feature = "TestLockedTrue" + const testLockedFalseGate Feature = "TestLockedFalse" tests := []struct { name string @@ -270,17 +272,54 @@ func TestFeatureGateSetFromMap(t *testing.T) { }, setmapError: "unrecognized feature gate:", }, + { + name: "set locked gates", + setmap: map[string]bool{ + "TestLockedTrue": true, + "TestLockedFalse": false, + }, + expect: map[Feature]bool{ + testAlphaGate: false, + testBetaGate: false, + }, + }, + { + name: "set locked gates", + setmap: map[string]bool{ + "TestLockedTrue": false, + }, + expect: map[Feature]bool{ + testAlphaGate: false, + testBetaGate: false, + }, + setmapError: "cannot set feature gate TestLockedTrue to false, feature is locked to true", + }, + { + name: "set locked gates", + setmap: map[string]bool{ + "TestLockedFalse": true, + }, + expect: map[Feature]bool{ + testAlphaGate: false, + testBetaGate: false, + }, + setmapError: "cannot set feature gate TestLockedFalse to true, feature is locked to false", + }, } for i, test := range tests { t.Run(fmt.Sprintf("SetFromMap %s", test.name), func(t *testing.T) { f := NewFeatureGate() f.Add(map[Feature]FeatureSpec{ - testAlphaGate: {Default: false, PreRelease: Alpha}, - testBetaGate: {Default: false, PreRelease: Beta}, + testAlphaGate: {Default: false, PreRelease: Alpha}, + testBetaGate: {Default: false, PreRelease: Beta}, + testLockedTrueGate: {Default: true, PreRelease: GA, LockToDefault: true}, + testLockedFalseGate: {Default: false, PreRelease: GA, LockToDefault: true}, }) err := f.SetFromMap(test.setmap) if test.setmapError != "" { - if !strings.Contains(err.Error(), test.setmapError) { + if err == nil { + t.Errorf("expected error, got none") + } else if !strings.Contains(err.Error(), test.setmapError) { t.Errorf("%d: SetFromMap(%#v) Expected err:%v, Got err:%v", i, test.setmap, test.setmapError, err) } } else if err != nil { diff --git a/staging/src/k8s.io/apiserver/pkg/util/webhook/authentication.go b/staging/src/k8s.io/apiserver/pkg/util/webhook/authentication.go index 1d1c0ad3bc9..dd0f4e5e663 100644 --- a/staging/src/k8s.io/apiserver/pkg/util/webhook/authentication.go +++ b/staging/src/k8s.io/apiserver/pkg/util/webhook/authentication.go @@ -177,6 +177,7 @@ func restConfigFromKubeconfig(configAuthInfo *clientcmdapi.AuthInfo) (*rest.Conf return nil, err } config.BearerToken = string(tokenBytes) + config.BearerTokenFile = configAuthInfo.TokenFile } if len(configAuthInfo.Impersonate) > 0 { config.Impersonate = rest.ImpersonationConfig{ diff --git a/staging/src/k8s.io/cli-runtime/Godeps/Godeps.json b/staging/src/k8s.io/cli-runtime/Godeps/Godeps.json index a94ef92452c..a07c63c8f5a 100644 --- a/staging/src/k8s.io/cli-runtime/Godeps/Godeps.json +++ b/staging/src/k8s.io/cli-runtime/Godeps/Godeps.json @@ -6,14 +6,50 @@ "./..." ], "Deps": [ + { + "ImportPath": "github.com/PuerkitoBio/purell", + "Rev": "8a290539e2e8629dbc4e6bad948158f790ec31f4" + }, + { + "ImportPath": "github.com/PuerkitoBio/urlesc", + "Rev": "5bd2802263f21d8788851d5305584c82a5c75d7e" + }, { "ImportPath": "github.com/davecgh/go-spew/spew", "Rev": "782f4967f2dc4564575ca782fe2d04090b5faca8" }, + { + "ImportPath": "github.com/emicklei/go-restful", + "Rev": "ff4f55a206334ef123e4f79bbf348980da81ca46" + }, + { + "ImportPath": "github.com/emicklei/go-restful/log", + "Rev": "ff4f55a206334ef123e4f79bbf348980da81ca46" + }, { "ImportPath": "github.com/evanphx/json-patch", "Rev": "36442dbdb585210f8d5a1b45e67aa323c197d5c4" }, + { + "ImportPath": "github.com/ghodss/yaml", + "Rev": "c7ce16629ff4cd059ed96ed06419dd3856fd3577" + }, + { + "ImportPath": "github.com/go-openapi/jsonpointer", + "Rev": "ef5f0afec364d3b9396b7b77b43dbe26bf1f8004" + }, + { + "ImportPath": "github.com/go-openapi/jsonreference", + "Rev": "8483a886a90412cd6858df4ea3483dce9c8e35a3" + }, + { + "ImportPath": "github.com/go-openapi/spec", + "Rev": "5bae59e25b21498baea7f9d46e9c147ec106a42e" + }, + { + "ImportPath": "github.com/go-openapi/swag", + "Rev": "5899d5c5e619fda5fa86e14795a835f473ca284c" + }, { "ImportPath": "github.com/gogo/protobuf/proto", "Rev": "342cbe0a04158f6dcb03ca0079991a51a4248c02" @@ -82,6 +118,18 @@ "ImportPath": "github.com/json-iterator/go", "Rev": "ab8a2e0c74be9d3be70b3184d9acc634935ded82" }, + { + "ImportPath": "github.com/mailru/easyjson/buffer", + "Rev": "2f5df55504ebc322e4d52d34df6a1f5b503bf26d" + }, + { + "ImportPath": "github.com/mailru/easyjson/jlexer", + "Rev": "2f5df55504ebc322e4d52d34df6a1f5b503bf26d" + }, + { + "ImportPath": "github.com/mailru/easyjson/jwriter", + "Rev": "2f5df55504ebc322e4d52d34df6a1f5b503bf26d" + }, { "ImportPath": "github.com/modern-go/concurrent", "Rev": "bacd9c7ef1dd9b15be4a9909b8ac7a4e313eec94" @@ -94,6 +142,10 @@ "ImportPath": "github.com/peterbourgon/diskv", "Rev": "5f041e8faa004a95c88a202771f4cc3e991971e6" }, + { + "ImportPath": "github.com/pkg/errors", + "Rev": "645ef00459ed84a119197bfb8d8205042c6df63d" + }, { "ImportPath": "github.com/pmezard/go-difflib/difflib", "Rev": "d8ed2627bdf02c080bf22230dbb337003b7aba2d" @@ -190,6 +242,10 @@ "ImportPath": "golang.org/x/text/unicode/norm", "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01" }, + { + "ImportPath": "golang.org/x/text/width", + "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01" + }, { "ImportPath": "golang.org/x/time/rate", "Rev": "f51c12702a4d776e4c1fa9b0fabab841babae631" @@ -270,6 +326,10 @@ "ImportPath": "k8s.io/api/certificates/v1beta1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/api/coordination/v1", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/api/coordination/v1beta1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" @@ -350,6 +410,10 @@ "ImportPath": "k8s.io/apimachinery/pkg/api/resource", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/apimachinery/pkg/api/validation", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/apimachinery/pkg/apis/meta/v1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" @@ -362,6 +426,10 @@ "ImportPath": "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/unstructuredscheme", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/apimachinery/pkg/apis/meta/v1/validation", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/apimachinery/pkg/apis/meta/v1beta1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" @@ -442,6 +510,10 @@ "ImportPath": "k8s.io/apimachinery/pkg/util/json", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/apimachinery/pkg/util/mergepatch", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/apimachinery/pkg/util/naming", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" @@ -458,6 +530,10 @@ "ImportPath": "k8s.io/apimachinery/pkg/util/sets", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/apimachinery/pkg/util/strategicpatch", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/apimachinery/pkg/util/validation", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" @@ -478,6 +554,10 @@ "ImportPath": "k8s.io/apimachinery/pkg/watch", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/apimachinery/third_party/forked/golang/json", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/apimachinery/third_party/forked/golang/reflect", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" @@ -570,6 +650,14 @@ "ImportPath": "k8s.io/klog", "Rev": "8139d8cb77af419532b33dfa7dd09fbc5f1d344f" }, + { + "ImportPath": "k8s.io/kube-openapi/pkg/common", + "Rev": "c59034cc13d587f5ef4e85ca0ade0c1866ae8e1d" + }, + { + "ImportPath": "k8s.io/kube-openapi/pkg/util/proto", + "Rev": "c59034cc13d587f5ef4e85ca0ade0c1866ae8e1d" + }, { "ImportPath": "k8s.io/client-go/discovery", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" @@ -614,6 +702,86 @@ "ImportPath": "k8s.io/client-go/util/testing", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "sigs.k8s.io/kustomize/pkg/commands/build", + "Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7" + }, + { + "ImportPath": "sigs.k8s.io/kustomize/pkg/constants", + "Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7" + }, + { + "ImportPath": "sigs.k8s.io/kustomize/pkg/expansion", + "Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7" + }, + { + "ImportPath": "sigs.k8s.io/kustomize/pkg/factory", + "Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7" + }, + { + "ImportPath": "sigs.k8s.io/kustomize/pkg/fs", + "Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7" + }, + { + "ImportPath": "sigs.k8s.io/kustomize/pkg/gvk", + "Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7" + }, + { + "ImportPath": "sigs.k8s.io/kustomize/pkg/ifc", + "Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7" + }, + { + "ImportPath": "sigs.k8s.io/kustomize/pkg/ifc/transformer", + "Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7" + }, + { + "ImportPath": "sigs.k8s.io/kustomize/pkg/internal/error", + "Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7" + }, + { + "ImportPath": "sigs.k8s.io/kustomize/pkg/loader", + "Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7" + }, + { + "ImportPath": "sigs.k8s.io/kustomize/pkg/patch", + "Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7" + }, + { + "ImportPath": "sigs.k8s.io/kustomize/pkg/patch/transformer", + "Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7" + }, + { + "ImportPath": "sigs.k8s.io/kustomize/pkg/resid", + "Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7" + }, + { + "ImportPath": "sigs.k8s.io/kustomize/pkg/resmap", + "Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7" + }, + { + "ImportPath": "sigs.k8s.io/kustomize/pkg/resource", + "Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7" + }, + { + "ImportPath": "sigs.k8s.io/kustomize/pkg/target", + "Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7" + }, + { + "ImportPath": "sigs.k8s.io/kustomize/pkg/transformers", + "Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7" + }, + { + "ImportPath": "sigs.k8s.io/kustomize/pkg/transformers/config", + "Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7" + }, + { + "ImportPath": "sigs.k8s.io/kustomize/pkg/transformers/config/defaultconfig", + "Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7" + }, + { + "ImportPath": "sigs.k8s.io/kustomize/pkg/types", + "Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7" + }, { "ImportPath": "sigs.k8s.io/yaml", "Rev": "fd68e9863619f6ec2fdd8625fe1f02e7c877e480" diff --git a/staging/src/k8s.io/cli-runtime/artifacts/kustomization/configMap.yaml b/staging/src/k8s.io/cli-runtime/artifacts/kustomization/configMap.yaml new file mode 100644 index 00000000000..00088530945 --- /dev/null +++ b/staging/src/k8s.io/cli-runtime/artifacts/kustomization/configMap.yaml @@ -0,0 +1,8 @@ + +apiVersion: v1 +kind: ConfigMap +metadata: + name: the-map +data: + altGreeting: "Good Morning!" + enableRisky: "false" diff --git a/staging/src/k8s.io/cli-runtime/artifacts/kustomization/deployment.yaml b/staging/src/k8s.io/cli-runtime/artifacts/kustomization/deployment.yaml new file mode 100644 index 00000000000..6e794090805 --- /dev/null +++ b/staging/src/k8s.io/cli-runtime/artifacts/kustomization/deployment.yaml @@ -0,0 +1,30 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: the-deployment +spec: + replicas: 3 + template: + metadata: + labels: + deployment: hello + spec: + containers: + - name: the-container + image: monopole/hello:1 + command: ["/hello", + "--port=8080", + "--enableRiskyFeature=$(ENABLE_RISKY)"] + ports: + - containerPort: 8080 + env: + - name: ALT_GREETING + valueFrom: + configMapKeyRef: + name: the-map + key: altGreeting + - name: ENABLE_RISKY + valueFrom: + configMapKeyRef: + name: the-map + key: enableRisky diff --git a/staging/src/k8s.io/cli-runtime/artifacts/kustomization/kustomization.yaml b/staging/src/k8s.io/cli-runtime/artifacts/kustomization/kustomization.yaml new file mode 100644 index 00000000000..eef31957114 --- /dev/null +++ b/staging/src/k8s.io/cli-runtime/artifacts/kustomization/kustomization.yaml @@ -0,0 +1,5 @@ +nameprefix: test- +resources: +- deployment.yaml +- service.yaml +- configMap.yaml diff --git a/staging/src/k8s.io/cli-runtime/artifacts/kustomization/service.yaml b/staging/src/k8s.io/cli-runtime/artifacts/kustomization/service.yaml new file mode 100644 index 00000000000..2942cdb7df0 --- /dev/null +++ b/staging/src/k8s.io/cli-runtime/artifacts/kustomization/service.yaml @@ -0,0 +1,13 @@ +kind: Service +apiVersion: v1 +metadata: + name: the-service +spec: + selector: + deployment: hello + type: LoadBalancer + ports: + - protocol: TCP + port: 8666 + targetPort: 8080 + \ No newline at end of file diff --git a/staging/src/k8s.io/cli-runtime/pkg/genericclioptions/builder_flags.go b/staging/src/k8s.io/cli-runtime/pkg/genericclioptions/builder_flags.go index f6686edd49c..1d2aec6dd53 100644 --- a/staging/src/k8s.io/cli-runtime/pkg/genericclioptions/builder_flags.go +++ b/staging/src/k8s.io/cli-runtime/pkg/genericclioptions/builder_flags.go @@ -120,7 +120,7 @@ func (o *ResourceBuilderFlags) AddFlags(flagset *pflag.FlagSet) { flagset.StringVar(o.FieldSelector, "field-selector", *o.FieldSelector, "Selector (field query) to filter on, supports '=', '==', and '!='.(e.g. --field-selector key1=value1,key2=value2). The server only supports a limited number of field queries per type.") } if o.AllNamespaces != nil { - flagset.BoolVar(o.AllNamespaces, "all-namespaces", *o.AllNamespaces, "If present, list the requested object(s) across all namespaces. Namespace in current context is ignored even if specified with --namespace.") + flagset.BoolVarP(o.AllNamespaces, "all-namespaces", "A", *o.AllNamespaces, "If present, list the requested object(s) across all namespaces. Namespace in current context is ignored even if specified with --namespace.") } if o.All != nil { flagset.BoolVar(o.All, "all", *o.All, "Select all resources in the namespace of the specified resource types") diff --git a/staging/src/k8s.io/cli-runtime/pkg/genericclioptions/resource/BUILD b/staging/src/k8s.io/cli-runtime/pkg/genericclioptions/resource/BUILD index 22b34de0087..7224780e3ea 100644 --- a/staging/src/k8s.io/cli-runtime/pkg/genericclioptions/resource/BUILD +++ b/staging/src/k8s.io/cli-runtime/pkg/genericclioptions/resource/BUILD @@ -35,12 +35,16 @@ go_library( "//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/yaml:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/watch:go_default_library", + "//staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps:go_default_library", "//staging/src/k8s.io/client-go/discovery:go_default_library", "//staging/src/k8s.io/client-go/kubernetes/scheme:go_default_library", "//staging/src/k8s.io/client-go/rest:go_default_library", "//staging/src/k8s.io/client-go/restmapper:go_default_library", "//vendor/golang.org/x/text/encoding/unicode:go_default_library", "//vendor/golang.org/x/text/transform:go_default_library", + "//vendor/sigs.k8s.io/kustomize/pkg/commands/build:go_default_library", + "//vendor/sigs.k8s.io/kustomize/pkg/constants:go_default_library", + "//vendor/sigs.k8s.io/kustomize/pkg/fs:go_default_library", ], ) diff --git a/staging/src/k8s.io/cli-runtime/pkg/genericclioptions/resource/builder_test.go b/staging/src/k8s.io/cli-runtime/pkg/genericclioptions/resource/builder_test.go index 7fd526b33c6..801f13f7723 100644 --- a/staging/src/k8s.io/cli-runtime/pkg/genericclioptions/resource/builder_test.go +++ b/staging/src/k8s.io/cli-runtime/pkg/genericclioptions/resource/builder_test.go @@ -465,27 +465,48 @@ func TestPathBuilderWithMultipleInvalid(t *testing.T) { } func TestDirectoryBuilder(t *testing.T) { - b := newDefaultBuilder(). - FilenameParam(false, &FilenameOptions{Recursive: false, Filenames: []string{"../../../artifacts/guestbook"}}). - NamespaceParam("test").DefaultNamespace() - - test := &testVisitor{} - singleItemImplied := false - - err := b.Do().IntoSingleItemImplied(&singleItemImplied).Visit(test.Handle) - if err != nil || singleItemImplied || len(test.Infos) < 3 { - t.Fatalf("unexpected response: %v %t %#v", err, singleItemImplied, test.Infos) + tests := []struct { + directories []string + singleItem bool + number int + expectedNames []string + }{ + {[]string{"../../../artifacts/guestbook"}, false, 3, []string{"redis-master"}}, + {[]string{"../../../artifacts/kustomization"}, true, 3, []string{"test-the-deployment"}}, + {[]string{"../../../artifacts/guestbook", "../../../artifacts/kustomization"}, false, 6, []string{"redis-master", "test-the-deployment"}}, } - found := false - for _, info := range test.Infos { - if info.Name == "redis-master" && info.Namespace == "test" && info.Object != nil { - found = true - break + for _, tt := range tests { + b := newDefaultBuilder(). + FilenameParam(false, &FilenameOptions{Recursive: false, Filenames: tt.directories}). + NamespaceParam("test").DefaultNamespace() + + test := &testVisitor{} + singleItemImplied := false + + err := b.Do().IntoSingleItemImplied(&singleItemImplied).Visit(test.Handle) + if err != nil || singleItemImplied != tt.singleItem || len(test.Infos) < tt.number { + t.Fatalf("unexpected response: %v %t %#v", err, singleItemImplied, test.Infos) + } + + contained := func(name string) bool { + for _, info := range test.Infos { + if info.Name == name && info.Namespace == "test" && info.Object != nil { + return true + } + } + return false + } + + allFound := true + for _, name := range tt.expectedNames { + if !contained(name) { + allFound = false + } + } + if !allFound { + t.Errorf("unexpected responses: %#v", test.Infos) } - } - if !found { - t.Errorf("unexpected responses: %#v", test.Infos) } } diff --git a/staging/src/k8s.io/cli-runtime/pkg/genericclioptions/resource/visitor.go b/staging/src/k8s.io/cli-runtime/pkg/genericclioptions/resource/visitor.go index 32c1a691a5a..15a9ff30728 100644 --- a/staging/src/k8s.io/cli-runtime/pkg/genericclioptions/resource/visitor.go +++ b/staging/src/k8s.io/cli-runtime/pkg/genericclioptions/resource/visitor.go @@ -20,6 +20,7 @@ import ( "bytes" "fmt" "io" + "io/ioutil" "net/http" "net/url" "os" @@ -38,6 +39,10 @@ import ( utilerrors "k8s.io/apimachinery/pkg/util/errors" "k8s.io/apimachinery/pkg/util/yaml" "k8s.io/apimachinery/pkg/watch" + "k8s.io/cli-runtime/pkg/kustomize/k8sdeps" + "sigs.k8s.io/kustomize/pkg/commands/build" + "sigs.k8s.io/kustomize/pkg/constants" + "sigs.k8s.io/kustomize/pkg/fs" ) const ( @@ -452,7 +457,10 @@ func ExpandPathsToFileVisitors(mapper *mapper, paths string, recursive bool, ext if err != nil { return err } - + if isKustomizationDir(path) { + visitors = append(visitors, NewKustomizationVisitor(mapper, path, schema)) + return filepath.SkipDir + } if fi.IsDir() { if path != paths && !recursive { return filepath.SkipDir @@ -463,7 +471,10 @@ func ExpandPathsToFileVisitors(mapper *mapper, paths string, recursive bool, ext if path != paths && ignoreFile(path, extensions) { return nil } - + if filepath.Base(path) == constants.KustomizationFileName { + visitors = append(visitors, NewKustomizationVisitor(mapper, filepath.Dir(path), schema)) + return nil + } visitor := &FileVisitor{ Path: path, StreamVisitor: NewStreamVisitor(nil, mapper, path, schema), @@ -479,6 +490,13 @@ func ExpandPathsToFileVisitors(mapper *mapper, paths string, recursive bool, ext return visitors, nil } +func isKustomizationDir(path string) bool { + if _, err := os.Stat(filepath.Join(path, constants.KustomizationFileName)); err == nil { + return true + } + return false +} + // FileVisitor is wrapping around a StreamVisitor, to handle open/close files type FileVisitor struct { Path string @@ -507,6 +525,37 @@ func (v *FileVisitor) Visit(fn VisitorFunc) error { return v.StreamVisitor.Visit(fn) } +// KustomizationVisitor prorvides the output of kustomization build +type KustomizationVisitor struct { + Path string + *StreamVisitor +} + +// Visit in a KustomizationVisitor build the kustomization output +func (v *KustomizationVisitor) Visit(fn VisitorFunc) error { + fSys := fs.MakeRealFS() + f := k8sdeps.NewFactory() + var out bytes.Buffer + cmd := build.NewCmdBuild(&out, fSys, f.ResmapF, f.TransformerF) + cmd.SetArgs([]string{v.Path}) + // we want to silence usage, error output, and any future output from cobra + // we will get error output as a golang error from execute + cmd.SetOutput(ioutil.Discard) + _, err := cmd.ExecuteC() + if err != nil { + return err + } + v.StreamVisitor.Reader = bytes.NewReader(out.Bytes()) + return v.StreamVisitor.Visit(fn) +} + +func NewKustomizationVisitor(mapper *mapper, path string, schema ContentValidator) *KustomizationVisitor { + return &KustomizationVisitor{ + Path: path, + StreamVisitor: NewStreamVisitor(nil, mapper, path, schema), + } +} + // StreamVisitor reads objects from an io.Reader and walks them. A stream visitor can only be // visited once. // TODO: depends on objects being in JSON format before being passed to decode - need to implement diff --git a/staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/BUILD b/staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/BUILD new file mode 100644 index 00000000000..146c7e3884d --- /dev/null +++ b/staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/BUILD @@ -0,0 +1,38 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = [ + "doc.go", + "factory.go", + ], + importmap = "k8s.io/kubernetes/vendor/k8s.io/cli-runtime/pkg/kustomize/k8sdeps", + importpath = "k8s.io/cli-runtime/pkg/kustomize/k8sdeps", + visibility = ["//visibility:public"], + deps = [ + "//staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/kunstruct:go_default_library", + "//staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/transformer:go_default_library", + "//staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/validator:go_default_library", + "//vendor/sigs.k8s.io/kustomize/pkg/factory:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [ + ":package-srcs", + "//staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/configmapandsecret:all-srcs", + "//staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/kunstruct:all-srcs", + "//staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/transformer:all-srcs", + "//staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/validator:all-srcs", + ], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/configmapandsecret/BUILD b/staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/configmapandsecret/BUILD new file mode 100644 index 00000000000..3ba280e8b9d --- /dev/null +++ b/staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/configmapandsecret/BUILD @@ -0,0 +1,51 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "go_default_library", + srcs = [ + "configmapfactory.go", + "kv.go", + "secretfactory.go", + ], + importmap = "k8s.io/kubernetes/vendor/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/configmapandsecret", + importpath = "k8s.io/cli-runtime/pkg/kustomize/k8sdeps/configmapandsecret", + visibility = ["//visibility:public"], + deps = [ + "//staging/src/k8s.io/api/core/v1:go_default_library", + "//staging/src/k8s.io/apimachinery/pkg/util/validation:go_default_library", + "//vendor/github.com/pkg/errors:go_default_library", + "//vendor/sigs.k8s.io/kustomize/pkg/fs:go_default_library", + "//vendor/sigs.k8s.io/kustomize/pkg/ifc:go_default_library", + "//vendor/sigs.k8s.io/kustomize/pkg/types:go_default_library", + ], +) + +go_test( + name = "go_default_test", + srcs = [ + "configmapfactory_test.go", + "kv_test.go", + ], + embed = [":go_default_library"], + deps = [ + "//staging/src/k8s.io/api/core/v1:go_default_library", + "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + "//vendor/sigs.k8s.io/kustomize/pkg/fs:go_default_library", + "//vendor/sigs.k8s.io/kustomize/pkg/loader:go_default_library", + "//vendor/sigs.k8s.io/kustomize/pkg/types:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/configmapandsecret/configmapfactory.go b/staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/configmapandsecret/configmapfactory.go new file mode 100644 index 00000000000..ff77e6fa4ed --- /dev/null +++ b/staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/configmapandsecret/configmapfactory.go @@ -0,0 +1,190 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package configmapandsecret generates configmaps and secrets per generator rules. +package configmapandsecret + +import ( + "fmt" + "path" + "strings" + + "github.com/pkg/errors" + "k8s.io/api/core/v1" + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/util/validation" + "sigs.k8s.io/kustomize/pkg/fs" + "sigs.k8s.io/kustomize/pkg/ifc" + "sigs.k8s.io/kustomize/pkg/types" +) + +// ConfigMapFactory makes ConfigMaps. +type ConfigMapFactory struct { + fSys fs.FileSystem + ldr ifc.Loader +} + +// NewConfigMapFactory returns a new ConfigMapFactory. +func NewConfigMapFactory( + fSys fs.FileSystem, l ifc.Loader) *ConfigMapFactory { + return &ConfigMapFactory{fSys: fSys, ldr: l} +} + +func (f *ConfigMapFactory) makeFreshConfigMap( + args *types.ConfigMapArgs) *corev1.ConfigMap { + cm := &corev1.ConfigMap{} + cm.APIVersion = "v1" + cm.Kind = "ConfigMap" + cm.Name = args.Name + cm.Data = map[string]string{} + return cm +} + +// MakeConfigMap returns a new ConfigMap, or nil and an error. +func (f *ConfigMapFactory) MakeConfigMap( + args *types.ConfigMapArgs, options *types.GeneratorOptions) (*corev1.ConfigMap, error) { + var all []kvPair + var err error + cm := f.makeFreshConfigMap(args) + + pairs, err := keyValuesFromEnvFile(f.ldr, args.EnvSource) + if err != nil { + return nil, errors.Wrap(err, fmt.Sprintf( + "env source file: %s", + args.EnvSource)) + } + all = append(all, pairs...) + + pairs, err = keyValuesFromLiteralSources(args.LiteralSources) + if err != nil { + return nil, errors.Wrap(err, fmt.Sprintf( + "literal sources %v", args.LiteralSources)) + } + all = append(all, pairs...) + + pairs, err = keyValuesFromFileSources(f.ldr, args.FileSources) + if err != nil { + return nil, errors.Wrap(err, fmt.Sprintf( + "file sources: %v", args.FileSources)) + } + all = append(all, pairs...) + + for _, kv := range all { + err = addKvToConfigMap(cm, kv.key, kv.value) + if err != nil { + return nil, err + } + } + if options != nil { + cm.SetLabels(options.Labels) + cm.SetAnnotations(options.Annotations) + } + return cm, nil +} + +func keyValuesFromLiteralSources(sources []string) ([]kvPair, error) { + var kvs []kvPair + for _, s := range sources { + k, v, err := parseLiteralSource(s) + if err != nil { + return nil, err + } + kvs = append(kvs, kvPair{key: k, value: v}) + } + return kvs, nil +} + +func keyValuesFromFileSources(ldr ifc.Loader, sources []string) ([]kvPair, error) { + var kvs []kvPair + for _, s := range sources { + k, fPath, err := parseFileSource(s) + if err != nil { + return nil, err + } + content, err := ldr.Load(fPath) + if err != nil { + return nil, err + } + kvs = append(kvs, kvPair{key: k, value: string(content)}) + } + return kvs, nil +} + +func keyValuesFromEnvFile(l ifc.Loader, path string) ([]kvPair, error) { + if path == "" { + return nil, nil + } + content, err := l.Load(path) + if err != nil { + return nil, err + } + return keyValuesFromLines(content) +} + +// addKvToConfigMap adds the given key and data to the given config map. +// Error if key invalid, or already exists. +func addKvToConfigMap(configMap *v1.ConfigMap, keyName, data string) error { + // Note, the rules for ConfigMap keys are the exact same as the ones for SecretKeys. + if errs := validation.IsConfigMapKey(keyName); len(errs) != 0 { + return fmt.Errorf("%q is not a valid key name for a ConfigMap: %s", keyName, strings.Join(errs, ";")) + } + if _, entryExists := configMap.Data[keyName]; entryExists { + return fmt.Errorf("cannot add key %s, another key by that name already exists: %v", keyName, configMap.Data) + } + configMap.Data[keyName] = data + return nil +} + +// parseFileSource parses the source given. +// +// Acceptable formats include: +// 1. source-path: the basename will become the key name +// 2. source-name=source-path: the source-name will become the key name and +// source-path is the path to the key file. +// +// Key names cannot include '='. +func parseFileSource(source string) (keyName, filePath string, err error) { + numSeparators := strings.Count(source, "=") + switch { + case numSeparators == 0: + return path.Base(source), source, nil + case numSeparators == 1 && strings.HasPrefix(source, "="): + return "", "", fmt.Errorf("key name for file path %v missing", strings.TrimPrefix(source, "=")) + case numSeparators == 1 && strings.HasSuffix(source, "="): + return "", "", fmt.Errorf("file path for key name %v missing", strings.TrimSuffix(source, "=")) + case numSeparators > 1: + return "", "", errors.New("key names or file paths cannot contain '='") + default: + components := strings.Split(source, "=") + return components[0], components[1], nil + } +} + +// parseLiteralSource parses the source key=val pair into its component pieces. +// This functionality is distinguished from strings.SplitN(source, "=", 2) since +// it returns an error in the case of empty keys, values, or a missing equals sign. +func parseLiteralSource(source string) (keyName, value string, err error) { + // leading equal is invalid + if strings.Index(source, "=") == 0 { + return "", "", fmt.Errorf("invalid literal source %v, expected key=value", source) + } + // split after the first equal (so values can have the = character) + items := strings.SplitN(source, "=", 2) + if len(items) != 2 { + return "", "", fmt.Errorf("invalid literal source %v, expected key=value", source) + } + return items[0], strings.Trim(items[1], "\"'"), nil +} diff --git a/staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/configmapandsecret/configmapfactory_test.go b/staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/configmapandsecret/configmapfactory_test.go new file mode 100644 index 00000000000..15f86c6aaa8 --- /dev/null +++ b/staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/configmapandsecret/configmapfactory_test.go @@ -0,0 +1,144 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package configmapandsecret + +import ( + "reflect" + "testing" + + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "sigs.k8s.io/kustomize/pkg/fs" + "sigs.k8s.io/kustomize/pkg/loader" + "sigs.k8s.io/kustomize/pkg/types" +) + +func makeEnvConfigMap(name string) *corev1.ConfigMap { + return &corev1.ConfigMap{ + TypeMeta: metav1.TypeMeta{ + APIVersion: "v1", + Kind: "ConfigMap", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: name, + }, + Data: map[string]string{ + "DB_USERNAME": "admin", + "DB_PASSWORD": "somepw", + }, + } +} + +func makeFileConfigMap(name string) *corev1.ConfigMap { + return &corev1.ConfigMap{ + TypeMeta: metav1.TypeMeta{ + APIVersion: "v1", + Kind: "ConfigMap", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: name, + }, + Data: map[string]string{ + "app-init.ini": `FOO=bar +BAR=baz +`, + }, + } +} + +func makeLiteralConfigMap(name string) *corev1.ConfigMap { + cm := &corev1.ConfigMap{ + TypeMeta: metav1.TypeMeta{ + APIVersion: "v1", + Kind: "ConfigMap", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: name, + }, + Data: map[string]string{ + "a": "x", + "b": "y", + "c": "Hello World", + "d": "true", + }, + } + cm.SetLabels(map[string]string{"foo": "bar"}) + return cm +} + +func TestConstructConfigMap(t *testing.T) { + type testCase struct { + description string + input types.ConfigMapArgs + options *types.GeneratorOptions + expected *corev1.ConfigMap + } + + testCases := []testCase{ + { + description: "construct config map from env", + input: types.ConfigMapArgs{ + Name: "envConfigMap", + DataSources: types.DataSources{ + EnvSource: "configmap/app.env", + }, + }, + options: nil, + expected: makeEnvConfigMap("envConfigMap"), + }, + { + description: "construct config map from file", + input: types.ConfigMapArgs{ + Name: "fileConfigMap", + DataSources: types.DataSources{ + FileSources: []string{"configmap/app-init.ini"}, + }, + }, + options: nil, + expected: makeFileConfigMap("fileConfigMap"), + }, + { + description: "construct config map from literal", + input: types.ConfigMapArgs{ + Name: "literalConfigMap", + DataSources: types.DataSources{ + LiteralSources: []string{"a=x", "b=y", "c=\"Hello World\"", "d='true'"}, + }, + }, + options: &types.GeneratorOptions{ + Labels: map[string]string{ + "foo": "bar", + }, + }, + expected: makeLiteralConfigMap("literalConfigMap"), + }, + } + + fSys := fs.MakeFakeFS() + fSys.WriteFile("/configmap/app.env", []byte("DB_USERNAME=admin\nDB_PASSWORD=somepw\n")) + fSys.WriteFile("/configmap/app-init.ini", []byte("FOO=bar\nBAR=baz\n")) + f := NewConfigMapFactory(fSys, loader.NewFileLoaderAtRoot(fSys)) + for _, tc := range testCases { + cm, err := f.MakeConfigMap(&tc.input, tc.options) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if !reflect.DeepEqual(*cm, *tc.expected) { + t.Fatalf("in testcase: %q updated:\n%#v\ndoesn't match expected:\n%#v\n", tc.description, *cm, tc.expected) + } + } +} diff --git a/staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/configmapandsecret/kv.go b/staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/configmapandsecret/kv.go new file mode 100644 index 00000000000..6d6c992499b --- /dev/null +++ b/staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/configmapandsecret/kv.go @@ -0,0 +1,102 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package configmapandsecret + +import ( + "bufio" + "bytes" + "fmt" + "os" + "strings" + "unicode" + "unicode/utf8" + + "k8s.io/apimachinery/pkg/util/validation" +) + +// kvPair represents a key value pair. +type kvPair struct { + key string + value string +} + +var utf8bom = []byte{0xEF, 0xBB, 0xBF} + +// keyValuesFromLines parses given content in to a list of key-value pairs. +func keyValuesFromLines(content []byte) ([]kvPair, error) { + var kvs []kvPair + + scanner := bufio.NewScanner(bytes.NewReader(content)) + currentLine := 0 + for scanner.Scan() { + // Process the current line, retrieving a key/value pair if + // possible. + scannedBytes := scanner.Bytes() + kv, err := kvFromLine(scannedBytes, currentLine) + if err != nil { + return nil, err + } + currentLine++ + + if len(kv.key) == 0 { + // no key means line was empty or a comment + continue + } + + kvs = append(kvs, kv) + } + return kvs, nil +} + +// kvFromLine returns a kv with blank key if the line is empty or a comment. +// The value will be retrieved from the environment if necessary. +func kvFromLine(line []byte, currentLine int) (kvPair, error) { + kv := kvPair{} + + if !utf8.Valid(line) { + return kv, fmt.Errorf("line %d has invalid utf8 bytes : %v", line, string(line)) + } + + // We trim UTF8 BOM from the first line of the file but no others + if currentLine == 0 { + line = bytes.TrimPrefix(line, utf8bom) + } + + // trim the line from all leading whitespace first + line = bytes.TrimLeftFunc(line, unicode.IsSpace) + + // If the line is empty or a comment, we return a blank key/value pair. + if len(line) == 0 || line[0] == '#' { + return kv, nil + } + + data := strings.SplitN(string(line), "=", 2) + key := data[0] + if errs := validation.IsEnvVarName(key); len(errs) != 0 { + return kv, fmt.Errorf("%q is not a valid key name: %s", key, strings.Join(errs, ";")) + } + + if len(data) == 2 { + kv.value = data[1] + } else { + // No value (no `=` in the line) is a signal to obtain the value + // from the environment. + kv.value = os.Getenv(key) + } + kv.key = key + return kv, nil +} diff --git a/staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/configmapandsecret/kv_test.go b/staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/configmapandsecret/kv_test.go new file mode 100644 index 00000000000..939e231f5f5 --- /dev/null +++ b/staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/configmapandsecret/kv_test.go @@ -0,0 +1,68 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package configmapandsecret + +import ( + "reflect" + "testing" +) + +func TestKeyValuesFromLines(t *testing.T) { + tests := []struct { + desc string + content string + expectedPairs []kvPair + expectedErr bool + }{ + { + desc: "valid kv content parse", + content: ` + k1=v1 + k2=v2 + `, + expectedPairs: []kvPair{ + {key: "k1", value: "v1"}, + {key: "k2", value: "v2"}, + }, + expectedErr: false, + }, + { + desc: "content with comments", + content: ` + k1=v1 + #k2=v2 + `, + expectedPairs: []kvPair{ + {key: "k1", value: "v1"}, + }, + expectedErr: false, + }, + // TODO: add negative testcases + } + + for _, test := range tests { + pairs, err := keyValuesFromLines([]byte(test.content)) + if test.expectedErr && err == nil { + t.Fatalf("%s should not return error", test.desc) + } + + if !reflect.DeepEqual(pairs, test.expectedPairs) { + t.Errorf("%s should succeed, got:%v exptected:%v", test.desc, pairs, test.expectedPairs) + } + + } +} diff --git a/staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/configmapandsecret/secretfactory.go b/staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/configmapandsecret/secretfactory.go new file mode 100644 index 00000000000..2d8db576b81 --- /dev/null +++ b/staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/configmapandsecret/secretfactory.go @@ -0,0 +1,162 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package configmapandsecret + +import ( + "context" + "fmt" + "log" + "os/exec" + "path/filepath" + "strings" + "time" + + "github.com/pkg/errors" + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/util/validation" + "sigs.k8s.io/kustomize/pkg/fs" + "sigs.k8s.io/kustomize/pkg/types" +) + +const ( + defaultCommandTimeout = 5 * time.Second +) + +// SecretFactory makes Secrets. +type SecretFactory struct { + fSys fs.FileSystem + wd string +} + +// NewSecretFactory returns a new SecretFactory. +func NewSecretFactory(fSys fs.FileSystem, wd string) *SecretFactory { + return &SecretFactory{fSys: fSys, wd: wd} +} + +func (f *SecretFactory) makeFreshSecret(args *types.SecretArgs) *corev1.Secret { + s := &corev1.Secret{} + s.APIVersion = "v1" + s.Kind = "Secret" + s.Name = args.Name + s.Type = corev1.SecretType(args.Type) + if s.Type == "" { + s.Type = corev1.SecretTypeOpaque + } + s.Data = map[string][]byte{} + return s +} + +// MakeSecret returns a new secret. +func (f *SecretFactory) MakeSecret(args *types.SecretArgs, options *types.GeneratorOptions) (*corev1.Secret, error) { + var all []kvPair + var err error + s := f.makeFreshSecret(args) + + timeout := defaultCommandTimeout + if args.TimeoutSeconds != nil { + log.Println("SecretArgs.TimeoutSeconds will be deprected in next release. Please use GeneratorOptions.TimeoutSeconds instread.") + timeout = time.Duration(*args.TimeoutSeconds) * time.Second + } + + pairs, err := f.keyValuesFromEnvFileCommand(args.EnvCommand, timeout, options) + if err != nil { + return nil, errors.Wrap(err, fmt.Sprintf( + "env source file: %s", + args.EnvCommand)) + } + all = append(all, pairs...) + + pairs, err = f.keyValuesFromCommands(args.Commands, timeout, options) + if err != nil { + return nil, errors.Wrap(err, fmt.Sprintf( + "commands %v", args.Commands)) + } + all = append(all, pairs...) + + for _, kv := range all { + err = addKvToSecret(s, kv.key, kv.value) + if err != nil { + return nil, err + } + } + if options != nil { + s.SetLabels(options.Labels) + s.SetAnnotations(options.Annotations) + } + return s, nil +} + +func addKvToSecret(secret *corev1.Secret, keyName, data string) error { + // Note, the rules for SecretKeys keys are the exact same as the ones for ConfigMap. + if errs := validation.IsConfigMapKey(keyName); len(errs) != 0 { + return fmt.Errorf("%q is not a valid key name for a Secret: %s", keyName, strings.Join(errs, ";")) + } + if _, entryExists := secret.Data[keyName]; entryExists { + return fmt.Errorf("cannot add key %s, another key by that name already exists", keyName) + } + secret.Data[keyName] = []byte(data) + return nil +} + +func (f *SecretFactory) keyValuesFromEnvFileCommand(cmd string, timeout time.Duration, options *types.GeneratorOptions) ([]kvPair, error) { + content, err := f.createSecretKey(cmd, timeout, options) + if err != nil { + return nil, err + } + return keyValuesFromLines(content) +} + +func (f *SecretFactory) keyValuesFromCommands(sources map[string]string, timeout time.Duration, options *types.GeneratorOptions) ([]kvPair, error) { + var kvs []kvPair + for k, cmd := range sources { + content, err := f.createSecretKey(cmd, timeout, options) + if err != nil { + return nil, err + } + kvs = append(kvs, kvPair{key: k, value: string(content)}) + } + return kvs, nil +} + +// Run a command, return its output as the secret. +func (f *SecretFactory) createSecretKey(command string, timeout time.Duration, options *types.GeneratorOptions) ([]byte, error) { + if !f.fSys.IsDir(f.wd) { + f.wd = filepath.Dir(f.wd) + if !f.fSys.IsDir(f.wd) { + return nil, errors.New("not a directory: " + f.wd) + } + } + + if options != nil && options.TimeoutSeconds != nil { + t := time.Duration(*options.TimeoutSeconds) * time.Second + if t > timeout { + timeout = t + } + } + + var commands []string + if options == nil || len(options.Shell) == 0 { + commands = []string{"sh", "-c", command} + } else { + commands = append(options.Shell, command) + } + ctx, cancel := context.WithTimeout(context.Background(), timeout) + defer cancel() + cmd := exec.CommandContext(ctx, commands[0], commands[1:]...) + cmd.Dir = f.wd + return cmd.Output() +} diff --git a/staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/doc.go b/staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/doc.go new file mode 100644 index 00000000000..c98cb8d6804 --- /dev/null +++ b/staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/doc.go @@ -0,0 +1,76 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// It's possible that kustomize's features will be vendored into +// the kubernetes/kubernetes repo and made available to kubectl +// commands, while at the same time the kustomize program will +// continue to exist as an independent CLI. Vendoring snapshots +// would be taken just before a kubectl release. +// +// This creates a problem in that freestanding-kustomize depends on +// (for example): +// +// https://github.com/kubernetes/apimachinery/ +// tree/master/pkg/util/yaml +// +// It vendors that package into +// sigs.k8s.io/kustomize/vendor/k8s.io/apimachinery/ +// +// Whereas kubectl-kustomize would have to depend on the "staging" +// version of this code, located at +// +// https://github.com/kubernetes/kubernetes/ +// blob/master/staging/src/k8s.io/apimachinery/pkg/util/yaml +// +// which is "vendored" via symlinks: +// k8s.io/kubernetes/vendor/k8s.io/apimachinery +// is a symlink to +// ../../staging/src/k8s.io/apimachinery +// +// The staging version is the canonical, under-development +// version of the code that kubectl depends on, whereas the packages +// at kubernetes/apimachinery are periodic snapshots of staging made +// for outside tools to depend on. +// +// apimachinery isn't the only package that poses this problem, just +// using it as a specific example. +// +// The kubectl binary cannot vendor in kustomize code that in +// turn vendors in the non-staging packages. +// +// One way to fix some of this would be to copy code - a hard fork. +// This has all the problems associated with a hard forking. +// +// Another way would be to break the kustomize repo into three: +// +// (1) kustomize - repo with the main() function, +// vendoring (2) and (3). +// +// (2) kustomize-libs - packages used by (1) with no +// apimachinery dependence. +// +// (3) kustomize-k8sdeps - A thin code layer that depends +// on (vendors) apimachinery to provide thin implementations +// to interfaces used in (2). +// +// The kubectl repo would then vendor from (2) only, and have +// a local implementation of (3). With that in mind, it's clear +// that (3) doesn't have to be a repo; the kustomize version of +// the thin layer can live directly in (1). +// +// This package is the code in (3), meant for kustomize. + +package k8sdeps diff --git a/staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/factory.go b/staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/factory.go new file mode 100644 index 00000000000..a83b4bdaae0 --- /dev/null +++ b/staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/factory.go @@ -0,0 +1,34 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package k8sdeps provides kustomize factory with k8s dependencies +package k8sdeps + +import ( + "k8s.io/cli-runtime/pkg/kustomize/k8sdeps/kunstruct" + "k8s.io/cli-runtime/pkg/kustomize/k8sdeps/transformer" + "k8s.io/cli-runtime/pkg/kustomize/k8sdeps/validator" + "sigs.k8s.io/kustomize/pkg/factory" +) + +// NewFactory creates an instance of KustFactory using k8sdeps factories +func NewFactory() *factory.KustFactory { + return factory.NewKustFactory( + kunstruct.NewKunstructuredFactoryImpl(), + validator.NewKustValidator(), + transformer.NewFactoryImpl(), + ) +} diff --git a/staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/kunstruct/BUILD b/staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/kunstruct/BUILD new file mode 100644 index 00000000000..ab73de168f5 --- /dev/null +++ b/staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/kunstruct/BUILD @@ -0,0 +1,48 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "go_default_library", + srcs = [ + "factory.go", + "helper.go", + "kunstruct.go", + ], + importmap = "k8s.io/kubernetes/vendor/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/kunstruct", + importpath = "k8s.io/cli-runtime/pkg/kustomize/k8sdeps/kunstruct", + visibility = ["//visibility:public"], + deps = [ + "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library", + "//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library", + "//staging/src/k8s.io/apimachinery/pkg/util/yaml:go_default_library", + "//staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/configmapandsecret:go_default_library", + "//vendor/sigs.k8s.io/kustomize/pkg/fs:go_default_library", + "//vendor/sigs.k8s.io/kustomize/pkg/gvk:go_default_library", + "//vendor/sigs.k8s.io/kustomize/pkg/ifc:go_default_library", + "//vendor/sigs.k8s.io/kustomize/pkg/types:go_default_library", + ], +) + +go_test( + name = "go_default_test", + srcs = [ + "factory_test.go", + "kunstruct_test.go", + ], + embed = [":go_default_library"], + deps = ["//vendor/sigs.k8s.io/kustomize/pkg/ifc:go_default_library"], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/kunstruct/factory.go b/staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/kunstruct/factory.go new file mode 100644 index 00000000000..3d4e60a781c --- /dev/null +++ b/staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/kunstruct/factory.go @@ -0,0 +1,112 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package kunstruct + +import ( + "bytes" + "fmt" + "io" + "strings" + + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/util/yaml" + "k8s.io/cli-runtime/pkg/kustomize/k8sdeps/configmapandsecret" + "sigs.k8s.io/kustomize/pkg/fs" + "sigs.k8s.io/kustomize/pkg/ifc" + "sigs.k8s.io/kustomize/pkg/types" +) + +// KunstructuredFactoryImpl hides construction using apimachinery types. +type KunstructuredFactoryImpl struct { + cmFactory *configmapandsecret.ConfigMapFactory + secretFactory *configmapandsecret.SecretFactory +} + +var _ ifc.KunstructuredFactory = &KunstructuredFactoryImpl{} + +// NewKunstructuredFactoryImpl returns a factory. +func NewKunstructuredFactoryImpl() ifc.KunstructuredFactory { + return &KunstructuredFactoryImpl{} +} + +// SliceFromBytes returns a slice of Kunstructured. +func (kf *KunstructuredFactoryImpl) SliceFromBytes( + in []byte) ([]ifc.Kunstructured, error) { + decoder := yaml.NewYAMLOrJSONDecoder(bytes.NewReader(in), 1024) + var result []ifc.Kunstructured + var err error + for err == nil || isEmptyYamlError(err) { + var out unstructured.Unstructured + err = decoder.Decode(&out) + if err == nil { + err = kf.validate(out) + if err != nil { + return nil, err + } + result = append(result, &UnstructAdapter{Unstructured: out}) + } + } + if err != io.EOF { + return nil, err + } + return result, nil +} + +func isEmptyYamlError(err error) bool { + return strings.Contains(err.Error(), "is missing in 'null'") +} + +// FromMap returns an instance of Kunstructured. +func (kf *KunstructuredFactoryImpl) FromMap( + m map[string]interface{}) ifc.Kunstructured { + return &UnstructAdapter{Unstructured: unstructured.Unstructured{Object: m}} +} + +// MakeConfigMap returns an instance of Kunstructured for ConfigMap +func (kf *KunstructuredFactoryImpl) MakeConfigMap(args *types.ConfigMapArgs, options *types.GeneratorOptions) (ifc.Kunstructured, error) { + cm, err := kf.cmFactory.MakeConfigMap(args, options) + if err != nil { + return nil, err + } + return NewKunstructuredFromObject(cm) +} + +// MakeSecret returns an instance of Kunstructured for Secret +func (kf *KunstructuredFactoryImpl) MakeSecret(args *types.SecretArgs, options *types.GeneratorOptions) (ifc.Kunstructured, error) { + sec, err := kf.secretFactory.MakeSecret(args, options) + if err != nil { + return nil, err + } + return NewKunstructuredFromObject(sec) +} + +// Set sets loader, filesystem and workdirectory +func (kf *KunstructuredFactoryImpl) Set(fs fs.FileSystem, ldr ifc.Loader) { + kf.cmFactory = configmapandsecret.NewConfigMapFactory(fs, ldr) + kf.secretFactory = configmapandsecret.NewSecretFactory(fs, ldr.Root()) +} + +// validate validates that u has kind and name +func (kf *KunstructuredFactoryImpl) validate(u unstructured.Unstructured) error { + if u.GetName() == "" { + return fmt.Errorf("Missing metadata.name in object %v", u) + } + if u.GetKind() == "" { + return fmt.Errorf("Missing kind in object %v", u) + } + return nil +} diff --git a/staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/kunstruct/factory_test.go b/staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/kunstruct/factory_test.go new file mode 100644 index 00000000000..24dbb8a250f --- /dev/null +++ b/staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/kunstruct/factory_test.go @@ -0,0 +1,136 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package kunstruct + +import ( + "reflect" + "testing" + + "sigs.k8s.io/kustomize/pkg/ifc" +) + +func TestSliceFromBytes(t *testing.T) { + factory := NewKunstructuredFactoryImpl() + testConfigMap := factory.FromMap( + map[string]interface{}{ + "apiVersion": "v1", + "kind": "ConfigMap", + "metadata": map[string]interface{}{ + "name": "winnie", + }, + }) + + tests := []struct { + name string + input []byte + expectedOut []ifc.Kunstructured + expectedErr bool + }{ + { + name: "garbage", + input: []byte("garbageIn: garbageOut"), + expectedOut: []ifc.Kunstructured{}, + expectedErr: true, + }, + { + name: "noBytes", + input: []byte{}, + expectedOut: []ifc.Kunstructured{}, + expectedErr: false, + }, + { + name: "goodJson", + input: []byte(` +{"apiVersion":"v1","kind":"ConfigMap","metadata":{"name":"winnie"}} +`), + expectedOut: []ifc.Kunstructured{testConfigMap}, + expectedErr: false, + }, + { + name: "goodYaml1", + input: []byte(` +apiVersion: v1 +kind: ConfigMap +metadata: + name: winnie +`), + expectedOut: []ifc.Kunstructured{testConfigMap}, + expectedErr: false, + }, + { + name: "goodYaml2", + input: []byte(` +apiVersion: v1 +kind: ConfigMap +metadata: + name: winnie +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: winnie +`), + expectedOut: []ifc.Kunstructured{testConfigMap, testConfigMap}, + expectedErr: false, + }, + { + name: "garbageInOneOfTwoObjects", + input: []byte(` +apiVersion: v1 +kind: ConfigMap +metadata: + name: winnie +--- +WOOOOOOOOOOOOOOOOOOOOOOOOT: woot +`), + expectedOut: []ifc.Kunstructured{}, + expectedErr: true, + }, + { + name: "Missing .metadata.name in object", + input: []byte(` +apiVersion: v1 +kind: Namespace +metadata: + annotations: + foo: bar +`), + expectedOut: nil, + expectedErr: true, + }, + } + + for _, test := range tests { + rs, err := factory.SliceFromBytes(test.input) + if test.expectedErr && err == nil { + t.Fatalf("%v: should return error", test.name) + } + if !test.expectedErr && err != nil { + t.Fatalf("%v: unexpected error: %s", test.name, err) + } + if len(rs) != len(test.expectedOut) { + t.Fatalf("%s: length mismatch %d != %d", + test.name, len(rs), len(test.expectedOut)) + } + for i := range rs { + if !reflect.DeepEqual(test.expectedOut[i], rs[i]) { + t.Fatalf("%s: Got: %v\nexpected:%v", + test.name, test.expectedOut[i], rs[i]) + } + } + } +} diff --git a/staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/kunstruct/helper.go b/staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/kunstruct/helper.go new file mode 100644 index 00000000000..e0b2f3775a3 --- /dev/null +++ b/staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/kunstruct/helper.go @@ -0,0 +1,71 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package kunstruct provides unstructured from api machinery and factory for creating unstructured +package kunstruct + +import ( + "fmt" + "strings" +) + +func parseFields(path string) ([]string, error) { + if !strings.Contains(path, "[") { + return strings.Split(path, "."), nil + } + + var fields []string + start := 0 + insideParentheses := false + for i := range path { + switch path[i] { + case '.': + if !insideParentheses { + fields = append(fields, path[start:i]) + start = i + 1 + } + case '[': + if !insideParentheses { + if i == start { + start = i + 1 + } else { + fields = append(fields, path[start:i]) + start = i + 1 + } + insideParentheses = true + } else { + return nil, fmt.Errorf("nested parentheses are not allowed: %s", path) + } + case ']': + if insideParentheses { + fields = append(fields, path[start:i]) + start = i + 1 + insideParentheses = false + } else { + return nil, fmt.Errorf("Invalid field path %s", path) + } + } + } + if start < len(path)-1 { + fields = append(fields, path[start:]) + } + for i, f := range fields { + if strings.HasPrefix(f, "\"") || strings.HasPrefix(f, "'") { + fields[i] = strings.Trim(f, "\"'") + } + } + return fields, nil +} diff --git a/staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/kunstruct/kunstruct.go b/staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/kunstruct/kunstruct.go new file mode 100644 index 00000000000..5ad306bf56c --- /dev/null +++ b/staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/kunstruct/kunstruct.go @@ -0,0 +1,92 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package kunstruct provides unstructured from api machinery and factory for creating unstructured +package kunstruct + +import ( + "encoding/json" + "fmt" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime" + "sigs.k8s.io/kustomize/pkg/gvk" + "sigs.k8s.io/kustomize/pkg/ifc" +) + +var _ ifc.Kunstructured = &UnstructAdapter{} + +// UnstructAdapter wraps unstructured.Unstructured from +// https://github.com/kubernetes/apimachinery/blob/master/ +// pkg/apis/meta/v1/unstructured/unstructured.go +// to isolate dependence on apimachinery. +type UnstructAdapter struct { + unstructured.Unstructured +} + +// NewKunstructuredFromObject returns a new instance of Kunstructured. +func NewKunstructuredFromObject(obj runtime.Object) (ifc.Kunstructured, error) { + // Convert obj to a byte stream, then convert that to JSON (Unstructured). + marshaled, err := json.Marshal(obj) + if err != nil { + return &UnstructAdapter{}, err + } + var u unstructured.Unstructured + err = u.UnmarshalJSON(marshaled) + // creationTimestamp always 'null', remove it + u.SetCreationTimestamp(metav1.Time{}) + return &UnstructAdapter{Unstructured: u}, err +} + +// GetGvk returns the Gvk name of the object. +func (fs *UnstructAdapter) GetGvk() gvk.Gvk { + x := fs.GroupVersionKind() + return gvk.Gvk{ + Group: x.Group, + Version: x.Version, + Kind: x.Kind, + } +} + +// Copy provides a copy behind an interface. +func (fs *UnstructAdapter) Copy() ifc.Kunstructured { + return &UnstructAdapter{*fs.DeepCopy()} +} + +// Map returns the unstructured content map. +func (fs *UnstructAdapter) Map() map[string]interface{} { + return fs.Object +} + +// SetMap overrides the unstructured content map. +func (fs *UnstructAdapter) SetMap(m map[string]interface{}) { + fs.Object = m +} + +// GetFieldValue returns value at the given fieldpath. +func (fs *UnstructAdapter) GetFieldValue(path string) (string, error) { + fields, err := parseFields(path) + if err != nil { + return "", err + } + s, found, err := unstructured.NestedString( + fs.UnstructuredContent(), fields...) + if found || err != nil { + return s, err + } + return "", fmt.Errorf("no field named '%s'", path) +} diff --git a/staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/kunstruct/kunstruct_test.go b/staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/kunstruct/kunstruct_test.go new file mode 100644 index 00000000000..dc7eb8bb2a3 --- /dev/null +++ b/staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/kunstruct/kunstruct_test.go @@ -0,0 +1,148 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package kunstruct + +import ( + "testing" +) + +func TestGetFieldValue(t *testing.T) { + factory := NewKunstructuredFactoryImpl() + kunstructured := factory.FromMap(map[string]interface{}{ + "Kind": "Service", + "metadata": map[string]interface{}{ + "labels": map[string]string{ + "app": "application-name", + }, + "name": "service-name", + }, + "spec": map[string]interface{}{ + "ports": map[string]interface{}{ + "port": "80", + }, + }, + "this": map[string]interface{}{ + "is": map[string]interface{}{ + "aNumber": 1000, + "aNilValue": nil, + "anEmptyMap": map[string]interface{}{}, + "unrecognizable": testing.InternalExample{ + Name: "fooBar", + }, + }, + }, + }) + + tests := []struct { + name string + pathToField string + expectedValue string + errorExpected bool + errorMsg string + }{ + { + name: "oneField", + pathToField: "Kind", + expectedValue: "Service", + errorExpected: false, + }, + { + name: "twoFields", + pathToField: "metadata.name", + expectedValue: "service-name", + errorExpected: false, + }, + { + name: "threeFields", + pathToField: "spec.ports.port", + expectedValue: "80", + errorExpected: false, + }, + { + name: "empty", + pathToField: "", + errorExpected: true, + errorMsg: "no field named ''", + }, + { + name: "emptyDotEmpty", + pathToField: ".", + errorExpected: true, + errorMsg: "no field named '.'", + }, + { + name: "twoFieldsOneMissing", + pathToField: "metadata.banana", + errorExpected: true, + errorMsg: "no field named 'metadata.banana'", + }, + { + name: "deeperMissingField", + pathToField: "this.is.aDeep.field.that.does.not.exist", + errorExpected: true, + errorMsg: "no field named 'this.is.aDeep.field.that.does.not.exist'", + }, + { + name: "emptyMap", + pathToField: "this.is.anEmptyMap", + errorExpected: true, + errorMsg: ".this.is.anEmptyMap accessor error: map[] is of the type map[string]interface {}, expected string", + }, + { + name: "numberAsValue", + pathToField: "this.is.aNumber", + errorExpected: true, + errorMsg: ".this.is.aNumber accessor error: 1000 is of the type int, expected string", + }, + { + name: "nilAsValue", + pathToField: "this.is.aNilValue", + errorExpected: true, + errorMsg: ".this.is.aNilValue accessor error: is of the type , expected string", + }, + { + name: "unrecognizable", + pathToField: "this.is.unrecognizable.Name", + errorExpected: true, + errorMsg: ".this.is.unrecognizable.Name accessor error: {fooBar false} is of the type testing.InternalExample, expected map[string]interface{}", + }, + } + + for _, test := range tests { + s, err := kunstructured.GetFieldValue(test.pathToField) + if test.errorExpected { + if err == nil { + t.Fatalf("%q; path %q - should return error, but no error returned", + test.name, test.pathToField) + } + if test.errorMsg != err.Error() { + t.Fatalf("%q; path %q - expected error: \"%s\", got error: \"%v\"", + test.name, test.pathToField, test.errorMsg, err.Error()) + } + continue + } + if err != nil { + t.Fatalf("%q; path %q - unexpected error %v", + test.name, test.pathToField, err) + } + if test.expectedValue != s { + t.Fatalf("%q; Got: %s expected: %s", + test.name, s, test.expectedValue) + } + + } +} diff --git a/staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/transformer/BUILD b/staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/transformer/BUILD new file mode 100644 index 00000000000..b6ab75a1076 --- /dev/null +++ b/staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/transformer/BUILD @@ -0,0 +1,33 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = ["factory.go"], + importmap = "k8s.io/kubernetes/vendor/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/transformer", + importpath = "k8s.io/cli-runtime/pkg/kustomize/k8sdeps/transformer", + visibility = ["//visibility:public"], + deps = [ + "//staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/transformer/hash:go_default_library", + "//staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/transformer/patch:go_default_library", + "//vendor/sigs.k8s.io/kustomize/pkg/resource:go_default_library", + "//vendor/sigs.k8s.io/kustomize/pkg/transformers:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [ + ":package-srcs", + "//staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/transformer/hash:all-srcs", + "//staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/transformer/patch:all-srcs", + ], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/transformer/factory.go b/staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/transformer/factory.go new file mode 100644 index 00000000000..bc435b37975 --- /dev/null +++ b/staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/transformer/factory.go @@ -0,0 +1,43 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package transformer provides transformer factory +package transformer + +import ( + "k8s.io/cli-runtime/pkg/kustomize/k8sdeps/transformer/hash" + "k8s.io/cli-runtime/pkg/kustomize/k8sdeps/transformer/patch" + "sigs.k8s.io/kustomize/pkg/resource" + "sigs.k8s.io/kustomize/pkg/transformers" +) + +// FactoryImpl makes patch transformer and name hash transformer +type FactoryImpl struct{} + +// NewFactoryImpl makes a new factoryImpl instance +func NewFactoryImpl() *FactoryImpl { + return &FactoryImpl{} +} + +// MakePatchTransformer makes a new patch transformer +func (p *FactoryImpl) MakePatchTransformer(slice []*resource.Resource, rf *resource.Factory) (transformers.Transformer, error) { + return patch.NewPatchTransformer(slice, rf) +} + +// MakeHashTransformer makes a new name hash transformer +func (p *FactoryImpl) MakeHashTransformer() transformers.Transformer { + return hash.NewNameHashTransformer() +} diff --git a/staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/transformer/hash/BUILD b/staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/transformer/hash/BUILD new file mode 100644 index 00000000000..bcd2eab3ec8 --- /dev/null +++ b/staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/transformer/hash/BUILD @@ -0,0 +1,50 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "go_default_library", + srcs = [ + "hash.go", + "namehash.go", + ], + importmap = "k8s.io/kubernetes/vendor/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/transformer/hash", + importpath = "k8s.io/cli-runtime/pkg/kustomize/k8sdeps/transformer/hash", + visibility = ["//visibility:public"], + deps = [ + "//staging/src/k8s.io/api/core/v1:go_default_library", + "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library", + "//vendor/sigs.k8s.io/kustomize/pkg/resmap:go_default_library", + "//vendor/sigs.k8s.io/kustomize/pkg/transformers:go_default_library", + ], +) + +go_test( + name = "go_default_test", + srcs = [ + "hash_test.go", + "namehash_test.go", + ], + embed = [":go_default_library"], + deps = [ + "//staging/src/k8s.io/api/core/v1:go_default_library", + "//staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/kunstruct:go_default_library", + "//vendor/sigs.k8s.io/kustomize/pkg/gvk:go_default_library", + "//vendor/sigs.k8s.io/kustomize/pkg/ifc:go_default_library", + "//vendor/sigs.k8s.io/kustomize/pkg/resid:go_default_library", + "//vendor/sigs.k8s.io/kustomize/pkg/resmap:go_default_library", + "//vendor/sigs.k8s.io/kustomize/pkg/resource:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/transformer/hash/hash.go b/staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/transformer/hash/hash.go new file mode 100644 index 00000000000..17e24ff3e64 --- /dev/null +++ b/staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/transformer/hash/hash.go @@ -0,0 +1,168 @@ +/* +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 hash + +import ( + "crypto/sha256" + "encoding/json" + "fmt" + + "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" +) + +// KustHash compute hash for unstructured objects +type KustHash struct{} + +// NewKustHash returns a KustHash object +func NewKustHash() *KustHash { + return &KustHash{} +} + +// Hash returns a hash of either a ConfigMap or a Secret +func (h *KustHash) Hash(m map[string]interface{}) (string, error) { + u := unstructured.Unstructured{ + Object: m, + } + kind := u.GetKind() + switch kind { + case "ConfigMap": + cm, err := unstructuredToConfigmap(u) + if err != nil { + return "", err + } + return ConfigMapHash(cm) + case "Secret": + sec, err := unstructuredToSecret(u) + + if err != nil { + return "", err + } + return SecretHash(sec) + default: + return "", fmt.Errorf("type %s is supported for hashing in %v", kind, m) + } +} + +// ConfigMapHash returns a hash of the ConfigMap. +// The Data, Kind, and Name are taken into account. +func ConfigMapHash(cm *v1.ConfigMap) (string, error) { + encoded, err := encodeConfigMap(cm) + if err != nil { + return "", err + } + h, err := encodeHash(hash(encoded)) + if err != nil { + return "", err + } + return h, nil +} + +// SecretHash returns a hash of the Secret. +// The Data, Kind, Name, and Type are taken into account. +func SecretHash(sec *v1.Secret) (string, error) { + encoded, err := encodeSecret(sec) + if err != nil { + return "", err + } + h, err := encodeHash(hash(encoded)) + if err != nil { + return "", err + } + return h, nil +} + +// encodeConfigMap encodes a ConfigMap. +// Data, Kind, and Name are taken into account. +func encodeConfigMap(cm *v1.ConfigMap) (string, error) { + // json.Marshal sorts the keys in a stable order in the encoding + m := map[string]interface{}{"kind": "ConfigMap", "name": cm.Name, "data": cm.Data} + if len(cm.BinaryData) > 0 { + m["binaryData"] = cm.BinaryData + } + data, err := json.Marshal(m) + if err != nil { + return "", err + } + return string(data), nil +} + +// encodeSecret encodes a Secret. +// Data, Kind, Name, and Type are taken into account. +func encodeSecret(sec *v1.Secret) (string, error) { + // json.Marshal sorts the keys in a stable order in the encoding + data, err := json.Marshal(map[string]interface{}{"kind": "Secret", "type": sec.Type, "name": sec.Name, "data": sec.Data}) + if err != nil { + return "", err + } + return string(data), nil +} + +// encodeHash extracts the first 40 bits of the hash from the hex string +// (1 hex char represents 4 bits), and then maps vowels and vowel-like hex +// characters to consonants to prevent bad words from being formed (the theory +// is that no vowels makes it really hard to make bad words). Since the string +// is hex, the only vowels it can contain are 'a' and 'e'. +// We picked some arbitrary consonants to map to from the same character set as GenerateName. +// See: https://github.com/kubernetes/apimachinery/blob/dc1f89aff9a7509782bde3b68824c8043a3e58cc/pkg/util/rand/rand.go#L75 +// If the hex string contains fewer than ten characters, returns an error. +func encodeHash(hex string) (string, error) { + if len(hex) < 10 { + return "", fmt.Errorf("the hex string must contain at least 10 characters") + } + enc := []rune(hex[:10]) + for i := range enc { + switch enc[i] { + case '0': + enc[i] = 'g' + case '1': + enc[i] = 'h' + case '3': + enc[i] = 'k' + case 'a': + enc[i] = 'm' + case 'e': + enc[i] = 't' + } + } + return string(enc), nil +} + +// hash hashes `data` with sha256 and returns the hex string +func hash(data string) string { + return fmt.Sprintf("%x", sha256.Sum256([]byte(data))) +} + +func unstructuredToConfigmap(u unstructured.Unstructured) (*v1.ConfigMap, error) { + marshaled, err := json.Marshal(u.Object) + if err != nil { + return nil, err + } + var out v1.ConfigMap + err = json.Unmarshal(marshaled, &out) + return &out, err +} + +func unstructuredToSecret(u unstructured.Unstructured) (*v1.Secret, error) { + marshaled, err := json.Marshal(u.Object) + if err != nil { + return nil, err + } + var out v1.Secret + err = json.Unmarshal(marshaled, &out) + return &out, err +} diff --git a/staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/transformer/hash/hash_test.go b/staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/transformer/hash/hash_test.go new file mode 100644 index 00000000000..2d336f35a82 --- /dev/null +++ b/staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/transformer/hash/hash_test.go @@ -0,0 +1,208 @@ +/* +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 hash + +import ( + "reflect" + "strings" + "testing" + + "k8s.io/api/core/v1" + "sigs.k8s.io/kustomize/pkg/gvk" +) + +var service = gvk.Gvk{Version: "v1", Kind: "Service"} +var secret = gvk.Gvk{Version: "v1", Kind: "Secret"} +var cmap = gvk.Gvk{Version: "v1", Kind: "ConfigMap"} +var deploy = gvk.Gvk{Group: "apps", Version: "v1", Kind: "Deployment"} + +func TestConfigMapHash(t *testing.T) { + cases := []struct { + desc string + cm *v1.ConfigMap + hash string + err string + }{ + // empty map + {"empty data", &v1.ConfigMap{Data: map[string]string{}, BinaryData: map[string][]byte{}}, "42745tchd9", ""}, + // one key + {"one key", &v1.ConfigMap{Data: map[string]string{"one": ""}}, "9g67k2htb6", ""}, + // three keys (tests sorting order) + {"three keys", &v1.ConfigMap{Data: map[string]string{"two": "2", "one": "", "three": "3"}}, "f5h7t85m9b", ""}, + // empty binary data map + {"empty binary data", &v1.ConfigMap{BinaryData: map[string][]byte{}}, "dk855m5d49", ""}, + // one key with binary data + {"one key with binary data", &v1.ConfigMap{BinaryData: map[string][]byte{"one": []byte("")}}, "mk79584b8c", ""}, + // three keys with binary data (tests sorting order) + {"three keys with binary data", &v1.ConfigMap{BinaryData: map[string][]byte{"two": []byte("2"), "one": []byte(""), "three": []byte("3")}}, "t458mc6db2", ""}, + // two keys, one with string and another with binary data + {"two keys with one each", &v1.ConfigMap{Data: map[string]string{"one": ""}, BinaryData: map[string][]byte{"two": []byte("")}}, "698h7c7t9m", ""}, + } + + for _, c := range cases { + h, err := ConfigMapHash(c.cm) + if SkipRest(t, c.desc, err, c.err) { + continue + } + if c.hash != h { + t.Errorf("case %q, expect hash %q but got %q", c.desc, c.hash, h) + } + } +} + +func TestSecretHash(t *testing.T) { + cases := []struct { + desc string + secret *v1.Secret + hash string + err string + }{ + // empty map + {"empty data", &v1.Secret{Type: "my-type", Data: map[string][]byte{}}, "t75bgf6ctb", ""}, + // one key + {"one key", &v1.Secret{Type: "my-type", Data: map[string][]byte{"one": []byte("")}}, "74bd68bm66", ""}, + // three keys (tests sorting order) + {"three keys", &v1.Secret{Type: "my-type", Data: map[string][]byte{"two": []byte("2"), "one": []byte(""), "three": []byte("3")}}, "dgcb6h9tmk", ""}, + } + + for _, c := range cases { + h, err := SecretHash(c.secret) + if SkipRest(t, c.desc, err, c.err) { + continue + } + if c.hash != h { + t.Errorf("case %q, expect hash %q but got %q", c.desc, c.hash, h) + } + } +} + +func TestEncodeConfigMap(t *testing.T) { + cases := []struct { + desc string + cm *v1.ConfigMap + expect string + err string + }{ + // empty map + {"empty data", &v1.ConfigMap{Data: map[string]string{}}, `{"data":{},"kind":"ConfigMap","name":""}`, ""}, + // one key + {"one key", &v1.ConfigMap{Data: map[string]string{"one": ""}}, `{"data":{"one":""},"kind":"ConfigMap","name":""}`, ""}, + // three keys (tests sorting order) + {"three keys", &v1.ConfigMap{Data: map[string]string{"two": "2", "one": "", "three": "3"}}, + `{"data":{"one":"","three":"3","two":"2"},"kind":"ConfigMap","name":""}`, ""}, + // empty binary map + {"empty data", &v1.ConfigMap{BinaryData: map[string][]byte{}}, `{"data":null,"kind":"ConfigMap","name":""}`, ""}, + // one key with binary data + {"one key", &v1.ConfigMap{BinaryData: map[string][]byte{"one": []byte("")}}, + `{"binaryData":{"one":""},"data":null,"kind":"ConfigMap","name":""}`, ""}, + // three keys with binary data (tests sorting order) + {"three keys", &v1.ConfigMap{BinaryData: map[string][]byte{"two": []byte("2"), "one": []byte(""), "three": []byte("3")}}, + `{"binaryData":{"one":"","three":"Mw==","two":"Mg=="},"data":null,"kind":"ConfigMap","name":""}`, ""}, + // two keys, one string and one binary values + {"two keys with one each", &v1.ConfigMap{Data: map[string]string{"one": ""}, BinaryData: map[string][]byte{"two": []byte("")}}, + `{"binaryData":{"two":""},"data":{"one":""},"kind":"ConfigMap","name":""}`, ""}, + } + for _, c := range cases { + s, err := encodeConfigMap(c.cm) + if SkipRest(t, c.desc, err, c.err) { + continue + } + if s != c.expect { + t.Errorf("case %q, expect %q but got %q from encode %#v", c.desc, c.expect, s, c.cm) + } + } +} + +func TestEncodeSecret(t *testing.T) { + cases := []struct { + desc string + secret *v1.Secret + expect string + err string + }{ + // empty map + {"empty data", &v1.Secret{Type: "my-type", Data: map[string][]byte{}}, `{"data":{},"kind":"Secret","name":"","type":"my-type"}`, ""}, + // one key + {"one key", &v1.Secret{Type: "my-type", Data: map[string][]byte{"one": []byte("")}}, `{"data":{"one":""},"kind":"Secret","name":"","type":"my-type"}`, ""}, + // three keys (tests sorting order) - note json.Marshal base64 encodes the values because they come in as []byte + {"three keys", &v1.Secret{ + Type: "my-type", + Data: map[string][]byte{"two": []byte("2"), "one": []byte(""), "three": []byte("3")}, + }, + `{"data":{"one":"","three":"Mw==","two":"Mg=="},"kind":"Secret","name":"","type":"my-type"}`, ""}, + } + for _, c := range cases { + s, err := encodeSecret(c.secret) + if SkipRest(t, c.desc, err, c.err) { + continue + } + if s != c.expect { + t.Errorf("case %q, expect %q but got %q from encode %#v", c.desc, c.expect, s, c.secret) + } + } +} + +func TestHash(t *testing.T) { + // hash the empty string to be sure that sha256 is being used + expect := "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + sum := hash("") + if expect != sum { + t.Errorf("expected hash %q but got %q", expect, sum) + } +} + +// warn devs who change types that they might have to update a hash function +// not perfect, as it only checks the number of top-level fields +func TestTypeStability(t *testing.T) { + errfmt := `case %q, expected %d fields but got %d +Depending on the field(s) you added, you may need to modify the hash function for this type. +To guide you: the hash function targets fields that comprise the contents of objects, +not their metadata (e.g. the Data of a ConfigMap, but nothing in ObjectMeta). +` + cases := []struct { + typeName string + obj interface{} + expect int + }{ + {"ConfigMap", v1.ConfigMap{}, 4}, + {"Secret", v1.Secret{}, 5}, + } + for _, c := range cases { + val := reflect.ValueOf(c.obj) + if num := val.NumField(); c.expect != num { + t.Errorf(errfmt, c.typeName, c.expect, num) + } + } +} + +// SkipRest returns true if there was a non-nil error or if we expected an error that didn't happen, +// and logs the appropriate error on the test object. +// The return value indicates whether we should skip the rest of the test case due to the error result. +func SkipRest(t *testing.T, desc string, err error, contains string) bool { + if err != nil { + if len(contains) == 0 { + t.Errorf("case %q, expect nil error but got %q", desc, err.Error()) + } else if !strings.Contains(err.Error(), contains) { + t.Errorf("case %q, expect error to contain %q but got %q", desc, contains, err.Error()) + } + return true + } else if len(contains) > 0 { + t.Errorf("case %q, expect error to contain %q but got nil error", desc, contains) + return true + } + return false +} diff --git a/staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/transformer/hash/namehash.go b/staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/transformer/hash/namehash.go new file mode 100644 index 00000000000..75b9e893ca2 --- /dev/null +++ b/staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/transformer/hash/namehash.go @@ -0,0 +1,47 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package hash + +import ( + "fmt" + + "sigs.k8s.io/kustomize/pkg/resmap" + "sigs.k8s.io/kustomize/pkg/transformers" +) + +type nameHashTransformer struct{} + +var _ transformers.Transformer = &nameHashTransformer{} + +// NewNameHashTransformer construct a nameHashTransformer. +func NewNameHashTransformer() transformers.Transformer { + return &nameHashTransformer{} +} + +// Transform appends hash to generated resources. +func (o *nameHashTransformer) Transform(m resmap.ResMap) error { + for _, res := range m { + if res.IsGenerated() { + h, err := NewKustHash().Hash(res.Map()) + if err != nil { + return err + } + res.SetName(fmt.Sprintf("%s-%s", res.GetName(), h)) + } + } + return nil +} diff --git a/staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/transformer/hash/namehash_test.go b/staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/transformer/hash/namehash_test.go new file mode 100644 index 00000000000..c0304addf3b --- /dev/null +++ b/staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/transformer/hash/namehash_test.go @@ -0,0 +1,162 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package hash + +import ( + "reflect" + "testing" + + "k8s.io/cli-runtime/pkg/kustomize/k8sdeps/kunstruct" + "sigs.k8s.io/kustomize/pkg/ifc" + "sigs.k8s.io/kustomize/pkg/resid" + "sigs.k8s.io/kustomize/pkg/resmap" + "sigs.k8s.io/kustomize/pkg/resource" +) + +func TestNameHashTransformer(t *testing.T) { + rf := resource.NewFactory( + kunstruct.NewKunstructuredFactoryImpl()) + objs := resmap.ResMap{ + resid.NewResId(cmap, "cm1"): rf.FromMap( + map[string]interface{}{ + "apiVersion": "v1", + "kind": "ConfigMap", + "metadata": map[string]interface{}{ + "name": "cm1", + }, + }), + resid.NewResId(deploy, "deploy1"): rf.FromMap( + map[string]interface{}{ + "group": "apps", + "apiVersion": "v1", + "kind": "Deployment", + "metadata": map[string]interface{}{ + "name": "deploy1", + }, + "spec": map[string]interface{}{ + "template": map[string]interface{}{ + "metadata": map[string]interface{}{ + "labels": map[string]interface{}{ + "old-label": "old-value", + }, + }, + "spec": map[string]interface{}{ + "containers": []interface{}{ + map[string]interface{}{ + "name": "nginx", + "image": "nginx:1.7.9", + }, + }, + }, + }, + }, + }), + resid.NewResId(service, "svc1"): rf.FromMap( + map[string]interface{}{ + "apiVersion": "v1", + "kind": "Service", + "metadata": map[string]interface{}{ + "name": "svc1", + }, + "spec": map[string]interface{}{ + "ports": []interface{}{ + map[string]interface{}{ + "name": "port1", + "port": "12345", + }, + }, + }, + }), + resid.NewResId(secret, "secret1"): rf.FromMap( + map[string]interface{}{ + "apiVersion": "v1", + "kind": "Secret", + "metadata": map[string]interface{}{ + "name": "secret1", + }, + }).SetBehavior(ifc.BehaviorCreate), + } + + expected := resmap.ResMap{ + resid.NewResId(cmap, "cm1"): rf.FromMap( + map[string]interface{}{ + "apiVersion": "v1", + "kind": "ConfigMap", + "metadata": map[string]interface{}{ + "name": "cm1", + }, + }), + resid.NewResId(deploy, "deploy1"): rf.FromMap( + map[string]interface{}{ + "group": "apps", + "apiVersion": "v1", + "kind": "Deployment", + "metadata": map[string]interface{}{ + "name": "deploy1", + }, + "spec": map[string]interface{}{ + "template": map[string]interface{}{ + "metadata": map[string]interface{}{ + "labels": map[string]interface{}{ + "old-label": "old-value", + }, + }, + "spec": map[string]interface{}{ + "containers": []interface{}{ + map[string]interface{}{ + "name": "nginx", + "image": "nginx:1.7.9", + }, + }, + }, + }, + }, + }), + resid.NewResId(service, "svc1"): rf.FromMap( + map[string]interface{}{ + "apiVersion": "v1", + "kind": "Service", + "metadata": map[string]interface{}{ + "name": "svc1", + }, + "spec": map[string]interface{}{ + "ports": []interface{}{ + map[string]interface{}{ + "name": "port1", + "port": "12345", + }, + }, + }, + }), + resid.NewResId(secret, "secret1"): rf.FromMap( + map[string]interface{}{ + "apiVersion": "v1", + "kind": "Secret", + "metadata": map[string]interface{}{ + "name": "secret1-7kc45hd5f7", + }, + }).SetBehavior(ifc.BehaviorCreate), + } + + tran := NewNameHashTransformer() + tran.Transform(objs) + + if !reflect.DeepEqual(objs, expected) { + err := expected.ErrorIfNotEqual(objs) + t.Fatalf("actual doesn't match expected: %v", err) + } +} diff --git a/staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/transformer/patch/BUILD b/staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/transformer/patch/BUILD new file mode 100644 index 00000000000..0cb7910dcef --- /dev/null +++ b/staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/transformer/patch/BUILD @@ -0,0 +1,51 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "go_default_library", + srcs = [ + "patch.go", + "patchconflictdetector.go", + ], + importmap = "k8s.io/kubernetes/vendor/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/transformer/patch", + importpath = "k8s.io/cli-runtime/pkg/kustomize/k8sdeps/transformer/patch", + visibility = ["//visibility:public"], + deps = [ + "//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library", + "//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", + "//staging/src/k8s.io/apimachinery/pkg/util/mergepatch:go_default_library", + "//staging/src/k8s.io/apimachinery/pkg/util/strategicpatch:go_default_library", + "//staging/src/k8s.io/client-go/kubernetes/scheme:go_default_library", + "//vendor/github.com/evanphx/json-patch:go_default_library", + "//vendor/sigs.k8s.io/kustomize/pkg/gvk:go_default_library", + "//vendor/sigs.k8s.io/kustomize/pkg/resmap:go_default_library", + "//vendor/sigs.k8s.io/kustomize/pkg/resource:go_default_library", + "//vendor/sigs.k8s.io/kustomize/pkg/transformers:go_default_library", + ], +) + +go_test( + name = "go_default_test", + srcs = ["patch_test.go"], + embed = [":go_default_library"], + deps = [ + "//staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/kunstruct:go_default_library", + "//vendor/sigs.k8s.io/kustomize/pkg/gvk:go_default_library", + "//vendor/sigs.k8s.io/kustomize/pkg/resid:go_default_library", + "//vendor/sigs.k8s.io/kustomize/pkg/resmap:go_default_library", + "//vendor/sigs.k8s.io/kustomize/pkg/resource:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/transformer/patch/patch.go b/staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/transformer/patch/patch.go new file mode 100644 index 00000000000..a57ea39f287 --- /dev/null +++ b/staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/transformer/patch/patch.go @@ -0,0 +1,174 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package patch + +import ( + "encoding/json" + "fmt" + + "github.com/evanphx/json-patch" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/util/strategicpatch" + "k8s.io/client-go/kubernetes/scheme" + "sigs.k8s.io/kustomize/pkg/gvk" + "sigs.k8s.io/kustomize/pkg/resmap" + "sigs.k8s.io/kustomize/pkg/resource" + "sigs.k8s.io/kustomize/pkg/transformers" +) + +// patchTransformer applies patches. +type patchTransformer struct { + patches []*resource.Resource + rf *resource.Factory +} + +var _ transformers.Transformer = &patchTransformer{} + +// NewPatchTransformer constructs a patchTransformer. +func NewPatchTransformer( + slice []*resource.Resource, rf *resource.Factory) (transformers.Transformer, error) { + if len(slice) == 0 { + return transformers.NewNoOpTransformer(), nil + } + return &patchTransformer{patches: slice, rf: rf}, nil +} + +// Transform apply the patches on top of the base resources. +func (pt *patchTransformer) Transform(baseResourceMap resmap.ResMap) error { + // Merge and then index the patches by Id. + patches, err := pt.mergePatches() + if err != nil { + return err + } + + // Strategic merge the resources exist in both base and patches. + for _, patch := range patches { + // Merge patches with base resource. + id := patch.Id() + matchedIds := baseResourceMap.FindByGVKN(id) + if len(matchedIds) == 0 { + return fmt.Errorf("failed to find an object with %#v to apply the patch", id.Gvk()) + } + if len(matchedIds) > 1 { + return fmt.Errorf("found multiple objects %#v targeted by patch %#v (ambiguous)", matchedIds, id) + } + id = matchedIds[0] + base := baseResourceMap[id] + merged := map[string]interface{}{} + versionedObj, err := scheme.Scheme.New(toSchemaGvk(id.Gvk())) + baseName := base.GetName() + switch { + case runtime.IsNotRegisteredError(err): + // Use JSON merge patch to handle types w/o schema + baseBytes, err := json.Marshal(base.Map()) + if err != nil { + return err + } + patchBytes, err := json.Marshal(patch.Map()) + if err != nil { + return err + } + mergedBytes, err := jsonpatch.MergePatch(baseBytes, patchBytes) + if err != nil { + return err + } + err = json.Unmarshal(mergedBytes, &merged) + if err != nil { + return err + } + case err != nil: + return err + default: + // Use Strategic-Merge-Patch to handle types w/ schema + // TODO: Change this to use the new Merge package. + // Store the name of the base object, because this name may have been munged. + // Apply this name to the patched object. + lookupPatchMeta, err := strategicpatch.NewPatchMetaFromStruct(versionedObj) + if err != nil { + return err + } + merged, err = strategicpatch.StrategicMergeMapPatchUsingLookupPatchMeta( + base.Map(), + patch.Map(), + lookupPatchMeta) + if err != nil { + return err + } + } + base.SetName(baseName) + baseResourceMap[id].SetMap(merged) + } + return nil +} + +// mergePatches merge and index patches by Id. +// It errors out if there is conflict between patches. +func (pt *patchTransformer) mergePatches() (resmap.ResMap, error) { + rc := resmap.ResMap{} + for ix, patch := range pt.patches { + id := patch.Id() + existing, found := rc[id] + if !found { + rc[id] = patch + continue + } + + versionedObj, err := scheme.Scheme.New(toSchemaGvk(id.Gvk())) + if err != nil && !runtime.IsNotRegisteredError(err) { + return nil, err + } + var cd conflictDetector + if err != nil { + cd = newJMPConflictDetector(pt.rf) + } else { + cd, err = newSMPConflictDetector(versionedObj, pt.rf) + if err != nil { + return nil, err + } + } + + conflict, err := cd.hasConflict(existing, patch) + if err != nil { + return nil, err + } + if conflict { + conflictingPatch, err := cd.findConflict(ix, pt.patches) + if err != nil { + return nil, err + } + return nil, fmt.Errorf( + "conflict between %#v and %#v", + conflictingPatch.Map(), patch.Map()) + } + merged, err := cd.mergePatches(existing, patch) + if err != nil { + return nil, err + } + rc[id] = merged + } + return rc, nil +} + +// toSchemaGvk converts to a schema.GroupVersionKind. +func toSchemaGvk(x gvk.Gvk) schema.GroupVersionKind { + return schema.GroupVersionKind{ + Group: x.Group, + Version: x.Version, + Kind: x.Kind, + } +} diff --git a/staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/transformer/patch/patch_test.go b/staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/transformer/patch/patch_test.go new file mode 100644 index 00000000000..1505abe2716 --- /dev/null +++ b/staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/transformer/patch/patch_test.go @@ -0,0 +1,563 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package patch + +import ( + "reflect" + "strings" + "testing" + + "k8s.io/cli-runtime/pkg/kustomize/k8sdeps/kunstruct" + "sigs.k8s.io/kustomize/pkg/gvk" + "sigs.k8s.io/kustomize/pkg/resid" + "sigs.k8s.io/kustomize/pkg/resmap" + "sigs.k8s.io/kustomize/pkg/resource" +) + +var rf = resource.NewFactory( + kunstruct.NewKunstructuredFactoryImpl()) +var deploy = gvk.Gvk{Group: "apps", Version: "v1", Kind: "Deployment"} +var foo = gvk.Gvk{Group: "example.com", Version: "v1", Kind: "Foo"} + +func TestOverlayRun(t *testing.T) { + base := resmap.ResMap{ + resid.NewResId(deploy, "deploy1"): rf.FromMap( + map[string]interface{}{ + "apiVersion": "apps/v1", + "kind": "Deployment", + "metadata": map[string]interface{}{ + "name": "deploy1", + }, + "spec": map[string]interface{}{ + "template": map[string]interface{}{ + "metadata": map[string]interface{}{ + "labels": map[string]interface{}{ + "old-label": "old-value", + }, + }, + "spec": map[string]interface{}{ + "containers": []interface{}{ + map[string]interface{}{ + "name": "nginx", + "image": "nginx", + }, + }, + }, + }, + }, + }), + } + patch := []*resource.Resource{ + rf.FromMap(map[string]interface{}{ + "apiVersion": "apps/v1", + "kind": "Deployment", + "metadata": map[string]interface{}{ + "name": "deploy1", + }, + "spec": map[string]interface{}{ + "template": map[string]interface{}{ + "metadata": map[string]interface{}{ + "labels": map[string]interface{}{ + "another-label": "foo", + }, + }, + "spec": map[string]interface{}{ + "containers": []interface{}{ + map[string]interface{}{ + "name": "nginx", + "image": "nginx:latest", + "env": []interface{}{ + map[string]interface{}{ + "name": "SOMEENV", + "value": "BAR", + }, + }, + }, + }, + }, + }, + }, + }, + ), + } + expected := resmap.ResMap{ + resid.NewResId(deploy, "deploy1"): rf.FromMap( + map[string]interface{}{ + "apiVersion": "apps/v1", + "kind": "Deployment", + "metadata": map[string]interface{}{ + "name": "deploy1", + }, + "spec": map[string]interface{}{ + "template": map[string]interface{}{ + "metadata": map[string]interface{}{ + "labels": map[string]interface{}{ + "old-label": "old-value", + "another-label": "foo", + }, + }, + "spec": map[string]interface{}{ + "containers": []interface{}{ + map[string]interface{}{ + "name": "nginx", + "image": "nginx:latest", + "env": []interface{}{ + map[string]interface{}{ + "name": "SOMEENV", + "value": "BAR", + }, + }, + }, + }, + }, + }, + }, + }), + } + lt, err := NewPatchTransformer(patch, rf) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + err = lt.Transform(base) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if !reflect.DeepEqual(base, expected) { + err = expected.ErrorIfNotEqual(base) + t.Fatalf("actual doesn't match expected: %v", err) + } +} + +func TestMultiplePatches(t *testing.T) { + base := resmap.ResMap{ + resid.NewResId(deploy, "deploy1"): rf.FromMap( + map[string]interface{}{ + "apiVersion": "apps/v1", + "kind": "Deployment", + "metadata": map[string]interface{}{ + "name": "deploy1", + }, + "spec": map[string]interface{}{ + "template": map[string]interface{}{ + "spec": map[string]interface{}{ + "containers": []interface{}{ + map[string]interface{}{ + "name": "nginx", + "image": "nginx", + }, + }, + }, + }, + }, + }), + } + patch := []*resource.Resource{ + rf.FromMap(map[string]interface{}{ + "apiVersion": "apps/v1", + "kind": "Deployment", + "metadata": map[string]interface{}{ + "name": "deploy1", + }, + "spec": map[string]interface{}{ + "template": map[string]interface{}{ + "spec": map[string]interface{}{ + "containers": []interface{}{ + map[string]interface{}{ + "name": "nginx", + "image": "nginx:latest", + "env": []interface{}{ + map[string]interface{}{ + "name": "SOMEENV", + "value": "BAR", + }, + }, + }, + }, + }, + }, + }, + }, + ), + rf.FromMap(map[string]interface{}{ + "apiVersion": "apps/v1", + "kind": "Deployment", + "metadata": map[string]interface{}{ + "name": "deploy1", + }, + "spec": map[string]interface{}{ + "template": map[string]interface{}{ + "spec": map[string]interface{}{ + "containers": []interface{}{ + map[string]interface{}{ + "name": "nginx", + "env": []interface{}{ + map[string]interface{}{ + "name": "ANOTHERENV", + "value": "HELLO", + }, + }, + }, + map[string]interface{}{ + "name": "busybox", + "image": "busybox", + }, + }, + }, + }, + }, + }, + ), + } + expected := resmap.ResMap{ + resid.NewResId(deploy, "deploy1"): rf.FromMap( + map[string]interface{}{ + "apiVersion": "apps/v1", + "kind": "Deployment", + "metadata": map[string]interface{}{ + "name": "deploy1", + }, + "spec": map[string]interface{}{ + "template": map[string]interface{}{ + "spec": map[string]interface{}{ + "containers": []interface{}{ + map[string]interface{}{ + "name": "nginx", + "image": "nginx:latest", + "env": []interface{}{ + map[string]interface{}{ + "name": "ANOTHERENV", + "value": "HELLO", + }, + map[string]interface{}{ + "name": "SOMEENV", + "value": "BAR", + }, + }, + }, + map[string]interface{}{ + "name": "busybox", + "image": "busybox", + }, + }, + }, + }, + }, + }), + } + lt, err := NewPatchTransformer(patch, rf) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + err = lt.Transform(base) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if !reflect.DeepEqual(base, expected) { + err = expected.ErrorIfNotEqual(base) + t.Fatalf("actual doesn't match expected: %v", err) + } +} + +func TestMultiplePatchesWithConflict(t *testing.T) { + base := resmap.ResMap{ + resid.NewResId(deploy, "deploy1"): rf.FromMap( + map[string]interface{}{ + "apiVersion": "apps/v1", + "kind": "Deployment", + "metadata": map[string]interface{}{ + "name": "deploy1", + }, + "spec": map[string]interface{}{ + "template": map[string]interface{}{ + "spec": map[string]interface{}{ + "containers": []interface{}{ + map[string]interface{}{ + "name": "nginx", + "image": "nginx", + }, + }, + }, + }, + }, + }), + } + patch := []*resource.Resource{ + rf.FromMap(map[string]interface{}{ + "apiVersion": "apps/v1", + "kind": "Deployment", + "metadata": map[string]interface{}{ + "name": "deploy1", + }, + "spec": map[string]interface{}{ + "template": map[string]interface{}{ + "spec": map[string]interface{}{ + "containers": []interface{}{ + map[string]interface{}{ + "name": "nginx", + "image": "nginx:latest", + "env": []interface{}{ + map[string]interface{}{ + "name": "SOMEENV", + "value": "BAR", + }, + }, + }, + }, + }, + }, + }, + }, + ), + rf.FromMap(map[string]interface{}{ + "apiVersion": "apps/v1", + "kind": "Deployment", + "metadata": map[string]interface{}{ + "name": "deploy1", + }, + "spec": map[string]interface{}{ + "template": map[string]interface{}{ + "spec": map[string]interface{}{ + "containers": []interface{}{ + map[string]interface{}{ + "name": "nginx", + "image": "nginx:1.7.9", + }, + }, + }, + }, + }, + }, + ), + } + + lt, err := NewPatchTransformer(patch, rf) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + err = lt.Transform(base) + if err == nil { + t.Fatalf("did not get expected error") + } + if !strings.Contains(err.Error(), "conflict") { + t.Fatalf("expected error to contain %q but get %v", "conflict", err) + } +} + +func TestNoSchemaOverlayRun(t *testing.T) { + base := resmap.ResMap{ + resid.NewResId(foo, "my-foo"): rf.FromMap( + map[string]interface{}{ + "apiVersion": "example.com/v1", + "kind": "Foo", + "metadata": map[string]interface{}{ + "name": "my-foo", + }, + "spec": map[string]interface{}{ + "bar": map[string]interface{}{ + "A": "X", + "B": "Y", + }, + }, + }), + } + patch := []*resource.Resource{ + rf.FromMap(map[string]interface{}{ + "apiVersion": "example.com/v1", + "kind": "Foo", + "metadata": map[string]interface{}{ + "name": "my-foo", + }, + "spec": map[string]interface{}{ + "bar": map[string]interface{}{ + "B": nil, + "C": "Z", + }, + }, + }, + ), + } + expected := resmap.ResMap{ + resid.NewResId(foo, "my-foo"): rf.FromMap( + map[string]interface{}{ + "apiVersion": "example.com/v1", + "kind": "Foo", + "metadata": map[string]interface{}{ + "name": "my-foo", + }, + "spec": map[string]interface{}{ + "bar": map[string]interface{}{ + "A": "X", + "C": "Z", + }, + }, + }), + } + + lt, err := NewPatchTransformer(patch, rf) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + err = lt.Transform(base) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if err = expected.ErrorIfNotEqual(base); err != nil { + t.Fatalf("actual doesn't match expected: %v", err) + } +} + +func TestNoSchemaMultiplePatches(t *testing.T) { + base := resmap.ResMap{ + resid.NewResId(foo, "my-foo"): rf.FromMap( + map[string]interface{}{ + "apiVersion": "example.com/v1", + "kind": "Foo", + "metadata": map[string]interface{}{ + "name": "my-foo", + }, + "spec": map[string]interface{}{ + "bar": map[string]interface{}{ + "A": "X", + "B": "Y", + }, + }, + }), + } + patch := []*resource.Resource{ + rf.FromMap(map[string]interface{}{ + "apiVersion": "example.com/v1", + "kind": "Foo", + "metadata": map[string]interface{}{ + "name": "my-foo", + }, + "spec": map[string]interface{}{ + "bar": map[string]interface{}{ + "B": nil, + "C": "Z", + }, + }, + }, + ), + rf.FromMap(map[string]interface{}{ + "apiVersion": "example.com/v1", + "kind": "Foo", + "metadata": map[string]interface{}{ + "name": "my-foo", + }, + "spec": map[string]interface{}{ + "bar": map[string]interface{}{ + "C": "Z", + "D": "W", + }, + "baz": map[string]interface{}{ + "hello": "world", + }, + }, + }, + ), + } + expected := resmap.ResMap{ + resid.NewResId(foo, "my-foo"): rf.FromMap( + map[string]interface{}{ + "apiVersion": "example.com/v1", + "kind": "Foo", + "metadata": map[string]interface{}{ + "name": "my-foo", + }, + "spec": map[string]interface{}{ + "bar": map[string]interface{}{ + "A": "X", + "C": "Z", + "D": "W", + }, + "baz": map[string]interface{}{ + "hello": "world", + }, + }, + }), + } + + lt, err := NewPatchTransformer(patch, rf) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + err = lt.Transform(base) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if err = expected.ErrorIfNotEqual(base); err != nil { + t.Fatalf("actual doesn't match expected: %v", err) + } +} + +func TestNoSchemaMultiplePatchesWithConflict(t *testing.T) { + base := resmap.ResMap{ + resid.NewResId(foo, "my-foo"): rf.FromMap( + map[string]interface{}{ + "apiVersion": "example.com/v1", + "kind": "Foo", + "metadata": map[string]interface{}{ + "name": "my-foo", + }, + "spec": map[string]interface{}{ + "bar": map[string]interface{}{ + "A": "X", + "B": "Y", + }, + }, + }), + } + patch := []*resource.Resource{ + rf.FromMap(map[string]interface{}{ + "apiVersion": "example.com/v1", + "kind": "Foo", + "metadata": map[string]interface{}{ + "name": "my-foo", + }, + "spec": map[string]interface{}{ + "bar": map[string]interface{}{ + "B": nil, + "C": "Z", + }, + }, + }), + rf.FromMap(map[string]interface{}{ + "apiVersion": "example.com/v1", + "kind": "Foo", + "metadata": map[string]interface{}{ + "name": "my-foo", + }, + "spec": map[string]interface{}{ + "bar": map[string]interface{}{ + "C": "NOT_Z", + }, + }, + }), + } + + lt, err := NewPatchTransformer(patch, rf) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + err = lt.Transform(base) + if err == nil { + t.Fatalf("did not get expected error") + } + if !strings.Contains(err.Error(), "conflict") { + t.Fatalf("expected error to contain %q but get %v", "conflict", err) + } +} diff --git a/staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/transformer/patch/patchconflictdetector.go b/staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/transformer/patch/patchconflictdetector.go new file mode 100644 index 00000000000..10353c77ff6 --- /dev/null +++ b/staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/transformer/patch/patchconflictdetector.go @@ -0,0 +1,137 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package patch + +import ( + "encoding/json" + + "github.com/evanphx/json-patch" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/util/mergepatch" + "k8s.io/apimachinery/pkg/util/strategicpatch" + "sigs.k8s.io/kustomize/pkg/resource" +) + +type conflictDetector interface { + hasConflict(patch1, patch2 *resource.Resource) (bool, error) + findConflict(conflictingPatchIdx int, patches []*resource.Resource) (*resource.Resource, error) + mergePatches(patch1, patch2 *resource.Resource) (*resource.Resource, error) +} + +type jsonMergePatch struct { + rf *resource.Factory +} + +var _ conflictDetector = &jsonMergePatch{} + +func newJMPConflictDetector(rf *resource.Factory) conflictDetector { + return &jsonMergePatch{rf: rf} +} + +func (jmp *jsonMergePatch) hasConflict( + patch1, patch2 *resource.Resource) (bool, error) { + return mergepatch.HasConflicts(patch1.Map(), patch2.Map()) +} + +func (jmp *jsonMergePatch) findConflict( + conflictingPatchIdx int, patches []*resource.Resource) (*resource.Resource, error) { + for i, patch := range patches { + if i == conflictingPatchIdx { + continue + } + if !patches[conflictingPatchIdx].Id().GvknEquals(patch.Id()) { + continue + } + conflict, err := mergepatch.HasConflicts( + patch.Map(), + patches[conflictingPatchIdx].Map()) + if err != nil { + return nil, err + } + if conflict { + return patch, nil + } + } + return nil, nil +} + +func (jmp *jsonMergePatch) mergePatches( + patch1, patch2 *resource.Resource) (*resource.Resource, error) { + baseBytes, err := json.Marshal(patch1.Map()) + if err != nil { + return nil, err + } + patchBytes, err := json.Marshal(patch2.Map()) + if err != nil { + return nil, err + } + mergedBytes, err := jsonpatch.MergeMergePatches(baseBytes, patchBytes) + if err != nil { + return nil, err + } + mergedMap := make(map[string]interface{}) + err = json.Unmarshal(mergedBytes, &mergedMap) + return jmp.rf.FromMap(mergedMap), err +} + +type strategicMergePatch struct { + lookupPatchMeta strategicpatch.LookupPatchMeta + rf *resource.Factory +} + +var _ conflictDetector = &strategicMergePatch{} + +func newSMPConflictDetector( + versionedObj runtime.Object, + rf *resource.Factory) (conflictDetector, error) { + lookupPatchMeta, err := strategicpatch.NewPatchMetaFromStruct(versionedObj) + return &strategicMergePatch{lookupPatchMeta: lookupPatchMeta, rf: rf}, err +} + +func (smp *strategicMergePatch) hasConflict(p1, p2 *resource.Resource) (bool, error) { + return strategicpatch.MergingMapsHaveConflicts( + p1.Map(), p2.Map(), smp.lookupPatchMeta) +} + +func (smp *strategicMergePatch) findConflict( + conflictingPatchIdx int, patches []*resource.Resource) (*resource.Resource, error) { + for i, patch := range patches { + if i == conflictingPatchIdx { + continue + } + if !patches[conflictingPatchIdx].Id().GvknEquals(patch.Id()) { + continue + } + conflict, err := strategicpatch.MergingMapsHaveConflicts( + patch.Map(), + patches[conflictingPatchIdx].Map(), + smp.lookupPatchMeta) + if err != nil { + return nil, err + } + if conflict { + return patch, nil + } + } + return nil, nil +} + +func (smp *strategicMergePatch) mergePatches(patch1, patch2 *resource.Resource) (*resource.Resource, error) { + mergeJSONMap, err := strategicpatch.MergeStrategicMergeMapPatchUsingLookupPatchMeta( + smp.lookupPatchMeta, patch1.Map(), patch2.Map()) + return smp.rf.FromMap(mergeJSONMap), err +} diff --git a/staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/validator/BUILD b/staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/validator/BUILD new file mode 100644 index 00000000000..b42649ce92e --- /dev/null +++ b/staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/validator/BUILD @@ -0,0 +1,29 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = ["validators.go"], + importmap = "k8s.io/kubernetes/vendor/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/validator", + importpath = "k8s.io/cli-runtime/pkg/kustomize/k8sdeps/validator", + visibility = ["//visibility:public"], + deps = [ + "//staging/src/k8s.io/apimachinery/pkg/api/validation:go_default_library", + "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/validation:go_default_library", + "//staging/src/k8s.io/apimachinery/pkg/util/validation:go_default_library", + "//staging/src/k8s.io/apimachinery/pkg/util/validation/field:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/validator/validators.go b/staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/validator/validators.go new file mode 100644 index 00000000000..563e8d6b9c0 --- /dev/null +++ b/staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/validator/validators.go @@ -0,0 +1,61 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package validator provides functions to validate labels, annotations, namespace using apimachinery +package validator + +import ( + "errors" + apivalidation "k8s.io/apimachinery/pkg/api/validation" + v1validation "k8s.io/apimachinery/pkg/apis/meta/v1/validation" + "k8s.io/apimachinery/pkg/util/validation" + "k8s.io/apimachinery/pkg/util/validation/field" +) + +// KustValidator validates Labels and annotations by apimachinery +type KustValidator struct{} + +// NewKustValidator returns a KustValidator object +func NewKustValidator() *KustValidator { + return &KustValidator{} +} + +// MakeAnnotationValidator returns a MapValidatorFunc using apimachinery. +func (v *KustValidator) MakeAnnotationValidator() func(map[string]string) error { + return func(x map[string]string) error { + errs := apivalidation.ValidateAnnotations(x, field.NewPath("field")) + if len(errs) > 0 { + return errors.New(errs.ToAggregate().Error()) + } + return nil + } +} + +// MakeLabelValidator returns a MapValidatorFunc using apimachinery. +func (v *KustValidator) MakeLabelValidator() func(map[string]string) error { + return func(x map[string]string) error { + errs := v1validation.ValidateLabels(x, field.NewPath("field")) + if len(errs) > 0 { + return errors.New(errs.ToAggregate().Error()) + } + return nil + } +} + +// ValidateNamespace validates a string is a valid namespace using apimachinery. +func (v *KustValidator) ValidateNamespace(s string) []string { + return validation.IsDNS1123Label(s) +} diff --git a/staging/src/k8s.io/client-go/Godeps/Godeps.json b/staging/src/k8s.io/client-go/Godeps/Godeps.json index 33492eee78b..c5e9b7f76e8 100644 --- a/staging/src/k8s.io/client-go/Godeps/Godeps.json +++ b/staging/src/k8s.io/client-go/Godeps/Godeps.json @@ -338,6 +338,10 @@ "ImportPath": "k8s.io/api/certificates/v1beta1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/api/coordination/v1", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/api/coordination/v1beta1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" diff --git a/staging/src/k8s.io/client-go/discovery/cached/BUILD b/staging/src/k8s.io/client-go/discovery/cached/BUILD index 3fa72ceb8a9..f40cadb6479 100644 --- a/staging/src/k8s.io/client-go/discovery/cached/BUILD +++ b/staging/src/k8s.io/client-go/discovery/cached/BUILD @@ -11,6 +11,7 @@ go_test( srcs = ["memcache_test.go"], embed = [":go_default_library"], deps = [ + "//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//staging/src/k8s.io/client-go/discovery/fake:go_default_library", ], @@ -22,6 +23,7 @@ go_library( importmap = "k8s.io/kubernetes/vendor/k8s.io/client-go/discovery/cached", importpath = "k8s.io/client-go/discovery/cached", deps = [ + "//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/runtime:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/version:go_default_library", diff --git a/staging/src/k8s.io/client-go/discovery/cached/memcache.go b/staging/src/k8s.io/client-go/discovery/cached/memcache.go index 702392514b5..bd6b478c908 100644 --- a/staging/src/k8s.io/client-go/discovery/cached/memcache.go +++ b/staging/src/k8s.io/client-go/discovery/cached/memcache.go @@ -19,10 +19,14 @@ package cached import ( "errors" "fmt" + "net" + "net/url" "sync" + "syscall" "github.com/googleapis/gnostic/OpenAPIv2" + errorsutil "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" utilruntime "k8s.io/apimachinery/pkg/util/runtime" "k8s.io/apimachinery/pkg/version" @@ -30,40 +34,87 @@ import ( restclient "k8s.io/client-go/rest" ) +type cacheEntry struct { + resourceList *metav1.APIResourceList + err error +} + // memCacheClient can Invalidate() to stay up-to-date with discovery // information. // -// TODO: Switch to a watch interface. Right now it will poll anytime -// Invalidate() is called. +// TODO: Switch to a watch interface. Right now it will poll after each +// Invalidate() call. type memCacheClient struct { delegate discovery.DiscoveryInterface lock sync.RWMutex - groupToServerResources map[string]*metav1.APIResourceList + groupToServerResources map[string]*cacheEntry groupList *metav1.APIGroupList cacheValid bool } // Error Constants var ( - ErrCacheEmpty = errors.New("the cache has not been filled yet") ErrCacheNotFound = errors.New("not found") ) var _ discovery.CachedDiscoveryInterface = &memCacheClient{} +// isTransientConnectionError checks whether given error is "Connection refused" or +// "Connection reset" error which usually means that apiserver is temporarily +// unavailable. +func isTransientConnectionError(err error) bool { + urlError, ok := err.(*url.Error) + if !ok { + return false + } + opError, ok := urlError.Err.(*net.OpError) + if !ok { + return false + } + errno, ok := opError.Err.(syscall.Errno) + if !ok { + return false + } + return errno == syscall.ECONNREFUSED || errno == syscall.ECONNRESET +} + +func isTransientError(err error) bool { + if isTransientConnectionError(err) { + return true + } + + if t, ok := err.(errorsutil.APIStatus); ok && t.Status().Code >= 500 { + return true + } + + return errorsutil.IsTooManyRequests(err) +} + // ServerResourcesForGroupVersion returns the supported resources for a group and version. func (d *memCacheClient) ServerResourcesForGroupVersion(groupVersion string) (*metav1.APIResourceList, error) { - d.lock.RLock() - defer d.lock.RUnlock() + d.lock.Lock() + defer d.lock.Unlock() if !d.cacheValid { - return nil, ErrCacheEmpty + if err := d.refreshLocked(); err != nil { + return nil, err + } } cachedVal, ok := d.groupToServerResources[groupVersion] if !ok { return nil, ErrCacheNotFound } - return cachedVal, nil + + if cachedVal.err != nil && isTransientError(cachedVal.err) { + r, err := d.serverResourcesForGroupVersion(groupVersion) + if err != nil { + utilruntime.HandleError(fmt.Errorf("couldn't get resource list for %v: %v", groupVersion, err)) + } + cachedVal = &cacheEntry{r, err} + d.groupToServerResources[groupVersion] = cachedVal + } + + return cachedVal.resourceList, cachedVal.err } // ServerResources returns the supported resources for all groups and versions. @@ -72,10 +123,12 @@ func (d *memCacheClient) ServerResources() ([]*metav1.APIResourceList, error) { } func (d *memCacheClient) ServerGroups() (*metav1.APIGroupList, error) { - d.lock.RLock() - defer d.lock.RUnlock() - if d.groupList == nil { - return nil, ErrCacheEmpty + d.lock.Lock() + defer d.lock.Unlock() + if !d.cacheValid { + if err := d.refreshLocked(); err != nil { + return nil, err + } } return d.groupList, nil } @@ -103,49 +156,59 @@ func (d *memCacheClient) OpenAPISchema() (*openapi_v2.Document, error) { func (d *memCacheClient) Fresh() bool { d.lock.RLock() defer d.lock.RUnlock() - // Fresh is supposed to tell the caller whether or not to retry if the cache - // fails to find something. The idea here is that Invalidate will be called - // periodically and therefore we'll always be returning the latest data. (And - // in the future we can watch and stay even more up-to-date.) So we only - // return false if the cache has never been filled. + // Return whether the cache is populated at all. It is still possible that + // a single entry is missing due to transient errors and the attempt to read + // that entry will trigger retry. return d.cacheValid } -// Invalidate refreshes the cache, blocking calls until the cache has been -// refreshed. It would be trivial to make a version that does this in the -// background while continuing to respond to requests if needed. +// Invalidate enforces that no cached data that is older than the current time +// is used. func (d *memCacheClient) Invalidate() { d.lock.Lock() defer d.lock.Unlock() + d.cacheValid = false + d.groupToServerResources = nil + d.groupList = nil +} +// refreshLocked refreshes the state of cache. The caller must hold d.lock for +// writing. +func (d *memCacheClient) refreshLocked() error { // TODO: Could this multiplicative set of calls be replaced by a single call // to ServerResources? If it's possible for more than one resulting // APIResourceList to have the same GroupVersion, the lists would need merged. gl, err := d.delegate.ServerGroups() if err != nil || len(gl.Groups) == 0 { - utilruntime.HandleError(fmt.Errorf("couldn't get current server API group list; will keep using cached value. (%v)", err)) - return + utilruntime.HandleError(fmt.Errorf("couldn't get current server API group list: %v", err)) + return err } - rl := map[string]*metav1.APIResourceList{} + rl := map[string]*cacheEntry{} for _, g := range gl.Groups { for _, v := range g.Versions { - r, err := d.delegate.ServerResourcesForGroupVersion(v.GroupVersion) - if err != nil || len(r.APIResources) == 0 { + r, err := d.serverResourcesForGroupVersion(v.GroupVersion) + rl[v.GroupVersion] = &cacheEntry{r, err} + if err != nil { utilruntime.HandleError(fmt.Errorf("couldn't get resource list for %v: %v", v.GroupVersion, err)) - if cur, ok := d.groupToServerResources[v.GroupVersion]; ok { - // retain the existing list, if we had it. - r = cur - } else { - continue - } } - rl[v.GroupVersion] = r } } d.groupToServerResources, d.groupList = rl, gl d.cacheValid = true + return nil +} + +func (d *memCacheClient) serverResourcesForGroupVersion(groupVersion string) (*metav1.APIResourceList, error) { + r, err := d.delegate.ServerResourcesForGroupVersion(groupVersion) + if err != nil { + return r, err + } + if len(r.APIResources) == 0 { + return r, fmt.Errorf("Got empty response for: %v", groupVersion) + } + return r, nil } // NewMemCacheClient creates a new CachedDiscoveryInterface which caches @@ -156,6 +219,6 @@ func (d *memCacheClient) Invalidate() { func NewMemCacheClient(delegate discovery.DiscoveryInterface) discovery.CachedDiscoveryInterface { return &memCacheClient{ delegate: delegate, - groupToServerResources: map[string]*metav1.APIResourceList{}, + groupToServerResources: map[string]*cacheEntry{}, } } diff --git a/staging/src/k8s.io/client-go/discovery/cached/memcache_test.go b/staging/src/k8s.io/client-go/discovery/cached/memcache_test.go index a9caa6e83d3..680c68d8967 100644 --- a/staging/src/k8s.io/client-go/discovery/cached/memcache_test.go +++ b/staging/src/k8s.io/client-go/discovery/cached/memcache_test.go @@ -18,27 +18,35 @@ package cached import ( "errors" + "net/http" "reflect" "sync" "testing" + errorsutil "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/discovery/fake" ) +type resourceMapEntry struct { + list *metav1.APIResourceList + err error +} + type fakeDiscovery struct { *fake.FakeDiscovery - lock sync.Mutex - groupList *metav1.APIGroupList - resourceMap map[string]*metav1.APIResourceList + lock sync.Mutex + groupList *metav1.APIGroupList + groupListErr error + resourceMap map[string]*resourceMapEntry } func (c *fakeDiscovery) ServerResourcesForGroupVersion(groupVersion string) (*metav1.APIResourceList, error) { c.lock.Lock() defer c.lock.Unlock() if rl, ok := c.resourceMap[groupVersion]; ok { - return rl, nil + return rl.list, rl.err } return nil, errors.New("doesn't exist") } @@ -49,7 +57,7 @@ func (c *fakeDiscovery) ServerGroups() (*metav1.APIGroupList, error) { if c.groupList == nil { return nil, errors.New("doesn't exist") } - return c.groupList, nil + return c.groupList, c.groupListErr } func TestClient(t *testing.T) { @@ -63,33 +71,37 @@ func TestClient(t *testing.T) { }}, }}, }, - resourceMap: map[string]*metav1.APIResourceList{ + resourceMap: map[string]*resourceMapEntry{ "astronomy/v8beta1": { - GroupVersion: "astronomy/v8beta1", - APIResources: []metav1.APIResource{{ - Name: "dwarfplanets", - SingularName: "dwarfplanet", - Namespaced: true, - Kind: "DwarfPlanet", - ShortNames: []string{"dp"}, - }}, + list: &metav1.APIResourceList{ + GroupVersion: "astronomy/v8beta1", + APIResources: []metav1.APIResource{{ + Name: "dwarfplanets", + SingularName: "dwarfplanet", + Namespaced: true, + Kind: "DwarfPlanet", + ShortNames: []string{"dp"}, + }}, + }, }, }, } c := NewMemCacheClient(fake) - g, err := c.ServerGroups() - if err == nil { - t.Errorf("Unexpected non-error.") - } if c.Fresh() { t.Errorf("Expected not fresh.") } - - c.Invalidate() + g, err := c.ServerGroups() + if err != nil { + t.Errorf("Unexpected error: %v", err) + } if !c.Fresh() { t.Errorf("Expected fresh.") } + c.Invalidate() + if c.Fresh() { + t.Errorf("Expected not fresh.") + } g, err = c.ServerGroups() if err != nil { @@ -98,25 +110,30 @@ func TestClient(t *testing.T) { if e, a := fake.groupList, g; !reflect.DeepEqual(e, a) { t.Errorf("Expected %#v, got %#v", e, a) } + if !c.Fresh() { + t.Errorf("Expected fresh.") + } r, err := c.ServerResourcesForGroupVersion("astronomy/v8beta1") if err != nil { t.Errorf("Unexpected error: %v", err) } - if e, a := fake.resourceMap["astronomy/v8beta1"], r; !reflect.DeepEqual(e, a) { + if e, a := fake.resourceMap["astronomy/v8beta1"].list, r; !reflect.DeepEqual(e, a) { t.Errorf("Expected %#v, got %#v", e, a) } fake.lock.Lock() - fake.resourceMap = map[string]*metav1.APIResourceList{ + fake.resourceMap = map[string]*resourceMapEntry{ "astronomy/v8beta1": { - GroupVersion: "astronomy/v8beta1", - APIResources: []metav1.APIResource{{ - Name: "stars", - SingularName: "star", - Namespaced: true, - Kind: "Star", - ShortNames: []string{"s"}, - }}, + list: &metav1.APIResourceList{ + GroupVersion: "astronomy/v8beta1", + APIResources: []metav1.APIResource{{ + Name: "stars", + SingularName: "star", + Namespaced: true, + Kind: "Star", + ShortNames: []string{"s"}, + }}, + }, }, } fake.lock.Unlock() @@ -126,7 +143,235 @@ func TestClient(t *testing.T) { if err != nil { t.Errorf("Unexpected error: %v", err) } - if e, a := fake.resourceMap["astronomy/v8beta1"], r; !reflect.DeepEqual(e, a) { + if e, a := fake.resourceMap["astronomy/v8beta1"].list, r; !reflect.DeepEqual(e, a) { + t.Errorf("Expected %#v, got %#v", e, a) + } +} + +func TestServerGroupsFails(t *testing.T) { + fake := &fakeDiscovery{ + groupList: &metav1.APIGroupList{ + Groups: []metav1.APIGroup{{ + Name: "astronomy", + Versions: []metav1.GroupVersionForDiscovery{{ + GroupVersion: "astronomy/v8beta1", + Version: "v8beta1", + }}, + }}, + }, + groupListErr: errors.New("some error"), + resourceMap: map[string]*resourceMapEntry{ + "astronomy/v8beta1": { + list: &metav1.APIResourceList{ + GroupVersion: "astronomy/v8beta1", + APIResources: []metav1.APIResource{{ + Name: "dwarfplanets", + SingularName: "dwarfplanet", + Namespaced: true, + Kind: "DwarfPlanet", + ShortNames: []string{"dp"}, + }}, + }, + }, + }, + } + + c := NewMemCacheClient(fake) + if c.Fresh() { + t.Errorf("Expected not fresh.") + } + _, err := c.ServerGroups() + if err == nil { + t.Errorf("Expected error") + } + if c.Fresh() { + t.Errorf("Expected not fresh.") + } + fake.lock.Lock() + fake.groupListErr = nil + fake.lock.Unlock() + r, err := c.ServerResourcesForGroupVersion("astronomy/v8beta1") + if err != nil { + t.Errorf("Unexpected error: %v", err) + } + if e, a := fake.resourceMap["astronomy/v8beta1"].list, r; !reflect.DeepEqual(e, a) { + t.Errorf("Expected %#v, got %#v", e, a) + } + if !c.Fresh() { + t.Errorf("Expected not fresh.") + } +} + +func TestPartialPermanentFailure(t *testing.T) { + fake := &fakeDiscovery{ + groupList: &metav1.APIGroupList{ + Groups: []metav1.APIGroup{{ + Name: "astronomy", + Versions: []metav1.GroupVersionForDiscovery{{ + GroupVersion: "astronomy/v8beta1", + Version: "v8beta1", + }, { + GroupVersion: "astronomy2/v8beta1", + Version: "v8beta1", + }}, + }}, + }, + resourceMap: map[string]*resourceMapEntry{ + "astronomy/v8beta1": { + err: errors.New("some permanent error"), + }, + "astronomy2/v8beta1": { + list: &metav1.APIResourceList{ + GroupVersion: "astronomy2/v8beta1", + APIResources: []metav1.APIResource{{ + Name: "dwarfplanets", + SingularName: "dwarfplanet", + Namespaced: true, + Kind: "DwarfPlanet", + ShortNames: []string{"dp"}, + }}, + }, + }, + }, + } + + c := NewMemCacheClient(fake) + if c.Fresh() { + t.Errorf("Expected not fresh.") + } + r, err := c.ServerResourcesForGroupVersion("astronomy2/v8beta1") + if err != nil { + t.Errorf("Unexpected error: %v", err) + } + if e, a := fake.resourceMap["astronomy2/v8beta1"].list, r; !reflect.DeepEqual(e, a) { + t.Errorf("Expected %#v, got %#v", e, a) + } + _, err = c.ServerResourcesForGroupVersion("astronomy/v8beta1") + if err == nil { + t.Errorf("Expected error, got nil") + } + + fake.lock.Lock() + fake.resourceMap["astronomy/v8beta1"] = &resourceMapEntry{ + list: &metav1.APIResourceList{ + GroupVersion: "astronomy/v8beta1", + APIResources: []metav1.APIResource{{ + Name: "dwarfplanets", + SingularName: "dwarfplanet", + Namespaced: true, + Kind: "DwarfPlanet", + ShortNames: []string{"dp"}, + }}, + }, + err: nil, + } + fake.lock.Unlock() + // We don't retry permanent errors, so it should fail. + _, err = c.ServerResourcesForGroupVersion("astronomy/v8beta1") + if err == nil { + t.Errorf("Expected error, got nil") + } + c.Invalidate() + + // After Invalidate, we should retry. + r, err = c.ServerResourcesForGroupVersion("astronomy/v8beta1") + if err != nil { + t.Errorf("Unexpected error: %v", err) + } + if e, a := fake.resourceMap["astronomy/v8beta1"].list, r; !reflect.DeepEqual(e, a) { + t.Errorf("Expected %#v, got %#v", e, a) + } +} + +func TestPartialRetryableFailure(t *testing.T) { + fake := &fakeDiscovery{ + groupList: &metav1.APIGroupList{ + Groups: []metav1.APIGroup{{ + Name: "astronomy", + Versions: []metav1.GroupVersionForDiscovery{{ + GroupVersion: "astronomy/v8beta1", + Version: "v8beta1", + }, { + GroupVersion: "astronomy2/v8beta1", + Version: "v8beta1", + }}, + }}, + }, + resourceMap: map[string]*resourceMapEntry{ + "astronomy/v8beta1": { + err: &errorsutil.StatusError{ + ErrStatus: metav1.Status{ + Message: "Some retryable error", + Code: int32(http.StatusServiceUnavailable), + Reason: metav1.StatusReasonServiceUnavailable, + }, + }, + }, + "astronomy2/v8beta1": { + list: &metav1.APIResourceList{ + GroupVersion: "astronomy2/v8beta1", + APIResources: []metav1.APIResource{{ + Name: "dwarfplanets", + SingularName: "dwarfplanet", + Namespaced: true, + Kind: "DwarfPlanet", + ShortNames: []string{"dp"}, + }}, + }, + }, + }, + } + + c := NewMemCacheClient(fake) + if c.Fresh() { + t.Errorf("Expected not fresh.") + } + r, err := c.ServerResourcesForGroupVersion("astronomy2/v8beta1") + if err != nil { + t.Errorf("Unexpected error: %v", err) + } + if e, a := fake.resourceMap["astronomy2/v8beta1"].list, r; !reflect.DeepEqual(e, a) { + t.Errorf("Expected %#v, got %#v", e, a) + } + _, err = c.ServerResourcesForGroupVersion("astronomy/v8beta1") + if err == nil { + t.Errorf("Expected error, got nil") + } + + fake.lock.Lock() + fake.resourceMap["astronomy/v8beta1"] = &resourceMapEntry{ + list: &metav1.APIResourceList{ + GroupVersion: "astronomy/v8beta1", + APIResources: []metav1.APIResource{{ + Name: "dwarfplanets", + SingularName: "dwarfplanet", + Namespaced: true, + Kind: "DwarfPlanet", + ShortNames: []string{"dp"}, + }}, + }, + err: nil, + } + fake.lock.Unlock() + // We should retry retryable error even without Invalidate() being called, + // so no error is expected. + r, err = c.ServerResourcesForGroupVersion("astronomy/v8beta1") + if err != nil { + t.Errorf("Expected no error, got %v", err) + } + if e, a := fake.resourceMap["astronomy/v8beta1"].list, r; !reflect.DeepEqual(e, a) { + t.Errorf("Expected %#v, got %#v", e, a) + } + + // Check that the last result was cached and we don't retry further. + fake.lock.Lock() + fake.resourceMap["astronomy/v8beta1"].err = errors.New("some permanent error") + fake.lock.Unlock() + r, err = c.ServerResourcesForGroupVersion("astronomy/v8beta1") + if err != nil { + t.Errorf("Expected no error, got %v", err) + } + if e, a := fake.resourceMap["astronomy/v8beta1"].list, r; !reflect.DeepEqual(e, a) { t.Errorf("Expected %#v, got %#v", e, a) } } diff --git a/staging/src/k8s.io/client-go/discovery/discovery_client.go b/staging/src/k8s.io/client-go/discovery/discovery_client.go index 17b39de0539..52f67af1de0 100644 --- a/staging/src/k8s.io/client-go/discovery/discovery_client.go +++ b/staging/src/k8s.io/client-go/discovery/discovery_client.go @@ -26,7 +26,7 @@ import ( "time" "github.com/golang/protobuf/proto" - "github.com/googleapis/gnostic/OpenAPIv2" + openapi_v2 "github.com/googleapis/gnostic/OpenAPIv2" "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -60,6 +60,9 @@ type DiscoveryInterface interface { } // CachedDiscoveryInterface is a DiscoveryInterface with cache invalidation and freshness. +// Note that If the ServerResourcesForGroupVersion method returns a cache miss +// error, the user needs to explicitly call Invalidate to clear the cache, +// otherwise the same cache miss error will be returned next time. type CachedDiscoveryInterface interface { DiscoveryInterface // Fresh is supposed to tell the caller whether or not to retry if the cache @@ -68,7 +71,8 @@ type CachedDiscoveryInterface interface { // TODO: this needs to be revisited, this interface can't be locked properly // and doesn't make a lot of sense. Fresh() bool - // Invalidate enforces that no cached data is used in the future that is older than the current time. + // Invalidate enforces that no cached data that is older than the current time + // is used. Invalidate() } diff --git a/staging/src/k8s.io/client-go/examples/create-update-delete-deployment/README.md b/staging/src/k8s.io/client-go/examples/create-update-delete-deployment/README.md index 72cfc5d91db..2c8b19a016c 100644 --- a/staging/src/k8s.io/client-go/examples/create-update-delete-deployment/README.md +++ b/staging/src/k8s.io/client-go/examples/create-update-delete-deployment/README.md @@ -36,15 +36,9 @@ Running this command will execute the following operations on your cluster: image to `nginx:1.13`. You are encouraged to inspect the retry loop that handles conflicts. Verify the new replica count and container image with `kubectl describe deployment demo`. -3. **Rollback Deployment:** This will rollback the Deployment to the last - revision. In this case, it's the revision that was created in Step 1. - Use `kubectl describe` to verify the container image is now `nginx:1.12`. - Also note that the Deployment's replica count is still 1; this is because a - Deployment revision is created if and only if the Deployment's pod template - (`.spec.template`) is changed. -4. **List Deployments:** This will retrieve Deployments in the `default` +3. **List Deployments:** This will retrieve Deployments in the `default` namespace and print their names and replica counts. -5. **Delete Deployment:** This will delete the Deployment object and its +4. **Delete Deployment:** This will delete the Deployment object and its dependent ReplicaSet resource. Verify with `kubectl get deployments`. Each step is separated by an interactive prompt. You must hit the @@ -63,10 +57,6 @@ Updating deployment... Updated deployment... -> Press Return key to continue. -Rolling back deployment... -Rolled back deployment... --> Press Return key to continue. - Listing deployments in namespace "default": * demo-deployment (1 replicas) -> Press Return key to continue. diff --git a/staging/src/k8s.io/client-go/informers/BUILD b/staging/src/k8s.io/client-go/informers/BUILD index 24af1356b8c..7810958a1c1 100644 --- a/staging/src/k8s.io/client-go/informers/BUILD +++ b/staging/src/k8s.io/client-go/informers/BUILD @@ -23,6 +23,7 @@ go_library( "//staging/src/k8s.io/api/batch/v1beta1:go_default_library", "//staging/src/k8s.io/api/batch/v2alpha1:go_default_library", "//staging/src/k8s.io/api/certificates/v1beta1:go_default_library", + "//staging/src/k8s.io/api/coordination/v1:go_default_library", "//staging/src/k8s.io/api/coordination/v1beta1:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library", "//staging/src/k8s.io/api/events/v1beta1:go_default_library", diff --git a/staging/src/k8s.io/client-go/informers/coordination/BUILD b/staging/src/k8s.io/client-go/informers/coordination/BUILD index 014cb3e098f..51e67990781 100644 --- a/staging/src/k8s.io/client-go/informers/coordination/BUILD +++ b/staging/src/k8s.io/client-go/informers/coordination/BUILD @@ -7,6 +7,7 @@ go_library( importpath = "k8s.io/client-go/informers/coordination", visibility = ["//visibility:public"], deps = [ + "//staging/src/k8s.io/client-go/informers/coordination/v1:go_default_library", "//staging/src/k8s.io/client-go/informers/coordination/v1beta1:go_default_library", "//staging/src/k8s.io/client-go/informers/internalinterfaces:go_default_library", ], @@ -23,6 +24,7 @@ filegroup( name = "all-srcs", srcs = [ ":package-srcs", + "//staging/src/k8s.io/client-go/informers/coordination/v1:all-srcs", "//staging/src/k8s.io/client-go/informers/coordination/v1beta1:all-srcs", ], tags = ["automanaged"], diff --git a/staging/src/k8s.io/client-go/informers/coordination/interface.go b/staging/src/k8s.io/client-go/informers/coordination/interface.go index 8e541d80d41..54cfd7b9f26 100644 --- a/staging/src/k8s.io/client-go/informers/coordination/interface.go +++ b/staging/src/k8s.io/client-go/informers/coordination/interface.go @@ -19,12 +19,15 @@ limitations under the License. package coordination import ( + v1 "k8s.io/client-go/informers/coordination/v1" v1beta1 "k8s.io/client-go/informers/coordination/v1beta1" internalinterfaces "k8s.io/client-go/informers/internalinterfaces" ) // Interface provides access to each of this group's versions. type Interface interface { + // V1 provides access to shared informers for resources in V1. + V1() v1.Interface // V1beta1 provides access to shared informers for resources in V1beta1. V1beta1() v1beta1.Interface } @@ -40,6 +43,11 @@ func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakList return &group{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} } +// V1 returns a new v1.Interface. +func (g *group) V1() v1.Interface { + return v1.New(g.factory, g.namespace, g.tweakListOptions) +} + // V1beta1 returns a new v1beta1.Interface. func (g *group) V1beta1() v1beta1.Interface { return v1beta1.New(g.factory, g.namespace, g.tweakListOptions) diff --git a/staging/src/k8s.io/sample-apiserver/pkg/client/informers/internalversion/wardle/internalversion/BUILD b/staging/src/k8s.io/client-go/informers/coordination/v1/BUILD similarity index 52% rename from staging/src/k8s.io/sample-apiserver/pkg/client/informers/internalversion/wardle/internalversion/BUILD rename to staging/src/k8s.io/client-go/informers/coordination/v1/BUILD index f75fdcef59c..d4c2ea57860 100644 --- a/staging/src/k8s.io/sample-apiserver/pkg/client/informers/internalversion/wardle/internalversion/BUILD +++ b/staging/src/k8s.io/client-go/informers/coordination/v1/BUILD @@ -3,22 +3,21 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library") go_library( name = "go_default_library", srcs = [ - "fischer.go", - "flunder.go", "interface.go", + "lease.go", ], - importmap = "k8s.io/kubernetes/vendor/k8s.io/sample-apiserver/pkg/client/informers/internalversion/wardle/internalversion", - importpath = "k8s.io/sample-apiserver/pkg/client/informers/internalversion/wardle/internalversion", + importmap = "k8s.io/kubernetes/vendor/k8s.io/client-go/informers/coordination/v1", + importpath = "k8s.io/client-go/informers/coordination/v1", visibility = ["//visibility:public"], deps = [ + "//staging/src/k8s.io/api/coordination/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/watch:go_default_library", + "//staging/src/k8s.io/client-go/informers/internalinterfaces:go_default_library", + "//staging/src/k8s.io/client-go/kubernetes:go_default_library", + "//staging/src/k8s.io/client-go/listers/coordination/v1:go_default_library", "//staging/src/k8s.io/client-go/tools/cache:go_default_library", - "//staging/src/k8s.io/sample-apiserver/pkg/apis/wardle:go_default_library", - "//staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion:go_default_library", - "//staging/src/k8s.io/sample-apiserver/pkg/client/informers/internalversion/internalinterfaces:go_default_library", - "//staging/src/k8s.io/sample-apiserver/pkg/client/listers/wardle/internalversion:go_default_library", ], ) diff --git a/staging/src/k8s.io/sample-apiserver/pkg/client/informers/internalversion/wardle/internalversion/interface.go b/staging/src/k8s.io/client-go/informers/coordination/v1/interface.go similarity index 64% rename from staging/src/k8s.io/sample-apiserver/pkg/client/informers/internalversion/wardle/internalversion/interface.go rename to staging/src/k8s.io/client-go/informers/coordination/v1/interface.go index b3b98a338e8..05c4acbef8b 100644 --- a/staging/src/k8s.io/sample-apiserver/pkg/client/informers/internalversion/wardle/internalversion/interface.go +++ b/staging/src/k8s.io/client-go/informers/coordination/v1/interface.go @@ -16,18 +16,16 @@ limitations under the License. // Code generated by informer-gen. DO NOT EDIT. -package internalversion +package v1 import ( - internalinterfaces "k8s.io/sample-apiserver/pkg/client/informers/internalversion/internalinterfaces" + internalinterfaces "k8s.io/client-go/informers/internalinterfaces" ) // Interface provides access to all the informers in this group version. type Interface interface { - // Fischers returns a FischerInformer. - Fischers() FischerInformer - // Flunders returns a FlunderInformer. - Flunders() FlunderInformer + // Leases returns a LeaseInformer. + Leases() LeaseInformer } type version struct { @@ -41,12 +39,7 @@ func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakList return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} } -// Fischers returns a FischerInformer. -func (v *version) Fischers() FischerInformer { - return &fischerInformer{factory: v.factory, tweakListOptions: v.tweakListOptions} -} - -// Flunders returns a FlunderInformer. -func (v *version) Flunders() FlunderInformer { - return &flunderInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} +// Leases returns a LeaseInformer. +func (v *version) Leases() LeaseInformer { + return &leaseInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} } diff --git a/staging/src/k8s.io/client-go/informers/coordination/v1/lease.go b/staging/src/k8s.io/client-go/informers/coordination/v1/lease.go new file mode 100644 index 00000000000..b8a3de471c9 --- /dev/null +++ b/staging/src/k8s.io/client-go/informers/coordination/v1/lease.go @@ -0,0 +1,89 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by informer-gen. DO NOT EDIT. + +package v1 + +import ( + time "time" + + coordinationv1 "k8s.io/api/coordination/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + watch "k8s.io/apimachinery/pkg/watch" + internalinterfaces "k8s.io/client-go/informers/internalinterfaces" + kubernetes "k8s.io/client-go/kubernetes" + v1 "k8s.io/client-go/listers/coordination/v1" + cache "k8s.io/client-go/tools/cache" +) + +// LeaseInformer provides access to a shared informer and lister for +// Leases. +type LeaseInformer interface { + Informer() cache.SharedIndexInformer + Lister() v1.LeaseLister +} + +type leaseInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc + namespace string +} + +// NewLeaseInformer constructs a new informer for Lease 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 NewLeaseInformer(client kubernetes.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredLeaseInformer(client, namespace, resyncPeriod, indexers, nil) +} + +// NewFilteredLeaseInformer constructs a new informer for Lease 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 NewFilteredLeaseInformer(client kubernetes.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options metav1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.CoordinationV1().Leases(namespace).List(options) + }, + WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.CoordinationV1().Leases(namespace).Watch(options) + }, + }, + &coordinationv1.Lease{}, + resyncPeriod, + indexers, + ) +} + +func (f *leaseInformer) defaultInformer(client kubernetes.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredLeaseInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *leaseInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&coordinationv1.Lease{}, f.defaultInformer) +} + +func (f *leaseInformer) Lister() v1.LeaseLister { + return v1.NewLeaseLister(f.Informer().GetIndexer()) +} diff --git a/staging/src/k8s.io/client-go/informers/generic.go b/staging/src/k8s.io/client-go/informers/generic.go index 09a5efe2ec8..ab1a410ed1a 100644 --- a/staging/src/k8s.io/client-go/informers/generic.go +++ b/staging/src/k8s.io/client-go/informers/generic.go @@ -34,6 +34,7 @@ import ( batchv1beta1 "k8s.io/api/batch/v1beta1" v2alpha1 "k8s.io/api/batch/v2alpha1" certificatesv1beta1 "k8s.io/api/certificates/v1beta1" + coordinationv1 "k8s.io/api/coordination/v1" coordinationv1beta1 "k8s.io/api/coordination/v1beta1" corev1 "k8s.io/api/core/v1" eventsv1beta1 "k8s.io/api/events/v1beta1" @@ -153,6 +154,10 @@ func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource case certificatesv1beta1.SchemeGroupVersion.WithResource("certificatesigningrequests"): return &genericInformer{resource: resource.GroupResource(), informer: f.Certificates().V1beta1().CertificateSigningRequests().Informer()}, nil + // Group=coordination.k8s.io, Version=v1 + case coordinationv1.SchemeGroupVersion.WithResource("leases"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Coordination().V1().Leases().Informer()}, nil + // Group=coordination.k8s.io, Version=v1beta1 case coordinationv1beta1.SchemeGroupVersion.WithResource("leases"): return &genericInformer{resource: resource.GroupResource(), informer: f.Coordination().V1beta1().Leases().Informer()}, nil diff --git a/staging/src/k8s.io/client-go/kubernetes/BUILD b/staging/src/k8s.io/client-go/kubernetes/BUILD index da4639ae342..ed3e7ca8c56 100644 --- a/staging/src/k8s.io/client-go/kubernetes/BUILD +++ b/staging/src/k8s.io/client-go/kubernetes/BUILD @@ -29,6 +29,7 @@ go_library( "//staging/src/k8s.io/client-go/kubernetes/typed/batch/v1beta1:go_default_library", "//staging/src/k8s.io/client-go/kubernetes/typed/batch/v2alpha1:go_default_library", "//staging/src/k8s.io/client-go/kubernetes/typed/certificates/v1beta1:go_default_library", + "//staging/src/k8s.io/client-go/kubernetes/typed/coordination/v1:go_default_library", "//staging/src/k8s.io/client-go/kubernetes/typed/coordination/v1beta1:go_default_library", "//staging/src/k8s.io/client-go/kubernetes/typed/core/v1:go_default_library", "//staging/src/k8s.io/client-go/kubernetes/typed/events/v1beta1:go_default_library", @@ -79,6 +80,7 @@ filegroup( "//staging/src/k8s.io/client-go/kubernetes/typed/batch/v1beta1:all-srcs", "//staging/src/k8s.io/client-go/kubernetes/typed/batch/v2alpha1:all-srcs", "//staging/src/k8s.io/client-go/kubernetes/typed/certificates/v1beta1:all-srcs", + "//staging/src/k8s.io/client-go/kubernetes/typed/coordination/v1:all-srcs", "//staging/src/k8s.io/client-go/kubernetes/typed/coordination/v1beta1:all-srcs", "//staging/src/k8s.io/client-go/kubernetes/typed/core/v1:all-srcs", "//staging/src/k8s.io/client-go/kubernetes/typed/events/v1beta1:all-srcs", diff --git a/staging/src/k8s.io/client-go/kubernetes/clientset.go b/staging/src/k8s.io/client-go/kubernetes/clientset.go index 6ad01d6db19..3b530df5429 100644 --- a/staging/src/k8s.io/client-go/kubernetes/clientset.go +++ b/staging/src/k8s.io/client-go/kubernetes/clientset.go @@ -37,6 +37,7 @@ import ( batchv1beta1 "k8s.io/client-go/kubernetes/typed/batch/v1beta1" batchv2alpha1 "k8s.io/client-go/kubernetes/typed/batch/v2alpha1" certificatesv1beta1 "k8s.io/client-go/kubernetes/typed/certificates/v1beta1" + coordinationv1 "k8s.io/client-go/kubernetes/typed/coordination/v1" coordinationv1beta1 "k8s.io/client-go/kubernetes/typed/coordination/v1beta1" corev1 "k8s.io/client-go/kubernetes/typed/core/v1" eventsv1beta1 "k8s.io/client-go/kubernetes/typed/events/v1beta1" @@ -62,11 +63,11 @@ type Interface interface { AdmissionregistrationV1beta1() admissionregistrationv1beta1.AdmissionregistrationV1beta1Interface // Deprecated: please explicitly pick a version if possible. Admissionregistration() admissionregistrationv1beta1.AdmissionregistrationV1beta1Interface - AppsV1beta1() appsv1beta1.AppsV1beta1Interface - AppsV1beta2() appsv1beta2.AppsV1beta2Interface AppsV1() appsv1.AppsV1Interface // Deprecated: please explicitly pick a version if possible. Apps() appsv1.AppsV1Interface + AppsV1beta1() appsv1beta1.AppsV1beta1Interface + AppsV1beta2() appsv1beta2.AppsV1beta2Interface AuditregistrationV1alpha1() auditregistrationv1alpha1.AuditregistrationV1alpha1Interface // Deprecated: please explicitly pick a version if possible. Auditregistration() auditregistrationv1alpha1.AuditregistrationV1alpha1Interface @@ -92,8 +93,9 @@ type Interface interface { // Deprecated: please explicitly pick a version if possible. Certificates() certificatesv1beta1.CertificatesV1beta1Interface CoordinationV1beta1() coordinationv1beta1.CoordinationV1beta1Interface + CoordinationV1() coordinationv1.CoordinationV1Interface // Deprecated: please explicitly pick a version if possible. - Coordination() coordinationv1beta1.CoordinationV1beta1Interface + Coordination() coordinationv1.CoordinationV1Interface CoreV1() corev1.CoreV1Interface // Deprecated: please explicitly pick a version if possible. Core() corev1.CoreV1Interface @@ -134,9 +136,9 @@ type Clientset struct { *discovery.DiscoveryClient admissionregistrationV1alpha1 *admissionregistrationv1alpha1.AdmissionregistrationV1alpha1Client admissionregistrationV1beta1 *admissionregistrationv1beta1.AdmissionregistrationV1beta1Client + appsV1 *appsv1.AppsV1Client appsV1beta1 *appsv1beta1.AppsV1beta1Client appsV1beta2 *appsv1beta2.AppsV1beta2Client - appsV1 *appsv1.AppsV1Client auditregistrationV1alpha1 *auditregistrationv1alpha1.AuditregistrationV1alpha1Client authenticationV1 *authenticationv1.AuthenticationV1Client authenticationV1beta1 *authenticationv1beta1.AuthenticationV1beta1Client @@ -150,6 +152,7 @@ type Clientset struct { batchV2alpha1 *batchv2alpha1.BatchV2alpha1Client certificatesV1beta1 *certificatesv1beta1.CertificatesV1beta1Client coordinationV1beta1 *coordinationv1beta1.CoordinationV1beta1Client + coordinationV1 *coordinationv1.CoordinationV1Client coreV1 *corev1.CoreV1Client eventsV1beta1 *eventsv1beta1.EventsV1beta1Client extensionsV1beta1 *extensionsv1beta1.ExtensionsV1beta1Client @@ -182,16 +185,6 @@ func (c *Clientset) Admissionregistration() admissionregistrationv1beta1.Admissi return c.admissionregistrationV1beta1 } -// AppsV1beta1 retrieves the AppsV1beta1Client -func (c *Clientset) AppsV1beta1() appsv1beta1.AppsV1beta1Interface { - return c.appsV1beta1 -} - -// AppsV1beta2 retrieves the AppsV1beta2Client -func (c *Clientset) AppsV1beta2() appsv1beta2.AppsV1beta2Interface { - return c.appsV1beta2 -} - // AppsV1 retrieves the AppsV1Client func (c *Clientset) AppsV1() appsv1.AppsV1Interface { return c.appsV1 @@ -203,6 +196,16 @@ func (c *Clientset) Apps() appsv1.AppsV1Interface { return c.appsV1 } +// AppsV1beta1 retrieves the AppsV1beta1Client +func (c *Clientset) AppsV1beta1() appsv1beta1.AppsV1beta1Interface { + return c.appsV1beta1 +} + +// AppsV1beta2 retrieves the AppsV1beta2Client +func (c *Clientset) AppsV1beta2() appsv1beta2.AppsV1beta2Interface { + return c.appsV1beta2 +} + // AuditregistrationV1alpha1 retrieves the AuditregistrationV1alpha1Client func (c *Clientset) AuditregistrationV1alpha1() auditregistrationv1alpha1.AuditregistrationV1alpha1Interface { return c.auditregistrationV1alpha1 @@ -304,10 +307,15 @@ func (c *Clientset) CoordinationV1beta1() coordinationv1beta1.CoordinationV1beta return c.coordinationV1beta1 } +// CoordinationV1 retrieves the CoordinationV1Client +func (c *Clientset) CoordinationV1() coordinationv1.CoordinationV1Interface { + return c.coordinationV1 +} + // Deprecated: Coordination retrieves the default version of CoordinationClient. // Please explicitly pick a version. -func (c *Clientset) Coordination() coordinationv1beta1.CoordinationV1beta1Interface { - return c.coordinationV1beta1 +func (c *Clientset) Coordination() coordinationv1.CoordinationV1Interface { + return c.coordinationV1 } // CoreV1 retrieves the CoreV1Client @@ -458,6 +466,10 @@ func NewForConfig(c *rest.Config) (*Clientset, error) { if err != nil { return nil, err } + cs.appsV1, err = appsv1.NewForConfig(&configShallowCopy) + if err != nil { + return nil, err + } cs.appsV1beta1, err = appsv1beta1.NewForConfig(&configShallowCopy) if err != nil { return nil, err @@ -466,10 +478,6 @@ func NewForConfig(c *rest.Config) (*Clientset, error) { if err != nil { return nil, err } - cs.appsV1, err = appsv1.NewForConfig(&configShallowCopy) - if err != nil { - return nil, err - } cs.auditregistrationV1alpha1, err = auditregistrationv1alpha1.NewForConfig(&configShallowCopy) if err != nil { return nil, err @@ -522,6 +530,10 @@ func NewForConfig(c *rest.Config) (*Clientset, error) { if err != nil { return nil, err } + cs.coordinationV1, err = coordinationv1.NewForConfig(&configShallowCopy) + if err != nil { + return nil, err + } cs.coreV1, err = corev1.NewForConfig(&configShallowCopy) if err != nil { return nil, err @@ -592,9 +604,9 @@ func NewForConfigOrDie(c *rest.Config) *Clientset { var cs Clientset cs.admissionregistrationV1alpha1 = admissionregistrationv1alpha1.NewForConfigOrDie(c) cs.admissionregistrationV1beta1 = admissionregistrationv1beta1.NewForConfigOrDie(c) + cs.appsV1 = appsv1.NewForConfigOrDie(c) cs.appsV1beta1 = appsv1beta1.NewForConfigOrDie(c) cs.appsV1beta2 = appsv1beta2.NewForConfigOrDie(c) - cs.appsV1 = appsv1.NewForConfigOrDie(c) cs.auditregistrationV1alpha1 = auditregistrationv1alpha1.NewForConfigOrDie(c) cs.authenticationV1 = authenticationv1.NewForConfigOrDie(c) cs.authenticationV1beta1 = authenticationv1beta1.NewForConfigOrDie(c) @@ -608,6 +620,7 @@ func NewForConfigOrDie(c *rest.Config) *Clientset { cs.batchV2alpha1 = batchv2alpha1.NewForConfigOrDie(c) cs.certificatesV1beta1 = certificatesv1beta1.NewForConfigOrDie(c) cs.coordinationV1beta1 = coordinationv1beta1.NewForConfigOrDie(c) + cs.coordinationV1 = coordinationv1.NewForConfigOrDie(c) cs.coreV1 = corev1.NewForConfigOrDie(c) cs.eventsV1beta1 = eventsv1beta1.NewForConfigOrDie(c) cs.extensionsV1beta1 = extensionsv1beta1.NewForConfigOrDie(c) @@ -632,9 +645,9 @@ func New(c rest.Interface) *Clientset { var cs Clientset cs.admissionregistrationV1alpha1 = admissionregistrationv1alpha1.New(c) cs.admissionregistrationV1beta1 = admissionregistrationv1beta1.New(c) + cs.appsV1 = appsv1.New(c) cs.appsV1beta1 = appsv1beta1.New(c) cs.appsV1beta2 = appsv1beta2.New(c) - cs.appsV1 = appsv1.New(c) cs.auditregistrationV1alpha1 = auditregistrationv1alpha1.New(c) cs.authenticationV1 = authenticationv1.New(c) cs.authenticationV1beta1 = authenticationv1beta1.New(c) @@ -648,6 +661,7 @@ func New(c rest.Interface) *Clientset { cs.batchV2alpha1 = batchv2alpha1.New(c) cs.certificatesV1beta1 = certificatesv1beta1.New(c) cs.coordinationV1beta1 = coordinationv1beta1.New(c) + cs.coordinationV1 = coordinationv1.New(c) cs.coreV1 = corev1.New(c) cs.eventsV1beta1 = eventsv1beta1.New(c) cs.extensionsV1beta1 = extensionsv1beta1.New(c) diff --git a/staging/src/k8s.io/client-go/kubernetes/fake/BUILD b/staging/src/k8s.io/client-go/kubernetes/fake/BUILD index 185e530d0bf..72a7fa05fc0 100644 --- a/staging/src/k8s.io/client-go/kubernetes/fake/BUILD +++ b/staging/src/k8s.io/client-go/kubernetes/fake/BUILD @@ -28,6 +28,7 @@ go_library( "//staging/src/k8s.io/api/batch/v1beta1:go_default_library", "//staging/src/k8s.io/api/batch/v2alpha1:go_default_library", "//staging/src/k8s.io/api/certificates/v1beta1:go_default_library", + "//staging/src/k8s.io/api/coordination/v1:go_default_library", "//staging/src/k8s.io/api/coordination/v1beta1:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library", "//staging/src/k8s.io/api/events/v1beta1:go_default_library", @@ -86,6 +87,8 @@ go_library( "//staging/src/k8s.io/client-go/kubernetes/typed/batch/v2alpha1/fake:go_default_library", "//staging/src/k8s.io/client-go/kubernetes/typed/certificates/v1beta1:go_default_library", "//staging/src/k8s.io/client-go/kubernetes/typed/certificates/v1beta1/fake:go_default_library", + "//staging/src/k8s.io/client-go/kubernetes/typed/coordination/v1:go_default_library", + "//staging/src/k8s.io/client-go/kubernetes/typed/coordination/v1/fake:go_default_library", "//staging/src/k8s.io/client-go/kubernetes/typed/coordination/v1beta1:go_default_library", "//staging/src/k8s.io/client-go/kubernetes/typed/coordination/v1beta1/fake:go_default_library", "//staging/src/k8s.io/client-go/kubernetes/typed/core/v1:go_default_library", diff --git a/staging/src/k8s.io/client-go/kubernetes/fake/clientset_generated.go b/staging/src/k8s.io/client-go/kubernetes/fake/clientset_generated.go index 47b63ffaed9..bf64a0c6d6b 100644 --- a/staging/src/k8s.io/client-go/kubernetes/fake/clientset_generated.go +++ b/staging/src/k8s.io/client-go/kubernetes/fake/clientset_generated.go @@ -58,6 +58,8 @@ import ( fakebatchv2alpha1 "k8s.io/client-go/kubernetes/typed/batch/v2alpha1/fake" certificatesv1beta1 "k8s.io/client-go/kubernetes/typed/certificates/v1beta1" fakecertificatesv1beta1 "k8s.io/client-go/kubernetes/typed/certificates/v1beta1/fake" + coordinationv1 "k8s.io/client-go/kubernetes/typed/coordination/v1" + fakecoordinationv1 "k8s.io/client-go/kubernetes/typed/coordination/v1/fake" coordinationv1beta1 "k8s.io/client-go/kubernetes/typed/coordination/v1beta1" fakecoordinationv1beta1 "k8s.io/client-go/kubernetes/typed/coordination/v1beta1/fake" corev1 "k8s.io/client-go/kubernetes/typed/core/v1" @@ -148,16 +150,6 @@ func (c *Clientset) Admissionregistration() admissionregistrationv1beta1.Admissi return &fakeadmissionregistrationv1beta1.FakeAdmissionregistrationV1beta1{Fake: &c.Fake} } -// AppsV1beta1 retrieves the AppsV1beta1Client -func (c *Clientset) AppsV1beta1() appsv1beta1.AppsV1beta1Interface { - return &fakeappsv1beta1.FakeAppsV1beta1{Fake: &c.Fake} -} - -// AppsV1beta2 retrieves the AppsV1beta2Client -func (c *Clientset) AppsV1beta2() appsv1beta2.AppsV1beta2Interface { - return &fakeappsv1beta2.FakeAppsV1beta2{Fake: &c.Fake} -} - // AppsV1 retrieves the AppsV1Client func (c *Clientset) AppsV1() appsv1.AppsV1Interface { return &fakeappsv1.FakeAppsV1{Fake: &c.Fake} @@ -168,6 +160,16 @@ func (c *Clientset) Apps() appsv1.AppsV1Interface { return &fakeappsv1.FakeAppsV1{Fake: &c.Fake} } +// AppsV1beta1 retrieves the AppsV1beta1Client +func (c *Clientset) AppsV1beta1() appsv1beta1.AppsV1beta1Interface { + return &fakeappsv1beta1.FakeAppsV1beta1{Fake: &c.Fake} +} + +// AppsV1beta2 retrieves the AppsV1beta2Client +func (c *Clientset) AppsV1beta2() appsv1beta2.AppsV1beta2Interface { + return &fakeappsv1beta2.FakeAppsV1beta2{Fake: &c.Fake} +} + // AuditregistrationV1alpha1 retrieves the AuditregistrationV1alpha1Client func (c *Clientset) AuditregistrationV1alpha1() auditregistrationv1alpha1.AuditregistrationV1alpha1Interface { return &fakeauditregistrationv1alpha1.FakeAuditregistrationV1alpha1{Fake: &c.Fake} @@ -263,9 +265,14 @@ func (c *Clientset) CoordinationV1beta1() coordinationv1beta1.CoordinationV1beta return &fakecoordinationv1beta1.FakeCoordinationV1beta1{Fake: &c.Fake} } -// Coordination retrieves the CoordinationV1beta1Client -func (c *Clientset) Coordination() coordinationv1beta1.CoordinationV1beta1Interface { - return &fakecoordinationv1beta1.FakeCoordinationV1beta1{Fake: &c.Fake} +// CoordinationV1 retrieves the CoordinationV1Client +func (c *Clientset) CoordinationV1() coordinationv1.CoordinationV1Interface { + return &fakecoordinationv1.FakeCoordinationV1{Fake: &c.Fake} +} + +// Coordination retrieves the CoordinationV1Client +func (c *Clientset) Coordination() coordinationv1.CoordinationV1Interface { + return &fakecoordinationv1.FakeCoordinationV1{Fake: &c.Fake} } // CoreV1 retrieves the CoreV1Client diff --git a/staging/src/k8s.io/client-go/kubernetes/fake/register.go b/staging/src/k8s.io/client-go/kubernetes/fake/register.go index 6e1e1fb2936..b9819b40b9e 100644 --- a/staging/src/k8s.io/client-go/kubernetes/fake/register.go +++ b/staging/src/k8s.io/client-go/kubernetes/fake/register.go @@ -36,6 +36,7 @@ import ( batchv1beta1 "k8s.io/api/batch/v1beta1" batchv2alpha1 "k8s.io/api/batch/v2alpha1" certificatesv1beta1 "k8s.io/api/certificates/v1beta1" + coordinationv1 "k8s.io/api/coordination/v1" coordinationv1beta1 "k8s.io/api/coordination/v1beta1" corev1 "k8s.io/api/core/v1" eventsv1beta1 "k8s.io/api/events/v1beta1" @@ -64,9 +65,9 @@ var parameterCodec = runtime.NewParameterCodec(scheme) var localSchemeBuilder = runtime.SchemeBuilder{ admissionregistrationv1alpha1.AddToScheme, admissionregistrationv1beta1.AddToScheme, + appsv1.AddToScheme, appsv1beta1.AddToScheme, appsv1beta2.AddToScheme, - appsv1.AddToScheme, auditregistrationv1alpha1.AddToScheme, authenticationv1.AddToScheme, authenticationv1beta1.AddToScheme, @@ -80,6 +81,7 @@ var localSchemeBuilder = runtime.SchemeBuilder{ batchv2alpha1.AddToScheme, certificatesv1beta1.AddToScheme, coordinationv1beta1.AddToScheme, + coordinationv1.AddToScheme, corev1.AddToScheme, eventsv1beta1.AddToScheme, extensionsv1beta1.AddToScheme, diff --git a/staging/src/k8s.io/client-go/kubernetes/scheme/BUILD b/staging/src/k8s.io/client-go/kubernetes/scheme/BUILD index e36fdd99ea6..97670574d9a 100644 --- a/staging/src/k8s.io/client-go/kubernetes/scheme/BUILD +++ b/staging/src/k8s.io/client-go/kubernetes/scheme/BUILD @@ -27,6 +27,7 @@ go_library( "//staging/src/k8s.io/api/batch/v1beta1:go_default_library", "//staging/src/k8s.io/api/batch/v2alpha1:go_default_library", "//staging/src/k8s.io/api/certificates/v1beta1:go_default_library", + "//staging/src/k8s.io/api/coordination/v1:go_default_library", "//staging/src/k8s.io/api/coordination/v1beta1:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library", "//staging/src/k8s.io/api/events/v1beta1:go_default_library", diff --git a/staging/src/k8s.io/client-go/kubernetes/scheme/register.go b/staging/src/k8s.io/client-go/kubernetes/scheme/register.go index e336eb9179e..3953dc9f89e 100644 --- a/staging/src/k8s.io/client-go/kubernetes/scheme/register.go +++ b/staging/src/k8s.io/client-go/kubernetes/scheme/register.go @@ -36,6 +36,7 @@ import ( batchv1beta1 "k8s.io/api/batch/v1beta1" batchv2alpha1 "k8s.io/api/batch/v2alpha1" certificatesv1beta1 "k8s.io/api/certificates/v1beta1" + coordinationv1 "k8s.io/api/coordination/v1" coordinationv1beta1 "k8s.io/api/coordination/v1beta1" corev1 "k8s.io/api/core/v1" eventsv1beta1 "k8s.io/api/events/v1beta1" @@ -64,9 +65,9 @@ var ParameterCodec = runtime.NewParameterCodec(Scheme) var localSchemeBuilder = runtime.SchemeBuilder{ admissionregistrationv1alpha1.AddToScheme, admissionregistrationv1beta1.AddToScheme, + appsv1.AddToScheme, appsv1beta1.AddToScheme, appsv1beta2.AddToScheme, - appsv1.AddToScheme, auditregistrationv1alpha1.AddToScheme, authenticationv1.AddToScheme, authenticationv1beta1.AddToScheme, @@ -80,6 +81,7 @@ var localSchemeBuilder = runtime.SchemeBuilder{ batchv2alpha1.AddToScheme, certificatesv1beta1.AddToScheme, coordinationv1beta1.AddToScheme, + coordinationv1.AddToScheme, corev1.AddToScheme, eventsv1beta1.AddToScheme, extensionsv1beta1.AddToScheme, diff --git a/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/typed/wardle/internalversion/BUILD b/staging/src/k8s.io/client-go/kubernetes/typed/coordination/v1/BUILD similarity index 56% rename from staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/typed/wardle/internalversion/BUILD rename to staging/src/k8s.io/client-go/kubernetes/typed/coordination/v1/BUILD index f07c432daef..1dd901ab4fc 100644 --- a/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/typed/wardle/internalversion/BUILD +++ b/staging/src/k8s.io/client-go/kubernetes/typed/coordination/v1/BUILD @@ -3,22 +3,22 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library") go_library( name = "go_default_library", srcs = [ + "coordination_client.go", "doc.go", - "fischer.go", - "flunder.go", "generated_expansion.go", - "wardle_client.go", + "lease.go", ], - importmap = "k8s.io/kubernetes/vendor/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/typed/wardle/internalversion", - importpath = "k8s.io/sample-apiserver/pkg/client/clientset/internalversion/typed/wardle/internalversion", + importmap = "k8s.io/kubernetes/vendor/k8s.io/client-go/kubernetes/typed/coordination/v1", + importpath = "k8s.io/client-go/kubernetes/typed/coordination/v1", visibility = ["//visibility:public"], deps = [ + "//staging/src/k8s.io/api/coordination/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + "//staging/src/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/types:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/watch:go_default_library", + "//staging/src/k8s.io/client-go/kubernetes/scheme:go_default_library", "//staging/src/k8s.io/client-go/rest:go_default_library", - "//staging/src/k8s.io/sample-apiserver/pkg/apis/wardle:go_default_library", - "//staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/scheme:go_default_library", ], ) @@ -33,7 +33,7 @@ filegroup( name = "all-srcs", srcs = [ ":package-srcs", - "//staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/typed/wardle/internalversion/fake:all-srcs", + "//staging/src/k8s.io/client-go/kubernetes/typed/coordination/v1/fake:all-srcs", ], tags = ["automanaged"], visibility = ["//visibility:public"], diff --git a/staging/src/k8s.io/client-go/kubernetes/typed/coordination/v1/coordination_client.go b/staging/src/k8s.io/client-go/kubernetes/typed/coordination/v1/coordination_client.go new file mode 100644 index 00000000000..9b566f3106e --- /dev/null +++ b/staging/src/k8s.io/client-go/kubernetes/typed/coordination/v1/coordination_client.go @@ -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 v1 + +import ( + v1 "k8s.io/api/coordination/v1" + serializer "k8s.io/apimachinery/pkg/runtime/serializer" + "k8s.io/client-go/kubernetes/scheme" + rest "k8s.io/client-go/rest" +) + +type CoordinationV1Interface interface { + RESTClient() rest.Interface + LeasesGetter +} + +// CoordinationV1Client is used to interact with features provided by the coordination.k8s.io group. +type CoordinationV1Client struct { + restClient rest.Interface +} + +func (c *CoordinationV1Client) Leases(namespace string) LeaseInterface { + return newLeases(c, namespace) +} + +// NewForConfig creates a new CoordinationV1Client for the given config. +func NewForConfig(c *rest.Config) (*CoordinationV1Client, error) { + config := *c + if err := setConfigDefaults(&config); err != nil { + return nil, err + } + client, err := rest.RESTClientFor(&config) + if err != nil { + return nil, err + } + return &CoordinationV1Client{client}, nil +} + +// NewForConfigOrDie creates a new CoordinationV1Client for the given config and +// panics if there is an error in the config. +func NewForConfigOrDie(c *rest.Config) *CoordinationV1Client { + client, err := NewForConfig(c) + if err != nil { + panic(err) + } + return client +} + +// New creates a new CoordinationV1Client for the given RESTClient. +func New(c rest.Interface) *CoordinationV1Client { + return &CoordinationV1Client{c} +} + +func setConfigDefaults(config *rest.Config) error { + gv := v1.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 *CoordinationV1Client) RESTClient() rest.Interface { + if c == nil { + return nil + } + return c.restClient +} diff --git a/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/typed/wardle/internalversion/doc.go b/staging/src/k8s.io/client-go/kubernetes/typed/coordination/v1/doc.go similarity index 96% rename from staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/typed/wardle/internalversion/doc.go rename to staging/src/k8s.io/client-go/kubernetes/typed/coordination/v1/doc.go index 86602442bab..3af5d054f10 100644 --- a/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/typed/wardle/internalversion/doc.go +++ b/staging/src/k8s.io/client-go/kubernetes/typed/coordination/v1/doc.go @@ -17,4 +17,4 @@ limitations under the License. // Code generated by client-gen. DO NOT EDIT. // This package has the automatically generated typed clients. -package internalversion +package v1 diff --git a/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/typed/wardle/internalversion/fake/BUILD b/staging/src/k8s.io/client-go/kubernetes/typed/coordination/v1/fake/BUILD similarity index 64% rename from staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/typed/wardle/internalversion/fake/BUILD rename to staging/src/k8s.io/client-go/kubernetes/typed/coordination/v1/fake/BUILD index feda5e743be..2ca4bee985f 100644 --- a/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/typed/wardle/internalversion/fake/BUILD +++ b/staging/src/k8s.io/client-go/kubernetes/typed/coordination/v1/fake/BUILD @@ -4,23 +4,22 @@ go_library( name = "go_default_library", srcs = [ "doc.go", - "fake_fischer.go", - "fake_flunder.go", - "fake_wardle_client.go", + "fake_coordination_client.go", + "fake_lease.go", ], - importmap = "k8s.io/kubernetes/vendor/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/typed/wardle/internalversion/fake", - importpath = "k8s.io/sample-apiserver/pkg/client/clientset/internalversion/typed/wardle/internalversion/fake", + importmap = "k8s.io/kubernetes/vendor/k8s.io/client-go/kubernetes/typed/coordination/v1/fake", + importpath = "k8s.io/client-go/kubernetes/typed/coordination/v1/fake", visibility = ["//visibility:public"], deps = [ + "//staging/src/k8s.io/api/coordination/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/labels:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/types:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/watch:go_default_library", + "//staging/src/k8s.io/client-go/kubernetes/typed/coordination/v1:go_default_library", "//staging/src/k8s.io/client-go/rest:go_default_library", "//staging/src/k8s.io/client-go/testing:go_default_library", - "//staging/src/k8s.io/sample-apiserver/pkg/apis/wardle:go_default_library", - "//staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/typed/wardle/internalversion:go_default_library", ], ) diff --git a/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/typed/wardle/internalversion/fake/doc.go b/staging/src/k8s.io/client-go/kubernetes/typed/coordination/v1/fake/doc.go similarity index 100% rename from staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/typed/wardle/internalversion/fake/doc.go rename to staging/src/k8s.io/client-go/kubernetes/typed/coordination/v1/fake/doc.go diff --git a/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/typed/wardle/internalversion/fake/fake_wardle_client.go b/staging/src/k8s.io/client-go/kubernetes/typed/coordination/v1/fake/fake_coordination_client.go similarity index 68% rename from staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/typed/wardle/internalversion/fake/fake_wardle_client.go rename to staging/src/k8s.io/client-go/kubernetes/typed/coordination/v1/fake/fake_coordination_client.go index b9282c03d34..6920275b209 100644 --- a/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/typed/wardle/internalversion/fake/fake_wardle_client.go +++ b/staging/src/k8s.io/client-go/kubernetes/typed/coordination/v1/fake/fake_coordination_client.go @@ -19,26 +19,22 @@ limitations under the License. package fake import ( + v1 "k8s.io/client-go/kubernetes/typed/coordination/v1" rest "k8s.io/client-go/rest" testing "k8s.io/client-go/testing" - internalversion "k8s.io/sample-apiserver/pkg/client/clientset/internalversion/typed/wardle/internalversion" ) -type FakeWardle struct { +type FakeCoordinationV1 struct { *testing.Fake } -func (c *FakeWardle) Fischers() internalversion.FischerInterface { - return &FakeFischers{c} -} - -func (c *FakeWardle) Flunders(namespace string) internalversion.FlunderInterface { - return &FakeFlunders{c, namespace} +func (c *FakeCoordinationV1) Leases(namespace string) v1.LeaseInterface { + return &FakeLeases{c, namespace} } // RESTClient returns a RESTClient that is used to communicate // with API server by this client implementation. -func (c *FakeWardle) RESTClient() rest.Interface { +func (c *FakeCoordinationV1) RESTClient() rest.Interface { var ret *rest.RESTClient return ret } diff --git a/staging/src/k8s.io/client-go/kubernetes/typed/coordination/v1/fake/fake_lease.go b/staging/src/k8s.io/client-go/kubernetes/typed/coordination/v1/fake/fake_lease.go new file mode 100644 index 00000000000..940c738c1b2 --- /dev/null +++ b/staging/src/k8s.io/client-go/kubernetes/typed/coordination/v1/fake/fake_lease.go @@ -0,0 +1,128 @@ +/* +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 ( + coordinationv1 "k8s.io/api/coordination/v1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + labels "k8s.io/apimachinery/pkg/labels" + schema "k8s.io/apimachinery/pkg/runtime/schema" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + testing "k8s.io/client-go/testing" +) + +// FakeLeases implements LeaseInterface +type FakeLeases struct { + Fake *FakeCoordinationV1 + ns string +} + +var leasesResource = schema.GroupVersionResource{Group: "coordination.k8s.io", Version: "v1", Resource: "leases"} + +var leasesKind = schema.GroupVersionKind{Group: "coordination.k8s.io", Version: "v1", Kind: "Lease"} + +// Get takes name of the lease, and returns the corresponding lease object, and an error if there is any. +func (c *FakeLeases) Get(name string, options v1.GetOptions) (result *coordinationv1.Lease, err error) { + obj, err := c.Fake. + Invokes(testing.NewGetAction(leasesResource, c.ns, name), &coordinationv1.Lease{}) + + if obj == nil { + return nil, err + } + return obj.(*coordinationv1.Lease), err +} + +// List takes label and field selectors, and returns the list of Leases that match those selectors. +func (c *FakeLeases) List(opts v1.ListOptions) (result *coordinationv1.LeaseList, err error) { + obj, err := c.Fake. + Invokes(testing.NewListAction(leasesResource, leasesKind, c.ns, opts), &coordinationv1.LeaseList{}) + + if obj == nil { + return nil, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &coordinationv1.LeaseList{ListMeta: obj.(*coordinationv1.LeaseList).ListMeta} + for _, item := range obj.(*coordinationv1.LeaseList).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 leases. +func (c *FakeLeases) Watch(opts v1.ListOptions) (watch.Interface, error) { + return c.Fake. + InvokesWatch(testing.NewWatchAction(leasesResource, c.ns, opts)) + +} + +// Create takes the representation of a lease and creates it. Returns the server's representation of the lease, and an error, if there is any. +func (c *FakeLeases) Create(lease *coordinationv1.Lease) (result *coordinationv1.Lease, err error) { + obj, err := c.Fake. + Invokes(testing.NewCreateAction(leasesResource, c.ns, lease), &coordinationv1.Lease{}) + + if obj == nil { + return nil, err + } + return obj.(*coordinationv1.Lease), err +} + +// Update takes the representation of a lease and updates it. Returns the server's representation of the lease, and an error, if there is any. +func (c *FakeLeases) Update(lease *coordinationv1.Lease) (result *coordinationv1.Lease, err error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateAction(leasesResource, c.ns, lease), &coordinationv1.Lease{}) + + if obj == nil { + return nil, err + } + return obj.(*coordinationv1.Lease), err +} + +// Delete takes name of the lease and deletes it. Returns an error if one occurs. +func (c *FakeLeases) Delete(name string, options *v1.DeleteOptions) error { + _, err := c.Fake. + Invokes(testing.NewDeleteAction(leasesResource, c.ns, name), &coordinationv1.Lease{}) + + return err +} + +// DeleteCollection deletes a collection of objects. +func (c *FakeLeases) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { + action := testing.NewDeleteCollectionAction(leasesResource, c.ns, listOptions) + + _, err := c.Fake.Invokes(action, &coordinationv1.LeaseList{}) + return err +} + +// Patch applies the patch and returns the patched lease. +func (c *FakeLeases) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *coordinationv1.Lease, err error) { + obj, err := c.Fake. + Invokes(testing.NewPatchSubresourceAction(leasesResource, c.ns, name, pt, data, subresources...), &coordinationv1.Lease{}) + + if obj == nil { + return nil, err + } + return obj.(*coordinationv1.Lease), err +} diff --git a/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/typed/wardle/internalversion/generated_expansion.go b/staging/src/k8s.io/client-go/kubernetes/typed/coordination/v1/generated_expansion.go similarity index 86% rename from staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/typed/wardle/internalversion/generated_expansion.go rename to staging/src/k8s.io/client-go/kubernetes/typed/coordination/v1/generated_expansion.go index c3270941d4d..ab24f3734ed 100644 --- a/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/typed/wardle/internalversion/generated_expansion.go +++ b/staging/src/k8s.io/client-go/kubernetes/typed/coordination/v1/generated_expansion.go @@ -16,8 +16,6 @@ limitations under the License. // Code generated by client-gen. DO NOT EDIT. -package internalversion +package v1 -type FischerExpansion interface{} - -type FlunderExpansion interface{} +type LeaseExpansion interface{} diff --git a/staging/src/k8s.io/client-go/kubernetes/typed/coordination/v1/lease.go b/staging/src/k8s.io/client-go/kubernetes/typed/coordination/v1/lease.go new file mode 100644 index 00000000000..b6cf1b64f65 --- /dev/null +++ b/staging/src/k8s.io/client-go/kubernetes/typed/coordination/v1/lease.go @@ -0,0 +1,174 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package v1 + +import ( + "time" + + v1 "k8s.io/api/coordination/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + scheme "k8s.io/client-go/kubernetes/scheme" + rest "k8s.io/client-go/rest" +) + +// LeasesGetter has a method to return a LeaseInterface. +// A group's client should implement this interface. +type LeasesGetter interface { + Leases(namespace string) LeaseInterface +} + +// LeaseInterface has methods to work with Lease resources. +type LeaseInterface interface { + Create(*v1.Lease) (*v1.Lease, error) + Update(*v1.Lease) (*v1.Lease, error) + Delete(name string, options *metav1.DeleteOptions) error + DeleteCollection(options *metav1.DeleteOptions, listOptions metav1.ListOptions) error + Get(name string, options metav1.GetOptions) (*v1.Lease, error) + List(opts metav1.ListOptions) (*v1.LeaseList, error) + Watch(opts metav1.ListOptions) (watch.Interface, error) + Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1.Lease, err error) + LeaseExpansion +} + +// leases implements LeaseInterface +type leases struct { + client rest.Interface + ns string +} + +// newLeases returns a Leases +func newLeases(c *CoordinationV1Client, namespace string) *leases { + return &leases{ + client: c.RESTClient(), + ns: namespace, + } +} + +// Get takes name of the lease, and returns the corresponding lease object, and an error if there is any. +func (c *leases) Get(name string, options metav1.GetOptions) (result *v1.Lease, err error) { + result = &v1.Lease{} + err = c.client.Get(). + Namespace(c.ns). + Resource("leases"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of Leases that match those selectors. +func (c *leases) List(opts metav1.ListOptions) (result *v1.LeaseList, err error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + result = &v1.LeaseList{} + err = c.client.Get(). + Namespace(c.ns). + Resource("leases"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Do(). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested leases. +func (c *leases) Watch(opts metav1.ListOptions) (watch.Interface, error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + opts.Watch = true + return c.client.Get(). + Namespace(c.ns). + Resource("leases"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Watch() +} + +// Create takes the representation of a lease and creates it. Returns the server's representation of the lease, and an error, if there is any. +func (c *leases) Create(lease *v1.Lease) (result *v1.Lease, err error) { + result = &v1.Lease{} + err = c.client.Post(). + Namespace(c.ns). + Resource("leases"). + Body(lease). + Do(). + Into(result) + return +} + +// Update takes the representation of a lease and updates it. Returns the server's representation of the lease, and an error, if there is any. +func (c *leases) Update(lease *v1.Lease) (result *v1.Lease, err error) { + result = &v1.Lease{} + err = c.client.Put(). + Namespace(c.ns). + Resource("leases"). + Name(lease.Name). + Body(lease). + Do(). + Into(result) + return +} + +// Delete takes name of the lease and deletes it. Returns an error if one occurs. +func (c *leases) Delete(name string, options *metav1.DeleteOptions) error { + return c.client.Delete(). + Namespace(c.ns). + Resource("leases"). + Name(name). + Body(options). + Do(). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (c *leases) DeleteCollection(options *metav1.DeleteOptions, listOptions metav1.ListOptions) error { + var timeout time.Duration + if listOptions.TimeoutSeconds != nil { + timeout = time.Duration(*listOptions.TimeoutSeconds) * time.Second + } + return c.client.Delete(). + Namespace(c.ns). + Resource("leases"). + VersionedParams(&listOptions, scheme.ParameterCodec). + Timeout(timeout). + Body(options). + Do(). + Error() +} + +// Patch applies the patch and returns the patched lease. +func (c *leases) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1.Lease, err error) { + result = &v1.Lease{} + err = c.client.Patch(pt). + Namespace(c.ns). + Resource("leases"). + SubResource(subresources...). + Name(name). + Body(data). + Do(). + Into(result) + return +} diff --git a/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_pod_expansion.go b/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_pod_expansion.go index 9c4b09d3e9f..b35d8aaa5fc 100644 --- a/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_pod_expansion.go +++ b/staging/src/k8s.io/client-go/kubernetes/typed/core/v1/fake/fake_pod_expansion.go @@ -60,6 +60,7 @@ func (c *FakePods) GetLogs(name string, opts *v1.PodLogOptions) *restclient.Requ func (c *FakePods) Evict(eviction *policy.Eviction) error { action := core.CreateActionImpl{} action.Verb = "create" + action.Namespace = c.ns action.Resource = podsResource action.Subresource = "eviction" action.Object = eviction diff --git a/staging/src/k8s.io/client-go/kubernetes/typed/policy/v1beta1/fake/fake_eviction_expansion.go b/staging/src/k8s.io/client-go/kubernetes/typed/policy/v1beta1/fake/fake_eviction_expansion.go index f3b5e93ab0d..d660d09e565 100644 --- a/staging/src/k8s.io/client-go/kubernetes/typed/policy/v1beta1/fake/fake_eviction_expansion.go +++ b/staging/src/k8s.io/client-go/kubernetes/typed/policy/v1beta1/fake/fake_eviction_expansion.go @@ -23,12 +23,13 @@ import ( ) func (c *FakeEvictions) Evict(eviction *policy.Eviction) error { - action := core.GetActionImpl{} - action.Verb = "post" + action := core.CreateActionImpl{} + action.Verb = "create" action.Namespace = c.ns action.Resource = schema.GroupVersionResource{Group: "", Version: "v1", Resource: "pods"} action.Subresource = "eviction" - action.Name = eviction.Name + action.Object = eviction + _, err := c.Fake.Invokes(action, eviction) return err } diff --git a/staging/src/k8s.io/sample-apiserver/pkg/client/listers/wardle/internalversion/BUILD b/staging/src/k8s.io/client-go/listers/coordination/v1/BUILD similarity index 68% rename from staging/src/k8s.io/sample-apiserver/pkg/client/listers/wardle/internalversion/BUILD rename to staging/src/k8s.io/client-go/listers/coordination/v1/BUILD index 9d89f3a907f..9507d35c441 100644 --- a/staging/src/k8s.io/sample-apiserver/pkg/client/listers/wardle/internalversion/BUILD +++ b/staging/src/k8s.io/client-go/listers/coordination/v1/BUILD @@ -4,17 +4,16 @@ go_library( name = "go_default_library", srcs = [ "expansion_generated.go", - "fischer.go", - "flunder.go", + "lease.go", ], - importmap = "k8s.io/kubernetes/vendor/k8s.io/sample-apiserver/pkg/client/listers/wardle/internalversion", - importpath = "k8s.io/sample-apiserver/pkg/client/listers/wardle/internalversion", + importmap = "k8s.io/kubernetes/vendor/k8s.io/client-go/listers/coordination/v1", + importpath = "k8s.io/client-go/listers/coordination/v1", visibility = ["//visibility:public"], deps = [ + "//staging/src/k8s.io/api/coordination/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/labels:go_default_library", "//staging/src/k8s.io/client-go/tools/cache:go_default_library", - "//staging/src/k8s.io/sample-apiserver/pkg/apis/wardle:go_default_library", ], ) diff --git a/staging/src/k8s.io/client-go/listers/coordination/v1/expansion_generated.go b/staging/src/k8s.io/client-go/listers/coordination/v1/expansion_generated.go new file mode 100644 index 00000000000..ddc494f1c36 --- /dev/null +++ b/staging/src/k8s.io/client-go/listers/coordination/v1/expansion_generated.go @@ -0,0 +1,27 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by lister-gen. DO NOT EDIT. + +package v1 + +// LeaseListerExpansion allows custom methods to be added to +// LeaseLister. +type LeaseListerExpansion interface{} + +// LeaseNamespaceListerExpansion allows custom methods to be added to +// LeaseNamespaceLister. +type LeaseNamespaceListerExpansion interface{} diff --git a/staging/src/k8s.io/client-go/listers/coordination/v1/lease.go b/staging/src/k8s.io/client-go/listers/coordination/v1/lease.go new file mode 100644 index 00000000000..cc379088cb6 --- /dev/null +++ b/staging/src/k8s.io/client-go/listers/coordination/v1/lease.go @@ -0,0 +1,94 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by lister-gen. DO NOT EDIT. + +package v1 + +import ( + v1 "k8s.io/api/coordination/v1" + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/tools/cache" +) + +// LeaseLister helps list Leases. +type LeaseLister interface { + // List lists all Leases in the indexer. + List(selector labels.Selector) (ret []*v1.Lease, err error) + // Leases returns an object that can list and get Leases. + Leases(namespace string) LeaseNamespaceLister + LeaseListerExpansion +} + +// leaseLister implements the LeaseLister interface. +type leaseLister struct { + indexer cache.Indexer +} + +// NewLeaseLister returns a new LeaseLister. +func NewLeaseLister(indexer cache.Indexer) LeaseLister { + return &leaseLister{indexer: indexer} +} + +// List lists all Leases in the indexer. +func (s *leaseLister) List(selector labels.Selector) (ret []*v1.Lease, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*v1.Lease)) + }) + return ret, err +} + +// Leases returns an object that can list and get Leases. +func (s *leaseLister) Leases(namespace string) LeaseNamespaceLister { + return leaseNamespaceLister{indexer: s.indexer, namespace: namespace} +} + +// LeaseNamespaceLister helps list and get Leases. +type LeaseNamespaceLister interface { + // List lists all Leases in the indexer for a given namespace. + List(selector labels.Selector) (ret []*v1.Lease, err error) + // Get retrieves the Lease from the indexer for a given namespace and name. + Get(name string) (*v1.Lease, error) + LeaseNamespaceListerExpansion +} + +// leaseNamespaceLister implements the LeaseNamespaceLister +// interface. +type leaseNamespaceLister struct { + indexer cache.Indexer + namespace string +} + +// List lists all Leases in the indexer for a given namespace. +func (s leaseNamespaceLister) List(selector labels.Selector) (ret []*v1.Lease, err error) { + err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { + ret = append(ret, m.(*v1.Lease)) + }) + return ret, err +} + +// Get retrieves the Lease from the indexer for a given namespace and name. +func (s leaseNamespaceLister) Get(name string) (*v1.Lease, error) { + obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(v1.Resource("lease"), name) + } + return obj.(*v1.Lease), nil +} diff --git a/staging/src/k8s.io/client-go/pkg/apis/clientauthentication/v1alpha1/types.go b/staging/src/k8s.io/client-go/pkg/apis/clientauthentication/v1alpha1/types.go index 921f3a2b94d..c714e2457ac 100644 --- a/staging/src/k8s.io/client-go/pkg/apis/clientauthentication/v1alpha1/types.go +++ b/staging/src/k8s.io/client-go/pkg/apis/clientauthentication/v1alpha1/types.go @@ -22,7 +22,7 @@ import ( // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object -// ExecCredentials is used by exec-based plugins to communicate credentials to +// ExecCredential is used by exec-based plugins to communicate credentials to // HTTP transports. type ExecCredential struct { metav1.TypeMeta `json:",inline"` diff --git a/staging/src/k8s.io/client-go/plugin/pkg/client/auth/azure/azure.go b/staging/src/k8s.io/client-go/plugin/pkg/client/auth/azure/azure.go index d42449fc257..e583100cc9c 100644 --- a/staging/src/k8s.io/client-go/plugin/pkg/client/auth/azure/azure.go +++ b/staging/src/k8s.io/client-go/plugin/pkg/client/auth/azure/azure.go @@ -145,6 +145,7 @@ func (r *azureRoundTripper) WrappedRoundTripper() http.RoundTripper { return r.r type azureToken struct { token adal.Token + environment string clientID string tenantID string apiserverID string @@ -219,6 +220,10 @@ func (ts *azureTokenSource) retrieveTokenFromCfg() (*azureToken, error) { if refreshToken == "" { return nil, fmt.Errorf("no refresh token in cfg: %s", cfgRefreshToken) } + environment := ts.cfg[cfgEnvironment] + if environment == "" { + return nil, fmt.Errorf("no environment in cfg: %s", cfgEnvironment) + } clientID := ts.cfg[cfgClientID] if clientID == "" { return nil, fmt.Errorf("no client ID in cfg: %s", cfgClientID) @@ -250,6 +255,7 @@ func (ts *azureTokenSource) retrieveTokenFromCfg() (*azureToken, error) { Resource: fmt.Sprintf("spn:%s", apiserverID), Type: tokenType, }, + environment: environment, clientID: clientID, tenantID: tenantID, apiserverID: apiserverID, @@ -260,6 +266,7 @@ func (ts *azureTokenSource) storeTokenInCfg(token *azureToken) error { newCfg := make(map[string]string) newCfg[cfgAccessToken] = token.token.AccessToken newCfg[cfgRefreshToken] = token.token.RefreshToken + newCfg[cfgEnvironment] = token.environment newCfg[cfgClientID] = token.clientID newCfg[cfgTenantID] = token.tenantID newCfg[cfgApiserverID] = token.apiserverID @@ -275,7 +282,12 @@ func (ts *azureTokenSource) storeTokenInCfg(token *azureToken) error { } func (ts *azureTokenSource) refreshToken(token *azureToken) (*azureToken, error) { - oauthConfig, err := adal.NewOAuthConfig(azure.PublicCloud.ActiveDirectoryEndpoint, token.tenantID) + env, err := azure.EnvironmentFromName(token.environment) + if err != nil { + return nil, err + } + + oauthConfig, err := adal.NewOAuthConfig(env.ActiveDirectoryEndpoint, token.tenantID) if err != nil { return nil, fmt.Errorf("building the OAuth configuration for token refresh: %v", err) } @@ -299,6 +311,7 @@ func (ts *azureTokenSource) refreshToken(token *azureToken) (*azureToken, error) return &azureToken{ token: spt.Token(), + environment: token.environment, clientID: token.clientID, tenantID: token.tenantID, apiserverID: token.apiserverID, @@ -353,6 +366,7 @@ func (ts *azureTokenSourceDeviceCode) Token() (*azureToken, error) { return &azureToken{ token: *token, + environment: ts.environment.Name, clientID: ts.clientID, tenantID: ts.tenantID, apiserverID: ts.apiserverID, diff --git a/staging/src/k8s.io/client-go/plugin/pkg/client/auth/azure/azure_test.go b/staging/src/k8s.io/client-go/plugin/pkg/client/auth/azure/azure_test.go index 810a097ded9..c2cac5633e4 100644 --- a/staging/src/k8s.io/client-go/plugin/pkg/client/auth/azure/azure_test.go +++ b/staging/src/k8s.io/client-go/plugin/pkg/client/auth/azure/azure_test.go @@ -53,6 +53,13 @@ func TestAzureTokenSource(t *testing.T) { wantCfg := token2Cfg(token) persistedCfg := persiter.Cache() + + wantCfgLen := len(wantCfg) + persistedCfgLen := len(persistedCfg) + if wantCfgLen != persistedCfgLen { + t.Errorf("wantCfgLen and persistedCfgLen do not match, wantCfgLen=%v, persistedCfgLen=%v", wantCfgLen, persistedCfgLen) + } + for k, v := range persistedCfg { if strings.Compare(v, wantCfg[k]) != 0 { t.Errorf("Token() persisted cfg %s: got %v, want %v", k, v, wantCfg[k]) @@ -103,6 +110,7 @@ type fakeTokenSource struct { func (ts *fakeTokenSource) Token() (*azureToken, error) { return &azureToken{ token: newFackeAzureToken(ts.accessToken, ts.expiresOn), + environment: "testenv", clientID: "fake", tenantID: "fake", apiserverID: "fake", @@ -113,6 +121,7 @@ func token2Cfg(token *azureToken) map[string]string { cfg := make(map[string]string) cfg[cfgAccessToken] = token.token.AccessToken cfg[cfgRefreshToken] = token.token.RefreshToken + cfg[cfgEnvironment] = token.environment cfg[cfgClientID] = token.clientID cfg[cfgTenantID] = token.tenantID cfg[cfgApiserverID] = token.apiserverID diff --git a/staging/src/k8s.io/client-go/rest/BUILD b/staging/src/k8s.io/client-go/rest/BUILD index 70920303e4e..9f00aac950e 100644 --- a/staging/src/k8s.io/client-go/rest/BUILD +++ b/staging/src/k8s.io/client-go/rest/BUILD @@ -13,7 +13,6 @@ go_test( "config_test.go", "plugin_test.go", "request_test.go", - "token_source_test.go", "url_utils_test.go", "urlbackoff_test.go", ], @@ -41,7 +40,6 @@ go_test( "//staging/src/k8s.io/client-go/util/testing:go_default_library", "//vendor/github.com/google/gofuzz:go_default_library", "//vendor/github.com/stretchr/testify/assert:go_default_library", - "//vendor/golang.org/x/oauth2:go_default_library", "//vendor/k8s.io/klog:go_default_library", ], ) @@ -53,7 +51,6 @@ go_library( "config.go", "plugin.go", "request.go", - "token_source.go", "transport.go", "url_utils.go", "urlbackoff.go", @@ -80,7 +77,6 @@ go_library( "//staging/src/k8s.io/client-go/util/cert:go_default_library", "//staging/src/k8s.io/client-go/util/flowcontrol:go_default_library", "//vendor/golang.org/x/net/http2:go_default_library", - "//vendor/golang.org/x/oauth2:go_default_library", "//vendor/k8s.io/klog:go_default_library", ], ) diff --git a/staging/src/k8s.io/client-go/rest/config.go b/staging/src/k8s.io/client-go/rest/config.go index 438eb3bedac..072e7392b19 100644 --- a/staging/src/k8s.io/client-go/rest/config.go +++ b/staging/src/k8s.io/client-go/rest/config.go @@ -70,6 +70,11 @@ type Config struct { // TODO: demonstrate an OAuth2 compatible client. BearerToken string + // Path to a file containing a BearerToken. + // If set, the contents are periodically read. + // The last successfully read value takes precedence over BearerToken. + BearerTokenFile string + // Impersonate is the configuration that RESTClient will use for impersonation. Impersonate ImpersonationConfig @@ -322,9 +327,8 @@ func InClusterConfig() (*Config, error) { return nil, ErrNotInCluster } - ts := NewCachedFileTokenSource(tokenFile) - - if _, err := ts.Token(); err != nil { + token, err := ioutil.ReadFile(tokenFile) + if err != nil { return nil, err } @@ -340,7 +344,8 @@ func InClusterConfig() (*Config, error) { // TODO: switch to using cluster DNS. Host: "https://" + net.JoinHostPort(host, port), TLSClientConfig: tlsClientConfig, - WrapTransport: TokenSourceWrapTransport(ts), + BearerToken: string(token), + BearerTokenFile: tokenFile, }, nil } @@ -430,12 +435,13 @@ func AnonymousClientConfig(config *Config) *Config { // CopyConfig returns a copy of the given config func CopyConfig(config *Config) *Config { return &Config{ - Host: config.Host, - APIPath: config.APIPath, - ContentConfig: config.ContentConfig, - Username: config.Username, - Password: config.Password, - BearerToken: config.BearerToken, + Host: config.Host, + APIPath: config.APIPath, + ContentConfig: config.ContentConfig, + Username: config.Username, + Password: config.Password, + BearerToken: config.BearerToken, + BearerTokenFile: config.BearerTokenFile, Impersonate: ImpersonationConfig{ Groups: config.Impersonate.Groups, Extra: config.Impersonate.Extra, diff --git a/staging/src/k8s.io/client-go/rest/config_test.go b/staging/src/k8s.io/client-go/rest/config_test.go index 34786428548..22c18d77ed4 100644 --- a/staging/src/k8s.io/client-go/rest/config_test.go +++ b/staging/src/k8s.io/client-go/rest/config_test.go @@ -264,6 +264,7 @@ func TestAnonymousConfig(t *testing.T) { // is added to Config, update AnonymousClientConfig to preserve the field otherwise. expected.Impersonate = ImpersonationConfig{} expected.BearerToken = "" + expected.BearerTokenFile = "" expected.Username = "" expected.Password = "" expected.AuthProvider = nil diff --git a/staging/src/k8s.io/client-go/rest/request.go b/staging/src/k8s.io/client-go/rest/request.go index 64901fba20d..dd0630387ab 100644 --- a/staging/src/k8s.io/client-go/rest/request.go +++ b/staging/src/k8s.io/client-go/rest/request.go @@ -1100,7 +1100,8 @@ func (r Result) Into(obj runtime.Object) error { return fmt.Errorf("serializer for %s doesn't exist", r.contentType) } if len(r.body) == 0 { - return fmt.Errorf("0-length response") + return fmt.Errorf("0-length response with status code: %d and content type: %s", + r.statusCode, r.contentType) } out, _, err := r.decoder.Decode(r.body, nil, obj) @@ -1195,7 +1196,6 @@ func IsValidPathSegmentPrefix(name string) []string { func ValidatePathSegmentName(name string, prefix bool) []string { if prefix { return IsValidPathSegmentPrefix(name) - } else { - return IsValidPathSegmentName(name) } + return IsValidPathSegmentName(name) } diff --git a/staging/src/k8s.io/client-go/rest/request_test.go b/staging/src/k8s.io/client-go/rest/request_test.go index a415f60ae79..e70770dcd6e 100755 --- a/staging/src/k8s.io/client-go/rest/request_test.go +++ b/staging/src/k8s.io/client-go/rest/request_test.go @@ -1218,10 +1218,9 @@ func TestBackoffLifecycle(t *testing.T) { if count == 5 || count == 9 { w.WriteHeader(http.StatusOK) return - } else { - w.WriteHeader(http.StatusGatewayTimeout) - return } + w.WriteHeader(http.StatusGatewayTimeout) + return })) defer testServer.Close() c := testRESTClient(t, testServer) diff --git a/staging/src/k8s.io/client-go/testing/fixture.go b/staging/src/k8s.io/client-go/testing/fixture.go index 90f16f56080..b468b328c1a 100644 --- a/staging/src/k8s.io/client-go/testing/fixture.go +++ b/staging/src/k8s.io/client-go/testing/fixture.go @@ -339,8 +339,10 @@ func (t *tracker) getWatches(gvr schema.GroupVersionResource, ns string) []*watc if w := t.watchers[gvr][ns]; w != nil { watches = append(watches, w...) } - if w := t.watchers[gvr][""]; w != nil { - watches = append(watches, w...) + if ns != metav1.NamespaceAll { + if w := t.watchers[gvr][metav1.NamespaceAll]; w != nil { + watches = append(watches, w...) + } } } return watches diff --git a/staging/src/k8s.io/client-go/testing/fixture_test.go b/staging/src/k8s.io/client-go/testing/fixture_test.go index 405fe1a7e23..7b01c12a9c5 100644 --- a/staging/src/k8s.io/client-go/testing/fixture_test.go +++ b/staging/src/k8s.io/client-go/testing/fixture_test.go @@ -131,26 +131,47 @@ func TestWatchCallMultipleInvocation(t *testing.T) { cases := []struct { name string op watch.EventType + ns string }{ { "foo", watch.Added, + "test_namespace", }, { "bar", watch.Added, + "test_namespace", + }, + { + "baz", + watch.Added, + "", }, { "bar", watch.Modified, + "test_namespace", + }, + { + "baz", + watch.Modified, + "", }, { "foo", watch.Deleted, + "test_namespace", }, { "bar", watch.Deleted, + "test_namespace", + }, + { + "baz", + watch.Deleted, + "", }, } @@ -169,6 +190,7 @@ func TestWatchCallMultipleInvocation(t *testing.T) { wg.Add(len(watchNamespaces)) for idx, watchNamespace := range watchNamespaces { i := idx + watchNamespace := watchNamespace w, err := o.Watch(testResource, watchNamespace) if err != nil { t.Fatalf("test resource watch failed in %s: %v", watchNamespace, err) @@ -176,14 +198,17 @@ func TestWatchCallMultipleInvocation(t *testing.T) { go func() { assert.NoError(t, err, "watch invocation failed") for _, c := range cases { - fmt.Printf("%#v %#v\n", c, i) - event := <-w.ResultChan() - accessor, err := meta.Accessor(event.Object) - if err != nil { - t.Fatalf("unexpected error: %v", err) + if watchNamespace == "" || c.ns == watchNamespace { + fmt.Printf("%#v %#v\n", c, i) + event := <-w.ResultChan() + accessor, err := meta.Accessor(event.Object) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + assert.Equal(t, c.op, event.Type, "watch event mismatched") + assert.Equal(t, c.name, accessor.GetName(), "watched object mismatch") + assert.Equal(t, c.ns, accessor.GetNamespace(), "watched object mismatch") } - assert.Equal(t, c.op, event.Type, "watch event mismatched") - assert.Equal(t, c.name, accessor.GetName(), "watched object mismatch") } wg.Done() }() @@ -191,13 +216,13 @@ func TestWatchCallMultipleInvocation(t *testing.T) { for _, c := range cases { switch c.op { case watch.Added: - obj := getArbitraryResource(testResource, c.name, "test_namespace") - o.Create(testResource, obj, "test_namespace") + obj := getArbitraryResource(testResource, c.name, c.ns) + o.Create(testResource, obj, c.ns) case watch.Modified: - obj := getArbitraryResource(testResource, c.name, "test_namespace") - o.Update(testResource, obj, "test_namespace") + obj := getArbitraryResource(testResource, c.name, c.ns) + o.Update(testResource, obj, c.ns) case watch.Deleted: - o.Delete(testResource, "test_namespace", c.name) + o.Delete(testResource, c.ns, c.name) } } wg.Wait() diff --git a/staging/src/k8s.io/client-go/tools/cache/OWNERS b/staging/src/k8s.io/client-go/tools/cache/OWNERS index 727377f9df2..917ca8afe46 100755 --- a/staging/src/k8s.io/client-go/tools/cache/OWNERS +++ b/staging/src/k8s.io/client-go/tools/cache/OWNERS @@ -22,7 +22,6 @@ reviewers: - erictune - davidopp - pmorie -- kargakis - janetkuo - justinsb - eparis diff --git a/staging/src/k8s.io/client-go/tools/cache/listers.go b/staging/src/k8s.io/client-go/tools/cache/listers.go index ce377329c7f..311ff8c4931 100644 --- a/staging/src/k8s.io/client-go/tools/cache/listers.go +++ b/staging/src/k8s.io/client-go/tools/cache/listers.go @@ -31,7 +31,14 @@ import ( type AppendFunc func(interface{}) func ListAll(store Store, selector labels.Selector, appendFn AppendFunc) error { + selectAll := selector.Empty() for _, m := range store.List() { + if selectAll { + // Avoid computing labels of the objects to speed up common flows + // of listing all objects. + appendFn(m) + continue + } metadata, err := meta.Accessor(m) if err != nil { return err @@ -44,8 +51,15 @@ func ListAll(store Store, selector labels.Selector, appendFn AppendFunc) error { } func ListAllByNamespace(indexer Indexer, namespace string, selector labels.Selector, appendFn AppendFunc) error { + selectAll := selector.Empty() if namespace == metav1.NamespaceAll { for _, m := range indexer.List() { + if selectAll { + // Avoid computing labels of the objects to speed up common flows + // of listing all objects. + appendFn(m) + continue + } metadata, err := meta.Accessor(m) if err != nil { return err @@ -74,6 +88,12 @@ func ListAllByNamespace(indexer Indexer, namespace string, selector labels.Selec return nil } for _, m := range items { + if selectAll { + // Avoid computing labels of the objects to speed up common flows + // of listing all objects. + appendFn(m) + continue + } metadata, err := meta.Accessor(m) if err != nil { return err diff --git a/staging/src/k8s.io/client-go/tools/clientcmd/client_config.go b/staging/src/k8s.io/client-go/tools/clientcmd/client_config.go index dea229c9182..a7b8c1c6e42 100644 --- a/staging/src/k8s.io/client-go/tools/clientcmd/client_config.go +++ b/staging/src/k8s.io/client-go/tools/clientcmd/client_config.go @@ -229,11 +229,12 @@ func (config *DirectClientConfig) getUserIdentificationPartialConfig(configAuthI if len(configAuthInfo.Token) > 0 { mergedConfig.BearerToken = configAuthInfo.Token } else if len(configAuthInfo.TokenFile) > 0 { - ts := restclient.NewCachedFileTokenSource(configAuthInfo.TokenFile) - if _, err := ts.Token(); err != nil { + tokenBytes, err := ioutil.ReadFile(configAuthInfo.TokenFile) + if err != nil { return nil, err } - mergedConfig.WrapTransport = restclient.TokenSourceWrapTransport(ts) + mergedConfig.BearerToken = string(tokenBytes) + mergedConfig.BearerTokenFile = configAuthInfo.TokenFile } if len(configAuthInfo.Impersonate) > 0 { mergedConfig.Impersonate = restclient.ImpersonationConfig{ diff --git a/staging/src/k8s.io/client-go/tools/clientcmd/client_config_test.go b/staging/src/k8s.io/client-go/tools/clientcmd/client_config_test.go index 6da850ed405..a13f08ae7d9 100644 --- a/staging/src/k8s.io/client-go/tools/clientcmd/client_config_test.go +++ b/staging/src/k8s.io/client-go/tools/clientcmd/client_config_test.go @@ -18,7 +18,6 @@ package clientcmd import ( "io/ioutil" - "net/http" "os" "reflect" "strings" @@ -334,19 +333,7 @@ func TestBasicTokenFile(t *testing.T) { t.Fatalf("Unexpected error: %v", err) } - var out *http.Request - clientConfig.WrapTransport(fakeTransport(func(req *http.Request) (*http.Response, error) { - out = req - return &http.Response{}, nil - })).RoundTrip(&http.Request{}) - - matchStringArg(token, strings.TrimPrefix(out.Header.Get("Authorization"), "Bearer "), t) -} - -type fakeTransport func(*http.Request) (*http.Response, error) - -func (ft fakeTransport) RoundTrip(req *http.Request) (*http.Response, error) { - return ft(req) + matchStringArg(token, clientConfig.BearerToken, t) } func TestPrecedenceTokenFile(t *testing.T) { diff --git a/staging/src/k8s.io/client-go/tools/watch/until_test.go b/staging/src/k8s.io/client-go/tools/watch/until_test.go index dd0559461eb..0243beeb3fd 100644 --- a/staging/src/k8s.io/client-go/tools/watch/until_test.go +++ b/staging/src/k8s.io/client-go/tools/watch/until_test.go @@ -53,7 +53,9 @@ func TestUntil(t *testing.T) { func(event watch.Event) (bool, error) { return event.Type == watch.Modified, nil }, } - ctx, _ := context.WithTimeout(context.Background(), time.Minute) + ctx, cancel := context.WithTimeout(context.Background(), time.Minute) + defer cancel() + lastEvent, err := UntilWithoutRetry(ctx, fw, conditions...) if err != nil { t.Fatalf("expected nil error, got %#v", err) @@ -80,7 +82,9 @@ func TestUntilMultipleConditions(t *testing.T) { func(event watch.Event) (bool, error) { return event.Type == watch.Added, nil }, } - ctx, _ := context.WithTimeout(context.Background(), time.Minute) + ctx, cancel := context.WithTimeout(context.Background(), time.Minute) + defer cancel() + lastEvent, err := UntilWithoutRetry(ctx, fw, conditions...) if err != nil { t.Fatalf("expected nil error, got %#v", err) @@ -108,7 +112,9 @@ func TestUntilMultipleConditionsFail(t *testing.T) { func(event watch.Event) (bool, error) { return event.Type == watch.Deleted, nil }, } - ctx, _ := context.WithTimeout(context.Background(), 10*time.Second) + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + defer cancel() + lastEvent, err := UntilWithoutRetry(ctx, fw, conditions...) if err != wait.ErrWaitTimeout { t.Fatalf("expected ErrWaitTimeout error, got %#v", err) @@ -169,6 +175,7 @@ func TestUntilErrorCondition(t *testing.T) { ctx, cancel := context.WithTimeout(context.Background(), time.Minute) defer cancel() + _, err := UntilWithoutRetry(ctx, fw, conditions...) if err == nil { t.Fatal("expected an error") diff --git a/staging/src/k8s.io/client-go/transport/BUILD b/staging/src/k8s.io/client-go/transport/BUILD index dc1800681d3..643750e2563 100644 --- a/staging/src/k8s.io/client-go/transport/BUILD +++ b/staging/src/k8s.io/client-go/transport/BUILD @@ -11,9 +11,11 @@ go_test( srcs = [ "cache_test.go", "round_trippers_test.go", + "token_source_test.go", "transport_test.go", ], embed = [":go_default_library"], + deps = ["//vendor/golang.org/x/oauth2:go_default_library"], ) go_library( @@ -22,12 +24,14 @@ go_library( "cache.go", "config.go", "round_trippers.go", + "token_source.go", "transport.go", ], importmap = "k8s.io/kubernetes/vendor/k8s.io/client-go/transport", importpath = "k8s.io/client-go/transport", deps = [ "//staging/src/k8s.io/apimachinery/pkg/util/net:go_default_library", + "//vendor/golang.org/x/oauth2:go_default_library", "//vendor/k8s.io/klog:go_default_library", ], ) diff --git a/staging/src/k8s.io/client-go/transport/config.go b/staging/src/k8s.io/client-go/transport/config.go index 4081c23e7ff..acb126d8b09 100644 --- a/staging/src/k8s.io/client-go/transport/config.go +++ b/staging/src/k8s.io/client-go/transport/config.go @@ -39,6 +39,11 @@ type Config struct { // Bearer token for authentication BearerToken string + // Path to a file containing a BearerToken. + // If set, the contents are periodically read. + // The last successfully read value takes precedence over BearerToken. + BearerTokenFile string + // Impersonate is the config that this Config will impersonate using Impersonate ImpersonationConfig @@ -80,7 +85,7 @@ func (c *Config) HasBasicAuth() bool { // HasTokenAuth returns whether the configuration has token authentication or not. func (c *Config) HasTokenAuth() bool { - return len(c.BearerToken) != 0 + return len(c.BearerToken) != 0 || len(c.BearerTokenFile) != 0 } // HasCertAuth returns whether the configuration has certificate authentication or not. diff --git a/staging/src/k8s.io/client-go/transport/round_trippers.go b/staging/src/k8s.io/client-go/transport/round_trippers.go index da417cf96ea..117a9c8c4de 100644 --- a/staging/src/k8s.io/client-go/transport/round_trippers.go +++ b/staging/src/k8s.io/client-go/transport/round_trippers.go @@ -22,6 +22,7 @@ import ( "strings" "time" + "golang.org/x/oauth2" "k8s.io/klog" utilnet "k8s.io/apimachinery/pkg/util/net" @@ -44,7 +45,11 @@ func HTTPWrappersForConfig(config *Config, rt http.RoundTripper) (http.RoundTrip case config.HasBasicAuth() && config.HasTokenAuth(): return nil, fmt.Errorf("username/password or bearer token may be set, but not both") case config.HasTokenAuth(): - rt = NewBearerAuthRoundTripper(config.BearerToken, rt) + var err error + rt, err = NewBearerAuthWithRefreshRoundTripper(config.BearerToken, config.BearerTokenFile, rt) + if err != nil { + return nil, err + } case config.HasBasicAuth(): rt = NewBasicAuthRoundTripper(config.Username, config.Password, rt) } @@ -265,13 +270,35 @@ func (rt *impersonatingRoundTripper) WrappedRoundTripper() http.RoundTripper { r type bearerAuthRoundTripper struct { bearer string + source oauth2.TokenSource rt http.RoundTripper } // NewBearerAuthRoundTripper adds the provided bearer token to a request // unless the authorization header has already been set. func NewBearerAuthRoundTripper(bearer string, rt http.RoundTripper) http.RoundTripper { - return &bearerAuthRoundTripper{bearer, rt} + return &bearerAuthRoundTripper{bearer, nil, rt} +} + +// NewBearerAuthRoundTripper adds the provided bearer token to a request +// unless the authorization header has already been set. +// If tokenFile is non-empty, it is periodically read, +// and the last successfully read content is used as the bearer token. +// If tokenFile is non-empty and bearer is empty, the tokenFile is read +// immediately to populate the initial bearer token. +func NewBearerAuthWithRefreshRoundTripper(bearer string, tokenFile string, rt http.RoundTripper) (http.RoundTripper, error) { + if len(tokenFile) == 0 { + return &bearerAuthRoundTripper{bearer, nil, rt}, nil + } + source := NewCachedFileTokenSource(tokenFile) + if len(bearer) == 0 { + token, err := source.Token() + if err != nil { + return nil, err + } + bearer = token.AccessToken + } + return &bearerAuthRoundTripper{bearer, source, rt}, nil } func (rt *bearerAuthRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) { @@ -280,7 +307,13 @@ func (rt *bearerAuthRoundTripper) RoundTrip(req *http.Request) (*http.Response, } req = utilnet.CloneRequest(req) - req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", rt.bearer)) + token := rt.bearer + if rt.source != nil { + if refreshedToken, err := rt.source.Token(); err == nil { + token = refreshedToken.AccessToken + } + } + req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", token)) return rt.rt.RoundTrip(req) } diff --git a/staging/src/k8s.io/client-go/rest/token_source.go b/staging/src/k8s.io/client-go/transport/token_source.go similarity index 99% rename from staging/src/k8s.io/client-go/rest/token_source.go rename to staging/src/k8s.io/client-go/transport/token_source.go index c251b5eb0bb..818baffd4e6 100644 --- a/staging/src/k8s.io/client-go/rest/token_source.go +++ b/staging/src/k8s.io/client-go/transport/token_source.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package rest +package transport import ( "fmt" diff --git a/staging/src/k8s.io/client-go/rest/token_source_test.go b/staging/src/k8s.io/client-go/transport/token_source_test.go similarity index 99% rename from staging/src/k8s.io/client-go/rest/token_source_test.go rename to staging/src/k8s.io/client-go/transport/token_source_test.go index 40851f80d71..a222495b94e 100644 --- a/staging/src/k8s.io/client-go/rest/token_source_test.go +++ b/staging/src/k8s.io/client-go/transport/token_source_test.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package rest +package transport import ( "fmt" diff --git a/staging/src/k8s.io/client-go/util/certificate/certificate_manager.go b/staging/src/k8s.io/client-go/util/certificate/certificate_manager.go index ed74559e203..4aa9f3ab4a7 100644 --- a/staging/src/k8s.io/client-go/util/certificate/certificate_manager.go +++ b/staging/src/k8s.io/client-go/util/certificate/certificate_manager.go @@ -48,11 +48,10 @@ var certificateWaitBackoff = wait.Backoff{Duration: 30 * time.Second, Steps: 4, // manager. In the background it communicates with the API server to get new // certificates for certificates about to expire. type Manager interface { - // CertificateSigningRequestClient sets the client interface that is used for - // signing new certificates generated as part of rotation. - SetCertificateSigningRequestClient(certificatesclient.CertificateSigningRequestInterface) error // Start the API server status sync loop. Start() + // Stop the cert manager loop. + Stop() // Current returns the currently selected certificate from the // certificate manager, as well as the associated certificate and key data // in PEM format. @@ -67,11 +66,11 @@ type Manager interface { // Config is the set of configuration parameters available for a new Manager. type Config struct { - // CertificateSigningRequestClient will be used for signing new certificate - // requests generated when a key rotation occurs. It must be set either at - // initialization or by using CertificateSigningRequestClient before - // Manager.Start() is called. - CertificateSigningRequestClient certificatesclient.CertificateSigningRequestInterface + // ClientFn will be used to create a client for + // signing new certificate requests generated when a key rotation occurs. + // It must be set at initialization. The function will never be invoked + // in parallel. It is passed the current client certificate if one exists. + ClientFn CSRClientFunc // Template is the CertificateRequest that will be used as a template for // generating certificate signing requests for all new keys generated as // part of rotation. It follows the same rules as the template parameter of @@ -141,21 +140,34 @@ type Gauge interface { // NoCertKeyError indicates there is no cert/key currently available. type NoCertKeyError string +// CSRClientFunc returns a new client for requesting CSRs. It passes the +// current certificate if one is available and valid. +type CSRClientFunc func(current *tls.Certificate) (certificatesclient.CertificateSigningRequestInterface, error) + func (e *NoCertKeyError) Error() string { return string(*e) } type manager struct { - certSigningRequestClient certificatesclient.CertificateSigningRequestInterface - getTemplate func() *x509.CertificateRequest - lastRequestLock sync.Mutex - lastRequest *x509.CertificateRequest - dynamicTemplate bool - usages []certificates.KeyUsage - certStore Store - certAccessLock sync.RWMutex - cert *tls.Certificate - forceRotation bool - certificateExpiration Gauge - serverHealth bool + getTemplate func() *x509.CertificateRequest + lastRequestLock sync.Mutex + lastRequest *x509.CertificateRequest + dynamicTemplate bool + usages []certificates.KeyUsage + forceRotation bool + + certStore Store + + certificateExpiration Gauge + + // the following variables must only be accessed under certAccessLock + certAccessLock sync.RWMutex + cert *tls.Certificate + serverHealth bool + + // the clientFn must only be accessed under the clientAccessLock + clientAccessLock sync.Mutex + clientFn CSRClientFunc + stopCh chan struct{} + stopped bool } // NewManager returns a new certificate manager. A certificate manager is @@ -176,14 +188,15 @@ func NewManager(config *Config) (Manager, error) { } m := manager{ - certSigningRequestClient: config.CertificateSigningRequestClient, - getTemplate: getTemplate, - dynamicTemplate: config.GetTemplate != nil, - usages: config.Usages, - certStore: config.CertificateStore, - cert: cert, - forceRotation: forceRotation, - certificateExpiration: config.CertificateExpiration, + stopCh: make(chan struct{}), + clientFn: config.ClientFn, + getTemplate: getTemplate, + dynamicTemplate: config.GetTemplate != nil, + usages: config.Usages, + certStore: config.CertificateStore, + cert: cert, + forceRotation: forceRotation, + certificateExpiration: config.CertificateExpiration, } return &m, nil @@ -192,10 +205,14 @@ func NewManager(config *Config) (Manager, error) { // Current returns the currently selected certificate from the certificate // manager. This can be nil if the manager was initialized without a // certificate and has not yet received one from the -// CertificateSigningRequestClient. +// CertificateSigningRequestClient, or if the current cert has expired. func (m *manager) Current() *tls.Certificate { m.certAccessLock.RLock() defer m.certAccessLock.RUnlock() + if m.cert != nil && m.cert.Leaf != nil && time.Now().After(m.cert.Leaf.NotAfter) { + klog.V(2).Infof("Current certificate is expired.") + return nil + } return m.cert } @@ -207,18 +224,15 @@ func (m *manager) ServerHealthy() bool { return m.serverHealth } -// SetCertificateSigningRequestClient sets the client interface that is used -// for signing new certificates generated as part of rotation. It must be -// called before Start() and can not be used to change the -// CertificateSigningRequestClient that has already been set. This method is to -// support the one specific scenario where the CertificateSigningRequestClient -// uses the CertificateManager. -func (m *manager) SetCertificateSigningRequestClient(certSigningRequestClient certificatesclient.CertificateSigningRequestInterface) error { - if m.certSigningRequestClient == nil { - m.certSigningRequestClient = certSigningRequestClient - return nil +// Stop terminates the manager. +func (m *manager) Stop() { + m.clientAccessLock.Lock() + defer m.clientAccessLock.Unlock() + if m.stopped { + return } - return fmt.Errorf("property CertificateSigningRequestClient is already set") + close(m.stopCh) + m.stopped = true } // Start will start the background work of rotating the certificates. @@ -226,7 +240,7 @@ func (m *manager) Start() { // Certificate rotation depends on access to the API server certificate // signing API, so don't start the certificate manager if we don't have a // client. - if m.certSigningRequestClient == nil { + if m.clientFn == nil { klog.V(2).Infof("Certificate rotation is not enabled, no connection to the apiserver.") return } @@ -234,7 +248,7 @@ func (m *manager) Start() { klog.V(2).Infof("Certificate rotation is enabled.") templateChanged := make(chan struct{}) - go wait.Forever(func() { + go wait.Until(func() { deadline := m.nextRotationDeadline() if sleepInterval := deadline.Sub(time.Now()); sleepInterval > 0 { klog.V(2).Infof("Waiting %v for next certificate rotation", sleepInterval) @@ -269,17 +283,17 @@ func (m *manager) Start() { utilruntime.HandleError(fmt.Errorf("Reached backoff limit, still unable to rotate certs: %v", err)) wait.PollInfinite(32*time.Second, m.rotateCerts) } - }, time.Second) + }, time.Second, m.stopCh) if m.dynamicTemplate { - go wait.Forever(func() { + go wait.Until(func() { // check if the current template matches what we last requested if !m.certSatisfiesTemplate() && !reflect.DeepEqual(m.getLastRequest(), m.getTemplate()) { // if the template is different, queue up an interrupt of the rotation deadline loop. // if we've requested a CSR that matches the new template by the time the interrupt is handled, the interrupt is disregarded. templateChanged <- struct{}{} } - }, time.Second) + }, time.Second, m.stopCh) } } @@ -327,11 +341,26 @@ func getCurrentCertificateOrBootstrap( return &bootstrapCert, true, nil } +func (m *manager) getClient() (certificatesclient.CertificateSigningRequestInterface, error) { + current := m.Current() + m.clientAccessLock.Lock() + defer m.clientAccessLock.Unlock() + return m.clientFn(current) +} + +// RotateCerts is exposed for testing only and is not a part of the public interface. +// Returns true if it changed the cert, false otherwise. Error is only returned in +// exceptional cases. +func (m *manager) RotateCerts() (bool, error) { + return m.rotateCerts() +} + // rotateCerts attempts to request a client cert from the server, wait a reasonable // period of time for it to be signed, and then update the cert on disk. If it cannot // retrieve a cert, it will return false. It will only return error in exceptional cases. // This method also keeps track of "server health" by interpreting the responses it gets // from the server on the various calls it makes. +// TODO: return errors, have callers handle and log them correctly func (m *manager) rotateCerts() (bool, error) { klog.V(2).Infof("Rotating certificates") @@ -341,9 +370,16 @@ func (m *manager) rotateCerts() (bool, error) { return false, nil } + // request the client each time + client, err := m.getClient() + if err != nil { + utilruntime.HandleError(fmt.Errorf("Unable to load a client to request certificates: %v", err)) + return false, nil + } + // Call the Certificate Signing Request API to get a certificate for the // new private key. - req, err := csr.RequestCertificate(m.certSigningRequestClient, csrPEM, "", m.usages, privateKey) + req, err := csr.RequestCertificate(client, csrPEM, "", m.usages, privateKey) if err != nil { utilruntime.HandleError(fmt.Errorf("Failed while requesting a signed certificate from the master: %v", err)) return false, m.updateServerError(err) @@ -359,7 +395,7 @@ func (m *manager) rotateCerts() (bool, error) { var crtPEM []byte watchDuration := time.Minute if err := wait.ExponentialBackoff(certificateWaitBackoff, func() (bool, error) { - data, err := csr.WaitForCertificate(m.certSigningRequestClient, req, watchDuration) + data, err := csr.WaitForCertificate(client, req, watchDuration) switch { case err == nil: crtPEM = data diff --git a/staging/src/k8s.io/client-go/util/certificate/certificate_manager_test.go b/staging/src/k8s.io/client-go/util/certificate/certificate_manager_test.go index 545097ea453..3ca7f767a01 100644 --- a/staging/src/k8s.io/client-go/util/certificate/certificate_manager_test.go +++ b/staging/src/k8s.io/client-go/util/certificate/certificate_manager_test.go @@ -60,6 +60,23 @@ iQIgZX08DA8VfvcA5/Xj1Zjdey9FVY6POLXen6RPiabE97UCICp6eUW7ht+2jjar e35EltCRCjoejRHTuN9TC0uCoVipAiAXaJIx/Q47vGwiw6Y8KXsNU6y54gTbOSxX 54LzHNk/+Q== -----END RSA PRIVATE KEY-----`) +var expiredStoreCertData = newCertificateData(`-----BEGIN CERTIFICATE----- +MIIBFzCBwgIJALhygXnxXmN1MA0GCSqGSIb3DQEBCwUAMBMxETAPBgNVBAMMCGhv +c3QtMTIzMB4XDTE4MTEwNDIzNTc1NFoXDTE4MTEwNTIzNTc1NFowEzERMA8GA1UE +AwwIaG9zdC0xMjMwXDANBgkqhkiG9w0BAQEFAANLADBIAkEAtBMa7NWpv3BVlKTC +PGO/LEsguKqWHBtKzweMY2CVtAL1rQm913huhxF9w+ai76KQ3MHK5IVnLJjYYA5M +zP2H5QIDAQABMA0GCSqGSIb3DQEBCwUAA0EAN2DPFUtCzqnidL+5nh+46Sk6dkMI +T5DD11UuuIjZusKvThsHKVCIsyJ2bDo7cTbI+/nklLRP+FcC2wESFUgXbA== +-----END CERTIFICATE-----`, `-----BEGIN RSA PRIVATE KEY----- +MIIBUwIBADANBgkqhkiG9w0BAQEFAASCAT0wggE5AgEAAkEAtBMa7NWpv3BVlKTC +PGO/LEsguKqWHBtKzweMY2CVtAL1rQm913huhxF9w+ai76KQ3MHK5IVnLJjYYA5M +zP2H5QIDAQABAkAS9BfXab3OKpK3bIgNNyp+DQJKrZnTJ4Q+OjsqkpXvNltPJosf +G8GsiKu/vAt4HGqI3eU77NvRI+mL4MnHRmXBAiEA3qM4FAtKSRBbcJzPxxLEUSwg +XSCcosCktbkXvpYrS30CIQDPDxgqlwDEJQ0uKuHkZI38/SPWWqfUmkecwlbpXABK +iQIgZX08DA8VfvcA5/Xj1Zjdey9FVY6POLXen6RPiabE97UCICp6eUW7ht+2jjar +e35EltCRCjoejRHTuN9TC0uCoVipAiAXaJIx/Q47vGwiw6Y8KXsNU6y54gTbOSxX +54LzHNk/+Q== +-----END RSA PRIVATE KEY-----`) var bootstrapCertData = newCertificateData( `-----BEGIN CERTIFICATE----- MIICRzCCAfGgAwIBAgIJANXr+UzRFq4TMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNV @@ -388,8 +405,8 @@ func TestRotateCertCreateCSRError(t *testing.T) { }, getTemplate: func() *x509.CertificateRequest { return &x509.CertificateRequest{} }, usages: []certificates.KeyUsage{}, - certSigningRequestClient: fakeClient{ - failureType: createError, + clientFn: func(_ *tls.Certificate) (certificatesclient.CertificateSigningRequestInterface, error) { + return fakeClient{failureType: createError}, nil }, } @@ -411,8 +428,8 @@ func TestRotateCertWaitingForResultError(t *testing.T) { }, getTemplate: func() *x509.CertificateRequest { return &x509.CertificateRequest{} }, usages: []certificates.KeyUsage{}, - certSigningRequestClient: fakeClient{ - failureType: watchError, + clientFn: func(_ *tls.Certificate) (certificatesclient.CertificateSigningRequestInterface, error) { + return fakeClient{failureType: watchError}, nil }, } @@ -598,6 +615,14 @@ func TestInitializeCertificateSigningRequestClient(t *testing.T) { expectedCertBeforeStart: storeCertData, expectedCertAfterStart: storeCertData, }, + { + description: "Current certificate expired, no bootstrap certificate", + storeCert: expiredStoreCertData, + bootstrapCert: nilCertificate, + apiCert: apiServerCertData, + expectedCertBeforeStart: nil, + expectedCertAfterStart: apiServerCertData, + }, } for _, tc := range testCases { @@ -621,19 +646,25 @@ func TestInitializeCertificateSigningRequestClient(t *testing.T) { CertificateStore: certificateStore, BootstrapCertificatePEM: tc.bootstrapCert.certificatePEM, BootstrapKeyPEM: tc.bootstrapCert.keyPEM, + ClientFn: func(_ *tls.Certificate) (certificatesclient.CertificateSigningRequestInterface, error) { + return &fakeClient{ + certificatePEM: tc.apiCert.certificatePEM, + }, nil + }, }) if err != nil { t.Errorf("Got %v, wanted no error.", err) } certificate := certificateManager.Current() - if !certificatesEqual(certificate, tc.expectedCertBeforeStart.certificate) { - t.Errorf("Got %v, wanted %v", certificateString(certificate), certificateString(tc.expectedCertBeforeStart.certificate)) - } - if err := certificateManager.SetCertificateSigningRequestClient(&fakeClient{ - certificatePEM: tc.apiCert.certificatePEM, - }); err != nil { - t.Errorf("Got error %v, expected none.", err) + if tc.expectedCertBeforeStart == nil { + if certificate != nil { + t.Errorf("Expected certificate to be nil, was %s", certificate.Leaf.NotAfter) + } + } else { + if !certificatesEqual(certificate, tc.expectedCertBeforeStart.certificate) { + t.Errorf("Got %v, wanted %v", certificateString(certificate), certificateString(tc.expectedCertBeforeStart.certificate)) + } } if m, ok := certificateManager.(*manager); !ok { @@ -649,6 +680,12 @@ func TestInitializeCertificateSigningRequestClient(t *testing.T) { } certificate = certificateManager.Current() + if tc.expectedCertAfterStart == nil { + if certificate != nil { + t.Errorf("Expected certificate to be nil, was %s", certificate.Leaf.NotAfter) + } + return + } if !certificatesEqual(certificate, tc.expectedCertAfterStart.certificate) { t.Errorf("Got %v, wanted %v", certificateString(certificate), certificateString(tc.expectedCertAfterStart.certificate)) } @@ -721,8 +758,10 @@ func TestInitializeOtherRESTClients(t *testing.T) { CertificateStore: certificateStore, BootstrapCertificatePEM: tc.bootstrapCert.certificatePEM, BootstrapKeyPEM: tc.bootstrapCert.keyPEM, - CertificateSigningRequestClient: &fakeClient{ - certificatePEM: tc.apiCert.certificatePEM, + ClientFn: func(_ *tls.Certificate) (certificatesclient.CertificateSigningRequestInterface, error) { + return &fakeClient{ + certificatePEM: tc.apiCert.certificatePEM, + }, nil }, }) if err != nil { @@ -873,10 +912,12 @@ func TestServerHealth(t *testing.T) { CertificateStore: certificateStore, BootstrapCertificatePEM: tc.bootstrapCert.certificatePEM, BootstrapKeyPEM: tc.bootstrapCert.keyPEM, - CertificateSigningRequestClient: &fakeClient{ - certificatePEM: tc.apiCert.certificatePEM, - failureType: tc.failureType, - err: tc.clientErr, + ClientFn: func(_ *tls.Certificate) (certificatesclient.CertificateSigningRequestInterface, error) { + return &fakeClient{ + certificatePEM: tc.apiCert.certificatePEM, + failureType: tc.failureType, + err: tc.clientErr, + }, nil }, }) if err != nil { diff --git a/staging/src/k8s.io/client-go/util/workqueue/BUILD b/staging/src/k8s.io/client-go/util/workqueue/BUILD index ff0e87a7c75..a298ba0710f 100644 --- a/staging/src/k8s.io/client-go/util/workqueue/BUILD +++ b/staging/src/k8s.io/client-go/util/workqueue/BUILD @@ -13,7 +13,7 @@ go_test( "delaying_queue_test.go", "metrics_test.go", "queue_test.go", - "rate_limitting_queue_test.go", + "rate_limiting_queue_test.go", ], embed = [":go_default_library"], deps = [ @@ -31,7 +31,7 @@ go_library( "metrics.go", "parallelizer.go", "queue.go", - "rate_limitting_queue.go", + "rate_limiting_queue.go", ], importmap = "k8s.io/kubernetes/vendor/k8s.io/client-go/util/workqueue", importpath = "k8s.io/client-go/util/workqueue", diff --git a/staging/src/k8s.io/client-go/util/workqueue/default_rate_limiters.go b/staging/src/k8s.io/client-go/util/workqueue/default_rate_limiters.go index a5bed29e007..71bb6322e07 100644 --- a/staging/src/k8s.io/client-go/util/workqueue/default_rate_limiters.go +++ b/staging/src/k8s.io/client-go/util/workqueue/default_rate_limiters.go @@ -35,7 +35,7 @@ type RateLimiter interface { } // DefaultControllerRateLimiter is a no-arg constructor for a default rate limiter for a workqueue. It has -// both overall and per-item rate limitting. The overall is a token bucket and the per-item is exponential +// both overall and per-item rate limiting. The overall is a token bucket and the per-item is exponential func DefaultControllerRateLimiter() RateLimiter { return NewMaxOfRateLimiter( NewItemExponentialFailureRateLimiter(5*time.Millisecond, 1000*time.Second), @@ -62,7 +62,7 @@ func (r *BucketRateLimiter) NumRequeues(item interface{}) int { func (r *BucketRateLimiter) Forget(item interface{}) { } -// ItemExponentialFailureRateLimiter does a simple baseDelay*10^ limit +// ItemExponentialFailureRateLimiter does a simple baseDelay*2^ limit // dealing with max failures and expiration are up to the caller type ItemExponentialFailureRateLimiter struct { failuresLock sync.Mutex diff --git a/staging/src/k8s.io/client-go/util/workqueue/delaying_queue.go b/staging/src/k8s.io/client-go/util/workqueue/delaying_queue.go index a37177425d7..bd654bf3112 100644 --- a/staging/src/k8s.io/client-go/util/workqueue/delaying_queue.go +++ b/staging/src/k8s.io/client-go/util/workqueue/delaying_queue.go @@ -43,12 +43,13 @@ func NewNamedDelayingQueue(name string) DelayingInterface { func newDelayingQueue(clock clock.Clock, name string) DelayingInterface { ret := &delayingType{ - Interface: NewNamed(name), - clock: clock, - heartbeat: clock.NewTicker(maxWait), - stopCh: make(chan struct{}), - waitingForAddCh: make(chan *waitFor, 1000), - metrics: newRetryMetrics(name), + Interface: NewNamed(name), + clock: clock, + heartbeat: clock.NewTicker(maxWait), + stopCh: make(chan struct{}), + waitingForAddCh: make(chan *waitFor, 1000), + metrics: newRetryMetrics(name), + deprecatedMetrics: newDeprecatedRetryMetrics(name), } go ret.waitingLoop() @@ -73,7 +74,8 @@ type delayingType struct { waitingForAddCh chan *waitFor // metrics counts the number of retries - metrics retryMetrics + metrics retryMetrics + deprecatedMetrics retryMetrics } // waitFor holds the data to add and the time it should be added @@ -146,6 +148,7 @@ func (q *delayingType) AddAfter(item interface{}, duration time.Duration) { } q.metrics.retry() + q.deprecatedMetrics.retry() // immediately add things with no delay if duration <= 0 { diff --git a/staging/src/k8s.io/client-go/util/workqueue/metrics.go b/staging/src/k8s.io/client-go/util/workqueue/metrics.go index d4c03d8378f..be23ddd05f7 100644 --- a/staging/src/k8s.io/client-go/util/workqueue/metrics.go +++ b/staging/src/k8s.io/client-go/util/workqueue/metrics.go @@ -57,6 +57,11 @@ type SummaryMetric interface { Observe(float64) } +// HistogramMetric counts individual observations. +type HistogramMetric interface { + Observe(float64) +} + type noopMetric struct{} func (noopMetric) Inc() {} @@ -73,15 +78,23 @@ type defaultQueueMetrics struct { // total number of adds handled by a workqueue adds CounterMetric // how long an item stays in a workqueue - latency SummaryMetric + latency HistogramMetric // how long processing an item from a workqueue takes - workDuration SummaryMetric + workDuration HistogramMetric addTimes map[t]time.Time processingStartTimes map[t]time.Time // how long have current threads been working? unfinishedWorkSeconds SettableGaugeMetric longestRunningProcessor SettableGaugeMetric + + // TODO(danielqsj): Remove the following metrics, they are deprecated + deprecatedDepth GaugeMetric + deprecatedAdds CounterMetric + deprecatedLatency SummaryMetric + deprecatedWorkDuration SummaryMetric + deprecatedUnfinishedWorkSeconds SettableGaugeMetric + deprecatedLongestRunningProcessor SettableGaugeMetric } func (m *defaultQueueMetrics) add(item t) { @@ -90,7 +103,9 @@ func (m *defaultQueueMetrics) add(item t) { } m.adds.Inc() + m.deprecatedAdds.Inc() m.depth.Inc() + m.deprecatedDepth.Inc() if _, exists := m.addTimes[item]; !exists { m.addTimes[item] = m.clock.Now() } @@ -102,9 +117,11 @@ func (m *defaultQueueMetrics) get(item t) { } m.depth.Dec() + m.deprecatedDepth.Dec() m.processingStartTimes[item] = m.clock.Now() if startTime, exists := m.addTimes[item]; exists { - m.latency.Observe(m.sinceInMicroseconds(startTime)) + m.latency.Observe(m.sinceInSeconds(startTime)) + m.deprecatedLatency.Observe(m.sinceInMicroseconds(startTime)) delete(m.addTimes, item) } } @@ -115,7 +132,8 @@ func (m *defaultQueueMetrics) done(item t) { } if startTime, exists := m.processingStartTimes[item]; exists { - m.workDuration.Observe(m.sinceInMicroseconds(startTime)) + m.workDuration.Observe(m.sinceInSeconds(startTime)) + m.deprecatedWorkDuration.Observe(m.sinceInMicroseconds(startTime)) delete(m.processingStartTimes, item) } } @@ -135,7 +153,9 @@ func (m *defaultQueueMetrics) updateUnfinishedWork() { // Convert to seconds; microseconds is unhelpfully granular for this. total /= 1000000 m.unfinishedWorkSeconds.Set(total) - m.longestRunningProcessor.Set(oldest) // in microseconds. + m.deprecatedUnfinishedWorkSeconds.Set(total) + m.longestRunningProcessor.Set(oldest / 1000000) + m.deprecatedLongestRunningProcessor.Set(oldest) // in microseconds. } type noMetrics struct{} @@ -150,6 +170,11 @@ func (m *defaultQueueMetrics) sinceInMicroseconds(start time.Time) float64 { return float64(m.clock.Since(start).Nanoseconds() / time.Microsecond.Nanoseconds()) } +// Gets the time since the specified start in seconds. +func (m *defaultQueueMetrics) sinceInSeconds(start time.Time) float64 { + return m.clock.Since(start).Seconds() +} + type retryMetrics interface { retry() } @@ -170,11 +195,18 @@ func (m *defaultRetryMetrics) retry() { type MetricsProvider interface { NewDepthMetric(name string) GaugeMetric NewAddsMetric(name string) CounterMetric - NewLatencyMetric(name string) SummaryMetric - NewWorkDurationMetric(name string) SummaryMetric + NewLatencyMetric(name string) HistogramMetric + NewWorkDurationMetric(name string) HistogramMetric NewUnfinishedWorkSecondsMetric(name string) SettableGaugeMetric - NewLongestRunningProcessorMicrosecondsMetric(name string) SettableGaugeMetric + NewLongestRunningProcessorSecondsMetric(name string) SettableGaugeMetric NewRetriesMetric(name string) CounterMetric + NewDeprecatedDepthMetric(name string) GaugeMetric + NewDeprecatedAddsMetric(name string) CounterMetric + NewDeprecatedLatencyMetric(name string) SummaryMetric + NewDeprecatedWorkDurationMetric(name string) SummaryMetric + NewDeprecatedUnfinishedWorkSecondsMetric(name string) SettableGaugeMetric + NewDeprecatedLongestRunningProcessorMicrosecondsMetric(name string) SettableGaugeMetric + NewDeprecatedRetriesMetric(name string) CounterMetric } type noopMetricsProvider struct{} @@ -187,11 +219,11 @@ func (_ noopMetricsProvider) NewAddsMetric(name string) CounterMetric { return noopMetric{} } -func (_ noopMetricsProvider) NewLatencyMetric(name string) SummaryMetric { +func (_ noopMetricsProvider) NewLatencyMetric(name string) HistogramMetric { return noopMetric{} } -func (_ noopMetricsProvider) NewWorkDurationMetric(name string) SummaryMetric { +func (_ noopMetricsProvider) NewWorkDurationMetric(name string) HistogramMetric { return noopMetric{} } @@ -199,7 +231,7 @@ func (_ noopMetricsProvider) NewUnfinishedWorkSecondsMetric(name string) Settabl return noopMetric{} } -func (_ noopMetricsProvider) NewLongestRunningProcessorMicrosecondsMetric(name string) SettableGaugeMetric { +func (_ noopMetricsProvider) NewLongestRunningProcessorSecondsMetric(name string) SettableGaugeMetric { return noopMetric{} } @@ -207,6 +239,34 @@ func (_ noopMetricsProvider) NewRetriesMetric(name string) CounterMetric { return noopMetric{} } +func (_ noopMetricsProvider) NewDeprecatedDepthMetric(name string) GaugeMetric { + return noopMetric{} +} + +func (_ noopMetricsProvider) NewDeprecatedAddsMetric(name string) CounterMetric { + return noopMetric{} +} + +func (_ noopMetricsProvider) NewDeprecatedLatencyMetric(name string) SummaryMetric { + return noopMetric{} +} + +func (_ noopMetricsProvider) NewDeprecatedWorkDurationMetric(name string) SummaryMetric { + return noopMetric{} +} + +func (_ noopMetricsProvider) NewDeprecatedUnfinishedWorkSecondsMetric(name string) SettableGaugeMetric { + return noopMetric{} +} + +func (_ noopMetricsProvider) NewDeprecatedLongestRunningProcessorMicrosecondsMetric(name string) SettableGaugeMetric { + return noopMetric{} +} + +func (_ noopMetricsProvider) NewDeprecatedRetriesMetric(name string) CounterMetric { + return noopMetric{} +} + var globalMetricsFactory = queueMetricsFactory{ metricsProvider: noopMetricsProvider{}, } @@ -229,15 +289,21 @@ func (f *queueMetricsFactory) newQueueMetrics(name string, clock clock.Clock) qu return noMetrics{} } return &defaultQueueMetrics{ - clock: clock, - depth: mp.NewDepthMetric(name), - adds: mp.NewAddsMetric(name), - latency: mp.NewLatencyMetric(name), - workDuration: mp.NewWorkDurationMetric(name), - unfinishedWorkSeconds: mp.NewUnfinishedWorkSecondsMetric(name), - longestRunningProcessor: mp.NewLongestRunningProcessorMicrosecondsMetric(name), - addTimes: map[t]time.Time{}, - processingStartTimes: map[t]time.Time{}, + clock: clock, + depth: mp.NewDepthMetric(name), + adds: mp.NewAddsMetric(name), + latency: mp.NewLatencyMetric(name), + workDuration: mp.NewWorkDurationMetric(name), + unfinishedWorkSeconds: mp.NewUnfinishedWorkSecondsMetric(name), + longestRunningProcessor: mp.NewLongestRunningProcessorSecondsMetric(name), + deprecatedDepth: mp.NewDeprecatedDepthMetric(name), + deprecatedAdds: mp.NewDeprecatedAddsMetric(name), + deprecatedLatency: mp.NewDeprecatedLatencyMetric(name), + deprecatedWorkDuration: mp.NewDeprecatedWorkDurationMetric(name), + deprecatedUnfinishedWorkSeconds: mp.NewDeprecatedUnfinishedWorkSecondsMetric(name), + deprecatedLongestRunningProcessor: mp.NewDeprecatedLongestRunningProcessorMicrosecondsMetric(name), + addTimes: map[t]time.Time{}, + processingStartTimes: map[t]time.Time{}, } } @@ -251,6 +317,16 @@ func newRetryMetrics(name string) retryMetrics { } } +func newDeprecatedRetryMetrics(name string) retryMetrics { + var ret *defaultRetryMetrics + if len(name) == 0 { + return ret + } + return &defaultRetryMetrics{ + retries: globalMetricsFactory.metricsProvider.NewDeprecatedRetriesMetric(name), + } +} + // SetProvider sets the metrics provider for all subsequently created work // queues. Only the first call has an effect. func SetProvider(metricsProvider MetricsProvider) { diff --git a/staging/src/k8s.io/client-go/util/workqueue/metrics_test.go b/staging/src/k8s.io/client-go/util/workqueue/metrics_test.go index 117f90801f8..ceb8f4c9ae3 100644 --- a/staging/src/k8s.io/client-go/util/workqueue/metrics_test.go +++ b/staging/src/k8s.io/client-go/util/workqueue/metrics_test.go @@ -137,6 +137,14 @@ type testMetricsProvider struct { unfinished testMetric longest testMetric retries testMetric + // deprecated metrics + deprecatedDepth testMetric + deprecatedAdds testMetric + deprecatedLatency testMetric + deprecatedDuration testMetric + deprecatedUnfinished testMetric + deprecatedLongest testMetric + deprecatedRetries testMetric } func (m *testMetricsProvider) NewDepthMetric(name string) GaugeMetric { @@ -147,11 +155,11 @@ func (m *testMetricsProvider) NewAddsMetric(name string) CounterMetric { return &m.adds } -func (m *testMetricsProvider) NewLatencyMetric(name string) SummaryMetric { +func (m *testMetricsProvider) NewLatencyMetric(name string) HistogramMetric { return &m.latency } -func (m *testMetricsProvider) NewWorkDurationMetric(name string) SummaryMetric { +func (m *testMetricsProvider) NewWorkDurationMetric(name string) HistogramMetric { return &m.duration } @@ -159,7 +167,7 @@ func (m *testMetricsProvider) NewUnfinishedWorkSecondsMetric(name string) Settab return &m.unfinished } -func (m *testMetricsProvider) NewLongestRunningProcessorMicrosecondsMetric(name string) SettableGaugeMetric { +func (m *testMetricsProvider) NewLongestRunningProcessorSecondsMetric(name string) SettableGaugeMetric { return &m.longest } @@ -167,6 +175,34 @@ func (m *testMetricsProvider) NewRetriesMetric(name string) CounterMetric { return &m.retries } +func (m *testMetricsProvider) NewDeprecatedDepthMetric(name string) GaugeMetric { + return &m.deprecatedDepth +} + +func (m *testMetricsProvider) NewDeprecatedAddsMetric(name string) CounterMetric { + return &m.deprecatedAdds +} + +func (m *testMetricsProvider) NewDeprecatedLatencyMetric(name string) SummaryMetric { + return &m.deprecatedLatency +} + +func (m *testMetricsProvider) NewDeprecatedWorkDurationMetric(name string) SummaryMetric { + return &m.deprecatedDuration +} + +func (m *testMetricsProvider) NewDeprecatedUnfinishedWorkSecondsMetric(name string) SettableGaugeMetric { + return &m.deprecatedUnfinished +} + +func (m *testMetricsProvider) NewDeprecatedLongestRunningProcessorMicrosecondsMetric(name string) SettableGaugeMetric { + return &m.deprecatedLongest +} + +func (m *testMetricsProvider) NewDeprecatedRetriesMetric(name string) CounterMetric { + return &m.deprecatedRetries +} + func TestSinceInMicroseconds(t *testing.T) { mp := testMetricsProvider{} c := clock.NewFakeClock(time.Now()) @@ -201,10 +237,18 @@ func TestMetrics(t *testing.T) { t.Errorf("expected %v, got %v", e, a) } + if e, a := 1.0, mp.deprecatedAdds.gaugeValue(); e != a { + t.Errorf("expected %v, got %v", e, a) + } + if e, a := 1.0, mp.depth.gaugeValue(); e != a { t.Errorf("expected %v, got %v", e, a) } + if e, a := 1.0, mp.deprecatedDepth.gaugeValue(); e != a { + t.Errorf("expected %v, got %v", e, a) + } + c.Step(50 * time.Microsecond) // Start processing @@ -213,15 +257,24 @@ func TestMetrics(t *testing.T) { t.Errorf("Expected %v, got %v", "foo", i) } - if e, a := 50.0, mp.latency.observationValue(); e != a { + if e, a := 5e-05, mp.latency.observationValue(); e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := 1, mp.latency.observationCount(); e != a { t.Errorf("expected %v, got %v", e, a) } + if e, a := 50.0, mp.deprecatedLatency.observationValue(); e != a { + t.Errorf("expected %v, got %v", e, a) + } + if e, a := 1, mp.deprecatedLatency.observationCount(); e != a { + t.Errorf("expected %v, got %v", e, a) + } if e, a := 0.0, mp.depth.gaugeValue(); e != a { t.Errorf("expected %v, got %v", e, a) } + if e, a := 0.0, mp.deprecatedDepth.gaugeValue(); e != a { + t.Errorf("expected %v, got %v", e, a) + } // Add it back while processing; multiple adds of the same item are // de-duped. @@ -233,27 +286,42 @@ func TestMetrics(t *testing.T) { if e, a := 2.0, mp.adds.gaugeValue(); e != a { t.Errorf("expected %v, got %v", e, a) } + if e, a := 2.0, mp.deprecatedAdds.gaugeValue(); e != a { + t.Errorf("expected %v, got %v", e, a) + } // One thing remains in the queue if e, a := 1.0, mp.depth.gaugeValue(); e != a { t.Errorf("expected %v, got %v", e, a) } + if e, a := 1.0, mp.deprecatedDepth.gaugeValue(); e != a { + t.Errorf("expected %v, got %v", e, a) + } c.Step(25 * time.Microsecond) // Finish it up q.Done(i) - if e, a := 25.0, mp.duration.observationValue(); e != a { + if e, a := 2.5e-05, mp.duration.observationValue(); e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := 1, mp.duration.observationCount(); e != a { t.Errorf("expected %v, got %v", e, a) } + if e, a := 25.0, mp.deprecatedDuration.observationValue(); e != a { + t.Errorf("expected %v, got %v", e, a) + } + if e, a := 1, mp.deprecatedDuration.observationCount(); e != a { + t.Errorf("expected %v, got %v", e, a) + } // One thing remains in the queue if e, a := 1.0, mp.depth.gaugeValue(); e != a { t.Errorf("expected %v, got %v", e, a) } + if e, a := 1.0, mp.deprecatedDepth.gaugeValue(); e != a { + t.Errorf("expected %v, got %v", e, a) + } // It should be back on the queue i, _ = q.Get() @@ -261,33 +329,54 @@ func TestMetrics(t *testing.T) { t.Errorf("Expected %v, got %v", "foo", i) } - if e, a := 25.0, mp.latency.observationValue(); e != a { + if e, a := 2.5e-05, mp.latency.observationValue(); e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := 2, mp.latency.observationCount(); e != a { t.Errorf("expected %v, got %v", e, a) } + if e, a := 25.0, mp.deprecatedLatency.observationValue(); e != a { + t.Errorf("expected %v, got %v", e, a) + } + if e, a := 2, mp.deprecatedLatency.observationCount(); e != a { + t.Errorf("expected %v, got %v", e, a) + } // use a channel to ensure we don't look at the metric before it's // been set. ch := make(chan struct{}, 1) mp.unfinished.notifyCh = ch + mp.deprecatedUnfinished.notifyCh = ch c.Step(time.Millisecond) <-ch + <-ch mp.unfinished.notifyCh = nil + mp.deprecatedUnfinished.notifyCh = nil if e, a := .001, mp.unfinished.gaugeValue(); e != a { t.Errorf("expected %v, got %v", e, a) } - if e, a := 1000.0, mp.longest.gaugeValue(); e != a { + if e, a := .001, mp.deprecatedUnfinished.gaugeValue(); e != a { + t.Errorf("expected %v, got %v", e, a) + } + if e, a := .001, mp.longest.gaugeValue(); e != a { + t.Errorf("expected %v, got %v", e, a) + } + if e, a := 1000.0, mp.deprecatedLongest.gaugeValue(); e != a { t.Errorf("expected %v, got %v", e, a) } // Finish that one up q.Done(i) - if e, a := 1000.0, mp.duration.observationValue(); e != a { + if e, a := .001, mp.duration.observationValue(); e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := 2, mp.duration.observationCount(); e != a { t.Errorf("expected %v, got %v", e, a) } + if e, a := 1000.0, mp.deprecatedDuration.observationValue(); e != a { + t.Errorf("expected %v, got %v", e, a) + } + if e, a := 2, mp.deprecatedDuration.observationCount(); e != a { + t.Errorf("expected %v, got %v", e, a) + } } diff --git a/staging/src/k8s.io/client-go/util/workqueue/rate_limitting_queue.go b/staging/src/k8s.io/client-go/util/workqueue/rate_limiting_queue.go similarity index 100% rename from staging/src/k8s.io/client-go/util/workqueue/rate_limitting_queue.go rename to staging/src/k8s.io/client-go/util/workqueue/rate_limiting_queue.go diff --git a/staging/src/k8s.io/client-go/util/workqueue/rate_limitting_queue_test.go b/staging/src/k8s.io/client-go/util/workqueue/rate_limiting_queue_test.go similarity index 88% rename from staging/src/k8s.io/client-go/util/workqueue/rate_limitting_queue_test.go rename to staging/src/k8s.io/client-go/util/workqueue/rate_limiting_queue_test.go index 3fbe07d0d8b..daa0d86041b 100644 --- a/staging/src/k8s.io/client-go/util/workqueue/rate_limitting_queue_test.go +++ b/staging/src/k8s.io/client-go/util/workqueue/rate_limiting_queue_test.go @@ -28,12 +28,13 @@ func TestRateLimitingQueue(t *testing.T) { queue := NewRateLimitingQueue(limiter).(*rateLimitingType) fakeClock := clock.NewFakeClock(time.Now()) delayingQueue := &delayingType{ - Interface: New(), - clock: fakeClock, - heartbeat: fakeClock.NewTicker(maxWait), - stopCh: make(chan struct{}), - waitingForAddCh: make(chan *waitFor, 1000), - metrics: newRetryMetrics(""), + Interface: New(), + clock: fakeClock, + heartbeat: fakeClock.NewTicker(maxWait), + stopCh: make(chan struct{}), + waitingForAddCh: make(chan *waitFor, 1000), + metrics: newRetryMetrics(""), + deprecatedMetrics: newDeprecatedRetryMetrics(""), } queue.DelayingInterface = delayingQueue diff --git a/staging/src/k8s.io/cloud-provider/Godeps/Godeps.json b/staging/src/k8s.io/cloud-provider/Godeps/Godeps.json index d06d7e43c38..45f67b4ae65 100644 --- a/staging/src/k8s.io/cloud-provider/Godeps/Godeps.json +++ b/staging/src/k8s.io/cloud-provider/Godeps/Godeps.json @@ -226,6 +226,10 @@ "ImportPath": "k8s.io/api/certificates/v1beta1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/api/coordination/v1", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/api/coordination/v1beta1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" @@ -530,6 +534,10 @@ "ImportPath": "k8s.io/client-go/informers/coordination", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/client-go/informers/coordination/v1", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/client-go/informers/coordination/v1beta1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" @@ -706,6 +714,10 @@ "ImportPath": "k8s.io/client-go/kubernetes/typed/certificates/v1beta1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/client-go/kubernetes/typed/coordination/v1", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/client-go/kubernetes/typed/coordination/v1beta1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" @@ -818,6 +830,10 @@ "ImportPath": "k8s.io/client-go/listers/certificates/v1beta1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/client-go/listers/coordination/v1", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/client-go/listers/coordination/v1beta1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" diff --git a/staging/src/k8s.io/code-generator/cmd/client-gen/generators/BUILD b/staging/src/k8s.io/code-generator/cmd/client-gen/generators/BUILD index cf386272f1a..36dcab0604a 100644 --- a/staging/src/k8s.io/code-generator/cmd/client-gen/generators/BUILD +++ b/staging/src/k8s.io/code-generator/cmd/client-gen/generators/BUILD @@ -13,7 +13,6 @@ go_library( "generator_for_expansion.go", "generator_for_group.go", "generator_for_type.go", - "tags.go", ], importmap = "k8s.io/kubernetes/vendor/k8s.io/code-generator/cmd/client-gen/generators", importpath = "k8s.io/code-generator/cmd/client-gen/generators", @@ -24,6 +23,7 @@ go_library( "//staging/src/k8s.io/code-generator/cmd/client-gen/generators/util:go_default_library", "//staging/src/k8s.io/code-generator/cmd/client-gen/path:go_default_library", "//staging/src/k8s.io/code-generator/cmd/client-gen/types:go_default_library", + "//staging/src/k8s.io/code-generator/pkg/namer:go_default_library", "//vendor/k8s.io/gengo/args:go_default_library", "//vendor/k8s.io/gengo/generator:go_default_library", "//vendor/k8s.io/gengo/namer:go_default_library", diff --git a/staging/src/k8s.io/code-generator/cmd/client-gen/generators/client_generator.go b/staging/src/k8s.io/code-generator/cmd/client-gen/generators/client_generator.go index ee6ebbcf093..18980744f01 100644 --- a/staging/src/k8s.io/code-generator/cmd/client-gen/generators/client_generator.go +++ b/staging/src/k8s.io/code-generator/cmd/client-gen/generators/client_generator.go @@ -27,6 +27,7 @@ import ( "k8s.io/code-generator/cmd/client-gen/generators/util" "k8s.io/code-generator/cmd/client-gen/path" clientgentypes "k8s.io/code-generator/cmd/client-gen/types" + codegennamer "k8s.io/code-generator/pkg/namer" "k8s.io/gengo/args" "k8s.io/gengo/generator" "k8s.io/gengo/namer" @@ -101,7 +102,7 @@ func NameSystems() namer.NameSystems { "publicPlural": publicPluralNamer, "privatePlural": privatePluralNamer, "allLowercasePlural": lowercaseNamer, - "resource": NewTagOverrideNamer("resourceName", lowercaseNamer), + "resource": codegennamer.NewTagOverrideNamer("resourceName", lowercaseNamer), } } @@ -400,27 +401,3 @@ func Packages(context *generator.Context, arguments *args.GeneratorArgs) generat return generator.Packages(packageList) } - -// tagOverrideNamer is a namer which pulls names from a given tag, if specified, -// and otherwise falls back to a different namer. -type tagOverrideNamer struct { - tagName string - fallback namer.Namer -} - -func (n *tagOverrideNamer) Name(t *types.Type) string { - if nameOverride := extractTag(n.tagName, append(t.SecondClosestCommentLines, t.CommentLines...)); nameOverride != "" { - return nameOverride - } - - return n.fallback.Name(t) -} - -// NewTagOverrideNamer creates a namer.Namer which uses the contents of the given tag as -// the name, or falls back to another Namer if the tag is not present. -func NewTagOverrideNamer(tagName string, fallback namer.Namer) namer.Namer { - return &tagOverrideNamer{ - tagName: tagName, - fallback: fallback, - } -} diff --git a/staging/src/k8s.io/code-generator/cmd/informer-gen/generators/BUILD b/staging/src/k8s.io/code-generator/cmd/informer-gen/generators/BUILD index 9902386d81b..1717edd83f8 100644 --- a/staging/src/k8s.io/code-generator/cmd/informer-gen/generators/BUILD +++ b/staging/src/k8s.io/code-generator/cmd/informer-gen/generators/BUILD @@ -24,6 +24,7 @@ go_library( "//staging/src/k8s.io/code-generator/cmd/client-gen/generators/util:go_default_library", "//staging/src/k8s.io/code-generator/cmd/client-gen/types:go_default_library", "//staging/src/k8s.io/code-generator/cmd/informer-gen/args:go_default_library", + "//staging/src/k8s.io/code-generator/pkg/namer:go_default_library", "//vendor/k8s.io/gengo/args:go_default_library", "//vendor/k8s.io/gengo/generator:go_default_library", "//vendor/k8s.io/gengo/namer:go_default_library", diff --git a/staging/src/k8s.io/code-generator/cmd/informer-gen/generators/generic.go b/staging/src/k8s.io/code-generator/cmd/informer-gen/generators/generic.go index 54632de0530..5ee918f17ea 100644 --- a/staging/src/k8s.io/code-generator/cmd/informer-gen/generators/generic.go +++ b/staging/src/k8s.io/code-generator/cmd/informer-gen/generators/generic.go @@ -22,6 +22,7 @@ import ( "strings" clientgentypes "k8s.io/code-generator/cmd/client-gen/types" + codegennamer "k8s.io/code-generator/pkg/namer" "k8s.io/gengo/generator" "k8s.io/gengo/namer" "k8s.io/gengo/types" @@ -56,6 +57,7 @@ func (g *genericGenerator) Namers(c *generator.Context) namer.NameSystems { "raw": namer.NewRawNamer(g.outputPackage, g.imports), "allLowercasePlural": namer.NewAllLowercasePluralNamer(pluralExceptions), "publicPlural": namer.NewPublicPluralNamer(pluralExceptions), + "resource": codegennamer.NewTagOverrideNamer("resourceName", namer.NewAllLowercasePluralNamer(pluralExceptions)), } } @@ -168,7 +170,7 @@ func (f *sharedInformerFactory) ForResource(resource {{.schemaGroupVersionResour {{range $version := .Versions -}} // Group={{$group.Name}}, Version={{.Name}} {{range .Resources -}} - case {{index $.schemeGVs $version|raw}}.WithResource("{{.|allLowercasePlural}}"): + case {{index $.schemeGVs $version|raw}}.WithResource("{{.|resource}}"): return &genericInformer{resource: resource.GroupResource(), informer: f.{{$GroupGoName}}().{{$version.GoName}}().{{.|publicPlural}}().Informer()}, nil {{end}} {{end}} diff --git a/staging/src/k8s.io/code-generator/pkg/namer/BUILD b/staging/src/k8s.io/code-generator/pkg/namer/BUILD new file mode 100644 index 00000000000..cbed26a69b6 --- /dev/null +++ b/staging/src/k8s.io/code-generator/pkg/namer/BUILD @@ -0,0 +1,27 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = ["tag-override.go"], + importmap = "k8s.io/kubernetes/vendor/k8s.io/code-generator/pkg/namer", + importpath = "k8s.io/code-generator/pkg/namer", + visibility = ["//visibility:public"], + deps = [ + "//vendor/k8s.io/gengo/namer:go_default_library", + "//vendor/k8s.io/gengo/types:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/staging/src/k8s.io/code-generator/pkg/namer/tag-override.go b/staging/src/k8s.io/code-generator/pkg/namer/tag-override.go new file mode 100644 index 00000000000..fd8c3a8553c --- /dev/null +++ b/staging/src/k8s.io/code-generator/pkg/namer/tag-override.go @@ -0,0 +1,58 @@ +/* +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 namer + +import ( + "k8s.io/gengo/namer" + "k8s.io/gengo/types" +) + +// TagOverrideNamer is a namer which pulls names from a given tag, if specified, +// and otherwise falls back to a different namer. +type TagOverrideNamer struct { + tagName string + fallback namer.Namer +} + +// Name returns the tag value if it exists. It no tag was found the fallback namer will be used +func (n *TagOverrideNamer) Name(t *types.Type) string { + if nameOverride := extractTag(n.tagName, append(t.SecondClosestCommentLines, t.CommentLines...)); nameOverride != "" { + return nameOverride + } + + return n.fallback.Name(t) +} + +// NewTagOverrideNamer creates a namer.Namer which uses the contents of the given tag as +// the name, or falls back to another Namer if the tag is not present. +func NewTagOverrideNamer(tagName string, fallback namer.Namer) namer.Namer { + return &TagOverrideNamer{ + tagName: tagName, + fallback: fallback, + } +} + +// extractTag gets the comment-tags for the key. If the tag did not exist, it +// returns the empty string. +func extractTag(key string, lines []string) string { + val, present := types.ExtractCommentTags("+", lines)[key] + if !present || len(val) < 1 { + return "" + } + + return val[0] +} diff --git a/staging/src/k8s.io/csi-api/Godeps/Godeps.json b/staging/src/k8s.io/csi-api/Godeps/Godeps.json index f8182d4a9d6..1ffb9f42da5 100644 --- a/staging/src/k8s.io/csi-api/Godeps/Godeps.json +++ b/staging/src/k8s.io/csi-api/Godeps/Godeps.json @@ -230,6 +230,10 @@ "ImportPath": "k8s.io/api/certificates/v1beta1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/api/coordination/v1", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/api/coordination/v1beta1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" diff --git a/staging/src/k8s.io/kube-aggregator/Godeps/Godeps.json b/staging/src/k8s.io/kube-aggregator/Godeps/Godeps.json index 4e69bda90fc..66230c8c905 100644 --- a/staging/src/k8s.io/kube-aggregator/Godeps/Godeps.json +++ b/staging/src/k8s.io/kube-aggregator/Godeps/Godeps.json @@ -260,7 +260,11 @@ }, { "ImportPath": "github.com/prometheus/client_golang/prometheus", - "Rev": "e7e903064f5e9eb5da98208bae10b475d4db0f8c" + "Rev": "abad2d1bd44235a26707c172eab6bca5bf2dbad3" + }, + { + "ImportPath": "github.com/prometheus/client_golang/prometheus/internal", + "Rev": "abad2d1bd44235a26707c172eab6bca5bf2dbad3" }, { "ImportPath": "github.com/prometheus/client_model/go", @@ -602,6 +606,10 @@ "ImportPath": "k8s.io/api/certificates/v1beta1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/api/coordination/v1", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/api/coordination/v1beta1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" @@ -1374,6 +1382,10 @@ "ImportPath": "k8s.io/client-go/informers/coordination", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/client-go/informers/coordination/v1", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/client-go/informers/coordination/v1beta1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" @@ -1550,6 +1562,10 @@ "ImportPath": "k8s.io/client-go/kubernetes/typed/certificates/v1beta1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/client-go/kubernetes/typed/coordination/v1", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/client-go/kubernetes/typed/coordination/v1beta1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" @@ -1662,6 +1678,10 @@ "ImportPath": "k8s.io/client-go/listers/certificates/v1beta1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/client-go/listers/coordination/v1", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/client-go/listers/coordination/v1beta1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" diff --git a/staging/src/k8s.io/kube-aggregator/pkg/apiserver/BUILD b/staging/src/k8s.io/kube-aggregator/pkg/apiserver/BUILD index 69af8089830..aa5763bd528 100644 --- a/staging/src/k8s.io/kube-aggregator/pkg/apiserver/BUILD +++ b/staging/src/k8s.io/kube-aggregator/pkg/apiserver/BUILD @@ -55,6 +55,7 @@ go_library( "//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library", "//staging/src/k8s.io/apiserver/pkg/endpoints/handlers/responsewriters:go_default_library", + "//staging/src/k8s.io/apiserver/pkg/endpoints/metrics:go_default_library", "//staging/src/k8s.io/apiserver/pkg/endpoints/request:go_default_library", "//staging/src/k8s.io/apiserver/pkg/features:go_default_library", "//staging/src/k8s.io/apiserver/pkg/server:go_default_library", diff --git a/staging/src/k8s.io/kube-aggregator/pkg/apiserver/apiserver.go b/staging/src/k8s.io/kube-aggregator/pkg/apiserver/apiserver.go index 6f236e873ab..0741e5486d6 100644 --- a/staging/src/k8s.io/kube-aggregator/pkg/apiserver/apiserver.go +++ b/staging/src/k8s.io/kube-aggregator/pkg/apiserver/apiserver.go @@ -225,7 +225,7 @@ func (c completedConfig) NewWithDelegate(delegationTarget genericapiserver.Deleg } // AddAPIService adds an API service. It is not thread-safe, so only call it on one thread at a time please. -// It's a slow moving API, so its ok to run the controller on a single thread +// It's a slow moving API, so it's ok to run the controller on a single thread func (s *APIAggregator) AddAPIService(apiService *apiregistration.APIService) error { // if the proxyHandler already exists, it needs to be updated. The aggregation bits do not // since they are wired against listers because they require multiple resources to respond @@ -285,7 +285,7 @@ func (s *APIAggregator) AddAPIService(apiService *apiregistration.APIService) er } // RemoveAPIService removes the APIService from being handled. It is not thread-safe, so only call it on one thread at a time please. -// It's a slow moving API, so its ok to run the controller on a single thread. +// It's a slow moving API, so it's ok to run the controller on a single thread. func (s *APIAggregator) RemoveAPIService(apiServiceName string) { version := apiregistration.APIServiceNameToGroupVersion(apiServiceName) diff --git a/staging/src/k8s.io/kube-aggregator/pkg/apiserver/handler_proxy.go b/staging/src/k8s.io/kube-aggregator/pkg/apiserver/handler_proxy.go index e8976f07eff..e6e30bbd44b 100644 --- a/staging/src/k8s.io/kube-aggregator/pkg/apiserver/handler_proxy.go +++ b/staging/src/k8s.io/kube-aggregator/pkg/apiserver/handler_proxy.go @@ -30,6 +30,7 @@ import ( utilnet "k8s.io/apimachinery/pkg/util/net" "k8s.io/apimachinery/pkg/util/proxy" "k8s.io/apiserver/pkg/endpoints/handlers/responsewriters" + endpointmetrics "k8s.io/apiserver/pkg/endpoints/metrics" genericapirequest "k8s.io/apiserver/pkg/endpoints/request" genericfeatures "k8s.io/apiserver/pkg/features" utilfeature "k8s.io/apiserver/pkg/util/feature" @@ -38,6 +39,8 @@ import ( apiregistrationapi "k8s.io/kube-aggregator/pkg/apis/apiregistration" ) +const aggregatorComponent string = "aggregator" + // proxyHandler provides a http.Handler which will proxy traffic to locations // specified by items implementing Redirector. type proxyHandler struct { @@ -60,6 +63,8 @@ type proxyHandlingInfo struct { // local indicates that this APIService is locally satisfied local bool + // name is the name of the APIService + name string // restConfig holds the information for building a roundtripper restConfig *restclient.Config // transportBuildingError is an error produced while building the transport. If this @@ -75,6 +80,19 @@ type proxyHandlingInfo struct { serviceAvailable bool } +func proxyError(w http.ResponseWriter, req *http.Request, error string, code int) { + http.Error(w, error, code) + + ctx := req.Context() + info, ok := genericapirequest.RequestInfoFrom(ctx) + if !ok { + klog.Warning("no RequestInfo found in the context") + return + } + // TODO: record long-running request differently? The long-running check func does not necessarily match the one of the aggregated apiserver + endpointmetrics.Record(req, info, aggregatorComponent, "", code, 0, 0) +} + func (r *proxyHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) { value := r.handlingInfo.Load() if value == nil { @@ -92,18 +110,18 @@ func (r *proxyHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) { } if !handlingInfo.serviceAvailable { - http.Error(w, "service unavailable", http.StatusServiceUnavailable) + proxyError(w, req, "service unavailable", http.StatusServiceUnavailable) return } if handlingInfo.transportBuildingError != nil { - http.Error(w, handlingInfo.transportBuildingError.Error(), http.StatusInternalServerError) + proxyError(w, req, handlingInfo.transportBuildingError.Error(), http.StatusInternalServerError) return } user, ok := genericapirequest.UserFrom(req.Context()) if !ok { - http.Error(w, "missing user", http.StatusInternalServerError) + proxyError(w, req, "missing user", http.StatusInternalServerError) return } @@ -113,7 +131,7 @@ func (r *proxyHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) { rloc, err := r.serviceResolver.ResolveEndpoint(handlingInfo.serviceNamespace, handlingInfo.serviceName) if err != nil { klog.Errorf("error resolving %s/%s: %v", handlingInfo.serviceNamespace, handlingInfo.serviceName, err) - http.Error(w, "service unavailable", http.StatusServiceUnavailable) + proxyError(w, req, "service unavailable", http.StatusServiceUnavailable) return } location.Host = rloc.Host @@ -126,14 +144,14 @@ func (r *proxyHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) { newReq.URL = location if handlingInfo.proxyRoundTripper == nil { - http.Error(w, "", http.StatusNotFound) + proxyError(w, req, "", http.StatusNotFound) return } // we need to wrap the roundtripper in another roundtripper which will apply the front proxy headers proxyRoundTripper, upgrade, err := maybeWrapForConnectionUpgrades(handlingInfo.restConfig, handlingInfo.proxyRoundTripper, req) if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) + proxyError(w, req, err.Error(), http.StatusInternalServerError) return } proxyRoundTripper = transport.NewAuthProxyRoundTripper(user.GetName(), user.GetGroups(), user.GetExtra(), proxyRoundTripper) @@ -195,6 +213,7 @@ func (r *proxyHandler) updateAPIService(apiService *apiregistrationapi.APIServic } newInfo := proxyHandlingInfo{ + name: apiService.Name, restConfig: &restclient.Config{ TLSClientConfig: restclient.TLSClientConfig{ Insecure: apiService.Spec.InsecureSkipTLSVerify, diff --git a/staging/src/k8s.io/kube-aggregator/pkg/controllers/status/BUILD b/staging/src/k8s.io/kube-aggregator/pkg/controllers/status/BUILD index 3810051bc50..1026e9bd86a 100644 --- a/staging/src/k8s.io/kube-aggregator/pkg/controllers/status/BUILD +++ b/staging/src/k8s.io/kube-aggregator/pkg/controllers/status/BUILD @@ -8,11 +8,15 @@ load( go_library( name = "go_default_library", - srcs = ["available_controller.go"], + srcs = [ + "available_controller.go", + "metrics.go", + ], importmap = "k8s.io/kubernetes/vendor/k8s.io/kube-aggregator/pkg/controllers/status", importpath = "k8s.io/kube-aggregator/pkg/controllers/status", deps = [ "//staging/src/k8s.io/api/core/v1:go_default_library", + "//staging/src/k8s.io/apimachinery/pkg/api/equality:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/meta:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", @@ -29,6 +33,7 @@ go_library( "//staging/src/k8s.io/kube-aggregator/pkg/client/informers/internalversion/apiregistration/internalversion:go_default_library", "//staging/src/k8s.io/kube-aggregator/pkg/client/listers/apiregistration/internalversion:go_default_library", "//staging/src/k8s.io/kube-aggregator/pkg/controllers:go_default_library", + "//vendor/github.com/prometheus/client_golang/prometheus:go_default_library", "//vendor/k8s.io/klog:go_default_library", ], ) @@ -46,6 +51,7 @@ go_test( "//staging/src/k8s.io/kube-aggregator/pkg/apis/apiregistration:go_default_library", "//staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/internalclientset/fake:go_default_library", "//staging/src/k8s.io/kube-aggregator/pkg/client/listers/apiregistration/internalversion:go_default_library", + "//vendor/github.com/davecgh/go-spew/spew:go_default_library", ], ) diff --git a/staging/src/k8s.io/kube-aggregator/pkg/controllers/status/available_controller.go b/staging/src/k8s.io/kube-aggregator/pkg/controllers/status/available_controller.go index 66a4d0f2f75..364e00ae9fb 100644 --- a/staging/src/k8s.io/kube-aggregator/pkg/controllers/status/available_controller.go +++ b/staging/src/k8s.io/kube-aggregator/pkg/controllers/status/available_controller.go @@ -26,6 +26,7 @@ import ( "k8s.io/klog" "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/equality" apierrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -140,7 +141,7 @@ func NewAvailableConditionController( } func (c *AvailableConditionController) sync(key string) error { - inAPIService, err := c.apiServiceLister.Get(key) + originalAPIService, err := c.apiServiceLister.Get(key) if apierrors.IsNotFound(err) { return nil } @@ -148,7 +149,7 @@ func (c *AvailableConditionController) sync(key string) error { return err } - apiService := inAPIService.DeepCopy() + apiService := originalAPIService.DeepCopy() availableCondition := apiregistration.APIServiceCondition{ Type: apiregistration.Available, @@ -159,7 +160,7 @@ func (c *AvailableConditionController) sync(key string) error { // local API services are always considered available if apiService.Spec.Service == nil { apiregistration.SetAPIServiceCondition(apiService, apiregistration.NewLocalAvailableAPIServiceCondition()) - _, err := c.apiServiceClient.APIServices().UpdateStatus(apiService) + _, err := updateAPIServiceStatus(c.apiServiceClient, originalAPIService, apiService) return err } @@ -169,14 +170,14 @@ func (c *AvailableConditionController) sync(key string) error { availableCondition.Reason = "ServiceNotFound" availableCondition.Message = fmt.Sprintf("service/%s in %q is not present", apiService.Spec.Service.Name, apiService.Spec.Service.Namespace) apiregistration.SetAPIServiceCondition(apiService, availableCondition) - _, err := c.apiServiceClient.APIServices().UpdateStatus(apiService) + _, err := updateAPIServiceStatus(c.apiServiceClient, originalAPIService, apiService) return err } else if err != nil { availableCondition.Status = apiregistration.ConditionUnknown availableCondition.Reason = "ServiceAccessError" availableCondition.Message = fmt.Sprintf("service/%s in %q cannot be checked due to: %v", apiService.Spec.Service.Name, apiService.Spec.Service.Namespace, err) apiregistration.SetAPIServiceCondition(apiService, availableCondition) - _, err := c.apiServiceClient.APIServices().UpdateStatus(apiService) + _, err := updateAPIServiceStatus(c.apiServiceClient, originalAPIService, apiService) return err } @@ -193,7 +194,7 @@ func (c *AvailableConditionController) sync(key string) error { availableCondition.Reason = "ServicePortError" availableCondition.Message = fmt.Sprintf("service/%s in %q is not listening on port 443", apiService.Spec.Service.Name, apiService.Spec.Service.Namespace) apiregistration.SetAPIServiceCondition(apiService, availableCondition) - _, err := c.apiServiceClient.APIServices().UpdateStatus(apiService) + _, err := updateAPIServiceStatus(c.apiServiceClient, originalAPIService, apiService) return err } @@ -203,14 +204,14 @@ func (c *AvailableConditionController) sync(key string) error { availableCondition.Reason = "EndpointsNotFound" availableCondition.Message = fmt.Sprintf("cannot find endpoints for service/%s in %q", apiService.Spec.Service.Name, apiService.Spec.Service.Namespace) apiregistration.SetAPIServiceCondition(apiService, availableCondition) - _, err := c.apiServiceClient.APIServices().UpdateStatus(apiService) + _, err := updateAPIServiceStatus(c.apiServiceClient, originalAPIService, apiService) return err } else if err != nil { availableCondition.Status = apiregistration.ConditionUnknown availableCondition.Reason = "EndpointsAccessError" availableCondition.Message = fmt.Sprintf("service/%s in %q cannot be checked due to: %v", apiService.Spec.Service.Name, apiService.Spec.Service.Namespace, err) apiregistration.SetAPIServiceCondition(apiService, availableCondition) - _, err := c.apiServiceClient.APIServices().UpdateStatus(apiService) + _, err := updateAPIServiceStatus(c.apiServiceClient, originalAPIService, apiService) return err } hasActiveEndpoints := false @@ -225,7 +226,7 @@ func (c *AvailableConditionController) sync(key string) error { availableCondition.Reason = "MissingEndpoints" availableCondition.Message = fmt.Sprintf("endpoints for service/%s in %q have no addresses", apiService.Spec.Service.Name, apiService.Spec.Service.Namespace) apiregistration.SetAPIServiceCondition(apiService, availableCondition) - _, err := c.apiServiceClient.APIServices().UpdateStatus(apiService) + _, err := updateAPIServiceStatus(c.apiServiceClient, originalAPIService, apiService) return err } } @@ -259,7 +260,7 @@ func (c *AvailableConditionController) sync(key string) error { availableCondition.Reason = "FailedDiscoveryCheck" availableCondition.Message = fmt.Sprintf("no response from %v: %v", discoveryURL, err) apiregistration.SetAPIServiceCondition(apiService, availableCondition) - _, updateErr := c.apiServiceClient.APIServices().UpdateStatus(apiService) + _, updateErr := updateAPIServiceStatus(c.apiServiceClient, originalAPIService, apiService) if updateErr != nil { return updateErr } @@ -272,10 +273,42 @@ func (c *AvailableConditionController) sync(key string) error { availableCondition.Reason = "Passed" availableCondition.Message = "all checks passed" apiregistration.SetAPIServiceCondition(apiService, availableCondition) - _, err = c.apiServiceClient.APIServices().UpdateStatus(apiService) + _, err = updateAPIServiceStatus(c.apiServiceClient, originalAPIService, apiService) return err } +// updateAPIServiceStatus only issues an update if a change is detected. We have a tight resync loop to quickly detect dead +// apiservices. Doing that means we don't want to quickly issue no-op updates. +func updateAPIServiceStatus(client apiregistrationclient.APIServicesGetter, originalAPIService, newAPIService *apiregistration.APIService) (*apiregistration.APIService, error) { + if equality.Semantic.DeepEqual(originalAPIService.Status, newAPIService.Status) { + return newAPIService, nil + } + + newAPIService, err := client.APIServices().UpdateStatus(newAPIService) + if err != nil { + return nil, err + } + + // update metrics + wasAvailable := apiregistration.IsAPIServiceConditionTrue(originalAPIService, apiregistration.Available) + isAvailable := apiregistration.IsAPIServiceConditionTrue(newAPIService, apiregistration.Available) + if isAvailable != wasAvailable { + if isAvailable { + unavailableGauge.WithLabelValues(newAPIService.Name).Set(0.0) + } else { + unavailableGauge.WithLabelValues(newAPIService.Name).Set(1.0) + + reason := "UnknownReason" + if newCondition := apiregistration.GetAPIServiceConditionByType(newAPIService, apiregistration.Available); newCondition != nil { + reason = newCondition.Reason + } + unavailableCounter.WithLabelValues(newAPIService.Name, reason).Inc() + } + } + + return newAPIService, nil +} + func (c *AvailableConditionController) Run(threadiness int, stopCh <-chan struct{}) { defer utilruntime.HandleCrash() defer c.queue.ShutDown() diff --git a/staging/src/k8s.io/kube-aggregator/pkg/controllers/status/available_controller_test.go b/staging/src/k8s.io/kube-aggregator/pkg/controllers/status/available_controller_test.go index d82a0a0bd39..5feec0e183e 100644 --- a/staging/src/k8s.io/kube-aggregator/pkg/controllers/status/available_controller_test.go +++ b/staging/src/k8s.io/kube-aggregator/pkg/controllers/status/available_controller_test.go @@ -19,6 +19,8 @@ package apiserver import ( "testing" + "github.com/davecgh/go-spew/spew" + "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" v1listers "k8s.io/client-go/listers/core/v1" @@ -226,5 +228,26 @@ func TestSync(t *testing.T) { if e, a := tc.expectedAvailability.Message, condition.Message; e != a { t.Errorf("%v expected %v, got %#v", tc.name, e, condition) } + if condition.LastTransitionTime.IsZero() { + t.Error("expected lastTransitionTime to be non-zero") + } } } + +func TestUpdateAPIServiceStatus(t *testing.T) { + foo := &apiregistration.APIService{Status: apiregistration.APIServiceStatus{Conditions: []apiregistration.APIServiceCondition{{Type: "foo"}}}} + bar := &apiregistration.APIService{Status: apiregistration.APIServiceStatus{Conditions: []apiregistration.APIServiceCondition{{Type: "bar"}}}} + + fakeClient := fake.NewSimpleClientset() + updateAPIServiceStatus(fakeClient.Apiregistration(), foo, foo) + if e, a := 0, len(fakeClient.Actions()); e != a { + t.Error(spew.Sdump(fakeClient.Actions())) + } + + fakeClient.ClearActions() + updateAPIServiceStatus(fakeClient.Apiregistration(), foo, bar) + if e, a := 1, len(fakeClient.Actions()); e != a { + t.Error(spew.Sdump(fakeClient.Actions())) + } + +} diff --git a/staging/src/k8s.io/kube-aggregator/pkg/controllers/status/metrics.go b/staging/src/k8s.io/kube-aggregator/pkg/controllers/status/metrics.go new file mode 100644 index 00000000000..c36527b1076 --- /dev/null +++ b/staging/src/k8s.io/kube-aggregator/pkg/controllers/status/metrics.go @@ -0,0 +1,43 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package apiserver + +import ( + "github.com/prometheus/client_golang/prometheus" +) + +var ( + unavailableCounter = prometheus.NewCounterVec( + prometheus.CounterOpts{ + Name: "aggregator_unavailable_apiservice_count", + Help: "Counter of APIServices which are marked as unavailable broken down by APIService name and reason.", + }, + []string{"name", "reason"}, + ) + unavailableGauge = prometheus.NewGaugeVec( + prometheus.GaugeOpts{ + Name: "aggregator_unavailable_apiserver_gauge", + Help: "Gauge of APIServices which are marked as unavailable broken down by APIService name.", + }, + []string{"name"}, + ) +) + +func init() { + prometheus.MustRegister(unavailableCounter) + prometheus.MustRegister(unavailableGauge) +} diff --git a/staging/src/k8s.io/kube-controller-manager/OWNERS b/staging/src/k8s.io/kube-controller-manager/OWNERS index b9492dc62e0..7b38dc3b373 100644 --- a/staging/src/k8s.io/kube-controller-manager/OWNERS +++ b/staging/src/k8s.io/kube-controller-manager/OWNERS @@ -10,3 +10,4 @@ reviewers: - mtaufen - sttts - stewart-yu +- cheftako diff --git a/staging/src/k8s.io/kube-scheduler/config/v1alpha1/types.go b/staging/src/k8s.io/kube-scheduler/config/v1alpha1/types.go index 811e4062ae9..6bdb5500d6d 100644 --- a/staging/src/k8s.io/kube-scheduler/config/v1alpha1/types.go +++ b/staging/src/k8s.io/kube-scheduler/config/v1alpha1/types.go @@ -75,7 +75,8 @@ type KubeSchedulerConfiguration struct { // at least "minFeasibleNodesToFind" feasible nodes no matter what the value of this flag is. // Example: if the cluster size is 500 nodes and the value of this flag is 30, // then scheduler stops finding further feasible nodes once it finds 150 feasible ones. - // When the value is 0, default percentage (50%) of the nodes will be scored. + // When the value is 0, default percentage (5%--50% based on the size of the cluster) of the + // nodes will be scored. PercentageOfNodesToScore int32 `json:"percentageOfNodesToScore"` // DEPRECATED. diff --git a/staging/src/k8s.io/metrics/Godeps/Godeps.json b/staging/src/k8s.io/metrics/Godeps/Godeps.json index f47f06718cc..72a922fcc11 100644 --- a/staging/src/k8s.io/metrics/Godeps/Godeps.json +++ b/staging/src/k8s.io/metrics/Godeps/Godeps.json @@ -234,6 +234,10 @@ "ImportPath": "k8s.io/api/certificates/v1beta1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/api/coordination/v1", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/api/coordination/v1beta1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" diff --git a/staging/src/k8s.io/node-api/.github/PULL_REQUEST_TEMPLATE.md b/staging/src/k8s.io/node-api/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 00000000000..e559c074bb5 --- /dev/null +++ b/staging/src/k8s.io/node-api/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,2 @@ +Sorry, we do not accept changes directly against this repository. Please see +CONTRIBUTING.md for information on where and how to contribute instead. diff --git a/staging/src/k8s.io/node-api/CONTRIBUTING.md b/staging/src/k8s.io/node-api/CONTRIBUTING.md new file mode 100644 index 00000000000..37da989dcd6 --- /dev/null +++ b/staging/src/k8s.io/node-api/CONTRIBUTING.md @@ -0,0 +1,7 @@ +# Contributing guidelines + +Do not open pull requests directly against this repository, they will be ignored. Instead, please open pull requests against [kubernetes/kubernetes](https://git.k8s.io/kubernetes/). Please follow the same [contributing guide](https://git.k8s.io/kubernetes/CONTRIBUTING.md) you would follow for any other pull request made to kubernetes/kubernetes. + +This repository is published from [kubernetes/kubernetes/staging/src/k8s.io/node-api](https://git.k8s.io/kubernetes/staging/src/k8s.io/node-api) by the [kubernetes publishing-bot](https://git.k8s.io/publishing-bot). + +Please see [Staging Directory and Publishing](https://git.k8s.io/community/contributors/devel/staging.md) for more information. diff --git a/staging/src/k8s.io/node-api/Godeps/Godeps.json b/staging/src/k8s.io/node-api/Godeps/Godeps.json new file mode 100644 index 00000000000..79ab737ecc1 --- /dev/null +++ b/staging/src/k8s.io/node-api/Godeps/Godeps.json @@ -0,0 +1,566 @@ +{ + "ImportPath": "k8s.io/node-api", + "GoVersion": "go1.11", + "GodepVersion": "v80-k8s-r1", + "Packages": [ + "./..." + ], + "Deps": [ + { + "ImportPath": "github.com/davecgh/go-spew/spew", + "Rev": "782f4967f2dc4564575ca782fe2d04090b5faca8" + }, + { + "ImportPath": "github.com/evanphx/json-patch", + "Rev": "36442dbdb585210f8d5a1b45e67aa323c197d5c4" + }, + { + "ImportPath": "github.com/gogo/protobuf/proto", + "Rev": "342cbe0a04158f6dcb03ca0079991a51a4248c02" + }, + { + "ImportPath": "github.com/gogo/protobuf/sortkeys", + "Rev": "342cbe0a04158f6dcb03ca0079991a51a4248c02" + }, + { + "ImportPath": "github.com/golang/protobuf/proto", + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" + }, + { + "ImportPath": "github.com/golang/protobuf/ptypes", + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" + }, + { + "ImportPath": "github.com/golang/protobuf/ptypes/any", + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" + }, + { + "ImportPath": "github.com/golang/protobuf/ptypes/duration", + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" + }, + { + "ImportPath": "github.com/golang/protobuf/ptypes/timestamp", + "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" + }, + { + "ImportPath": "github.com/google/btree", + "Rev": "7d79101e329e5a3adf994758c578dab82b90c017" + }, + { + "ImportPath": "github.com/google/gofuzz", + "Rev": "44d81051d367757e1c7c6a5a86423ece9afcf63c" + }, + { + "ImportPath": "github.com/googleapis/gnostic/OpenAPIv2", + "Rev": "0c5108395e2debce0d731cf0287ddf7242066aba" + }, + { + "ImportPath": "github.com/googleapis/gnostic/compiler", + "Rev": "0c5108395e2debce0d731cf0287ddf7242066aba" + }, + { + "ImportPath": "github.com/googleapis/gnostic/extensions", + "Rev": "0c5108395e2debce0d731cf0287ddf7242066aba" + }, + { + "ImportPath": "github.com/gregjones/httpcache", + "Rev": "787624de3eb7bd915c329cba748687a3b22666a6" + }, + { + "ImportPath": "github.com/gregjones/httpcache/diskcache", + "Rev": "787624de3eb7bd915c329cba748687a3b22666a6" + }, + { + "ImportPath": "github.com/hashicorp/golang-lru", + "Rev": "a0d98a5f288019575c6d1f4bb1573fef2d1fcdc4" + }, + { + "ImportPath": "github.com/hashicorp/golang-lru/simplelru", + "Rev": "a0d98a5f288019575c6d1f4bb1573fef2d1fcdc4" + }, + { + "ImportPath": "github.com/json-iterator/go", + "Rev": "ab8a2e0c74be9d3be70b3184d9acc634935ded82" + }, + { + "ImportPath": "github.com/modern-go/concurrent", + "Rev": "bacd9c7ef1dd9b15be4a9909b8ac7a4e313eec94" + }, + { + "ImportPath": "github.com/modern-go/reflect2", + "Rev": "94122c33edd36123c84d5368cfb2b69df93a0ec8" + }, + { + "ImportPath": "github.com/peterbourgon/diskv", + "Rev": "5f041e8faa004a95c88a202771f4cc3e991971e6" + }, + { + "ImportPath": "golang.org/x/crypto/ssh/terminal", + "Rev": "de0752318171da717af4ce24d0a2e8626afaeb11" + }, + { + "ImportPath": "golang.org/x/net/context", + "Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" + }, + { + "ImportPath": "golang.org/x/net/http2", + "Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" + }, + { + "ImportPath": "golang.org/x/net/http2/hpack", + "Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" + }, + { + "ImportPath": "golang.org/x/net/idna", + "Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" + }, + { + "ImportPath": "golang.org/x/net/lex/httplex", + "Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" + }, + { + "ImportPath": "golang.org/x/oauth2", + "Rev": "a6bd8cefa1811bd24b86f8902872e4e8225f74c4" + }, + { + "ImportPath": "golang.org/x/oauth2/internal", + "Rev": "a6bd8cefa1811bd24b86f8902872e4e8225f74c4" + }, + { + "ImportPath": "golang.org/x/sys/unix", + "Rev": "95c6576299259db960f6c5b9b69ea52422860fce" + }, + { + "ImportPath": "golang.org/x/sys/windows", + "Rev": "95c6576299259db960f6c5b9b69ea52422860fce" + }, + { + "ImportPath": "golang.org/x/text/secure/bidirule", + "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01" + }, + { + "ImportPath": "golang.org/x/text/transform", + "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01" + }, + { + "ImportPath": "golang.org/x/text/unicode/bidi", + "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01" + }, + { + "ImportPath": "golang.org/x/text/unicode/norm", + "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01" + }, + { + "ImportPath": "golang.org/x/time/rate", + "Rev": "f51c12702a4d776e4c1fa9b0fabab841babae631" + }, + { + "ImportPath": "gopkg.in/inf.v0", + "Rev": "3887ee99ecf07df5b447e9b00d9c0b2adaa9f3e4" + }, + { + "ImportPath": "gopkg.in/yaml.v2", + "Rev": "5420a8b6744d3b0345ab293f6fcba19c978f1183" + }, + { + "ImportPath": "k8s.io/api/admissionregistration/v1alpha1", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/api/admissionregistration/v1beta1", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/api/apps/v1", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/api/apps/v1beta1", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/api/apps/v1beta2", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/api/auditregistration/v1alpha1", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/api/authentication/v1", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/api/authentication/v1beta1", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/api/authorization/v1", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/api/authorization/v1beta1", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/api/autoscaling/v1", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/api/autoscaling/v2beta1", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/api/autoscaling/v2beta2", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/api/batch/v1", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/api/batch/v1beta1", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/api/batch/v2alpha1", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/api/certificates/v1beta1", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/api/coordination/v1", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/api/coordination/v1beta1", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/api/core/v1", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/api/events/v1beta1", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/api/extensions/v1beta1", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/api/networking/v1", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/api/policy/v1beta1", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/api/rbac/v1", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/api/rbac/v1alpha1", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/api/rbac/v1beta1", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/api/scheduling/v1alpha1", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/api/scheduling/v1beta1", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/api/settings/v1alpha1", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/api/storage/v1", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/api/storage/v1alpha1", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/api/storage/v1beta1", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/apimachinery/pkg/api/errors", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/apimachinery/pkg/api/meta", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/apimachinery/pkg/api/resource", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/apimachinery/pkg/apis/meta/internalversion", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/apimachinery/pkg/apis/meta/v1", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/apimachinery/pkg/apis/meta/v1beta1", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/apimachinery/pkg/conversion", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/apimachinery/pkg/conversion/queryparams", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/apimachinery/pkg/fields", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/apimachinery/pkg/labels", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/apimachinery/pkg/runtime", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/apimachinery/pkg/runtime/schema", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/json", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/protobuf", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/recognizer", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/streaming", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/versioning", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/apimachinery/pkg/selection", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/apimachinery/pkg/types", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/apimachinery/pkg/util/cache", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/apimachinery/pkg/util/clock", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/apimachinery/pkg/util/diff", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/apimachinery/pkg/util/errors", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/apimachinery/pkg/util/framer", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/apimachinery/pkg/util/intstr", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/apimachinery/pkg/util/json", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/apimachinery/pkg/util/mergepatch", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/apimachinery/pkg/util/naming", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/apimachinery/pkg/util/net", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/apimachinery/pkg/util/runtime", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/apimachinery/pkg/util/sets", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/apimachinery/pkg/util/strategicpatch", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/apimachinery/pkg/util/validation", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/apimachinery/pkg/util/validation/field", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/apimachinery/pkg/util/wait", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/apimachinery/pkg/util/yaml", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/apimachinery/pkg/version", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/apimachinery/pkg/watch", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/apimachinery/third_party/forked/golang/json", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/apimachinery/third_party/forked/golang/reflect", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/client-go/discovery", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/client-go/discovery/fake", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/client-go/kubernetes/scheme", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/client-go/pkg/apis/clientauthentication", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/client-go/pkg/apis/clientauthentication/v1alpha1", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/client-go/pkg/apis/clientauthentication/v1beta1", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/client-go/pkg/version", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/client-go/plugin/pkg/client/auth/exec", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/client-go/rest", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/client-go/rest/watch", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/client-go/testing", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/client-go/tools/cache", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/client-go/tools/clientcmd/api", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/client-go/tools/metrics", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/client-go/tools/pager", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/client-go/transport", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/client-go/util/buffer", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/client-go/util/cert", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/client-go/util/connrotation", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/client-go/util/flowcontrol", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/client-go/util/integer", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/client-go/util/retry", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/klog", + "Rev": "8139d8cb77af419532b33dfa7dd09fbc5f1d344f" + }, + { + "ImportPath": "k8s.io/kube-openapi/pkg/util/proto", + "Rev": "c59034cc13d587f5ef4e85ca0ade0c1866ae8e1d" + }, + { + "ImportPath": "sigs.k8s.io/yaml", + "Rev": "fd68e9863619f6ec2fdd8625fe1f02e7c877e480" + } + ] +} diff --git a/staging/src/k8s.io/node-api/Godeps/OWNERS b/staging/src/k8s.io/node-api/Godeps/OWNERS new file mode 100644 index 00000000000..3d49f30605a --- /dev/null +++ b/staging/src/k8s.io/node-api/Godeps/OWNERS @@ -0,0 +1,2 @@ +approvers: +- dep-approvers diff --git a/staging/src/k8s.io/node-api/LICENSE b/staging/src/k8s.io/node-api/LICENSE new file mode 100644 index 00000000000..8dada3edaf5 --- /dev/null +++ b/staging/src/k8s.io/node-api/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/staging/src/k8s.io/node-api/OWNERS b/staging/src/k8s.io/node-api/OWNERS new file mode 100644 index 00000000000..03759e15dc5 --- /dev/null +++ b/staging/src/k8s.io/node-api/OWNERS @@ -0,0 +1,4 @@ +approvers: + - tallclair + - dchen1107 + - derekwaynecarr diff --git a/staging/src/k8s.io/node-api/README.md b/staging/src/k8s.io/node-api/README.md new file mode 100644 index 00000000000..b5b251fe980 --- /dev/null +++ b/staging/src/k8s.io/node-api/README.md @@ -0,0 +1,29 @@ +## Purpose + +This repository contains type definitions and client code for the Kubernetes +APIs in the node.k8s.io API group. These APIs are primarily used by the Kubelet +for managing node operations, such as container runtime support. + +Consumers of the node APIs can make use of this repository to access +implementations of the APIs. + +## Community, discussion, contribution, and support + +Learn how to engage with the Kubernetes community on the [community +page](http://kubernetes.io/community/). + +You can reach the maintainers of this repository at: + +- Slack: #sig-node (on https://kubernetes.slack.com -- get an + invite at slack.kubernetes.io) +- Mailing List: + https://groups.google.com/forum/#!forum/kubernetes-sig-node + +### Code of Conduct + +Participation in the Kubernetes community is governed by the [Kubernetes +Code of Conduct](code-of-conduct.md). + +### Contibution Guidelines + +See [CONTRIBUTING.md](CONTRIBUTING.md) for more information. diff --git a/staging/src/k8s.io/node-api/SECURITY_CONTACTS b/staging/src/k8s.io/node-api/SECURITY_CONTACTS new file mode 100644 index 00000000000..19f6a5a18ab --- /dev/null +++ b/staging/src/k8s.io/node-api/SECURITY_CONTACTS @@ -0,0 +1,13 @@ +# Defined below are the security contacts for this repo. +# +# They are the contact point for the Product Security Team to reach out +# to for triaging and handling of incoming issues. +# +# The below names agree to abide by the +# [Embargo Policy](https://github.com/kubernetes/sig-release/blob/master/security-release-process-documentation/security-release-process.md#embargo-policy) +# and will be removed and replaced if they violate that agreement. +# +# DO NOT REPORT SECURITY VULNERABILITIES DIRECTLY TO THESE NAMES, FOLLOW THE +# INSTRUCTIONS AT https://kubernetes.io/security/ + +tallclair diff --git a/staging/src/k8s.io/node-api/code-of-conduct.md b/staging/src/k8s.io/node-api/code-of-conduct.md new file mode 100644 index 00000000000..0d15c00cf32 --- /dev/null +++ b/staging/src/k8s.io/node-api/code-of-conduct.md @@ -0,0 +1,3 @@ +# Kubernetes Community Code of Conduct + +Please refer to our [Kubernetes Community Code of Conduct](https://git.k8s.io/community/code-of-conduct.md) diff --git a/staging/src/k8s.io/node-api/hack/boilerplate.go.txt b/staging/src/k8s.io/node-api/hack/boilerplate.go.txt new file mode 100644 index 00000000000..b7c650da470 --- /dev/null +++ b/staging/src/k8s.io/node-api/hack/boilerplate.go.txt @@ -0,0 +1,16 @@ +/* +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. +*/ + diff --git a/staging/src/k8s.io/node-api/hack/update-codegen.sh b/staging/src/k8s.io/node-api/hack/update-codegen.sh new file mode 100755 index 00000000000..c92b3cc9f68 --- /dev/null +++ b/staging/src/k8s.io/node-api/hack/update-codegen.sh @@ -0,0 +1,32 @@ +#!/usr/bin/env bash + +# Copyright 2018 The Kubernetes Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -o errexit +set -o nounset +set -o pipefail + +SCRIPT_ROOT=$(dirname ${BASH_SOURCE})/.. +CODEGEN_PKG=${CODEGEN_PKG:-$(cd ${SCRIPT_ROOT}; ls -d -1 ./vendor/k8s.io/code-generator 2>/dev/null || echo ../code-generator)} + +# generate the code with: +# --output-base because this script should also be able to run inside the vendor dir of +# k8s.io/kubernetes. The output-base is needed for the generators to output into the vendor dir +# instead of the $GOPATH directly. For normal projects this can be dropped. +${CODEGEN_PKG}/generate-groups.sh "deepcopy,client,informer,lister" \ + k8s.io/node-api/pkg/client k8s.io/node-api/pkg/apis \ + "node:v1alpha1" \ + --output-base "$(dirname ${BASH_SOURCE})/../../.." \ + --go-header-file ${SCRIPT_ROOT}/hack/boilerplate.go.txt diff --git a/staging/src/k8s.io/node-api/hack/verify-codegen.sh b/staging/src/k8s.io/node-api/hack/verify-codegen.sh new file mode 100755 index 00000000000..d02a6fa395e --- /dev/null +++ b/staging/src/k8s.io/node-api/hack/verify-codegen.sh @@ -0,0 +1,48 @@ +#!/usr/bin/env bash + +# 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. + +set -o errexit +set -o nounset +set -o pipefail + +SCRIPT_ROOT=$(dirname "${BASH_SOURCE}")/.. + +DIFFROOT="${SCRIPT_ROOT}/pkg" +TMP_DIFFROOT="${SCRIPT_ROOT}/_tmp/pkg" +_tmp="${SCRIPT_ROOT}/_tmp" + +cleanup() { + rm -rf "${_tmp}" +} +trap "cleanup" EXIT SIGINT + +cleanup + +mkdir -p "${TMP_DIFFROOT}" +cp -a "${DIFFROOT}"/* "${TMP_DIFFROOT}" + +"${SCRIPT_ROOT}/hack/update-codegen.sh" +echo "diffing ${DIFFROOT} against freshly generated codegen" +ret=0 +diff -Naupr "${DIFFROOT}" "${TMP_DIFFROOT}" || ret=$? +cp -a "${TMP_DIFFROOT}"/* "${DIFFROOT}" +if [[ $ret -eq 0 ]] +then + echo "${DIFFROOT} up to date." +else + echo "${DIFFROOT} is out of date. Please run hack/update-codegen.sh" + exit 1 +fi diff --git a/staging/src/k8s.io/node-api/pkg/apis/OWNERS b/staging/src/k8s.io/node-api/pkg/apis/OWNERS new file mode 100644 index 00000000000..bae178f8175 --- /dev/null +++ b/staging/src/k8s.io/node-api/pkg/apis/OWNERS @@ -0,0 +1,9 @@ +# Disable inheritance as this is an api owners file +options: + no_parent_owners: true +approvers: +- api-approvers +reviewers: +- api-reviewers +labels: +- kind/api-change diff --git a/staging/src/k8s.io/node-api/pkg/apis/node/v1alpha1/BUILD b/staging/src/k8s.io/node-api/pkg/apis/node/v1alpha1/BUILD new file mode 100644 index 00000000000..af66cb26e08 --- /dev/null +++ b/staging/src/k8s.io/node-api/pkg/apis/node/v1alpha1/BUILD @@ -0,0 +1,33 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = [ + "doc.go", + "register.go", + "types.go", + "zz_generated.deepcopy.go", + ], + importmap = "k8s.io/kubernetes/vendor/k8s.io/node-api/pkg/apis/node/v1alpha1", + importpath = "k8s.io/node-api/pkg/apis/node/v1alpha1", + visibility = ["//visibility:public"], + deps = [ + "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + "//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library", + "//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/staging/src/k8s.io/node-api/pkg/apis/node/v1alpha1/doc.go b/staging/src/k8s.io/node-api/pkg/apis/node/v1alpha1/doc.go new file mode 100644 index 00000000000..30145d5bb88 --- /dev/null +++ b/staging/src/k8s.io/node-api/pkg/apis/node/v1alpha1/doc.go @@ -0,0 +1,21 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// +k8s:deepcopy-gen=package +// +k8s:openapi-gen=true + +// +groupName=node.k8s.io +package v1alpha1 // import "k8s.io/node-api/pkg/apis/node/v1alpha1" diff --git a/staging/src/k8s.io/node-api/pkg/apis/node/v1alpha1/register.go b/staging/src/k8s.io/node-api/pkg/apis/node/v1alpha1/register.go new file mode 100644 index 00000000000..6f74ffed6e0 --- /dev/null +++ b/staging/src/k8s.io/node-api/pkg/apis/node/v1alpha1/register.go @@ -0,0 +1,50 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1alpha1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" +) + +// GroupName is the group name use in this package +const GroupName = "node.k8s.io" + +// SchemeGroupVersion is group version used to register these objects +var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1alpha1"} + +// Resource takes an unqualified resource and returns a Group qualified GroupResource +func Resource(resource string) schema.GroupResource { + return SchemeGroupVersion.WithResource(resource).GroupResource() +} + +var ( + SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes) + AddToScheme = SchemeBuilder.AddToScheme +) + +// Adds the list of known types to api.Scheme. +func addKnownTypes(scheme *runtime.Scheme) error { + scheme.AddKnownTypes(SchemeGroupVersion, + &RuntimeClass{}, + &RuntimeClassList{}, + ) + + metav1.AddToGroupVersion(scheme, SchemeGroupVersion) + return nil +} diff --git a/staging/src/k8s.io/node-api/pkg/apis/node/v1alpha1/types.go b/staging/src/k8s.io/node-api/pkg/apis/node/v1alpha1/types.go new file mode 100644 index 00000000000..1951321da26 --- /dev/null +++ b/staging/src/k8s.io/node-api/pkg/apis/node/v1alpha1/types.go @@ -0,0 +1,76 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1alpha1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// +genclient +// +genclient:nonNamespaced +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// RuntimeClass defines a class of container runtime supported in the cluster. +// The RuntimeClass is used to select or configure the container runtime that is +// used to run all containers in a pod. RuntimeClasses are (currently) manually +// defined by a user or cluster provisioner, and referenced in the PodSpec. The +// Kubelet is responsible for resolving the RuntimeClassName reference before +// running the pod. For more details, see +// https://git.k8s.io/enhancements/keps/sig-node/0014-runtime-class.md +type RuntimeClass struct { + metav1.TypeMeta `json:",inline"` + // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata + // +optional + metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` + + // Specification of the RuntimeClass + // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status + Spec RuntimeClassSpec `json:"spec" protobuf:"bytes,2,name=spec"` +} + +// RuntimeClassSpec is a specification of a RuntimeClass. It contains parameters +// that required to describe the RuntimeClass to the Container Runtime Interface +// (CRI) implementation, as well as any other components that need to understand +// how the pod will be run. The RuntimeClassSpec should be treated as immutable. +type RuntimeClassSpec struct { + // RuntimeHandler specifies the underlying runtime and configuration that the + // CRI implementation will use to handle pods of this class. The possible + // values are specific to the node configuration & CRI implementation. It is + // assumed that all handlers are available on every node, and handlers of the + // same name are equivalent on every node. + // For example, a handler called "runc" might specify that the runc OCI + // runtime (using native Linux containers) should be used to run the + // containers in a pod. + // If this is not specified (or empty), a default will be chosen by the + // implementation. + // +optional + RuntimeHandler *string `json:"runtimeHandler,omitempty" protobuf:"bytes,1,opt,name=runtimeHandler"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// RuntimeClassList is a list of RuntimeClass objects. +type RuntimeClassList struct { + metav1.TypeMeta `json:",inline"` + // Standard list metadata. + // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata + // +optional + metav1.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` + + // Items is a list of schema objects. + Items []RuntimeClass `json:"items" protobuf:"bytes,2,rep,name=items"` +} diff --git a/staging/src/k8s.io/node-api/pkg/apis/node/v1alpha1/zz_generated.deepcopy.go b/staging/src/k8s.io/node-api/pkg/apis/node/v1alpha1/zz_generated.deepcopy.go new file mode 100644 index 00000000000..4c6ff7e5d50 --- /dev/null +++ b/staging/src/k8s.io/node-api/pkg/apis/node/v1alpha1/zz_generated.deepcopy.go @@ -0,0 +1,106 @@ +// +build !ignore_autogenerated + +/* +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 deepcopy-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + runtime "k8s.io/apimachinery/pkg/runtime" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RuntimeClass) DeepCopyInto(out *RuntimeClass) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RuntimeClass. +func (in *RuntimeClass) DeepCopy() *RuntimeClass { + if in == nil { + return nil + } + out := new(RuntimeClass) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *RuntimeClass) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RuntimeClassList) DeepCopyInto(out *RuntimeClassList) { + *out = *in + out.TypeMeta = in.TypeMeta + out.ListMeta = in.ListMeta + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]RuntimeClass, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RuntimeClassList. +func (in *RuntimeClassList) DeepCopy() *RuntimeClassList { + if in == nil { + return nil + } + out := new(RuntimeClassList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *RuntimeClassList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RuntimeClassSpec) DeepCopyInto(out *RuntimeClassSpec) { + *out = *in + if in.RuntimeHandler != nil { + in, out := &in.RuntimeHandler, &out.RuntimeHandler + *out = new(string) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RuntimeClassSpec. +func (in *RuntimeClassSpec) DeepCopy() *RuntimeClassSpec { + if in == nil { + return nil + } + out := new(RuntimeClassSpec) + in.DeepCopyInto(out) + return out +} diff --git a/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/BUILD b/staging/src/k8s.io/node-api/pkg/client/clientset/versioned/BUILD similarity index 53% rename from staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/BUILD rename to staging/src/k8s.io/node-api/pkg/client/clientset/versioned/BUILD index 86b1b0e4dd1..88e404f45b7 100644 --- a/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/BUILD +++ b/staging/src/k8s.io/node-api/pkg/client/clientset/versioned/BUILD @@ -6,14 +6,14 @@ go_library( "clientset.go", "doc.go", ], - importmap = "k8s.io/kubernetes/vendor/k8s.io/sample-apiserver/pkg/client/clientset/internalversion", - importpath = "k8s.io/sample-apiserver/pkg/client/clientset/internalversion", + importmap = "k8s.io/kubernetes/vendor/k8s.io/node-api/pkg/client/clientset/versioned", + importpath = "k8s.io/node-api/pkg/client/clientset/versioned", visibility = ["//visibility:public"], deps = [ "//staging/src/k8s.io/client-go/discovery:go_default_library", "//staging/src/k8s.io/client-go/rest:go_default_library", "//staging/src/k8s.io/client-go/util/flowcontrol:go_default_library", - "//staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/typed/wardle/internalversion:go_default_library", + "//staging/src/k8s.io/node-api/pkg/client/clientset/versioned/typed/node/v1alpha1:go_default_library", ], ) @@ -28,9 +28,9 @@ filegroup( name = "all-srcs", srcs = [ ":package-srcs", - "//staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/fake:all-srcs", - "//staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/scheme:all-srcs", - "//staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/typed/wardle/internalversion:all-srcs", + "//staging/src/k8s.io/node-api/pkg/client/clientset/versioned/fake:all-srcs", + "//staging/src/k8s.io/node-api/pkg/client/clientset/versioned/scheme:all-srcs", + "//staging/src/k8s.io/node-api/pkg/client/clientset/versioned/typed/node/v1alpha1:all-srcs", ], tags = ["automanaged"], visibility = ["//visibility:public"], diff --git a/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/clientset.go b/staging/src/k8s.io/node-api/pkg/client/clientset/versioned/clientset.go similarity index 72% rename from staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/clientset.go rename to staging/src/k8s.io/node-api/pkg/client/clientset/versioned/clientset.go index b0a9bd43d81..dac1ab38bfb 100644 --- a/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/clientset.go +++ b/staging/src/k8s.io/node-api/pkg/client/clientset/versioned/clientset.go @@ -16,30 +16,38 @@ limitations under the License. // Code generated by client-gen. DO NOT EDIT. -package internalversion +package versioned import ( discovery "k8s.io/client-go/discovery" rest "k8s.io/client-go/rest" flowcontrol "k8s.io/client-go/util/flowcontrol" - wardleinternalversion "k8s.io/sample-apiserver/pkg/client/clientset/internalversion/typed/wardle/internalversion" + nodev1alpha1 "k8s.io/node-api/pkg/client/clientset/versioned/typed/node/v1alpha1" ) type Interface interface { Discovery() discovery.DiscoveryInterface - Wardle() wardleinternalversion.WardleInterface + NodeV1alpha1() nodev1alpha1.NodeV1alpha1Interface + // Deprecated: please explicitly pick a version if possible. + Node() nodev1alpha1.NodeV1alpha1Interface } // Clientset contains the clients for groups. Each group has exactly one // version included in a Clientset. type Clientset struct { *discovery.DiscoveryClient - wardle *wardleinternalversion.WardleClient + nodeV1alpha1 *nodev1alpha1.NodeV1alpha1Client } -// Wardle retrieves the WardleClient -func (c *Clientset) Wardle() wardleinternalversion.WardleInterface { - return c.wardle +// NodeV1alpha1 retrieves the NodeV1alpha1Client +func (c *Clientset) NodeV1alpha1() nodev1alpha1.NodeV1alpha1Interface { + return c.nodeV1alpha1 +} + +// Deprecated: Node retrieves the default version of NodeClient. +// Please explicitly pick a version. +func (c *Clientset) Node() nodev1alpha1.NodeV1alpha1Interface { + return c.nodeV1alpha1 } // Discovery retrieves the DiscoveryClient @@ -58,7 +66,7 @@ func NewForConfig(c *rest.Config) (*Clientset, error) { } var cs Clientset var err error - cs.wardle, err = wardleinternalversion.NewForConfig(&configShallowCopy) + cs.nodeV1alpha1, err = nodev1alpha1.NewForConfig(&configShallowCopy) if err != nil { return nil, err } @@ -74,7 +82,7 @@ func NewForConfig(c *rest.Config) (*Clientset, error) { // panics if there is an error in the config. func NewForConfigOrDie(c *rest.Config) *Clientset { var cs Clientset - cs.wardle = wardleinternalversion.NewForConfigOrDie(c) + cs.nodeV1alpha1 = nodev1alpha1.NewForConfigOrDie(c) cs.DiscoveryClient = discovery.NewDiscoveryClientForConfigOrDie(c) return &cs @@ -83,7 +91,7 @@ func NewForConfigOrDie(c *rest.Config) *Clientset { // New creates a new Clientset for the given RESTClient. func New(c rest.Interface) *Clientset { var cs Clientset - cs.wardle = wardleinternalversion.New(c) + cs.nodeV1alpha1 = nodev1alpha1.New(c) cs.DiscoveryClient = discovery.NewDiscoveryClient(c) return &cs diff --git a/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/doc.go b/staging/src/k8s.io/node-api/pkg/client/clientset/versioned/doc.go similarity index 96% rename from staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/doc.go rename to staging/src/k8s.io/node-api/pkg/client/clientset/versioned/doc.go index 6c970b092aa..41721ca52d4 100644 --- a/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/doc.go +++ b/staging/src/k8s.io/node-api/pkg/client/clientset/versioned/doc.go @@ -17,4 +17,4 @@ limitations under the License. // Code generated by client-gen. DO NOT EDIT. // This package has the automatically generated clientset. -package internalversion +package versioned diff --git a/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/fake/BUILD b/staging/src/k8s.io/node-api/pkg/client/clientset/versioned/fake/BUILD similarity index 65% rename from staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/fake/BUILD rename to staging/src/k8s.io/node-api/pkg/client/clientset/versioned/fake/BUILD index f9de0c31c64..ca52e9b4125 100644 --- a/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/fake/BUILD +++ b/staging/src/k8s.io/node-api/pkg/client/clientset/versioned/fake/BUILD @@ -7,8 +7,8 @@ go_library( "doc.go", "register.go", ], - importmap = "k8s.io/kubernetes/vendor/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/fake", - importpath = "k8s.io/sample-apiserver/pkg/client/clientset/internalversion/fake", + importmap = "k8s.io/kubernetes/vendor/k8s.io/node-api/pkg/client/clientset/versioned/fake", + importpath = "k8s.io/node-api/pkg/client/clientset/versioned/fake", visibility = ["//visibility:public"], deps = [ "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", @@ -20,10 +20,10 @@ go_library( "//staging/src/k8s.io/client-go/discovery:go_default_library", "//staging/src/k8s.io/client-go/discovery/fake:go_default_library", "//staging/src/k8s.io/client-go/testing:go_default_library", - "//staging/src/k8s.io/sample-apiserver/pkg/apis/wardle:go_default_library", - "//staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion:go_default_library", - "//staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/typed/wardle/internalversion:go_default_library", - "//staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/typed/wardle/internalversion/fake:go_default_library", + "//staging/src/k8s.io/node-api/pkg/apis/node/v1alpha1:go_default_library", + "//staging/src/k8s.io/node-api/pkg/client/clientset/versioned:go_default_library", + "//staging/src/k8s.io/node-api/pkg/client/clientset/versioned/typed/node/v1alpha1:go_default_library", + "//staging/src/k8s.io/node-api/pkg/client/clientset/versioned/typed/node/v1alpha1/fake:go_default_library", ], ) diff --git a/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/fake/clientset_generated.go b/staging/src/k8s.io/node-api/pkg/client/clientset/versioned/fake/clientset_generated.go similarity index 79% rename from staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/fake/clientset_generated.go rename to staging/src/k8s.io/node-api/pkg/client/clientset/versioned/fake/clientset_generated.go index 79c8eeb4612..1126d72d94e 100644 --- a/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/fake/clientset_generated.go +++ b/staging/src/k8s.io/node-api/pkg/client/clientset/versioned/fake/clientset_generated.go @@ -24,9 +24,9 @@ import ( "k8s.io/client-go/discovery" fakediscovery "k8s.io/client-go/discovery/fake" "k8s.io/client-go/testing" - clientset "k8s.io/sample-apiserver/pkg/client/clientset/internalversion" - wardleinternalversion "k8s.io/sample-apiserver/pkg/client/clientset/internalversion/typed/wardle/internalversion" - fakewardleinternalversion "k8s.io/sample-apiserver/pkg/client/clientset/internalversion/typed/wardle/internalversion/fake" + clientset "k8s.io/node-api/pkg/client/clientset/versioned" + nodev1alpha1 "k8s.io/node-api/pkg/client/clientset/versioned/typed/node/v1alpha1" + fakenodev1alpha1 "k8s.io/node-api/pkg/client/clientset/versioned/typed/node/v1alpha1/fake" ) // NewSimpleClientset returns a clientset that will respond with the provided objects. @@ -71,7 +71,12 @@ func (c *Clientset) Discovery() discovery.DiscoveryInterface { var _ clientset.Interface = &Clientset{} -// Wardle retrieves the WardleClient -func (c *Clientset) Wardle() wardleinternalversion.WardleInterface { - return &fakewardleinternalversion.FakeWardle{Fake: &c.Fake} +// NodeV1alpha1 retrieves the NodeV1alpha1Client +func (c *Clientset) NodeV1alpha1() nodev1alpha1.NodeV1alpha1Interface { + return &fakenodev1alpha1.FakeNodeV1alpha1{Fake: &c.Fake} +} + +// Node retrieves the NodeV1alpha1Client +func (c *Clientset) Node() nodev1alpha1.NodeV1alpha1Interface { + return &fakenodev1alpha1.FakeNodeV1alpha1{Fake: &c.Fake} } diff --git a/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/fake/doc.go b/staging/src/k8s.io/node-api/pkg/client/clientset/versioned/fake/doc.go similarity index 100% rename from staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/fake/doc.go rename to staging/src/k8s.io/node-api/pkg/client/clientset/versioned/fake/doc.go diff --git a/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/fake/register.go b/staging/src/k8s.io/node-api/pkg/client/clientset/versioned/fake/register.go similarity index 94% rename from staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/fake/register.go rename to staging/src/k8s.io/node-api/pkg/client/clientset/versioned/fake/register.go index f617753ac3e..b1a3a013aab 100644 --- a/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/fake/register.go +++ b/staging/src/k8s.io/node-api/pkg/client/clientset/versioned/fake/register.go @@ -24,14 +24,14 @@ import ( schema "k8s.io/apimachinery/pkg/runtime/schema" serializer "k8s.io/apimachinery/pkg/runtime/serializer" utilruntime "k8s.io/apimachinery/pkg/util/runtime" - wardleinternalversion "k8s.io/sample-apiserver/pkg/apis/wardle" + nodev1alpha1 "k8s.io/node-api/pkg/apis/node/v1alpha1" ) var scheme = runtime.NewScheme() var codecs = serializer.NewCodecFactory(scheme) var parameterCodec = runtime.NewParameterCodec(scheme) var localSchemeBuilder = runtime.SchemeBuilder{ - wardleinternalversion.AddToScheme, + nodev1alpha1.AddToScheme, } // AddToScheme adds all types of this clientset into the given scheme. This allows composition diff --git a/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/scheme/BUILD b/staging/src/k8s.io/node-api/pkg/client/clientset/versioned/scheme/BUILD similarity index 71% rename from staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/scheme/BUILD rename to staging/src/k8s.io/node-api/pkg/client/clientset/versioned/scheme/BUILD index fb08c925277..0e630b6f395 100644 --- a/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/scheme/BUILD +++ b/staging/src/k8s.io/node-api/pkg/client/clientset/versioned/scheme/BUILD @@ -6,15 +6,16 @@ go_library( "doc.go", "register.go", ], - importmap = "k8s.io/kubernetes/vendor/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/scheme", - importpath = "k8s.io/sample-apiserver/pkg/client/clientset/internalversion/scheme", + importmap = "k8s.io/kubernetes/vendor/k8s.io/node-api/pkg/client/clientset/versioned/scheme", + importpath = "k8s.io/node-api/pkg/client/clientset/versioned/scheme", visibility = ["//visibility:public"], deps = [ "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library", - "//staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/install:go_default_library", + "//staging/src/k8s.io/apimachinery/pkg/util/runtime:go_default_library", + "//staging/src/k8s.io/node-api/pkg/apis/node/v1alpha1:go_default_library", ], ) diff --git a/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/scheme/doc.go b/staging/src/k8s.io/node-api/pkg/client/clientset/versioned/scheme/doc.go similarity index 100% rename from staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/scheme/doc.go rename to staging/src/k8s.io/node-api/pkg/client/clientset/versioned/scheme/doc.go diff --git a/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/scheme/register.go b/staging/src/k8s.io/node-api/pkg/client/clientset/versioned/scheme/register.go similarity index 55% rename from staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/scheme/register.go rename to staging/src/k8s.io/node-api/pkg/client/clientset/versioned/scheme/register.go index 7a519381928..3cea7048601 100644 --- a/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/scheme/register.go +++ b/staging/src/k8s.io/node-api/pkg/client/clientset/versioned/scheme/register.go @@ -23,19 +23,34 @@ import ( runtime "k8s.io/apimachinery/pkg/runtime" schema "k8s.io/apimachinery/pkg/runtime/schema" serializer "k8s.io/apimachinery/pkg/runtime/serializer" - wardle "k8s.io/sample-apiserver/pkg/apis/wardle/install" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" + nodev1alpha1 "k8s.io/node-api/pkg/apis/node/v1alpha1" ) var Scheme = runtime.NewScheme() var Codecs = serializer.NewCodecFactory(Scheme) var ParameterCodec = runtime.NewParameterCodec(Scheme) +var localSchemeBuilder = runtime.SchemeBuilder{ + nodev1alpha1.AddToScheme, +} + +// AddToScheme adds all types of this clientset into the given scheme. This allows composition +// of clientsets, like in: +// +// import ( +// "k8s.io/client-go/kubernetes" +// clientsetscheme "k8s.io/client-go/kubernetes/scheme" +// aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme" +// ) +// +// kclientset, _ := kubernetes.NewForConfig(c) +// _ = aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme) +// +// After this, RawExtensions in Kubernetes types will serialize kube-aggregator types +// correctly. +var AddToScheme = localSchemeBuilder.AddToScheme func init() { v1.AddToGroupVersion(Scheme, schema.GroupVersion{Version: "v1"}) - Install(Scheme) -} - -// Install registers the API group and adds types to a scheme -func Install(scheme *runtime.Scheme) { - wardle.Install(scheme) + utilruntime.Must(AddToScheme(Scheme)) } diff --git a/staging/src/k8s.io/node-api/pkg/client/clientset/versioned/typed/node/v1alpha1/BUILD b/staging/src/k8s.io/node-api/pkg/client/clientset/versioned/typed/node/v1alpha1/BUILD new file mode 100644 index 00000000000..cf31c44f448 --- /dev/null +++ b/staging/src/k8s.io/node-api/pkg/client/clientset/versioned/typed/node/v1alpha1/BUILD @@ -0,0 +1,40 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = [ + "doc.go", + "generated_expansion.go", + "node_client.go", + "runtimeclass.go", + ], + importmap = "k8s.io/kubernetes/vendor/k8s.io/node-api/pkg/client/clientset/versioned/typed/node/v1alpha1", + importpath = "k8s.io/node-api/pkg/client/clientset/versioned/typed/node/v1alpha1", + visibility = ["//visibility:public"], + deps = [ + "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + "//staging/src/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library", + "//staging/src/k8s.io/apimachinery/pkg/types:go_default_library", + "//staging/src/k8s.io/apimachinery/pkg/watch:go_default_library", + "//staging/src/k8s.io/client-go/rest:go_default_library", + "//staging/src/k8s.io/node-api/pkg/apis/node/v1alpha1:go_default_library", + "//staging/src/k8s.io/node-api/pkg/client/clientset/versioned/scheme:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [ + ":package-srcs", + "//staging/src/k8s.io/node-api/pkg/client/clientset/versioned/typed/node/v1alpha1/fake:all-srcs", + ], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/staging/src/k8s.io/node-api/pkg/client/clientset/versioned/typed/node/v1alpha1/doc.go b/staging/src/k8s.io/node-api/pkg/client/clientset/versioned/typed/node/v1alpha1/doc.go new file mode 100644 index 00000000000..df51baa4d4c --- /dev/null +++ b/staging/src/k8s.io/node-api/pkg/client/clientset/versioned/typed/node/v1alpha1/doc.go @@ -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 v1alpha1 diff --git a/staging/src/k8s.io/node-api/pkg/client/clientset/versioned/typed/node/v1alpha1/fake/BUILD b/staging/src/k8s.io/node-api/pkg/client/clientset/versioned/typed/node/v1alpha1/fake/BUILD new file mode 100644 index 00000000000..ac9194d8012 --- /dev/null +++ b/staging/src/k8s.io/node-api/pkg/client/clientset/versioned/typed/node/v1alpha1/fake/BUILD @@ -0,0 +1,38 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = [ + "doc.go", + "fake_node_client.go", + "fake_runtimeclass.go", + ], + importmap = "k8s.io/kubernetes/vendor/k8s.io/node-api/pkg/client/clientset/versioned/typed/node/v1alpha1/fake", + importpath = "k8s.io/node-api/pkg/client/clientset/versioned/typed/node/v1alpha1/fake", + visibility = ["//visibility:public"], + deps = [ + "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + "//staging/src/k8s.io/apimachinery/pkg/labels:go_default_library", + "//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", + "//staging/src/k8s.io/apimachinery/pkg/types:go_default_library", + "//staging/src/k8s.io/apimachinery/pkg/watch:go_default_library", + "//staging/src/k8s.io/client-go/rest:go_default_library", + "//staging/src/k8s.io/client-go/testing:go_default_library", + "//staging/src/k8s.io/node-api/pkg/apis/node/v1alpha1:go_default_library", + "//staging/src/k8s.io/node-api/pkg/client/clientset/versioned/typed/node/v1alpha1:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/staging/src/k8s.io/node-api/pkg/client/clientset/versioned/typed/node/v1alpha1/fake/doc.go b/staging/src/k8s.io/node-api/pkg/client/clientset/versioned/typed/node/v1alpha1/fake/doc.go new file mode 100644 index 00000000000..16f44399065 --- /dev/null +++ b/staging/src/k8s.io/node-api/pkg/client/clientset/versioned/typed/node/v1alpha1/fake/doc.go @@ -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 diff --git a/staging/src/k8s.io/node-api/pkg/client/clientset/versioned/typed/node/v1alpha1/fake/fake_node_client.go b/staging/src/k8s.io/node-api/pkg/client/clientset/versioned/typed/node/v1alpha1/fake/fake_node_client.go new file mode 100644 index 00000000000..e8fa76b8948 --- /dev/null +++ b/staging/src/k8s.io/node-api/pkg/client/clientset/versioned/typed/node/v1alpha1/fake/fake_node_client.go @@ -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 ( + rest "k8s.io/client-go/rest" + testing "k8s.io/client-go/testing" + v1alpha1 "k8s.io/node-api/pkg/client/clientset/versioned/typed/node/v1alpha1" +) + +type FakeNodeV1alpha1 struct { + *testing.Fake +} + +func (c *FakeNodeV1alpha1) RuntimeClasses() v1alpha1.RuntimeClassInterface { + return &FakeRuntimeClasses{c} +} + +// RESTClient returns a RESTClient that is used to communicate +// with API server by this client implementation. +func (c *FakeNodeV1alpha1) RESTClient() rest.Interface { + var ret *rest.RESTClient + return ret +} diff --git a/staging/src/k8s.io/node-api/pkg/client/clientset/versioned/typed/node/v1alpha1/fake/fake_runtimeclass.go b/staging/src/k8s.io/node-api/pkg/client/clientset/versioned/typed/node/v1alpha1/fake/fake_runtimeclass.go new file mode 100644 index 00000000000..c034a1e29a9 --- /dev/null +++ b/staging/src/k8s.io/node-api/pkg/client/clientset/versioned/typed/node/v1alpha1/fake/fake_runtimeclass.go @@ -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 ( + 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" + v1alpha1 "k8s.io/node-api/pkg/apis/node/v1alpha1" +) + +// FakeRuntimeClasses implements RuntimeClassInterface +type FakeRuntimeClasses struct { + Fake *FakeNodeV1alpha1 +} + +var runtimeclassesResource = schema.GroupVersionResource{Group: "node.k8s.io", Version: "v1alpha1", Resource: "runtimeclasses"} + +var runtimeclassesKind = schema.GroupVersionKind{Group: "node.k8s.io", Version: "v1alpha1", Kind: "RuntimeClass"} + +// Get takes name of the runtimeClass, and returns the corresponding runtimeClass object, and an error if there is any. +func (c *FakeRuntimeClasses) Get(name string, options v1.GetOptions) (result *v1alpha1.RuntimeClass, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootGetAction(runtimeclassesResource, name), &v1alpha1.RuntimeClass{}) + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.RuntimeClass), err +} + +// List takes label and field selectors, and returns the list of RuntimeClasses that match those selectors. +func (c *FakeRuntimeClasses) List(opts v1.ListOptions) (result *v1alpha1.RuntimeClassList, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootListAction(runtimeclassesResource, runtimeclassesKind, opts), &v1alpha1.RuntimeClassList{}) + if obj == nil { + return nil, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &v1alpha1.RuntimeClassList{ListMeta: obj.(*v1alpha1.RuntimeClassList).ListMeta} + for _, item := range obj.(*v1alpha1.RuntimeClassList).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 runtimeClasses. +func (c *FakeRuntimeClasses) Watch(opts v1.ListOptions) (watch.Interface, error) { + return c.Fake. + InvokesWatch(testing.NewRootWatchAction(runtimeclassesResource, opts)) +} + +// Create takes the representation of a runtimeClass and creates it. Returns the server's representation of the runtimeClass, and an error, if there is any. +func (c *FakeRuntimeClasses) Create(runtimeClass *v1alpha1.RuntimeClass) (result *v1alpha1.RuntimeClass, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootCreateAction(runtimeclassesResource, runtimeClass), &v1alpha1.RuntimeClass{}) + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.RuntimeClass), err +} + +// Update takes the representation of a runtimeClass and updates it. Returns the server's representation of the runtimeClass, and an error, if there is any. +func (c *FakeRuntimeClasses) Update(runtimeClass *v1alpha1.RuntimeClass) (result *v1alpha1.RuntimeClass, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootUpdateAction(runtimeclassesResource, runtimeClass), &v1alpha1.RuntimeClass{}) + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.RuntimeClass), err +} + +// Delete takes name of the runtimeClass and deletes it. Returns an error if one occurs. +func (c *FakeRuntimeClasses) Delete(name string, options *v1.DeleteOptions) error { + _, err := c.Fake. + Invokes(testing.NewRootDeleteAction(runtimeclassesResource, name), &v1alpha1.RuntimeClass{}) + return err +} + +// DeleteCollection deletes a collection of objects. +func (c *FakeRuntimeClasses) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { + action := testing.NewRootDeleteCollectionAction(runtimeclassesResource, listOptions) + + _, err := c.Fake.Invokes(action, &v1alpha1.RuntimeClassList{}) + return err +} + +// Patch applies the patch and returns the patched runtimeClass. +func (c *FakeRuntimeClasses) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.RuntimeClass, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootPatchSubresourceAction(runtimeclassesResource, name, pt, data, subresources...), &v1alpha1.RuntimeClass{}) + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.RuntimeClass), err +} diff --git a/staging/src/k8s.io/node-api/pkg/client/clientset/versioned/typed/node/v1alpha1/generated_expansion.go b/staging/src/k8s.io/node-api/pkg/client/clientset/versioned/typed/node/v1alpha1/generated_expansion.go new file mode 100644 index 00000000000..fcef31d1695 --- /dev/null +++ b/staging/src/k8s.io/node-api/pkg/client/clientset/versioned/typed/node/v1alpha1/generated_expansion.go @@ -0,0 +1,21 @@ +/* +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 v1alpha1 + +type RuntimeClassExpansion interface{} diff --git a/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/typed/wardle/internalversion/wardle_client.go b/staging/src/k8s.io/node-api/pkg/client/clientset/versioned/typed/node/v1alpha1/node_client.go similarity index 51% rename from staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/typed/wardle/internalversion/wardle_client.go rename to staging/src/k8s.io/node-api/pkg/client/clientset/versioned/typed/node/v1alpha1/node_client.go index 12e618e9699..6feccd4d626 100644 --- a/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/typed/wardle/internalversion/wardle_client.go +++ b/staging/src/k8s.io/node-api/pkg/client/clientset/versioned/typed/node/v1alpha1/node_client.go @@ -16,34 +16,31 @@ limitations under the License. // Code generated by client-gen. DO NOT EDIT. -package internalversion +package v1alpha1 import ( + serializer "k8s.io/apimachinery/pkg/runtime/serializer" rest "k8s.io/client-go/rest" - "k8s.io/sample-apiserver/pkg/client/clientset/internalversion/scheme" + v1alpha1 "k8s.io/node-api/pkg/apis/node/v1alpha1" + "k8s.io/node-api/pkg/client/clientset/versioned/scheme" ) -type WardleInterface interface { +type NodeV1alpha1Interface interface { RESTClient() rest.Interface - FischersGetter - FlundersGetter + RuntimeClassesGetter } -// WardleClient is used to interact with features provided by the wardle.k8s.io group. -type WardleClient struct { +// NodeV1alpha1Client is used to interact with features provided by the node.k8s.io group. +type NodeV1alpha1Client struct { restClient rest.Interface } -func (c *WardleClient) Fischers() FischerInterface { - return newFischers(c) +func (c *NodeV1alpha1Client) RuntimeClasses() RuntimeClassInterface { + return newRuntimeClasses(c) } -func (c *WardleClient) Flunders(namespace string) FlunderInterface { - return newFlunders(c, namespace) -} - -// NewForConfig creates a new WardleClient for the given config. -func NewForConfig(c *rest.Config) (*WardleClient, error) { +// NewForConfig creates a new NodeV1alpha1Client for the given config. +func NewForConfig(c *rest.Config) (*NodeV1alpha1Client, error) { config := *c if err := setConfigDefaults(&config); err != nil { return nil, err @@ -52,12 +49,12 @@ func NewForConfig(c *rest.Config) (*WardleClient, error) { if err != nil { return nil, err } - return &WardleClient{client}, nil + return &NodeV1alpha1Client{client}, nil } -// NewForConfigOrDie creates a new WardleClient for the given config and +// NewForConfigOrDie creates a new NodeV1alpha1Client for the given config and // panics if there is an error in the config. -func NewForConfigOrDie(c *rest.Config) *WardleClient { +func NewForConfigOrDie(c *rest.Config) *NodeV1alpha1Client { client, err := NewForConfig(c) if err != nil { panic(err) @@ -65,35 +62,27 @@ func NewForConfigOrDie(c *rest.Config) *WardleClient { return client } -// New creates a new WardleClient for the given RESTClient. -func New(c rest.Interface) *WardleClient { - return &WardleClient{c} +// New creates a new NodeV1alpha1Client for the given RESTClient. +func New(c rest.Interface) *NodeV1alpha1Client { + return &NodeV1alpha1Client{c} } func setConfigDefaults(config *rest.Config) error { + gv := v1alpha1.SchemeGroupVersion + config.GroupVersion = &gv config.APIPath = "/apis" + config.NegotiatedSerializer = serializer.DirectCodecFactory{CodecFactory: scheme.Codecs} + if config.UserAgent == "" { config.UserAgent = rest.DefaultKubernetesUserAgent() } - if config.GroupVersion == nil || config.GroupVersion.Group != scheme.Scheme.PrioritizedVersionsForGroup("wardle.k8s.io")[0].Group { - gv := scheme.Scheme.PrioritizedVersionsForGroup("wardle.k8s.io")[0] - config.GroupVersion = &gv - } - config.NegotiatedSerializer = scheme.Codecs - - if config.QPS == 0 { - config.QPS = 5 - } - if config.Burst == 0 { - config.Burst = 10 - } return nil } // RESTClient returns a RESTClient that is used to communicate // with API server by this client implementation. -func (c *WardleClient) RESTClient() rest.Interface { +func (c *NodeV1alpha1Client) RESTClient() rest.Interface { if c == nil { return nil } diff --git a/staging/src/k8s.io/node-api/pkg/client/clientset/versioned/typed/node/v1alpha1/runtimeclass.go b/staging/src/k8s.io/node-api/pkg/client/clientset/versioned/typed/node/v1alpha1/runtimeclass.go new file mode 100644 index 00000000000..f401a99a0d7 --- /dev/null +++ b/staging/src/k8s.io/node-api/pkg/client/clientset/versioned/typed/node/v1alpha1/runtimeclass.go @@ -0,0 +1,164 @@ +/* +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 v1alpha1 + +import ( + "time" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + rest "k8s.io/client-go/rest" + v1alpha1 "k8s.io/node-api/pkg/apis/node/v1alpha1" + scheme "k8s.io/node-api/pkg/client/clientset/versioned/scheme" +) + +// RuntimeClassesGetter has a method to return a RuntimeClassInterface. +// A group's client should implement this interface. +type RuntimeClassesGetter interface { + RuntimeClasses() RuntimeClassInterface +} + +// RuntimeClassInterface has methods to work with RuntimeClass resources. +type RuntimeClassInterface interface { + Create(*v1alpha1.RuntimeClass) (*v1alpha1.RuntimeClass, error) + Update(*v1alpha1.RuntimeClass) (*v1alpha1.RuntimeClass, error) + Delete(name string, options *v1.DeleteOptions) error + DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error + Get(name string, options v1.GetOptions) (*v1alpha1.RuntimeClass, error) + List(opts v1.ListOptions) (*v1alpha1.RuntimeClassList, error) + Watch(opts v1.ListOptions) (watch.Interface, error) + Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.RuntimeClass, err error) + RuntimeClassExpansion +} + +// runtimeClasses implements RuntimeClassInterface +type runtimeClasses struct { + client rest.Interface +} + +// newRuntimeClasses returns a RuntimeClasses +func newRuntimeClasses(c *NodeV1alpha1Client) *runtimeClasses { + return &runtimeClasses{ + client: c.RESTClient(), + } +} + +// Get takes name of the runtimeClass, and returns the corresponding runtimeClass object, and an error if there is any. +func (c *runtimeClasses) Get(name string, options v1.GetOptions) (result *v1alpha1.RuntimeClass, err error) { + result = &v1alpha1.RuntimeClass{} + err = c.client.Get(). + Resource("runtimeclasses"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of RuntimeClasses that match those selectors. +func (c *runtimeClasses) List(opts v1.ListOptions) (result *v1alpha1.RuntimeClassList, err error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + result = &v1alpha1.RuntimeClassList{} + err = c.client.Get(). + Resource("runtimeclasses"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Do(). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested runtimeClasses. +func (c *runtimeClasses) Watch(opts v1.ListOptions) (watch.Interface, error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + opts.Watch = true + return c.client.Get(). + Resource("runtimeclasses"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Watch() +} + +// Create takes the representation of a runtimeClass and creates it. Returns the server's representation of the runtimeClass, and an error, if there is any. +func (c *runtimeClasses) Create(runtimeClass *v1alpha1.RuntimeClass) (result *v1alpha1.RuntimeClass, err error) { + result = &v1alpha1.RuntimeClass{} + err = c.client.Post(). + Resource("runtimeclasses"). + Body(runtimeClass). + Do(). + Into(result) + return +} + +// Update takes the representation of a runtimeClass and updates it. Returns the server's representation of the runtimeClass, and an error, if there is any. +func (c *runtimeClasses) Update(runtimeClass *v1alpha1.RuntimeClass) (result *v1alpha1.RuntimeClass, err error) { + result = &v1alpha1.RuntimeClass{} + err = c.client.Put(). + Resource("runtimeclasses"). + Name(runtimeClass.Name). + Body(runtimeClass). + Do(). + Into(result) + return +} + +// Delete takes name of the runtimeClass and deletes it. Returns an error if one occurs. +func (c *runtimeClasses) Delete(name string, options *v1.DeleteOptions) error { + return c.client.Delete(). + Resource("runtimeclasses"). + Name(name). + Body(options). + Do(). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (c *runtimeClasses) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { + var timeout time.Duration + if listOptions.TimeoutSeconds != nil { + timeout = time.Duration(*listOptions.TimeoutSeconds) * time.Second + } + return c.client.Delete(). + Resource("runtimeclasses"). + VersionedParams(&listOptions, scheme.ParameterCodec). + Timeout(timeout). + Body(options). + Do(). + Error() +} + +// Patch applies the patch and returns the patched runtimeClass. +func (c *runtimeClasses) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.RuntimeClass, err error) { + result = &v1alpha1.RuntimeClass{} + err = c.client.Patch(pt). + Resource("runtimeclasses"). + SubResource(subresources...). + Name(name). + Body(data). + Do(). + Into(result) + return +} diff --git a/staging/src/k8s.io/sample-apiserver/pkg/client/informers/internalversion/BUILD b/staging/src/k8s.io/node-api/pkg/client/informers/externalversions/BUILD similarity index 50% rename from staging/src/k8s.io/sample-apiserver/pkg/client/informers/internalversion/BUILD rename to staging/src/k8s.io/node-api/pkg/client/informers/externalversions/BUILD index c626b200205..4bb1ac15002 100644 --- a/staging/src/k8s.io/sample-apiserver/pkg/client/informers/internalversion/BUILD +++ b/staging/src/k8s.io/node-api/pkg/client/informers/externalversions/BUILD @@ -6,18 +6,18 @@ go_library( "factory.go", "generic.go", ], - importmap = "k8s.io/kubernetes/vendor/k8s.io/sample-apiserver/pkg/client/informers/internalversion", - importpath = "k8s.io/sample-apiserver/pkg/client/informers/internalversion", + importmap = "k8s.io/kubernetes/vendor/k8s.io/node-api/pkg/client/informers/externalversions", + importpath = "k8s.io/node-api/pkg/client/informers/externalversions", visibility = ["//visibility:public"], deps = [ "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", "//staging/src/k8s.io/client-go/tools/cache:go_default_library", - "//staging/src/k8s.io/sample-apiserver/pkg/apis/wardle:go_default_library", - "//staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion:go_default_library", - "//staging/src/k8s.io/sample-apiserver/pkg/client/informers/internalversion/internalinterfaces:go_default_library", - "//staging/src/k8s.io/sample-apiserver/pkg/client/informers/internalversion/wardle:go_default_library", + "//staging/src/k8s.io/node-api/pkg/apis/node/v1alpha1:go_default_library", + "//staging/src/k8s.io/node-api/pkg/client/clientset/versioned:go_default_library", + "//staging/src/k8s.io/node-api/pkg/client/informers/externalversions/internalinterfaces:go_default_library", + "//staging/src/k8s.io/node-api/pkg/client/informers/externalversions/node:go_default_library", ], ) @@ -32,8 +32,8 @@ filegroup( name = "all-srcs", srcs = [ ":package-srcs", - "//staging/src/k8s.io/sample-apiserver/pkg/client/informers/internalversion/internalinterfaces:all-srcs", - "//staging/src/k8s.io/sample-apiserver/pkg/client/informers/internalversion/wardle:all-srcs", + "//staging/src/k8s.io/node-api/pkg/client/informers/externalversions/internalinterfaces:all-srcs", + "//staging/src/k8s.io/node-api/pkg/client/informers/externalversions/node:all-srcs", ], tags = ["automanaged"], visibility = ["//visibility:public"], diff --git a/staging/src/k8s.io/sample-apiserver/pkg/client/informers/internalversion/factory.go b/staging/src/k8s.io/node-api/pkg/client/informers/externalversions/factory.go similarity index 85% rename from staging/src/k8s.io/sample-apiserver/pkg/client/informers/internalversion/factory.go rename to staging/src/k8s.io/node-api/pkg/client/informers/externalversions/factory.go index 8cb755ece29..79f25145cba 100644 --- a/staging/src/k8s.io/sample-apiserver/pkg/client/informers/internalversion/factory.go +++ b/staging/src/k8s.io/node-api/pkg/client/informers/externalversions/factory.go @@ -16,7 +16,7 @@ limitations under the License. // Code generated by informer-gen. DO NOT EDIT. -package internalversion +package externalversions import ( reflect "reflect" @@ -27,16 +27,16 @@ import ( runtime "k8s.io/apimachinery/pkg/runtime" schema "k8s.io/apimachinery/pkg/runtime/schema" cache "k8s.io/client-go/tools/cache" - internalversion "k8s.io/sample-apiserver/pkg/client/clientset/internalversion" - internalinterfaces "k8s.io/sample-apiserver/pkg/client/informers/internalversion/internalinterfaces" - wardle "k8s.io/sample-apiserver/pkg/client/informers/internalversion/wardle" + versioned "k8s.io/node-api/pkg/client/clientset/versioned" + internalinterfaces "k8s.io/node-api/pkg/client/informers/externalversions/internalinterfaces" + node "k8s.io/node-api/pkg/client/informers/externalversions/node" ) // SharedInformerOption defines the functional option type for SharedInformerFactory. type SharedInformerOption func(*sharedInformerFactory) *sharedInformerFactory type sharedInformerFactory struct { - client internalversion.Interface + client versioned.Interface namespace string tweakListOptions internalinterfaces.TweakListOptionsFunc lock sync.Mutex @@ -76,7 +76,7 @@ func WithNamespace(namespace string) SharedInformerOption { } // NewSharedInformerFactory constructs a new instance of sharedInformerFactory for all namespaces. -func NewSharedInformerFactory(client internalversion.Interface, defaultResync time.Duration) SharedInformerFactory { +func NewSharedInformerFactory(client versioned.Interface, defaultResync time.Duration) SharedInformerFactory { return NewSharedInformerFactoryWithOptions(client, defaultResync) } @@ -84,12 +84,12 @@ func NewSharedInformerFactory(client internalversion.Interface, defaultResync ti // Listers obtained via this SharedInformerFactory will be subject to the same filters // as specified here. // Deprecated: Please use NewSharedInformerFactoryWithOptions instead -func NewFilteredSharedInformerFactory(client internalversion.Interface, defaultResync time.Duration, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerFactory { +func NewFilteredSharedInformerFactory(client versioned.Interface, defaultResync time.Duration, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerFactory { return NewSharedInformerFactoryWithOptions(client, defaultResync, WithNamespace(namespace), WithTweakListOptions(tweakListOptions)) } // NewSharedInformerFactoryWithOptions constructs a new instance of a SharedInformerFactory with additional options. -func NewSharedInformerFactoryWithOptions(client internalversion.Interface, defaultResync time.Duration, options ...SharedInformerOption) SharedInformerFactory { +func NewSharedInformerFactoryWithOptions(client versioned.Interface, defaultResync time.Duration, options ...SharedInformerOption) SharedInformerFactory { factory := &sharedInformerFactory{ client: client, namespace: v1.NamespaceAll, @@ -172,9 +172,9 @@ type SharedInformerFactory interface { ForResource(resource schema.GroupVersionResource) (GenericInformer, error) WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool - Wardle() wardle.Interface + Node() node.Interface } -func (f *sharedInformerFactory) Wardle() wardle.Interface { - return wardle.New(f, f.namespace, f.tweakListOptions) +func (f *sharedInformerFactory) Node() node.Interface { + return node.New(f, f.namespace, f.tweakListOptions) } diff --git a/staging/src/k8s.io/sample-apiserver/pkg/client/informers/internalversion/generic.go b/staging/src/k8s.io/node-api/pkg/client/informers/externalversions/generic.go similarity index 80% rename from staging/src/k8s.io/sample-apiserver/pkg/client/informers/internalversion/generic.go rename to staging/src/k8s.io/node-api/pkg/client/informers/externalversions/generic.go index a0291d38a8a..ea8bab15894 100644 --- a/staging/src/k8s.io/sample-apiserver/pkg/client/informers/internalversion/generic.go +++ b/staging/src/k8s.io/node-api/pkg/client/informers/externalversions/generic.go @@ -16,14 +16,14 @@ limitations under the License. // Code generated by informer-gen. DO NOT EDIT. -package internalversion +package externalversions import ( "fmt" schema "k8s.io/apimachinery/pkg/runtime/schema" cache "k8s.io/client-go/tools/cache" - wardle "k8s.io/sample-apiserver/pkg/apis/wardle" + v1alpha1 "k8s.io/node-api/pkg/apis/node/v1alpha1" ) // GenericInformer is type of SharedIndexInformer which will locate and delegate to other @@ -52,11 +52,9 @@ func (f *genericInformer) Lister() cache.GenericLister { // TODO extend this to unknown resources with a client pool func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource) (GenericInformer, error) { switch resource { - // Group=wardle.k8s.io, Version=internalVersion - case wardle.SchemeGroupVersion.WithResource("fischers"): - return &genericInformer{resource: resource.GroupResource(), informer: f.Wardle().InternalVersion().Fischers().Informer()}, nil - case wardle.SchemeGroupVersion.WithResource("flunders"): - return &genericInformer{resource: resource.GroupResource(), informer: f.Wardle().InternalVersion().Flunders().Informer()}, nil + // Group=node.k8s.io, Version=v1alpha1 + case v1alpha1.SchemeGroupVersion.WithResource("runtimeclasses"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Node().V1alpha1().RuntimeClasses().Informer()}, nil } diff --git a/staging/src/k8s.io/sample-apiserver/pkg/client/informers/internalversion/internalinterfaces/BUILD b/staging/src/k8s.io/node-api/pkg/client/informers/externalversions/internalinterfaces/BUILD similarity index 68% rename from staging/src/k8s.io/sample-apiserver/pkg/client/informers/internalversion/internalinterfaces/BUILD rename to staging/src/k8s.io/node-api/pkg/client/informers/externalversions/internalinterfaces/BUILD index 02e8076f85f..a75f8bf2b3d 100644 --- a/staging/src/k8s.io/sample-apiserver/pkg/client/informers/internalversion/internalinterfaces/BUILD +++ b/staging/src/k8s.io/node-api/pkg/client/informers/externalversions/internalinterfaces/BUILD @@ -3,14 +3,14 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library") go_library( name = "go_default_library", srcs = ["factory_interfaces.go"], - importmap = "k8s.io/kubernetes/vendor/k8s.io/sample-apiserver/pkg/client/informers/internalversion/internalinterfaces", - importpath = "k8s.io/sample-apiserver/pkg/client/informers/internalversion/internalinterfaces", + importmap = "k8s.io/kubernetes/vendor/k8s.io/node-api/pkg/client/informers/externalversions/internalinterfaces", + importpath = "k8s.io/node-api/pkg/client/informers/externalversions/internalinterfaces", visibility = ["//visibility:public"], deps = [ "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library", "//staging/src/k8s.io/client-go/tools/cache:go_default_library", - "//staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion:go_default_library", + "//staging/src/k8s.io/node-api/pkg/client/clientset/versioned:go_default_library", ], ) diff --git a/staging/src/k8s.io/sample-apiserver/pkg/client/informers/internalversion/internalinterfaces/factory_interfaces.go b/staging/src/k8s.io/node-api/pkg/client/informers/externalversions/internalinterfaces/factory_interfaces.go similarity index 80% rename from staging/src/k8s.io/sample-apiserver/pkg/client/informers/internalversion/internalinterfaces/factory_interfaces.go rename to staging/src/k8s.io/node-api/pkg/client/informers/externalversions/internalinterfaces/factory_interfaces.go index abd5bbe58bb..fe89883c274 100644 --- a/staging/src/k8s.io/sample-apiserver/pkg/client/informers/internalversion/internalinterfaces/factory_interfaces.go +++ b/staging/src/k8s.io/node-api/pkg/client/informers/externalversions/internalinterfaces/factory_interfaces.go @@ -24,11 +24,11 @@ import ( v1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" cache "k8s.io/client-go/tools/cache" - internalversion "k8s.io/sample-apiserver/pkg/client/clientset/internalversion" + versioned "k8s.io/node-api/pkg/client/clientset/versioned" ) -// NewInformerFunc takes internalversion.Interface and time.Duration to return a SharedIndexInformer. -type NewInformerFunc func(internalversion.Interface, time.Duration) cache.SharedIndexInformer +// NewInformerFunc takes versioned.Interface and time.Duration to return a SharedIndexInformer. +type NewInformerFunc func(versioned.Interface, time.Duration) cache.SharedIndexInformer // SharedInformerFactory a small interface to allow for adding an informer without an import cycle type SharedInformerFactory interface { diff --git a/staging/src/k8s.io/node-api/pkg/client/informers/externalversions/node/BUILD b/staging/src/k8s.io/node-api/pkg/client/informers/externalversions/node/BUILD new file mode 100644 index 00000000000..8a46de4a9c6 --- /dev/null +++ b/staging/src/k8s.io/node-api/pkg/client/informers/externalversions/node/BUILD @@ -0,0 +1,30 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = ["interface.go"], + importmap = "k8s.io/kubernetes/vendor/k8s.io/node-api/pkg/client/informers/externalversions/node", + importpath = "k8s.io/node-api/pkg/client/informers/externalversions/node", + visibility = ["//visibility:public"], + deps = [ + "//staging/src/k8s.io/node-api/pkg/client/informers/externalversions/internalinterfaces:go_default_library", + "//staging/src/k8s.io/node-api/pkg/client/informers/externalversions/node/v1alpha1:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [ + ":package-srcs", + "//staging/src/k8s.io/node-api/pkg/client/informers/externalversions/node/v1alpha1:all-srcs", + ], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/staging/src/k8s.io/sample-apiserver/pkg/client/informers/internalversion/wardle/interface.go b/staging/src/k8s.io/node-api/pkg/client/informers/externalversions/node/interface.go similarity index 67% rename from staging/src/k8s.io/sample-apiserver/pkg/client/informers/internalversion/wardle/interface.go rename to staging/src/k8s.io/node-api/pkg/client/informers/externalversions/node/interface.go index bccd11a2a57..a5a27264da4 100644 --- a/staging/src/k8s.io/sample-apiserver/pkg/client/informers/internalversion/wardle/interface.go +++ b/staging/src/k8s.io/node-api/pkg/client/informers/externalversions/node/interface.go @@ -16,17 +16,17 @@ limitations under the License. // Code generated by informer-gen. DO NOT EDIT. -package wardle +package node import ( - internalinterfaces "k8s.io/sample-apiserver/pkg/client/informers/internalversion/internalinterfaces" - internalversion "k8s.io/sample-apiserver/pkg/client/informers/internalversion/wardle/internalversion" + internalinterfaces "k8s.io/node-api/pkg/client/informers/externalversions/internalinterfaces" + v1alpha1 "k8s.io/node-api/pkg/client/informers/externalversions/node/v1alpha1" ) // Interface provides access to each of this group's versions. type Interface interface { - // InternalVersion provides access to shared informers for resources in InternalVersion. - InternalVersion() internalversion.Interface + // V1alpha1 provides access to shared informers for resources in V1alpha1. + V1alpha1() v1alpha1.Interface } type group struct { @@ -40,7 +40,7 @@ func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakList return &group{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} } -// InternalVersion returns a new internalversion.Interface. -func (g *group) InternalVersion() internalversion.Interface { - return internalversion.New(g.factory, g.namespace, g.tweakListOptions) +// V1alpha1 returns a new v1alpha1.Interface. +func (g *group) V1alpha1() v1alpha1.Interface { + return v1alpha1.New(g.factory, g.namespace, g.tweakListOptions) } diff --git a/staging/src/k8s.io/node-api/pkg/client/informers/externalversions/node/v1alpha1/BUILD b/staging/src/k8s.io/node-api/pkg/client/informers/externalversions/node/v1alpha1/BUILD new file mode 100644 index 00000000000..d67dee767be --- /dev/null +++ b/staging/src/k8s.io/node-api/pkg/client/informers/externalversions/node/v1alpha1/BUILD @@ -0,0 +1,36 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = [ + "interface.go", + "runtimeclass.go", + ], + importmap = "k8s.io/kubernetes/vendor/k8s.io/node-api/pkg/client/informers/externalversions/node/v1alpha1", + importpath = "k8s.io/node-api/pkg/client/informers/externalversions/node/v1alpha1", + visibility = ["//visibility:public"], + deps = [ + "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + "//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library", + "//staging/src/k8s.io/apimachinery/pkg/watch:go_default_library", + "//staging/src/k8s.io/client-go/tools/cache:go_default_library", + "//staging/src/k8s.io/node-api/pkg/apis/node/v1alpha1:go_default_library", + "//staging/src/k8s.io/node-api/pkg/client/clientset/versioned:go_default_library", + "//staging/src/k8s.io/node-api/pkg/client/informers/externalversions/internalinterfaces:go_default_library", + "//staging/src/k8s.io/node-api/pkg/client/listers/node/v1alpha1:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/staging/src/k8s.io/node-api/pkg/client/informers/externalversions/node/v1alpha1/interface.go b/staging/src/k8s.io/node-api/pkg/client/informers/externalversions/node/v1alpha1/interface.go new file mode 100644 index 00000000000..013ec2c4e85 --- /dev/null +++ b/staging/src/k8s.io/node-api/pkg/client/informers/externalversions/node/v1alpha1/interface.go @@ -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 v1alpha1 + +import ( + internalinterfaces "k8s.io/node-api/pkg/client/informers/externalversions/internalinterfaces" +) + +// Interface provides access to all the informers in this group version. +type Interface interface { + // RuntimeClasses returns a RuntimeClassInformer. + RuntimeClasses() RuntimeClassInformer +} + +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} +} + +// RuntimeClasses returns a RuntimeClassInformer. +func (v *version) RuntimeClasses() RuntimeClassInformer { + return &runtimeClassInformer{factory: v.factory, tweakListOptions: v.tweakListOptions} +} diff --git a/staging/src/k8s.io/node-api/pkg/client/informers/externalversions/node/v1alpha1/runtimeclass.go b/staging/src/k8s.io/node-api/pkg/client/informers/externalversions/node/v1alpha1/runtimeclass.go new file mode 100644 index 00000000000..23eed1b87f8 --- /dev/null +++ b/staging/src/k8s.io/node-api/pkg/client/informers/externalversions/node/v1alpha1/runtimeclass.go @@ -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 v1alpha1 + +import ( + time "time" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + watch "k8s.io/apimachinery/pkg/watch" + cache "k8s.io/client-go/tools/cache" + nodev1alpha1 "k8s.io/node-api/pkg/apis/node/v1alpha1" + versioned "k8s.io/node-api/pkg/client/clientset/versioned" + internalinterfaces "k8s.io/node-api/pkg/client/informers/externalversions/internalinterfaces" + v1alpha1 "k8s.io/node-api/pkg/client/listers/node/v1alpha1" +) + +// RuntimeClassInformer provides access to a shared informer and lister for +// RuntimeClasses. +type RuntimeClassInformer interface { + Informer() cache.SharedIndexInformer + Lister() v1alpha1.RuntimeClassLister +} + +type runtimeClassInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc +} + +// NewRuntimeClassInformer constructs a new informer for RuntimeClass 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 NewRuntimeClassInformer(client versioned.Interface, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredRuntimeClassInformer(client, resyncPeriod, indexers, nil) +} + +// NewFilteredRuntimeClassInformer constructs a new informer for RuntimeClass 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 NewFilteredRuntimeClassInformer(client versioned.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.NodeV1alpha1().RuntimeClasses().List(options) + }, + WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.NodeV1alpha1().RuntimeClasses().Watch(options) + }, + }, + &nodev1alpha1.RuntimeClass{}, + resyncPeriod, + indexers, + ) +} + +func (f *runtimeClassInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredRuntimeClassInformer(client, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *runtimeClassInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&nodev1alpha1.RuntimeClass{}, f.defaultInformer) +} + +func (f *runtimeClassInformer) Lister() v1alpha1.RuntimeClassLister { + return v1alpha1.NewRuntimeClassLister(f.Informer().GetIndexer()) +} diff --git a/staging/src/k8s.io/node-api/pkg/client/listers/node/v1alpha1/BUILD b/staging/src/k8s.io/node-api/pkg/client/listers/node/v1alpha1/BUILD new file mode 100644 index 00000000000..003ae4ac953 --- /dev/null +++ b/staging/src/k8s.io/node-api/pkg/client/listers/node/v1alpha1/BUILD @@ -0,0 +1,32 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = [ + "expansion_generated.go", + "runtimeclass.go", + ], + importmap = "k8s.io/kubernetes/vendor/k8s.io/node-api/pkg/client/listers/node/v1alpha1", + importpath = "k8s.io/node-api/pkg/client/listers/node/v1alpha1", + visibility = ["//visibility:public"], + deps = [ + "//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library", + "//staging/src/k8s.io/apimachinery/pkg/labels:go_default_library", + "//staging/src/k8s.io/client-go/tools/cache:go_default_library", + "//staging/src/k8s.io/node-api/pkg/apis/node/v1alpha1:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/staging/src/k8s.io/node-api/pkg/client/listers/node/v1alpha1/expansion_generated.go b/staging/src/k8s.io/node-api/pkg/client/listers/node/v1alpha1/expansion_generated.go new file mode 100644 index 00000000000..a65c208fac3 --- /dev/null +++ b/staging/src/k8s.io/node-api/pkg/client/listers/node/v1alpha1/expansion_generated.go @@ -0,0 +1,23 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by lister-gen. DO NOT EDIT. + +package v1alpha1 + +// RuntimeClassListerExpansion allows custom methods to be added to +// RuntimeClassLister. +type RuntimeClassListerExpansion interface{} diff --git a/staging/src/k8s.io/node-api/pkg/client/listers/node/v1alpha1/runtimeclass.go b/staging/src/k8s.io/node-api/pkg/client/listers/node/v1alpha1/runtimeclass.go new file mode 100644 index 00000000000..56b7573672a --- /dev/null +++ b/staging/src/k8s.io/node-api/pkg/client/listers/node/v1alpha1/runtimeclass.go @@ -0,0 +1,65 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by lister-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/tools/cache" + v1alpha1 "k8s.io/node-api/pkg/apis/node/v1alpha1" +) + +// RuntimeClassLister helps list RuntimeClasses. +type RuntimeClassLister interface { + // List lists all RuntimeClasses in the indexer. + List(selector labels.Selector) (ret []*v1alpha1.RuntimeClass, err error) + // Get retrieves the RuntimeClass from the index for a given name. + Get(name string) (*v1alpha1.RuntimeClass, error) + RuntimeClassListerExpansion +} + +// runtimeClassLister implements the RuntimeClassLister interface. +type runtimeClassLister struct { + indexer cache.Indexer +} + +// NewRuntimeClassLister returns a new RuntimeClassLister. +func NewRuntimeClassLister(indexer cache.Indexer) RuntimeClassLister { + return &runtimeClassLister{indexer: indexer} +} + +// List lists all RuntimeClasses in the indexer. +func (s *runtimeClassLister) List(selector labels.Selector) (ret []*v1alpha1.RuntimeClass, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*v1alpha1.RuntimeClass)) + }) + return ret, err +} + +// Get retrieves the RuntimeClass from the index for a given name. +func (s *runtimeClassLister) Get(name string) (*v1alpha1.RuntimeClass, error) { + obj, exists, err := s.indexer.GetByKey(name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(v1alpha1.Resource("runtimeclass"), name) + } + return obj.(*v1alpha1.RuntimeClass), nil +} diff --git a/staging/src/k8s.io/sample-apiserver/BUILD b/staging/src/k8s.io/sample-apiserver/BUILD index c2dcbc96442..cf5033eb6ca 100644 --- a/staging/src/k8s.io/sample-apiserver/BUILD +++ b/staging/src/k8s.io/sample-apiserver/BUILD @@ -39,11 +39,8 @@ filegroup( "//staging/src/k8s.io/sample-apiserver/pkg/admission/wardleinitializer:all-srcs", "//staging/src/k8s.io/sample-apiserver/pkg/apis/wardle:all-srcs", "//staging/src/k8s.io/sample-apiserver/pkg/apiserver:all-srcs", - "//staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion:all-srcs", "//staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned:all-srcs", "//staging/src/k8s.io/sample-apiserver/pkg/client/informers/externalversions:all-srcs", - "//staging/src/k8s.io/sample-apiserver/pkg/client/informers/internalversion:all-srcs", - "//staging/src/k8s.io/sample-apiserver/pkg/client/listers/wardle/internalversion:all-srcs", "//staging/src/k8s.io/sample-apiserver/pkg/client/listers/wardle/v1alpha1:all-srcs", "//staging/src/k8s.io/sample-apiserver/pkg/client/listers/wardle/v1beta1:all-srcs", "//staging/src/k8s.io/sample-apiserver/pkg/cmd/server:all-srcs", diff --git a/staging/src/k8s.io/sample-apiserver/Godeps/Godeps.json b/staging/src/k8s.io/sample-apiserver/Godeps/Godeps.json index cea95b14686..a117a4b2bef 100644 --- a/staging/src/k8s.io/sample-apiserver/Godeps/Godeps.json +++ b/staging/src/k8s.io/sample-apiserver/Godeps/Godeps.json @@ -244,7 +244,11 @@ }, { "ImportPath": "github.com/prometheus/client_golang/prometheus", - "Rev": "e7e903064f5e9eb5da98208bae10b475d4db0f8c" + "Rev": "abad2d1bd44235a26707c172eab6bca5bf2dbad3" + }, + { + "ImportPath": "github.com/prometheus/client_golang/prometheus/internal", + "Rev": "abad2d1bd44235a26707c172eab6bca5bf2dbad3" }, { "ImportPath": "github.com/prometheus/client_model/go", @@ -574,6 +578,10 @@ "ImportPath": "k8s.io/api/certificates/v1beta1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/api/coordination/v1", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/api/coordination/v1beta1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" @@ -1334,6 +1342,10 @@ "ImportPath": "k8s.io/client-go/informers/coordination", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/client-go/informers/coordination/v1", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/client-go/informers/coordination/v1beta1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" @@ -1510,6 +1522,10 @@ "ImportPath": "k8s.io/client-go/kubernetes/typed/certificates/v1beta1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/client-go/kubernetes/typed/coordination/v1", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/client-go/kubernetes/typed/coordination/v1beta1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" @@ -1622,6 +1638,10 @@ "ImportPath": "k8s.io/client-go/listers/certificates/v1beta1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/client-go/listers/coordination/v1", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/client-go/listers/coordination/v1beta1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" diff --git a/staging/src/k8s.io/sample-apiserver/OWNERS b/staging/src/k8s.io/sample-apiserver/OWNERS index 9e337a812b1..2268629156c 100644 --- a/staging/src/k8s.io/sample-apiserver/OWNERS +++ b/staging/src/k8s.io/sample-apiserver/OWNERS @@ -10,5 +10,6 @@ reviewers: - deads2k - sttts - liggitt +- cheftako labels: - sig/api-machinery diff --git a/staging/src/k8s.io/sample-apiserver/artifacts/example/rc.yaml b/staging/src/k8s.io/sample-apiserver/artifacts/example/rc.yaml index 9513a849484..3852a2273f7 100644 --- a/staging/src/k8s.io/sample-apiserver/artifacts/example/rc.yaml +++ b/staging/src/k8s.io/sample-apiserver/artifacts/example/rc.yaml @@ -21,4 +21,4 @@ spec: imagePullPolicy: Never command: [ "/kube-sample-apiserver", "--etcd-servers=http://localhost:2379" ] - name: etcd - image: quay.io/coreos/etcd:v3.2.24 + image: quay.io/coreos/etcd:v3.3.10 diff --git a/staging/src/k8s.io/sample-apiserver/hack/update-codegen.sh b/staging/src/k8s.io/sample-apiserver/hack/update-codegen.sh index 9dcc8f10242..98c9ae9e1aa 100755 --- a/staging/src/k8s.io/sample-apiserver/hack/update-codegen.sh +++ b/staging/src/k8s.io/sample-apiserver/hack/update-codegen.sh @@ -25,7 +25,13 @@ CODEGEN_PKG=${CODEGEN_PKG:-$(cd ${SCRIPT_ROOT}; ls -d -1 ./vendor/k8s.io/code-ge # --output-base because this script should also be able to run inside the vendor dir of # k8s.io/kubernetes. The output-base is needed for the generators to output into the vendor dir # instead of the $GOPATH directly. For normal projects this can be dropped. -${CODEGEN_PKG}/generate-internal-groups.sh all \ +${CODEGEN_PKG}/generate-groups.sh all \ + k8s.io/sample-apiserver/pkg/client k8s.io/sample-apiserver/pkg/apis \ + "wardle:v1alpha1,v1beta1" \ + --output-base "$(dirname ${BASH_SOURCE})/../../.." \ + --go-header-file ${SCRIPT_ROOT}/hack/boilerplate.go.txt + +${CODEGEN_PKG}/generate-internal-groups.sh "deepcopy,defaulter,conversion" \ k8s.io/sample-apiserver/pkg/client k8s.io/sample-apiserver/pkg/apis k8s.io/sample-apiserver/pkg/apis \ "wardle:v1alpha1,v1beta1" \ --output-base "$(dirname ${BASH_SOURCE})/../../.." \ diff --git a/staging/src/k8s.io/sample-apiserver/pkg/admission/plugin/banflunder/BUILD b/staging/src/k8s.io/sample-apiserver/pkg/admission/plugin/banflunder/BUILD index 56a4f47e473..6a4c5dfea82 100644 --- a/staging/src/k8s.io/sample-apiserver/pkg/admission/plugin/banflunder/BUILD +++ b/staging/src/k8s.io/sample-apiserver/pkg/admission/plugin/banflunder/BUILD @@ -18,8 +18,8 @@ go_library( "//staging/src/k8s.io/apiserver/pkg/admission:go_default_library", "//staging/src/k8s.io/sample-apiserver/pkg/admission/wardleinitializer:go_default_library", "//staging/src/k8s.io/sample-apiserver/pkg/apis/wardle:go_default_library", - "//staging/src/k8s.io/sample-apiserver/pkg/client/informers/internalversion:go_default_library", - "//staging/src/k8s.io/sample-apiserver/pkg/client/listers/wardle/internalversion:go_default_library", + "//staging/src/k8s.io/sample-apiserver/pkg/client/informers/externalversions:go_default_library", + "//staging/src/k8s.io/sample-apiserver/pkg/client/listers/wardle/v1alpha1:go_default_library", ], ) @@ -34,9 +34,9 @@ go_test( "//staging/src/k8s.io/apiserver/pkg/admission:go_default_library", "//staging/src/k8s.io/client-go/testing:go_default_library", "//staging/src/k8s.io/sample-apiserver/pkg/admission/wardleinitializer:go_default_library", - "//staging/src/k8s.io/sample-apiserver/pkg/apis/wardle:go_default_library", - "//staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/fake:go_default_library", - "//staging/src/k8s.io/sample-apiserver/pkg/client/informers/internalversion:go_default_library", + "//staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1:go_default_library", + "//staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/fake:go_default_library", + "//staging/src/k8s.io/sample-apiserver/pkg/client/informers/externalversions:go_default_library", ], ) diff --git a/staging/src/k8s.io/sample-apiserver/pkg/admission/plugin/banflunder/admission.go b/staging/src/k8s.io/sample-apiserver/pkg/admission/plugin/banflunder/admission.go index 4acfe6448ba..70d618614a9 100644 --- a/staging/src/k8s.io/sample-apiserver/pkg/admission/plugin/banflunder/admission.go +++ b/staging/src/k8s.io/sample-apiserver/pkg/admission/plugin/banflunder/admission.go @@ -26,8 +26,8 @@ import ( "k8s.io/apiserver/pkg/admission" "k8s.io/sample-apiserver/pkg/admission/wardleinitializer" "k8s.io/sample-apiserver/pkg/apis/wardle" - informers "k8s.io/sample-apiserver/pkg/client/informers/internalversion" - listers "k8s.io/sample-apiserver/pkg/client/listers/wardle/internalversion" + informers "k8s.io/sample-apiserver/pkg/client/informers/externalversions" + listers "k8s.io/sample-apiserver/pkg/client/listers/wardle/v1alpha1" ) // Register registers a plugin @@ -85,11 +85,11 @@ func (d *DisallowFlunder) Admit(a admission.Attributes) error { // SetInternalWardleInformerFactory gets Lister from SharedInformerFactory. // The lister knows how to lists Fischers. func (d *DisallowFlunder) SetInternalWardleInformerFactory(f informers.SharedInformerFactory) { - d.lister = f.Wardle().InternalVersion().Fischers().Lister() - d.SetReadyFunc(f.Wardle().InternalVersion().Fischers().Informer().HasSynced) + d.lister = f.Wardle().V1alpha1().Fischers().Lister() + d.SetReadyFunc(f.Wardle().V1alpha1().Fischers().Informer().HasSynced) } -// ValidaValidateInitializationte checks whether the plugin was correctly initialized. +// ValidateInitialization checks whether the plugin was correctly initialized. func (d *DisallowFlunder) ValidateInitialization() error { if d.lister == nil { return fmt.Errorf("missing fischer lister") diff --git a/staging/src/k8s.io/sample-apiserver/pkg/admission/plugin/banflunder/admission_test.go b/staging/src/k8s.io/sample-apiserver/pkg/admission/plugin/banflunder/admission_test.go index 9023d82c281..b60ae0dbae8 100644 --- a/staging/src/k8s.io/sample-apiserver/pkg/admission/plugin/banflunder/admission_test.go +++ b/staging/src/k8s.io/sample-apiserver/pkg/admission/plugin/banflunder/admission_test.go @@ -27,9 +27,9 @@ import ( clienttesting "k8s.io/client-go/testing" "k8s.io/sample-apiserver/pkg/admission/plugin/banflunder" "k8s.io/sample-apiserver/pkg/admission/wardleinitializer" - "k8s.io/sample-apiserver/pkg/apis/wardle" - "k8s.io/sample-apiserver/pkg/client/clientset/internalversion/fake" - informers "k8s.io/sample-apiserver/pkg/client/informers/internalversion" + wardle "k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1" + "k8s.io/sample-apiserver/pkg/client/clientset/versioned/fake" + informers "k8s.io/sample-apiserver/pkg/client/informers/externalversions" ) // TestBanfluderAdmissionPlugin tests various test cases against @@ -56,7 +56,7 @@ func TestBanflunderAdmissionPlugin(t *testing.T) { Namespace: "", }, }, - admissionInputKind: wardle.Kind("Flunder").WithVersion("version"), + admissionInputKind: wardle.SchemeGroupVersion.WithKind("Flunder").GroupKind().WithVersion("version"), admissionInputResource: wardle.Resource("flunders").WithVersion("version"), admissionMustFail: true, }, @@ -74,7 +74,7 @@ func TestBanflunderAdmissionPlugin(t *testing.T) { Namespace: "", }, }, - admissionInputKind: wardle.Kind("Flunder").WithVersion("version"), + admissionInputKind: wardle.SchemeGroupVersion.WithKind("Flunder").GroupKind().WithVersion("version"), admissionInputResource: wardle.Resource("flunders").WithVersion("version"), admissionMustFail: false, }, @@ -93,7 +93,7 @@ func TestBanflunderAdmissionPlugin(t *testing.T) { Namespace: "", }, }, - admissionInputKind: wardle.Kind("NotFlunder").WithVersion("version"), + admissionInputKind: wardle.SchemeGroupVersion.WithKind("NotFlunder").GroupKind().WithVersion("version"), admissionInputResource: wardle.Resource("notflunders").WithVersion("version"), admissionMustFail: false, }, diff --git a/staging/src/k8s.io/sample-apiserver/pkg/admission/wardleinitializer/BUILD b/staging/src/k8s.io/sample-apiserver/pkg/admission/wardleinitializer/BUILD index 11bb979dc6b..0d9f62e676a 100644 --- a/staging/src/k8s.io/sample-apiserver/pkg/admission/wardleinitializer/BUILD +++ b/staging/src/k8s.io/sample-apiserver/pkg/admission/wardleinitializer/BUILD @@ -16,7 +16,7 @@ go_library( importpath = "k8s.io/sample-apiserver/pkg/admission/wardleinitializer", deps = [ "//staging/src/k8s.io/apiserver/pkg/admission:go_default_library", - "//staging/src/k8s.io/sample-apiserver/pkg/client/informers/internalversion:go_default_library", + "//staging/src/k8s.io/sample-apiserver/pkg/client/informers/externalversions:go_default_library", ], ) @@ -26,8 +26,8 @@ go_test( embed = [":go_default_library"], deps = [ "//staging/src/k8s.io/apiserver/pkg/admission:go_default_library", - "//staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/fake:go_default_library", - "//staging/src/k8s.io/sample-apiserver/pkg/client/informers/internalversion:go_default_library", + "//staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned/fake:go_default_library", + "//staging/src/k8s.io/sample-apiserver/pkg/client/informers/externalversions:go_default_library", ], ) diff --git a/staging/src/k8s.io/sample-apiserver/pkg/admission/wardleinitializer/interfaces.go b/staging/src/k8s.io/sample-apiserver/pkg/admission/wardleinitializer/interfaces.go index f5c6e41579b..248cd045d82 100644 --- a/staging/src/k8s.io/sample-apiserver/pkg/admission/wardleinitializer/interfaces.go +++ b/staging/src/k8s.io/sample-apiserver/pkg/admission/wardleinitializer/interfaces.go @@ -18,7 +18,7 @@ package wardleinitializer import ( "k8s.io/apiserver/pkg/admission" - informers "k8s.io/sample-apiserver/pkg/client/informers/internalversion" + informers "k8s.io/sample-apiserver/pkg/client/informers/externalversions" ) // WantsInternalWardleInformerFactory defines a function which sets InformerFactory for admission plugins that need it diff --git a/staging/src/k8s.io/sample-apiserver/pkg/admission/wardleinitializer/wardleinitializer.go b/staging/src/k8s.io/sample-apiserver/pkg/admission/wardleinitializer/wardleinitializer.go index b41e3dfba09..455d51c9eaa 100644 --- a/staging/src/k8s.io/sample-apiserver/pkg/admission/wardleinitializer/wardleinitializer.go +++ b/staging/src/k8s.io/sample-apiserver/pkg/admission/wardleinitializer/wardleinitializer.go @@ -18,7 +18,7 @@ package wardleinitializer import ( "k8s.io/apiserver/pkg/admission" - informers "k8s.io/sample-apiserver/pkg/client/informers/internalversion" + informers "k8s.io/sample-apiserver/pkg/client/informers/externalversions" ) type pluginInitializer struct { diff --git a/staging/src/k8s.io/sample-apiserver/pkg/admission/wardleinitializer/wardleinitializer_test.go b/staging/src/k8s.io/sample-apiserver/pkg/admission/wardleinitializer/wardleinitializer_test.go index c64ed3ab3e1..ff6fee1a92f 100644 --- a/staging/src/k8s.io/sample-apiserver/pkg/admission/wardleinitializer/wardleinitializer_test.go +++ b/staging/src/k8s.io/sample-apiserver/pkg/admission/wardleinitializer/wardleinitializer_test.go @@ -22,8 +22,8 @@ import ( "k8s.io/apiserver/pkg/admission" "k8s.io/sample-apiserver/pkg/admission/wardleinitializer" - "k8s.io/sample-apiserver/pkg/client/clientset/internalversion/fake" - informers "k8s.io/sample-apiserver/pkg/client/informers/internalversion" + "k8s.io/sample-apiserver/pkg/client/clientset/versioned/fake" + informers "k8s.io/sample-apiserver/pkg/client/informers/externalversions" ) // TestWantsInternalWardleInformerFactory ensures that the informer factory is injected diff --git a/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/typed/wardle/internalversion/fake/fake_fischer.go b/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/typed/wardle/internalversion/fake/fake_fischer.go deleted file mode 100644 index 77eb5f27355..00000000000 --- a/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/typed/wardle/internalversion/fake/fake_fischer.go +++ /dev/null @@ -1,120 +0,0 @@ -/* -Copyright The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// Code generated by client-gen. DO NOT EDIT. - -package fake - -import ( - 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" - wardle "k8s.io/sample-apiserver/pkg/apis/wardle" -) - -// FakeFischers implements FischerInterface -type FakeFischers struct { - Fake *FakeWardle -} - -var fischersResource = schema.GroupVersionResource{Group: "wardle.k8s.io", Version: "", Resource: "fischers"} - -var fischersKind = schema.GroupVersionKind{Group: "wardle.k8s.io", Version: "", Kind: "Fischer"} - -// Get takes name of the fischer, and returns the corresponding fischer object, and an error if there is any. -func (c *FakeFischers) Get(name string, options v1.GetOptions) (result *wardle.Fischer, err error) { - obj, err := c.Fake. - Invokes(testing.NewRootGetAction(fischersResource, name), &wardle.Fischer{}) - if obj == nil { - return nil, err - } - return obj.(*wardle.Fischer), err -} - -// List takes label and field selectors, and returns the list of Fischers that match those selectors. -func (c *FakeFischers) List(opts v1.ListOptions) (result *wardle.FischerList, err error) { - obj, err := c.Fake. - Invokes(testing.NewRootListAction(fischersResource, fischersKind, opts), &wardle.FischerList{}) - if obj == nil { - return nil, err - } - - label, _, _ := testing.ExtractFromListOptions(opts) - if label == nil { - label = labels.Everything() - } - list := &wardle.FischerList{ListMeta: obj.(*wardle.FischerList).ListMeta} - for _, item := range obj.(*wardle.FischerList).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 fischers. -func (c *FakeFischers) Watch(opts v1.ListOptions) (watch.Interface, error) { - return c.Fake. - InvokesWatch(testing.NewRootWatchAction(fischersResource, opts)) -} - -// Create takes the representation of a fischer and creates it. Returns the server's representation of the fischer, and an error, if there is any. -func (c *FakeFischers) Create(fischer *wardle.Fischer) (result *wardle.Fischer, err error) { - obj, err := c.Fake. - Invokes(testing.NewRootCreateAction(fischersResource, fischer), &wardle.Fischer{}) - if obj == nil { - return nil, err - } - return obj.(*wardle.Fischer), err -} - -// Update takes the representation of a fischer and updates it. Returns the server's representation of the fischer, and an error, if there is any. -func (c *FakeFischers) Update(fischer *wardle.Fischer) (result *wardle.Fischer, err error) { - obj, err := c.Fake. - Invokes(testing.NewRootUpdateAction(fischersResource, fischer), &wardle.Fischer{}) - if obj == nil { - return nil, err - } - return obj.(*wardle.Fischer), err -} - -// Delete takes name of the fischer and deletes it. Returns an error if one occurs. -func (c *FakeFischers) Delete(name string, options *v1.DeleteOptions) error { - _, err := c.Fake. - Invokes(testing.NewRootDeleteAction(fischersResource, name), &wardle.Fischer{}) - return err -} - -// DeleteCollection deletes a collection of objects. -func (c *FakeFischers) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { - action := testing.NewRootDeleteCollectionAction(fischersResource, listOptions) - - _, err := c.Fake.Invokes(action, &wardle.FischerList{}) - return err -} - -// Patch applies the patch and returns the patched fischer. -func (c *FakeFischers) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *wardle.Fischer, err error) { - obj, err := c.Fake. - Invokes(testing.NewRootPatchSubresourceAction(fischersResource, name, pt, data, subresources...), &wardle.Fischer{}) - if obj == nil { - return nil, err - } - return obj.(*wardle.Fischer), err -} diff --git a/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/typed/wardle/internalversion/fake/fake_flunder.go b/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/typed/wardle/internalversion/fake/fake_flunder.go deleted file mode 100644 index 2c893d3ff2d..00000000000 --- a/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/typed/wardle/internalversion/fake/fake_flunder.go +++ /dev/null @@ -1,140 +0,0 @@ -/* -Copyright The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// Code generated by client-gen. DO NOT EDIT. - -package fake - -import ( - v1 "k8s.io/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" - wardle "k8s.io/sample-apiserver/pkg/apis/wardle" -) - -// FakeFlunders implements FlunderInterface -type FakeFlunders struct { - Fake *FakeWardle - ns string -} - -var flundersResource = schema.GroupVersionResource{Group: "wardle.k8s.io", Version: "", Resource: "flunders"} - -var flundersKind = schema.GroupVersionKind{Group: "wardle.k8s.io", Version: "", Kind: "Flunder"} - -// Get takes name of the flunder, and returns the corresponding flunder object, and an error if there is any. -func (c *FakeFlunders) Get(name string, options v1.GetOptions) (result *wardle.Flunder, err error) { - obj, err := c.Fake. - Invokes(testing.NewGetAction(flundersResource, c.ns, name), &wardle.Flunder{}) - - if obj == nil { - return nil, err - } - return obj.(*wardle.Flunder), err -} - -// List takes label and field selectors, and returns the list of Flunders that match those selectors. -func (c *FakeFlunders) List(opts v1.ListOptions) (result *wardle.FlunderList, err error) { - obj, err := c.Fake. - Invokes(testing.NewListAction(flundersResource, flundersKind, c.ns, opts), &wardle.FlunderList{}) - - if obj == nil { - return nil, err - } - - label, _, _ := testing.ExtractFromListOptions(opts) - if label == nil { - label = labels.Everything() - } - list := &wardle.FlunderList{ListMeta: obj.(*wardle.FlunderList).ListMeta} - for _, item := range obj.(*wardle.FlunderList).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 flunders. -func (c *FakeFlunders) Watch(opts v1.ListOptions) (watch.Interface, error) { - return c.Fake. - InvokesWatch(testing.NewWatchAction(flundersResource, c.ns, opts)) - -} - -// Create takes the representation of a flunder and creates it. Returns the server's representation of the flunder, and an error, if there is any. -func (c *FakeFlunders) Create(flunder *wardle.Flunder) (result *wardle.Flunder, err error) { - obj, err := c.Fake. - Invokes(testing.NewCreateAction(flundersResource, c.ns, flunder), &wardle.Flunder{}) - - if obj == nil { - return nil, err - } - return obj.(*wardle.Flunder), err -} - -// Update takes the representation of a flunder and updates it. Returns the server's representation of the flunder, and an error, if there is any. -func (c *FakeFlunders) Update(flunder *wardle.Flunder) (result *wardle.Flunder, err error) { - obj, err := c.Fake. - Invokes(testing.NewUpdateAction(flundersResource, c.ns, flunder), &wardle.Flunder{}) - - if obj == nil { - return nil, err - } - return obj.(*wardle.Flunder), err -} - -// UpdateStatus was generated because the type contains a Status member. -// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). -func (c *FakeFlunders) UpdateStatus(flunder *wardle.Flunder) (*wardle.Flunder, error) { - obj, err := c.Fake. - Invokes(testing.NewUpdateSubresourceAction(flundersResource, "status", c.ns, flunder), &wardle.Flunder{}) - - if obj == nil { - return nil, err - } - return obj.(*wardle.Flunder), err -} - -// Delete takes name of the flunder and deletes it. Returns an error if one occurs. -func (c *FakeFlunders) Delete(name string, options *v1.DeleteOptions) error { - _, err := c.Fake. - Invokes(testing.NewDeleteAction(flundersResource, c.ns, name), &wardle.Flunder{}) - - return err -} - -// DeleteCollection deletes a collection of objects. -func (c *FakeFlunders) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { - action := testing.NewDeleteCollectionAction(flundersResource, c.ns, listOptions) - - _, err := c.Fake.Invokes(action, &wardle.FlunderList{}) - return err -} - -// Patch applies the patch and returns the patched flunder. -func (c *FakeFlunders) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *wardle.Flunder, err error) { - obj, err := c.Fake. - Invokes(testing.NewPatchSubresourceAction(flundersResource, c.ns, name, pt, data, subresources...), &wardle.Flunder{}) - - if obj == nil { - return nil, err - } - return obj.(*wardle.Flunder), err -} diff --git a/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/typed/wardle/internalversion/fischer.go b/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/typed/wardle/internalversion/fischer.go deleted file mode 100644 index f5d88411fd4..00000000000 --- a/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/typed/wardle/internalversion/fischer.go +++ /dev/null @@ -1,164 +0,0 @@ -/* -Copyright The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// Code generated by client-gen. DO NOT EDIT. - -package internalversion - -import ( - "time" - - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" - types "k8s.io/apimachinery/pkg/types" - watch "k8s.io/apimachinery/pkg/watch" - rest "k8s.io/client-go/rest" - wardle "k8s.io/sample-apiserver/pkg/apis/wardle" - scheme "k8s.io/sample-apiserver/pkg/client/clientset/internalversion/scheme" -) - -// FischersGetter has a method to return a FischerInterface. -// A group's client should implement this interface. -type FischersGetter interface { - Fischers() FischerInterface -} - -// FischerInterface has methods to work with Fischer resources. -type FischerInterface interface { - Create(*wardle.Fischer) (*wardle.Fischer, error) - Update(*wardle.Fischer) (*wardle.Fischer, error) - Delete(name string, options *v1.DeleteOptions) error - DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error - Get(name string, options v1.GetOptions) (*wardle.Fischer, error) - List(opts v1.ListOptions) (*wardle.FischerList, error) - Watch(opts v1.ListOptions) (watch.Interface, error) - Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *wardle.Fischer, err error) - FischerExpansion -} - -// fischers implements FischerInterface -type fischers struct { - client rest.Interface -} - -// newFischers returns a Fischers -func newFischers(c *WardleClient) *fischers { - return &fischers{ - client: c.RESTClient(), - } -} - -// Get takes name of the fischer, and returns the corresponding fischer object, and an error if there is any. -func (c *fischers) Get(name string, options v1.GetOptions) (result *wardle.Fischer, err error) { - result = &wardle.Fischer{} - err = c.client.Get(). - Resource("fischers"). - Name(name). - VersionedParams(&options, scheme.ParameterCodec). - Do(). - Into(result) - return -} - -// List takes label and field selectors, and returns the list of Fischers that match those selectors. -func (c *fischers) List(opts v1.ListOptions) (result *wardle.FischerList, err error) { - var timeout time.Duration - if opts.TimeoutSeconds != nil { - timeout = time.Duration(*opts.TimeoutSeconds) * time.Second - } - result = &wardle.FischerList{} - err = c.client.Get(). - Resource("fischers"). - VersionedParams(&opts, scheme.ParameterCodec). - Timeout(timeout). - Do(). - Into(result) - return -} - -// Watch returns a watch.Interface that watches the requested fischers. -func (c *fischers) Watch(opts v1.ListOptions) (watch.Interface, error) { - var timeout time.Duration - if opts.TimeoutSeconds != nil { - timeout = time.Duration(*opts.TimeoutSeconds) * time.Second - } - opts.Watch = true - return c.client.Get(). - Resource("fischers"). - VersionedParams(&opts, scheme.ParameterCodec). - Timeout(timeout). - Watch() -} - -// Create takes the representation of a fischer and creates it. Returns the server's representation of the fischer, and an error, if there is any. -func (c *fischers) Create(fischer *wardle.Fischer) (result *wardle.Fischer, err error) { - result = &wardle.Fischer{} - err = c.client.Post(). - Resource("fischers"). - Body(fischer). - Do(). - Into(result) - return -} - -// Update takes the representation of a fischer and updates it. Returns the server's representation of the fischer, and an error, if there is any. -func (c *fischers) Update(fischer *wardle.Fischer) (result *wardle.Fischer, err error) { - result = &wardle.Fischer{} - err = c.client.Put(). - Resource("fischers"). - Name(fischer.Name). - Body(fischer). - Do(). - Into(result) - return -} - -// Delete takes name of the fischer and deletes it. Returns an error if one occurs. -func (c *fischers) Delete(name string, options *v1.DeleteOptions) error { - return c.client.Delete(). - Resource("fischers"). - Name(name). - Body(options). - Do(). - Error() -} - -// DeleteCollection deletes a collection of objects. -func (c *fischers) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { - var timeout time.Duration - if listOptions.TimeoutSeconds != nil { - timeout = time.Duration(*listOptions.TimeoutSeconds) * time.Second - } - return c.client.Delete(). - Resource("fischers"). - VersionedParams(&listOptions, scheme.ParameterCodec). - Timeout(timeout). - Body(options). - Do(). - Error() -} - -// Patch applies the patch and returns the patched fischer. -func (c *fischers) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *wardle.Fischer, err error) { - result = &wardle.Fischer{} - err = c.client.Patch(pt). - Resource("fischers"). - SubResource(subresources...). - Name(name). - Body(data). - Do(). - Into(result) - return -} diff --git a/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/typed/wardle/internalversion/flunder.go b/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/typed/wardle/internalversion/flunder.go deleted file mode 100644 index 7d72dbf993a..00000000000 --- a/staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion/typed/wardle/internalversion/flunder.go +++ /dev/null @@ -1,191 +0,0 @@ -/* -Copyright The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// Code generated by client-gen. DO NOT EDIT. - -package internalversion - -import ( - "time" - - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" - types "k8s.io/apimachinery/pkg/types" - watch "k8s.io/apimachinery/pkg/watch" - rest "k8s.io/client-go/rest" - wardle "k8s.io/sample-apiserver/pkg/apis/wardle" - scheme "k8s.io/sample-apiserver/pkg/client/clientset/internalversion/scheme" -) - -// FlundersGetter has a method to return a FlunderInterface. -// A group's client should implement this interface. -type FlundersGetter interface { - Flunders(namespace string) FlunderInterface -} - -// FlunderInterface has methods to work with Flunder resources. -type FlunderInterface interface { - Create(*wardle.Flunder) (*wardle.Flunder, error) - Update(*wardle.Flunder) (*wardle.Flunder, error) - UpdateStatus(*wardle.Flunder) (*wardle.Flunder, error) - Delete(name string, options *v1.DeleteOptions) error - DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error - Get(name string, options v1.GetOptions) (*wardle.Flunder, error) - List(opts v1.ListOptions) (*wardle.FlunderList, error) - Watch(opts v1.ListOptions) (watch.Interface, error) - Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *wardle.Flunder, err error) - FlunderExpansion -} - -// flunders implements FlunderInterface -type flunders struct { - client rest.Interface - ns string -} - -// newFlunders returns a Flunders -func newFlunders(c *WardleClient, namespace string) *flunders { - return &flunders{ - client: c.RESTClient(), - ns: namespace, - } -} - -// Get takes name of the flunder, and returns the corresponding flunder object, and an error if there is any. -func (c *flunders) Get(name string, options v1.GetOptions) (result *wardle.Flunder, err error) { - result = &wardle.Flunder{} - err = c.client.Get(). - Namespace(c.ns). - Resource("flunders"). - Name(name). - VersionedParams(&options, scheme.ParameterCodec). - Do(). - Into(result) - return -} - -// List takes label and field selectors, and returns the list of Flunders that match those selectors. -func (c *flunders) List(opts v1.ListOptions) (result *wardle.FlunderList, err error) { - var timeout time.Duration - if opts.TimeoutSeconds != nil { - timeout = time.Duration(*opts.TimeoutSeconds) * time.Second - } - result = &wardle.FlunderList{} - err = c.client.Get(). - Namespace(c.ns). - Resource("flunders"). - VersionedParams(&opts, scheme.ParameterCodec). - Timeout(timeout). - Do(). - Into(result) - return -} - -// Watch returns a watch.Interface that watches the requested flunders. -func (c *flunders) Watch(opts v1.ListOptions) (watch.Interface, error) { - var timeout time.Duration - if opts.TimeoutSeconds != nil { - timeout = time.Duration(*opts.TimeoutSeconds) * time.Second - } - opts.Watch = true - return c.client.Get(). - Namespace(c.ns). - Resource("flunders"). - VersionedParams(&opts, scheme.ParameterCodec). - Timeout(timeout). - Watch() -} - -// Create takes the representation of a flunder and creates it. Returns the server's representation of the flunder, and an error, if there is any. -func (c *flunders) Create(flunder *wardle.Flunder) (result *wardle.Flunder, err error) { - result = &wardle.Flunder{} - err = c.client.Post(). - Namespace(c.ns). - Resource("flunders"). - Body(flunder). - Do(). - Into(result) - return -} - -// Update takes the representation of a flunder and updates it. Returns the server's representation of the flunder, and an error, if there is any. -func (c *flunders) Update(flunder *wardle.Flunder) (result *wardle.Flunder, err error) { - result = &wardle.Flunder{} - err = c.client.Put(). - Namespace(c.ns). - Resource("flunders"). - Name(flunder.Name). - Body(flunder). - Do(). - Into(result) - return -} - -// UpdateStatus was generated because the type contains a Status member. -// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). - -func (c *flunders) UpdateStatus(flunder *wardle.Flunder) (result *wardle.Flunder, err error) { - result = &wardle.Flunder{} - err = c.client.Put(). - Namespace(c.ns). - Resource("flunders"). - Name(flunder.Name). - SubResource("status"). - Body(flunder). - Do(). - Into(result) - return -} - -// Delete takes name of the flunder and deletes it. Returns an error if one occurs. -func (c *flunders) Delete(name string, options *v1.DeleteOptions) error { - return c.client.Delete(). - Namespace(c.ns). - Resource("flunders"). - Name(name). - Body(options). - Do(). - Error() -} - -// DeleteCollection deletes a collection of objects. -func (c *flunders) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { - var timeout time.Duration - if listOptions.TimeoutSeconds != nil { - timeout = time.Duration(*listOptions.TimeoutSeconds) * time.Second - } - return c.client.Delete(). - Namespace(c.ns). - Resource("flunders"). - VersionedParams(&listOptions, scheme.ParameterCodec). - Timeout(timeout). - Body(options). - Do(). - Error() -} - -// Patch applies the patch and returns the patched flunder. -func (c *flunders) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *wardle.Flunder, err error) { - result = &wardle.Flunder{} - err = c.client.Patch(pt). - Namespace(c.ns). - Resource("flunders"). - SubResource(subresources...). - Name(name). - Body(data). - Do(). - Into(result) - return -} diff --git a/staging/src/k8s.io/sample-apiserver/pkg/client/informers/internalversion/wardle/BUILD b/staging/src/k8s.io/sample-apiserver/pkg/client/informers/internalversion/wardle/BUILD deleted file mode 100644 index 90d6566cb50..00000000000 --- a/staging/src/k8s.io/sample-apiserver/pkg/client/informers/internalversion/wardle/BUILD +++ /dev/null @@ -1,30 +0,0 @@ -load("@io_bazel_rules_go//go:def.bzl", "go_library") - -go_library( - name = "go_default_library", - srcs = ["interface.go"], - importmap = "k8s.io/kubernetes/vendor/k8s.io/sample-apiserver/pkg/client/informers/internalversion/wardle", - importpath = "k8s.io/sample-apiserver/pkg/client/informers/internalversion/wardle", - visibility = ["//visibility:public"], - deps = [ - "//staging/src/k8s.io/sample-apiserver/pkg/client/informers/internalversion/internalinterfaces:go_default_library", - "//staging/src/k8s.io/sample-apiserver/pkg/client/informers/internalversion/wardle/internalversion:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [ - ":package-srcs", - "//staging/src/k8s.io/sample-apiserver/pkg/client/informers/internalversion/wardle/internalversion:all-srcs", - ], - tags = ["automanaged"], - visibility = ["//visibility:public"], -) diff --git a/staging/src/k8s.io/sample-apiserver/pkg/client/informers/internalversion/wardle/internalversion/fischer.go b/staging/src/k8s.io/sample-apiserver/pkg/client/informers/internalversion/wardle/internalversion/fischer.go deleted file mode 100644 index ede44539ac6..00000000000 --- a/staging/src/k8s.io/sample-apiserver/pkg/client/informers/internalversion/wardle/internalversion/fischer.go +++ /dev/null @@ -1,88 +0,0 @@ -/* -Copyright The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// Code generated by informer-gen. DO NOT EDIT. - -package internalversion - -import ( - time "time" - - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" - runtime "k8s.io/apimachinery/pkg/runtime" - watch "k8s.io/apimachinery/pkg/watch" - cache "k8s.io/client-go/tools/cache" - wardle "k8s.io/sample-apiserver/pkg/apis/wardle" - clientsetinternalversion "k8s.io/sample-apiserver/pkg/client/clientset/internalversion" - internalinterfaces "k8s.io/sample-apiserver/pkg/client/informers/internalversion/internalinterfaces" - internalversion "k8s.io/sample-apiserver/pkg/client/listers/wardle/internalversion" -) - -// FischerInformer provides access to a shared informer and lister for -// Fischers. -type FischerInformer interface { - Informer() cache.SharedIndexInformer - Lister() internalversion.FischerLister -} - -type fischerInformer struct { - factory internalinterfaces.SharedInformerFactory - tweakListOptions internalinterfaces.TweakListOptionsFunc -} - -// NewFischerInformer constructs a new informer for Fischer 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 NewFischerInformer(client clientsetinternalversion.Interface, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { - return NewFilteredFischerInformer(client, resyncPeriod, indexers, nil) -} - -// NewFilteredFischerInformer constructs a new informer for Fischer 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 NewFilteredFischerInformer(client clientsetinternalversion.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.Wardle().Fischers().List(options) - }, - WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { - if tweakListOptions != nil { - tweakListOptions(&options) - } - return client.Wardle().Fischers().Watch(options) - }, - }, - &wardle.Fischer{}, - resyncPeriod, - indexers, - ) -} - -func (f *fischerInformer) defaultInformer(client clientsetinternalversion.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { - return NewFilteredFischerInformer(client, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) -} - -func (f *fischerInformer) Informer() cache.SharedIndexInformer { - return f.factory.InformerFor(&wardle.Fischer{}, f.defaultInformer) -} - -func (f *fischerInformer) Lister() internalversion.FischerLister { - return internalversion.NewFischerLister(f.Informer().GetIndexer()) -} diff --git a/staging/src/k8s.io/sample-apiserver/pkg/client/informers/internalversion/wardle/internalversion/flunder.go b/staging/src/k8s.io/sample-apiserver/pkg/client/informers/internalversion/wardle/internalversion/flunder.go deleted file mode 100644 index 2fdd3ef0f91..00000000000 --- a/staging/src/k8s.io/sample-apiserver/pkg/client/informers/internalversion/wardle/internalversion/flunder.go +++ /dev/null @@ -1,89 +0,0 @@ -/* -Copyright The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// Code generated by informer-gen. DO NOT EDIT. - -package internalversion - -import ( - time "time" - - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" - runtime "k8s.io/apimachinery/pkg/runtime" - watch "k8s.io/apimachinery/pkg/watch" - cache "k8s.io/client-go/tools/cache" - wardle "k8s.io/sample-apiserver/pkg/apis/wardle" - clientsetinternalversion "k8s.io/sample-apiserver/pkg/client/clientset/internalversion" - internalinterfaces "k8s.io/sample-apiserver/pkg/client/informers/internalversion/internalinterfaces" - internalversion "k8s.io/sample-apiserver/pkg/client/listers/wardle/internalversion" -) - -// FlunderInformer provides access to a shared informer and lister for -// Flunders. -type FlunderInformer interface { - Informer() cache.SharedIndexInformer - Lister() internalversion.FlunderLister -} - -type flunderInformer struct { - factory internalinterfaces.SharedInformerFactory - tweakListOptions internalinterfaces.TweakListOptionsFunc - namespace string -} - -// NewFlunderInformer constructs a new informer for Flunder 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 NewFlunderInformer(client clientsetinternalversion.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { - return NewFilteredFlunderInformer(client, namespace, resyncPeriod, indexers, nil) -} - -// NewFilteredFlunderInformer constructs a new informer for Flunder 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 NewFilteredFlunderInformer(client clientsetinternalversion.Interface, namespace string, 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.Wardle().Flunders(namespace).List(options) - }, - WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { - if tweakListOptions != nil { - tweakListOptions(&options) - } - return client.Wardle().Flunders(namespace).Watch(options) - }, - }, - &wardle.Flunder{}, - resyncPeriod, - indexers, - ) -} - -func (f *flunderInformer) defaultInformer(client clientsetinternalversion.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { - return NewFilteredFlunderInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) -} - -func (f *flunderInformer) Informer() cache.SharedIndexInformer { - return f.factory.InformerFor(&wardle.Flunder{}, f.defaultInformer) -} - -func (f *flunderInformer) Lister() internalversion.FlunderLister { - return internalversion.NewFlunderLister(f.Informer().GetIndexer()) -} diff --git a/staging/src/k8s.io/sample-apiserver/pkg/client/listers/wardle/internalversion/fischer.go b/staging/src/k8s.io/sample-apiserver/pkg/client/listers/wardle/internalversion/fischer.go deleted file mode 100644 index 63ec3b50698..00000000000 --- a/staging/src/k8s.io/sample-apiserver/pkg/client/listers/wardle/internalversion/fischer.go +++ /dev/null @@ -1,65 +0,0 @@ -/* -Copyright The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// Code generated by lister-gen. DO NOT EDIT. - -package internalversion - -import ( - "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/labels" - "k8s.io/client-go/tools/cache" - wardle "k8s.io/sample-apiserver/pkg/apis/wardle" -) - -// FischerLister helps list Fischers. -type FischerLister interface { - // List lists all Fischers in the indexer. - List(selector labels.Selector) (ret []*wardle.Fischer, err error) - // Get retrieves the Fischer from the index for a given name. - Get(name string) (*wardle.Fischer, error) - FischerListerExpansion -} - -// fischerLister implements the FischerLister interface. -type fischerLister struct { - indexer cache.Indexer -} - -// NewFischerLister returns a new FischerLister. -func NewFischerLister(indexer cache.Indexer) FischerLister { - return &fischerLister{indexer: indexer} -} - -// List lists all Fischers in the indexer. -func (s *fischerLister) List(selector labels.Selector) (ret []*wardle.Fischer, err error) { - err = cache.ListAll(s.indexer, selector, func(m interface{}) { - ret = append(ret, m.(*wardle.Fischer)) - }) - return ret, err -} - -// Get retrieves the Fischer from the index for a given name. -func (s *fischerLister) Get(name string) (*wardle.Fischer, error) { - obj, exists, err := s.indexer.GetByKey(name) - if err != nil { - return nil, err - } - if !exists { - return nil, errors.NewNotFound(wardle.Resource("fischer"), name) - } - return obj.(*wardle.Fischer), nil -} diff --git a/staging/src/k8s.io/sample-apiserver/pkg/client/listers/wardle/internalversion/flunder.go b/staging/src/k8s.io/sample-apiserver/pkg/client/listers/wardle/internalversion/flunder.go deleted file mode 100644 index f15119845ee..00000000000 --- a/staging/src/k8s.io/sample-apiserver/pkg/client/listers/wardle/internalversion/flunder.go +++ /dev/null @@ -1,94 +0,0 @@ -/* -Copyright The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// Code generated by lister-gen. DO NOT EDIT. - -package internalversion - -import ( - "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/labels" - "k8s.io/client-go/tools/cache" - wardle "k8s.io/sample-apiserver/pkg/apis/wardle" -) - -// FlunderLister helps list Flunders. -type FlunderLister interface { - // List lists all Flunders in the indexer. - List(selector labels.Selector) (ret []*wardle.Flunder, err error) - // Flunders returns an object that can list and get Flunders. - Flunders(namespace string) FlunderNamespaceLister - FlunderListerExpansion -} - -// flunderLister implements the FlunderLister interface. -type flunderLister struct { - indexer cache.Indexer -} - -// NewFlunderLister returns a new FlunderLister. -func NewFlunderLister(indexer cache.Indexer) FlunderLister { - return &flunderLister{indexer: indexer} -} - -// List lists all Flunders in the indexer. -func (s *flunderLister) List(selector labels.Selector) (ret []*wardle.Flunder, err error) { - err = cache.ListAll(s.indexer, selector, func(m interface{}) { - ret = append(ret, m.(*wardle.Flunder)) - }) - return ret, err -} - -// Flunders returns an object that can list and get Flunders. -func (s *flunderLister) Flunders(namespace string) FlunderNamespaceLister { - return flunderNamespaceLister{indexer: s.indexer, namespace: namespace} -} - -// FlunderNamespaceLister helps list and get Flunders. -type FlunderNamespaceLister interface { - // List lists all Flunders in the indexer for a given namespace. - List(selector labels.Selector) (ret []*wardle.Flunder, err error) - // Get retrieves the Flunder from the indexer for a given namespace and name. - Get(name string) (*wardle.Flunder, error) - FlunderNamespaceListerExpansion -} - -// flunderNamespaceLister implements the FlunderNamespaceLister -// interface. -type flunderNamespaceLister struct { - indexer cache.Indexer - namespace string -} - -// List lists all Flunders in the indexer for a given namespace. -func (s flunderNamespaceLister) List(selector labels.Selector) (ret []*wardle.Flunder, err error) { - err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { - ret = append(ret, m.(*wardle.Flunder)) - }) - return ret, err -} - -// Get retrieves the Flunder from the indexer for a given namespace and name. -func (s flunderNamespaceLister) Get(name string) (*wardle.Flunder, error) { - obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) - if err != nil { - return nil, err - } - if !exists { - return nil, errors.NewNotFound(wardle.Resource("flunder"), name) - } - return obj.(*wardle.Flunder), nil -} diff --git a/staging/src/k8s.io/sample-apiserver/pkg/cmd/server/BUILD b/staging/src/k8s.io/sample-apiserver/pkg/cmd/server/BUILD index e51546ee850..db6621acce8 100644 --- a/staging/src/k8s.io/sample-apiserver/pkg/cmd/server/BUILD +++ b/staging/src/k8s.io/sample-apiserver/pkg/cmd/server/BUILD @@ -19,8 +19,8 @@ go_library( "//staging/src/k8s.io/sample-apiserver/pkg/admission/wardleinitializer:go_default_library", "//staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1:go_default_library", "//staging/src/k8s.io/sample-apiserver/pkg/apiserver:go_default_library", - "//staging/src/k8s.io/sample-apiserver/pkg/client/clientset/internalversion:go_default_library", - "//staging/src/k8s.io/sample-apiserver/pkg/client/informers/internalversion:go_default_library", + "//staging/src/k8s.io/sample-apiserver/pkg/client/clientset/versioned:go_default_library", + "//staging/src/k8s.io/sample-apiserver/pkg/client/informers/externalversions:go_default_library", "//vendor/github.com/spf13/cobra:go_default_library", ], ) diff --git a/staging/src/k8s.io/sample-apiserver/pkg/cmd/server/start.go b/staging/src/k8s.io/sample-apiserver/pkg/cmd/server/start.go index c9fa45850f5..e492925353e 100644 --- a/staging/src/k8s.io/sample-apiserver/pkg/cmd/server/start.go +++ b/staging/src/k8s.io/sample-apiserver/pkg/cmd/server/start.go @@ -31,8 +31,8 @@ import ( "k8s.io/sample-apiserver/pkg/admission/wardleinitializer" "k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1" "k8s.io/sample-apiserver/pkg/apiserver" - clientset "k8s.io/sample-apiserver/pkg/client/clientset/internalversion" - informers "k8s.io/sample-apiserver/pkg/client/informers/internalversion" + clientset "k8s.io/sample-apiserver/pkg/client/clientset/versioned" + informers "k8s.io/sample-apiserver/pkg/client/informers/externalversions" ) const defaultEtcdPathPrefix = "/registry/wardle.kubernetes.io" diff --git a/staging/src/k8s.io/sample-cli-plugin/Godeps/Godeps.json b/staging/src/k8s.io/sample-cli-plugin/Godeps/Godeps.json index a969e1453c8..678b85e3863 100644 --- a/staging/src/k8s.io/sample-cli-plugin/Godeps/Godeps.json +++ b/staging/src/k8s.io/sample-cli-plugin/Godeps/Godeps.json @@ -6,10 +6,50 @@ "./..." ], "Deps": [ + { + "ImportPath": "github.com/PuerkitoBio/purell", + "Rev": "8a290539e2e8629dbc4e6bad948158f790ec31f4" + }, + { + "ImportPath": "github.com/PuerkitoBio/urlesc", + "Rev": "5bd2802263f21d8788851d5305584c82a5c75d7e" + }, + { + "ImportPath": "github.com/davecgh/go-spew/spew", + "Rev": "782f4967f2dc4564575ca782fe2d04090b5faca8" + }, + { + "ImportPath": "github.com/emicklei/go-restful", + "Rev": "ff4f55a206334ef123e4f79bbf348980da81ca46" + }, + { + "ImportPath": "github.com/emicklei/go-restful/log", + "Rev": "ff4f55a206334ef123e4f79bbf348980da81ca46" + }, { "ImportPath": "github.com/evanphx/json-patch", "Rev": "36442dbdb585210f8d5a1b45e67aa323c197d5c4" }, + { + "ImportPath": "github.com/ghodss/yaml", + "Rev": "c7ce16629ff4cd059ed96ed06419dd3856fd3577" + }, + { + "ImportPath": "github.com/go-openapi/jsonpointer", + "Rev": "ef5f0afec364d3b9396b7b77b43dbe26bf1f8004" + }, + { + "ImportPath": "github.com/go-openapi/jsonreference", + "Rev": "8483a886a90412cd6858df4ea3483dce9c8e35a3" + }, + { + "ImportPath": "github.com/go-openapi/spec", + "Rev": "5bae59e25b21498baea7f9d46e9c147ec106a42e" + }, + { + "ImportPath": "github.com/go-openapi/swag", + "Rev": "5899d5c5e619fda5fa86e14795a835f473ca284c" + }, { "ImportPath": "github.com/gogo/protobuf/proto", "Rev": "342cbe0a04158f6dcb03ca0079991a51a4248c02" @@ -78,6 +118,18 @@ "ImportPath": "github.com/json-iterator/go", "Rev": "ab8a2e0c74be9d3be70b3184d9acc634935ded82" }, + { + "ImportPath": "github.com/mailru/easyjson/buffer", + "Rev": "2f5df55504ebc322e4d52d34df6a1f5b503bf26d" + }, + { + "ImportPath": "github.com/mailru/easyjson/jlexer", + "Rev": "2f5df55504ebc322e4d52d34df6a1f5b503bf26d" + }, + { + "ImportPath": "github.com/mailru/easyjson/jwriter", + "Rev": "2f5df55504ebc322e4d52d34df6a1f5b503bf26d" + }, { "ImportPath": "github.com/modern-go/concurrent", "Rev": "bacd9c7ef1dd9b15be4a9909b8ac7a4e313eec94" @@ -90,6 +142,10 @@ "ImportPath": "github.com/peterbourgon/diskv", "Rev": "5f041e8faa004a95c88a202771f4cc3e991971e6" }, + { + "ImportPath": "github.com/pkg/errors", + "Rev": "645ef00459ed84a119197bfb8d8205042c6df63d" + }, { "ImportPath": "github.com/spf13/cobra", "Rev": "c439c4fa093711d42e1b01acb1235b52004753c1" @@ -138,6 +194,10 @@ "ImportPath": "golang.org/x/sys/windows", "Rev": "95c6576299259db960f6c5b9b69ea52422860fce" }, + { + "ImportPath": "golang.org/x/text/cases", + "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01" + }, { "ImportPath": "golang.org/x/text/encoding", "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01" @@ -154,10 +214,22 @@ "ImportPath": "golang.org/x/text/encoding/unicode", "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01" }, + { + "ImportPath": "golang.org/x/text/internal", + "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01" + }, + { + "ImportPath": "golang.org/x/text/internal/tag", + "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01" + }, { "ImportPath": "golang.org/x/text/internal/utf8internal", "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01" }, + { + "ImportPath": "golang.org/x/text/language", + "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01" + }, { "ImportPath": "golang.org/x/text/runes", "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01" @@ -166,6 +238,10 @@ "ImportPath": "golang.org/x/text/secure/bidirule", "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01" }, + { + "ImportPath": "golang.org/x/text/secure/precis", + "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01" + }, { "ImportPath": "golang.org/x/text/transform", "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01" @@ -178,6 +254,10 @@ "ImportPath": "golang.org/x/text/unicode/norm", "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01" }, + { + "ImportPath": "golang.org/x/text/width", + "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01" + }, { "ImportPath": "golang.org/x/time/rate", "Rev": "f51c12702a4d776e4c1fa9b0fabab841babae631" @@ -258,6 +338,10 @@ "ImportPath": "k8s.io/api/certificates/v1beta1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/api/coordination/v1", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/api/coordination/v1beta1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" @@ -318,6 +402,10 @@ "ImportPath": "k8s.io/api/storage/v1beta1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/apimachinery/pkg/api/equality", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/apimachinery/pkg/api/errors", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" @@ -330,6 +418,10 @@ "ImportPath": "k8s.io/apimachinery/pkg/api/resource", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/apimachinery/pkg/api/validation", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/apimachinery/pkg/apis/meta/v1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" @@ -342,6 +434,10 @@ "ImportPath": "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/unstructuredscheme", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/apimachinery/pkg/apis/meta/v1/validation", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/apimachinery/pkg/apis/meta/v1beta1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" @@ -422,6 +518,10 @@ "ImportPath": "k8s.io/apimachinery/pkg/util/json", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/apimachinery/pkg/util/mergepatch", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/apimachinery/pkg/util/naming", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" @@ -438,6 +538,10 @@ "ImportPath": "k8s.io/apimachinery/pkg/util/sets", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/apimachinery/pkg/util/strategicpatch", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/apimachinery/pkg/util/validation", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" @@ -458,6 +562,10 @@ "ImportPath": "k8s.io/apimachinery/pkg/watch", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/apimachinery/third_party/forked/golang/json", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/apimachinery/third_party/forked/golang/reflect", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" @@ -474,6 +582,34 @@ "ImportPath": "k8s.io/cli-runtime/pkg/genericclioptions/resource", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/cli-runtime/pkg/kustomize/k8sdeps", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/cli-runtime/pkg/kustomize/k8sdeps/configmapandsecret", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/cli-runtime/pkg/kustomize/k8sdeps/kunstruct", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/cli-runtime/pkg/kustomize/k8sdeps/transformer", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/cli-runtime/pkg/kustomize/k8sdeps/transformer/hash", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/cli-runtime/pkg/kustomize/k8sdeps/transformer/patch", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/cli-runtime/pkg/kustomize/k8sdeps/validator", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/client-go/discovery", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" @@ -574,6 +710,94 @@ "ImportPath": "k8s.io/klog", "Rev": "8139d8cb77af419532b33dfa7dd09fbc5f1d344f" }, + { + "ImportPath": "k8s.io/kube-openapi/pkg/common", + "Rev": "c59034cc13d587f5ef4e85ca0ade0c1866ae8e1d" + }, + { + "ImportPath": "k8s.io/kube-openapi/pkg/util/proto", + "Rev": "c59034cc13d587f5ef4e85ca0ade0c1866ae8e1d" + }, + { + "ImportPath": "sigs.k8s.io/kustomize/pkg/commands/build", + "Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7" + }, + { + "ImportPath": "sigs.k8s.io/kustomize/pkg/constants", + "Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7" + }, + { + "ImportPath": "sigs.k8s.io/kustomize/pkg/expansion", + "Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7" + }, + { + "ImportPath": "sigs.k8s.io/kustomize/pkg/factory", + "Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7" + }, + { + "ImportPath": "sigs.k8s.io/kustomize/pkg/fs", + "Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7" + }, + { + "ImportPath": "sigs.k8s.io/kustomize/pkg/gvk", + "Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7" + }, + { + "ImportPath": "sigs.k8s.io/kustomize/pkg/ifc", + "Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7" + }, + { + "ImportPath": "sigs.k8s.io/kustomize/pkg/ifc/transformer", + "Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7" + }, + { + "ImportPath": "sigs.k8s.io/kustomize/pkg/internal/error", + "Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7" + }, + { + "ImportPath": "sigs.k8s.io/kustomize/pkg/loader", + "Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7" + }, + { + "ImportPath": "sigs.k8s.io/kustomize/pkg/patch", + "Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7" + }, + { + "ImportPath": "sigs.k8s.io/kustomize/pkg/patch/transformer", + "Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7" + }, + { + "ImportPath": "sigs.k8s.io/kustomize/pkg/resid", + "Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7" + }, + { + "ImportPath": "sigs.k8s.io/kustomize/pkg/resmap", + "Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7" + }, + { + "ImportPath": "sigs.k8s.io/kustomize/pkg/resource", + "Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7" + }, + { + "ImportPath": "sigs.k8s.io/kustomize/pkg/target", + "Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7" + }, + { + "ImportPath": "sigs.k8s.io/kustomize/pkg/transformers", + "Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7" + }, + { + "ImportPath": "sigs.k8s.io/kustomize/pkg/transformers/config", + "Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7" + }, + { + "ImportPath": "sigs.k8s.io/kustomize/pkg/transformers/config/defaultconfig", + "Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7" + }, + { + "ImportPath": "sigs.k8s.io/kustomize/pkg/types", + "Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7" + }, { "ImportPath": "sigs.k8s.io/yaml", "Rev": "fd68e9863619f6ec2fdd8625fe1f02e7c877e480" diff --git a/staging/src/k8s.io/sample-controller/Godeps/Godeps.json b/staging/src/k8s.io/sample-controller/Godeps/Godeps.json index 5cb9d139c77..d5636749f8a 100644 --- a/staging/src/k8s.io/sample-controller/Godeps/Godeps.json +++ b/staging/src/k8s.io/sample-controller/Godeps/Godeps.json @@ -242,6 +242,10 @@ "ImportPath": "k8s.io/api/certificates/v1beta1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/api/coordination/v1", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/api/coordination/v1beta1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" @@ -562,6 +566,10 @@ "ImportPath": "k8s.io/client-go/informers/coordination", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/client-go/informers/coordination/v1", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/client-go/informers/coordination/v1beta1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" @@ -810,6 +818,14 @@ "ImportPath": "k8s.io/client-go/kubernetes/typed/certificates/v1beta1/fake", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/client-go/kubernetes/typed/coordination/v1", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + { + "ImportPath": "k8s.io/client-go/kubernetes/typed/coordination/v1/fake", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/client-go/kubernetes/typed/coordination/v1beta1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" @@ -982,6 +998,10 @@ "ImportPath": "k8s.io/client-go/listers/certificates/v1beta1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/client-go/listers/coordination/v1", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/client-go/listers/coordination/v1beta1", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" diff --git a/staging/src/k8s.io/sample-controller/OWNERS b/staging/src/k8s.io/sample-controller/OWNERS index 791ce717973..0d8570da80d 100644 --- a/staging/src/k8s.io/sample-controller/OWNERS +++ b/staging/src/k8s.io/sample-controller/OWNERS @@ -3,7 +3,6 @@ approvers: - munnerz reviewers: - gregory-m -- kargakis - sttts - munnerz - nikhita diff --git a/test/OWNERS b/test/OWNERS index ea5cffadabb..832701e5309 100644 --- a/test/OWNERS +++ b/test/OWNERS @@ -27,6 +27,7 @@ reviewers: - zmerlynn - vishh - MaciekPytel # for test/e2e/common/autoscaling_utils.go + - oomichi approvers: - bowei # for test/e2e/{dns*,network}.go - cblecker diff --git a/test/cmd/apps.sh b/test/cmd/apps.sh index 8811ef0a0d8..4c50a20bc83 100755 --- a/test/cmd/apps.sh +++ b/test/cmd/apps.sh @@ -183,7 +183,7 @@ run_deployment_tests() { # Post-Condition: Deployment "nginx" is created. kube::test::get_object_assert 'deploy test-nginx-extensions' "{{$container_name_field}}" 'nginx' # and old generator was used, iow. old defaults are applied - output_message=$(kubectl get deployment.extensions/test-nginx-extensions -o jsonpath='{.spec.revisionHistoryLimit}') + output_message=$(kubectl get deployment.apps/test-nginx-extensions -o jsonpath='{.spec.revisionHistoryLimit}') kube::test::if_has_not_string "${output_message}" '2' # Ensure we can interact with deployments through extensions and apps endpoints output_message=$(kubectl get deployment.extensions -o=jsonpath='{.items[0].apiVersion}' 2>&1 "${kube_flags[@]}") @@ -275,7 +275,7 @@ run_deployment_tests() { # Clean up # Note that we should delete hpa first, otherwise it may fight with the deployment reaper. kubectl delete hpa nginx-deployment "${kube_flags[@]}" - kubectl delete deployment.extensions nginx-deployment "${kube_flags[@]}" + kubectl delete deployment.apps nginx-deployment "${kube_flags[@]}" ### Rollback a deployment # Pre-condition: no deployment exists @@ -290,10 +290,10 @@ run_deployment_tests() { kube::test::get_object_assert deployment "{{range.items}}{{$image_field0}}:{{end}}" "${IMAGE_DEPLOYMENT_R1}:" # Update the deployment (revision 2) kubectl apply -f hack/testdata/deployment-revision2.yaml "${kube_flags[@]}" - kube::test::get_object_assert deployment.extensions "{{range.items}}{{$image_field0}}:{{end}}" "${IMAGE_DEPLOYMENT_R2}:" + kube::test::get_object_assert deployment.apps "{{range.items}}{{$image_field0}}:{{end}}" "${IMAGE_DEPLOYMENT_R2}:" # Rollback to revision 1 with dry-run - should be no-op kubectl rollout undo deployment nginx --dry-run=true "${kube_flags[@]}" | grep "test-cmd" - kube::test::get_object_assert deployment.extensions "{{range.items}}{{$image_field0}}:{{end}}" "${IMAGE_DEPLOYMENT_R2}:" + kube::test::get_object_assert deployment.apps "{{range.items}}{{$image_field0}}:{{end}}" "${IMAGE_DEPLOYMENT_R2}:" # Rollback to revision 1 kubectl rollout undo deployment nginx --to-revision=1 "${kube_flags[@]}" sleep 1 diff --git a/test/cmd/core.sh b/test/cmd/core.sh index 656ef330f57..5f645c2d5c5 100755 --- a/test/cmd/core.sh +++ b/test/cmd/core.sh @@ -739,7 +739,7 @@ run_secrets_test() { # Post-condition: secret exists and has expected values kube::test::get_object_assert 'secret/test-secret --namespace=test-secrets' "{{$id_field}}" 'test-secret' kube::test::get_object_assert 'secret/test-secret --namespace=test-secrets' "{{$secret_type}}" 'kubernetes.io/dockerconfigjson' - [[ "$(kubectl get secret/test-secret --namespace=test-secrets -o yaml "${kube_flags[@]}" | grep '.dockerconfigjson:')" ]] + [[ "$(kubectl get secret/test-secret --namespace=test-secrets -o yaml "${kube_flags[@]}" | grep '.dockerconfigjson: eyJhdXRocyI6eyJodHRwczovL2luZGV4LmRvY2tlci5pby92MS8iOnsidXNlcm5hbWUiOiJ0ZXN0LXVzZXIiLCJwYXNzd29yZCI6InRlc3QtcGFzc3dvcmQiLCJlbWFpbCI6InRlc3QtdXNlckB0ZXN0LmNvbSIsImF1dGgiOiJkR1Z6ZEMxMWMyVnlPblJsYzNRdGNHRnpjM2R2Y21RPSJ9fX0=')" ]] # Clean-up kubectl delete secret test-secret --namespace=test-secrets diff --git a/test/cmd/diff.sh b/test/cmd/diff.sh index 6d0d5a12752..1441f7c4f6e 100755 --- a/test/cmd/diff.sh +++ b/test/cmd/diff.sh @@ -40,3 +40,20 @@ run_kubectl_diff_tests() { set +o nounset set +o errexit } + +run_kubectl_diff_same_names() { + set -o nounset + set -o errexit + + create_and_use_new_namespace + kube::log::status "Test kubectl diff with multiple resources with the same name" + + output_message=$(KUBECTL_EXTERNAL_DIFF=find kubectl diff -Rf hack/testdata/diff/) + kube::test::if_has_string "${output_message}" 'v1\.Pod\..*\.test' + kube::test::if_has_string "${output_message}" 'apps\.v1\.Deployment\..*\.test' + kube::test::if_has_string "${output_message}" 'v1\.ConfigMap\..*\.test' + kube::test::if_has_string "${output_message}" 'v1\.Secret\..*\.test' + + set +o nounset + set +o errexit +} diff --git a/test/cmd/generic-resources.sh b/test/cmd/generic-resources.sh index 66eb82f5c06..a24410d6e22 100755 --- a/test/cmd/generic-resources.sh +++ b/test/cmd/generic-resources.sh @@ -268,10 +268,10 @@ run_recursive_resources_tests() { kube::test::get_object_assert deployment "{{range.items}}{{$id_field}}:{{end}}" 'nginx:' kube::test::get_object_assert deployment "{{range.items}}{{$image_field0}}:{{end}}" "${IMAGE_DEPLOYMENT_R1}:" # Command - output_message=$(kubectl convert --local -f hack/testdata/deployment-revision1.yaml --output-version=apps/v1beta1 -o yaml "${kube_flags[@]}") + output_message=$(kubectl convert --local -f hack/testdata/deployment-revision1.yaml --output-version=apps/v1 -o yaml "${kube_flags[@]}") # Post-condition: apiVersion is still extensions/v1beta1 in the live deployment, but command output is the new value kube::test::get_object_assert 'deployment nginx' "{{ .apiVersion }}" 'extensions/v1beta1' - kube::test::if_has_string "${output_message}" "apps/v1beta1" + kube::test::if_has_string "${output_message}" "apps/v1" # Clean up kubectl delete deployment nginx "${kube_flags[@]}" diff --git a/test/cmd/get.sh b/test/cmd/get.sh index 26ffcf4dda7..f14e65cb804 100755 --- a/test/cmd/get.sh +++ b/test/cmd/get.sh @@ -333,10 +333,14 @@ run_kubectl_all_namespace_tests() { kubectl create "${kube_flags[@]}" serviceaccount test -n all-ns-test-1 kubectl create "${kube_flags[@]}" namespace all-ns-test-2 kubectl create "${kube_flags[@]}" serviceaccount test -n all-ns-test-2 - # Ensure listing across namespaces displays the namespace + # Ensure listing across namespaces displays the namespace (--all-namespaces) output_message=$(kubectl get serviceaccounts --all-namespaces "${kube_flags[@]}") kube::test::if_has_string "${output_message}" "all-ns-test-1" kube::test::if_has_string "${output_message}" "all-ns-test-2" + # Ensure listing across namespaces displays the namespace (-A) + output_message=$(kubectl get serviceaccounts -A "${kube_flags[@]}") + kube::test::if_has_string "${output_message}" "all-ns-test-1" + kube::test::if_has_string "${output_message}" "all-ns-test-2" # Clean up kubectl delete "${kube_flags[@]}" namespace all-ns-test-1 kubectl delete "${kube_flags[@]}" namespace all-ns-test-2 diff --git a/test/cmd/legacy-script.sh b/test/cmd/legacy-script.sh index 49c849e8b37..c838ee4d928 100755 --- a/test/cmd/legacy-script.sh +++ b/test/cmd/legacy-script.sh @@ -473,6 +473,7 @@ runTests() { # Kubectl diff # ################ record_command run_kubectl_diff_tests + record_command run_kubectl_diff_same_names ############### # Kubectl get # diff --git a/test/cmd/rbac.sh b/test/cmd/rbac.sh index 65136050ddd..e874c7e8bea 100755 --- a/test/cmd/rbac.sh +++ b/test/cmd/rbac.sh @@ -34,10 +34,10 @@ run_clusterroles_tests() { kube::test::get_object_assert clusterrole/pod-admin "{{range.rules}}{{range.verbs}}{{.}}:{{end}}{{end}}" '\*:' kube::test::get_object_assert clusterrole/pod-admin "{{range.rules}}{{range.resources}}{{.}}:{{end}}{{end}}" 'pods:' kube::test::get_object_assert clusterrole/pod-admin "{{range.rules}}{{range.apiGroups}}{{.}}:{{end}}{{end}}" ':' - kubectl create "${kube_flags[@]}" clusterrole resource-reader --verb=get,list --resource=pods,deployments.extensions + kubectl create "${kube_flags[@]}" clusterrole resource-reader --verb=get,list --resource=pods,deployments.apps kube::test::get_object_assert clusterrole/resource-reader "{{range.rules}}{{range.verbs}}{{.}}:{{end}}{{end}}" 'get:list:get:list:' kube::test::get_object_assert clusterrole/resource-reader "{{range.rules}}{{range.resources}}{{.}}:{{end}}{{end}}" 'pods:deployments:' - kube::test::get_object_assert clusterrole/resource-reader "{{range.rules}}{{range.apiGroups}}{{.}}:{{end}}{{end}}" ':extensions:' + kube::test::get_object_assert clusterrole/resource-reader "{{range.rules}}{{range.apiGroups}}{{.}}:{{end}}{{end}}" ':apps:' kubectl create "${kube_flags[@]}" clusterrole resourcename-reader --verb=get,list --resource=pods --resource-name=foo kube::test::get_object_assert clusterrole/resourcename-reader "{{range.rules}}{{range.verbs}}{{.}}:{{end}}{{end}}" 'get:list:' kube::test::get_object_assert clusterrole/resourcename-reader "{{range.rules}}{{range.resources}}{{.}}:{{end}}{{end}}" 'pods:' @@ -124,10 +124,10 @@ run_role_tests() { output_message=$(! kubectl create "${kube_flags[@]}" role invalid-pod-admin --verb=* --resource=invalid-resource 2>&1) kube::test::if_has_string "${output_message}" "the server doesn't have a resource type \"invalid-resource\"" # Create Role from command (resource + group) - kubectl create "${kube_flags[@]}" role group-reader --verb=get,list --resource=deployments.extensions + kubectl create "${kube_flags[@]}" role group-reader --verb=get,list --resource=deployments.apps kube::test::get_object_assert role/group-reader "{{range.rules}}{{range.verbs}}{{.}}:{{end}}{{end}}" 'get:list:' kube::test::get_object_assert role/group-reader "{{range.rules}}{{range.resources}}{{.}}:{{end}}{{end}}" 'deployments:' - kube::test::get_object_assert role/group-reader "{{range.rules}}{{range.apiGroups}}{{.}}:{{end}}{{end}}" 'extensions:' + kube::test::get_object_assert role/group-reader "{{range.rules}}{{range.apiGroups}}{{.}}:{{end}}{{end}}" 'apps:' output_message=$(! kubectl create "${kube_flags[@]}" role invalid-group --verb=get,list --resource=deployments.invalid-group 2>&1) kube::test::if_has_string "${output_message}" "the server doesn't have a resource type \"deployments\" in group \"invalid-group\"" # Create Role from command (resource / subresource) @@ -136,10 +136,10 @@ run_role_tests() { kube::test::get_object_assert role/subresource-reader "{{range.rules}}{{range.resources}}{{.}}:{{end}}{{end}}" 'pods/status:' kube::test::get_object_assert role/subresource-reader "{{range.rules}}{{range.apiGroups}}{{.}}:{{end}}{{end}}" ':' # Create Role from command (resource + group / subresource) - kubectl create "${kube_flags[@]}" role group-subresource-reader --verb=get,list --resource=replicasets.extensions/scale + kubectl create "${kube_flags[@]}" role group-subresource-reader --verb=get,list --resource=replicasets.apps/scale kube::test::get_object_assert role/group-subresource-reader "{{range.rules}}{{range.verbs}}{{.}}:{{end}}{{end}}" 'get:list:' kube::test::get_object_assert role/group-subresource-reader "{{range.rules}}{{range.resources}}{{.}}:{{end}}{{end}}" 'replicasets/scale:' - kube::test::get_object_assert role/group-subresource-reader "{{range.rules}}{{range.apiGroups}}{{.}}:{{end}}{{end}}" 'extensions:' + kube::test::get_object_assert role/group-subresource-reader "{{range.rules}}{{range.apiGroups}}{{.}}:{{end}}{{end}}" 'apps:' output_message=$(! kubectl create "${kube_flags[@]}" role invalid-group --verb=get,list --resource=rs.invalid-group/scale 2>&1) kube::test::if_has_string "${output_message}" "the server doesn't have a resource type \"rs\" in group \"invalid-group\"" # Create Role from command (resource + resourcename) @@ -149,10 +149,10 @@ run_role_tests() { kube::test::get_object_assert role/resourcename-reader "{{range.rules}}{{range.apiGroups}}{{.}}:{{end}}{{end}}" ':' kube::test::get_object_assert role/resourcename-reader "{{range.rules}}{{range.resourceNames}}{{.}}:{{end}}{{end}}" 'foo:' # Create Role from command (multi-resources) - kubectl create "${kube_flags[@]}" role resource-reader --verb=get,list --resource=pods/status,deployments.extensions + kubectl create "${kube_flags[@]}" role resource-reader --verb=get,list --resource=pods/status,deployments.apps kube::test::get_object_assert role/resource-reader "{{range.rules}}{{range.verbs}}{{.}}:{{end}}{{end}}" 'get:list:get:list:' kube::test::get_object_assert role/resource-reader "{{range.rules}}{{range.resources}}{{.}}:{{end}}{{end}}" 'pods/status:deployments:' - kube::test::get_object_assert role/resource-reader "{{range.rules}}{{range.apiGroups}}{{.}}:{{end}}{{end}}" ':extensions:' + kube::test::get_object_assert role/resource-reader "{{range.rules}}{{range.apiGroups}}{{.}}:{{end}}{{end}}" ':apps:' set +o nounset set +o errexit diff --git a/test/cmd/run.sh b/test/cmd/run.sh index 45e7eb56945..38d03854b66 100755 --- a/test/cmd/run.sh +++ b/test/cmd/run.sh @@ -43,7 +43,7 @@ run_kubectl_run_tests() { # Command kubectl run nginx-extensions "--image=$IMAGE_NGINX" "${kube_flags[@]}" # Post-Condition: Deployment "nginx" is created - kube::test::get_object_assert deployment.extensions "{{range.items}}{{$id_field}}:{{end}}" 'nginx-extensions:' + kube::test::get_object_assert deployment.apps "{{range.items}}{{$id_field}}:{{end}}" 'nginx-extensions:' # new generator was used output_message=$(kubectl get deployment.apps/nginx-extensions -o jsonpath='{.spec.revisionHistoryLimit}') kube::test::if_has_string "${output_message}" '10' diff --git a/test/conformance/testdata/OWNERS b/test/conformance/testdata/OWNERS index f948d2de612..3dfb0c82ba4 100644 --- a/test/conformance/testdata/OWNERS +++ b/test/conformance/testdata/OWNERS @@ -4,6 +4,9 @@ options: reviewers: - bgrant0607 - smarterclayton + - spiffxp + - timothysc + - dims approvers: - bgrant0607 - smarterclayton diff --git a/test/e2e/apimachinery/BUILD b/test/e2e/apimachinery/BUILD index ea3fbc2d673..ba37035994e 100644 --- a/test/e2e/apimachinery/BUILD +++ b/test/e2e/apimachinery/BUILD @@ -20,6 +20,7 @@ go_library( "generated_clientset.go", "initializers.go", "namespace.go", + "resource_quota.go", "table_conversion.go", "watch.go", "webhook.go", @@ -29,6 +30,7 @@ go_library( "//pkg/api/v1/pod:go_default_library", "//pkg/apis/rbac/v1beta1:go_default_library", "//pkg/printers:go_default_library", + "//pkg/quota/v1/evaluator/core:go_default_library", "//staging/src/k8s.io/api/admissionregistration/v1alpha1:go_default_library", "//staging/src/k8s.io/api/admissionregistration/v1beta1:go_default_library", "//staging/src/k8s.io/api/apps/v1:go_default_library", @@ -36,9 +38,9 @@ go_library( "//staging/src/k8s.io/api/batch/v1:go_default_library", "//staging/src/k8s.io/api/batch/v1beta1:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library", - "//staging/src/k8s.io/api/extensions/v1beta1:go_default_library", "//staging/src/k8s.io/api/rbac/v1:go_default_library", "//staging/src/k8s.io/api/rbac/v1beta1:go_default_library", + "//staging/src/k8s.io/api/scheduling/v1beta1:go_default_library", "//staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1:go_default_library", "//staging/src/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset:go_default_library", "//staging/src/k8s.io/apiextensions-apiserver/test/integration:go_default_library", @@ -46,6 +48,7 @@ go_library( "//staging/src/k8s.io/apimachinery/pkg/api/equality:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/meta:go_default_library", + "//staging/src/k8s.io/apimachinery/pkg/api/resource:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1beta1:go_default_library", diff --git a/test/e2e/apimachinery/aggregator.go b/test/e2e/apimachinery/aggregator.go index e3d964ddd3a..8c515047b14 100644 --- a/test/e2e/apimachinery/aggregator.go +++ b/test/e2e/apimachinery/aggregator.go @@ -179,7 +179,7 @@ func TestSampleAPIServer(f *framework.Framework, image string) { // kubectl create -f deploy.yaml deploymentName := "sample-apiserver-deployment" - etcdImage := "quay.io/coreos/etcd:v3.2.24" + etcdImage := "quay.io/coreos/etcd:v3.3.10" podLabels := map[string]string{"app": "sample-apiserver", "apiserver": "true"} replicas := int32(1) zero := int64(0) diff --git a/test/e2e/apimachinery/garbage_collector.go b/test/e2e/apimachinery/garbage_collector.go index 875e390ae8b..7ff06539001 100644 --- a/test/e2e/apimachinery/garbage_collector.go +++ b/test/e2e/apimachinery/garbage_collector.go @@ -21,10 +21,10 @@ import ( "sync/atomic" "time" + apps "k8s.io/api/apps/v1" batchv1 "k8s.io/api/batch/v1" batchv1beta1 "k8s.io/api/batch/v1beta1" "k8s.io/api/core/v1" - "k8s.io/api/extensions/v1beta1" apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" apiextensionsclientset "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset" apiextensionstestserver "k8s.io/apiextensions-apiserver/test/integration/fixtures" @@ -111,17 +111,17 @@ func getPodTemplateSpec(labels map[string]string) v1.PodTemplateSpec { } } -func newOwnerDeployment(f *framework.Framework, deploymentName string, labels map[string]string) *v1beta1.Deployment { +func newOwnerDeployment(f *framework.Framework, deploymentName string, labels map[string]string) *apps.Deployment { replicas := int32(2) - return &v1beta1.Deployment{ + return &apps.Deployment{ ObjectMeta: metav1.ObjectMeta{ Name: deploymentName, }, - Spec: v1beta1.DeploymentSpec{ + Spec: apps.DeploymentSpec{ Replicas: &replicas, Selector: &metav1.LabelSelector{MatchLabels: labels}, - Strategy: v1beta1.DeploymentStrategy{ - Type: v1beta1.RollingUpdateDeploymentStrategyType, + Strategy: apps.DeploymentStrategy{ + Type: apps.RollingUpdateDeploymentStrategyType, }, Template: getPodTemplateSpec(labels), }, @@ -185,7 +185,7 @@ func verifyRemainingObjects(f *framework.Framework, objects map[string]int) (boo By(fmt.Sprintf("expected %d pods, got %d pods", num, len(pods.Items))) } case "Deployments": - deployments, err := f.ClientSet.ExtensionsV1beta1().Deployments(f.Namespace.Name).List(metav1.ListOptions{}) + deployments, err := f.ClientSet.AppsV1().Deployments(f.Namespace.Name).List(metav1.ListOptions{}) if err != nil { return false, fmt.Errorf("failed to list deployments: %v", err) } @@ -194,7 +194,7 @@ func verifyRemainingObjects(f *framework.Framework, objects map[string]int) (boo By(fmt.Sprintf("expected %d Deployments, got %d Deployments", num, len(deployments.Items))) } case "ReplicaSets": - rs, err := f.ClientSet.ExtensionsV1beta1().ReplicaSets(f.Namespace.Name).List(metav1.ListOptions{}) + rs, err := f.ClientSet.AppsV1().ReplicaSets(f.Namespace.Name).List(metav1.ListOptions{}) if err != nil { return false, fmt.Errorf("failed to list rs: %v", err) } @@ -480,8 +480,8 @@ var _ = SIGDescribe("Garbage collector", func() { */ framework.ConformanceIt("should delete RS created by deployment when not orphaning", func() { clientSet := f.ClientSet - deployClient := clientSet.ExtensionsV1beta1().Deployments(f.Namespace.Name) - rsClient := clientSet.ExtensionsV1beta1().ReplicaSets(f.Namespace.Name) + deployClient := clientSet.AppsV1().Deployments(f.Namespace.Name) + rsClient := clientSet.AppsV1().ReplicaSets(f.Namespace.Name) deploymentName := "simpletest.deployment" uniqLabels := getUniqLabel("gctest", "delete_rs") deployment := newOwnerDeployment(f, deploymentName, uniqLabels) @@ -539,8 +539,8 @@ var _ = SIGDescribe("Garbage collector", func() { */ framework.ConformanceIt("should orphan RS created by deployment when deleteOptions.PropagationPolicy is Orphan", func() { clientSet := f.ClientSet - deployClient := clientSet.ExtensionsV1beta1().Deployments(f.Namespace.Name) - rsClient := clientSet.ExtensionsV1beta1().ReplicaSets(f.Namespace.Name) + deployClient := clientSet.AppsV1().Deployments(f.Namespace.Name) + rsClient := clientSet.AppsV1().ReplicaSets(f.Namespace.Name) deploymentName := "simpletest.deployment" uniqLabels := getUniqLabel("gctest", "orphan_rs") deployment := newOwnerDeployment(f, deploymentName, uniqLabels) @@ -593,7 +593,7 @@ var _ = SIGDescribe("Garbage collector", func() { aggregatedError := utilerrors.NewAggregate(errList) framework.Failf("Failed to verify remaining deployments, rs, and pods: %v", aggregatedError) } - rs, err := clientSet.ExtensionsV1beta1().ReplicaSets(f.Namespace.Name).List(metav1.ListOptions{}) + rs, err := clientSet.AppsV1().ReplicaSets(f.Namespace.Name).List(metav1.ListOptions{}) if err != nil { framework.Failf("Failed to list ReplicaSet %v", err) } diff --git a/test/e2e/apimachinery/initializers.go b/test/e2e/apimachinery/initializers.go index 1adfd2d0471..7420f320e4b 100644 --- a/test/e2e/apimachinery/initializers.go +++ b/test/e2e/apimachinery/initializers.go @@ -25,8 +25,8 @@ import ( . "github.com/onsi/gomega" "k8s.io/api/admissionregistration/v1alpha1" + apps "k8s.io/api/apps/v1" "k8s.io/api/core/v1" - "k8s.io/api/extensions/v1beta1" "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" @@ -242,7 +242,7 @@ var _ = SIGDescribe("Initializers [Feature:Initializers]", func() { // create a replicaset rs := newReplicaset() - persistedRS, err := c.ExtensionsV1beta1().ReplicaSets(ns).Create(rs) + persistedRS, err := c.AppsV1().ReplicaSets(ns).Create(rs) Expect(err).NotTo(HaveOccurred(), "failed to create replicaset %s in namespace: %s", persistedRS.Name, ns) // wait for replicaset controller to confirm that it has handled the creation err = waitForRSObservedGeneration(c, persistedRS.Namespace, persistedRS.Name, persistedRS.Generation) @@ -250,7 +250,7 @@ var _ = SIGDescribe("Initializers [Feature:Initializers]", func() { // update the replicaset spec to trigger a resync patch := []byte(`{"spec":{"minReadySeconds":5}}`) - persistedRS, err = c.ExtensionsV1beta1().ReplicaSets(ns).Patch(persistedRS.Name, types.StrategicMergePatchType, patch) + persistedRS, err = c.AppsV1().ReplicaSets(ns).Patch(persistedRS.Name, types.StrategicMergePatchType, patch) Expect(err).NotTo(HaveOccurred(), "failed to apply to replicaset %s in namespace %s a strategic merge patch: %s", persistedRS.Name, ns, patch) // wait for replicaset controller to confirm that it has handle the spec update @@ -302,15 +302,15 @@ func newUninitializedPod(podName string) *v1.Pod { return pod } -func newReplicaset() *v1beta1.ReplicaSet { +func newReplicaset() *apps.ReplicaSet { name := "initializer-test-replicaset" replicas := int32(1) labels := map[string]string{"initializer-test": "single-replicaset"} - return &v1beta1.ReplicaSet{ + return &apps.ReplicaSet{ ObjectMeta: metav1.ObjectMeta{ Name: name, }, - Spec: v1beta1.ReplicaSetSpec{ + Spec: apps.ReplicaSetSpec{ Replicas: &replicas, Template: v1.PodTemplateSpec{ ObjectMeta: metav1.ObjectMeta{ @@ -411,7 +411,7 @@ func cleanupInitializer(c clientset.Interface, initializerConfigName, initialize // waits till the RS status.observedGeneration matches metadata.generation. func waitForRSObservedGeneration(c clientset.Interface, ns, name string, generation int64) error { return wait.PollImmediate(1*time.Second, 1*time.Minute, func() (bool, error) { - rs, err := c.ExtensionsV1beta1().ReplicaSets(ns).Get(name, metav1.GetOptions{}) + rs, err := c.AppsV1().ReplicaSets(ns).Get(name, metav1.GetOptions{}) if err != nil { return false, err } diff --git a/test/e2e/scheduling/resource_quota.go b/test/e2e/apimachinery/resource_quota.go similarity index 98% rename from test/e2e/scheduling/resource_quota.go rename to test/e2e/apimachinery/resource_quota.go index 3c33caa3909..c34ae9c7d35 100644 --- a/test/e2e/scheduling/resource_quota.go +++ b/test/e2e/apimachinery/resource_quota.go @@ -14,14 +14,14 @@ See the License for the specific language governing permissions and limitations under the License. */ -package scheduling +package apimachinery import ( "fmt" "time" + appsv1 "k8s.io/api/apps/v1" "k8s.io/api/core/v1" - extensions "k8s.io/api/extensions/v1beta1" "k8s.io/api/scheduling/v1beta1" "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/resource" @@ -40,6 +40,7 @@ import ( const ( // how long to wait for a resource quota update to occur resourceQuotaTimeout = 30 * time.Second + podName = "pfpod" ) var classGold string = "gold" @@ -464,27 +465,27 @@ var _ = SIGDescribe("ResourceQuota", func() { By("Ensuring resource quota status is calculated") usedResources := v1.ResourceList{} usedResources[v1.ResourceQuotas] = resource.MustParse("1") - usedResources[v1.ResourceName("count/replicasets.extensions")] = resource.MustParse("0") + usedResources[v1.ResourceName("count/replicasets.apps")] = resource.MustParse("0") err = waitForResourceQuota(f.ClientSet, f.Namespace.Name, quotaName, usedResources) Expect(err).NotTo(HaveOccurred()) By("Creating a ReplicaSet") replicaSet := newTestReplicaSetForQuota("test-rs", "nginx", 0) - replicaSet, err = f.ClientSet.ExtensionsV1beta1().ReplicaSets(f.Namespace.Name).Create(replicaSet) + replicaSet, err = f.ClientSet.AppsV1().ReplicaSets(f.Namespace.Name).Create(replicaSet) Expect(err).NotTo(HaveOccurred()) By("Ensuring resource quota status captures replicaset creation") usedResources = v1.ResourceList{} - usedResources[v1.ResourceName("count/replicasets.extensions")] = resource.MustParse("1") + usedResources[v1.ResourceName("count/replicasets.apps")] = resource.MustParse("1") err = waitForResourceQuota(f.ClientSet, f.Namespace.Name, quotaName, usedResources) Expect(err).NotTo(HaveOccurred()) By("Deleting a ReplicaSet") - err = f.ClientSet.ExtensionsV1beta1().ReplicaSets(f.Namespace.Name).Delete(replicaSet.Name, nil) + err = f.ClientSet.AppsV1().ReplicaSets(f.Namespace.Name).Delete(replicaSet.Name, nil) Expect(err).NotTo(HaveOccurred()) By("Ensuring resource quota status released usage") - usedResources[v1.ResourceName("count/replicasets.extensions")] = resource.MustParse("0") + usedResources[v1.ResourceName("count/replicasets.apps")] = resource.MustParse("0") err = waitForResourceQuota(f.ClientSet, f.Namespace.Name, quotaName, usedResources) Expect(err).NotTo(HaveOccurred()) }) @@ -1351,7 +1352,7 @@ func newTestResourceQuota(name string) *v1.ResourceQuota { hard[core.V1ResourceByStorageClass(classGold, v1.ResourcePersistentVolumeClaims)] = resource.MustParse("10") hard[core.V1ResourceByStorageClass(classGold, v1.ResourceRequestsStorage)] = resource.MustParse("10Gi") // test quota on discovered resource type - hard[v1.ResourceName("count/replicasets.extensions")] = resource.MustParse("5") + hard[v1.ResourceName("count/replicasets.apps")] = resource.MustParse("5") // test quota on extended resource hard[v1.ResourceName(v1.DefaultResourceRequestsPrefix+extendedResourceName)] = resource.MustParse("3") return &v1.ResourceQuota{ @@ -1453,14 +1454,15 @@ func newTestReplicationControllerForQuota(name, image string, replicas int32) *v } // newTestReplicaSetForQuota returns a simple replica set -func newTestReplicaSetForQuota(name, image string, replicas int32) *extensions.ReplicaSet { +func newTestReplicaSetForQuota(name, image string, replicas int32) *appsv1.ReplicaSet { zero := int64(0) - return &extensions.ReplicaSet{ + return &appsv1.ReplicaSet{ ObjectMeta: metav1.ObjectMeta{ Name: name, }, - Spec: extensions.ReplicaSetSpec{ + Spec: appsv1.ReplicaSetSpec{ Replicas: &replicas, + Selector: &metav1.LabelSelector{MatchLabels: map[string]string{"name": name}}, Template: v1.PodTemplateSpec{ ObjectMeta: metav1.ObjectMeta{ Labels: map[string]string{"name": name}, diff --git a/test/e2e/apimachinery/watch.go b/test/e2e/apimachinery/watch.go index f26edbee0ff..394577d8255 100644 --- a/test/e2e/apimachinery/watch.go +++ b/test/e2e/apimachinery/watch.go @@ -345,7 +345,7 @@ var _ = SIGDescribe("Watchers", func() { resourceVersion := "0" for i := 0; i < iterations; i++ { wc, err := c.CoreV1().ConfigMaps(ns).Watch(metav1.ListOptions{ResourceVersion: resourceVersion}) - Expect(err).NotTo(HaveOccurred()) + Expect(err).NotTo(HaveOccurred(), "Failed to watch configmaps in the namespace %s", ns) wcs = append(wcs, wc) resourceVersion = waitForNextConfigMapEvent(wcs[0]).ResourceVersion for _, wc := range wcs[1:] { @@ -472,18 +472,18 @@ func produceConfigMapEvents(f *framework.Framework, stopc <-chan struct{}, minWa case createEvent: cm.Name = name(i) _, err := c.CoreV1().ConfigMaps(ns).Create(cm) - Expect(err).NotTo(HaveOccurred()) + Expect(err).NotTo(HaveOccurred(), "Failed to create configmap %s in namespace %s", cm.Name, ns) existing = append(existing, i) i += 1 case updateEvent: idx := rand.Intn(len(existing)) cm.Name = name(existing[idx]) _, err := c.CoreV1().ConfigMaps(ns).Update(cm) - Expect(err).NotTo(HaveOccurred()) + Expect(err).NotTo(HaveOccurred(), "Failed to update configmap %s in namespace %s", cm.Name, ns) case deleteEvent: idx := rand.Intn(len(existing)) err := c.CoreV1().ConfigMaps(ns).Delete(name(existing[idx]), &metav1.DeleteOptions{}) - Expect(err).NotTo(HaveOccurred()) + Expect(err).NotTo(HaveOccurred(), "Failed to delete configmap %s in namespace %s", name(existing[idx]), ns) existing = append(existing[:idx], existing[idx+1:]...) default: framework.Failf("Unsupported event operation: %d", op) diff --git a/test/e2e/apps/BUILD b/test/e2e/apps/BUILD index 3ac8ab15068..75b06a53607 100644 --- a/test/e2e/apps/BUILD +++ b/test/e2e/apps/BUILD @@ -36,7 +36,7 @@ go_library( "//pkg/controller/replicaset:go_default_library", "//pkg/controller/replication:go_default_library", "//pkg/master/ports:go_default_library", - "//pkg/scheduler/cache:go_default_library", + "//pkg/scheduler/nodeinfo:go_default_library", "//staging/src/k8s.io/api/apps/v1:go_default_library", "//staging/src/k8s.io/api/batch/v1:go_default_library", "//staging/src/k8s.io/api/batch/v1beta1:go_default_library", diff --git a/test/e2e/apps/cronjob.go b/test/e2e/apps/cronjob.go index ec2b10a146f..018be8e450a 100644 --- a/test/e2e/apps/cronjob.go +++ b/test/e2e/apps/cronjob.go @@ -60,21 +60,21 @@ var _ = SIGDescribe("CronJob", func() { cronJob := newTestCronJob("concurrent", "*/1 * * * ?", batchv1beta1.AllowConcurrent, sleepCommand, nil) cronJob, err := createCronJob(f.ClientSet, f.Namespace.Name, cronJob) - Expect(err).NotTo(HaveOccurred()) + Expect(err).NotTo(HaveOccurred(), "Failed to create CronJob in namespace %s", f.Namespace.Name) By("Ensuring more than one job is running at a time") err = waitForActiveJobs(f.ClientSet, f.Namespace.Name, cronJob.Name, 2) - Expect(err).NotTo(HaveOccurred()) + Expect(err).NotTo(HaveOccurred(), "Failed to wait for active jobs in CronJob %s in namespace %s", cronJob.Name, f.Namespace.Name) By("Ensuring at least two running jobs exists by listing jobs explicitly") jobs, err := f.ClientSet.BatchV1().Jobs(f.Namespace.Name).List(metav1.ListOptions{}) - Expect(err).NotTo(HaveOccurred()) + Expect(err).NotTo(HaveOccurred(), "Failed to list the CronJobs in namespace %s", f.Namespace.Name) activeJobs, _ := filterActiveJobs(jobs) Expect(len(activeJobs) >= 2).To(BeTrue()) By("Removing cronjob") err = deleteCronJob(f.ClientSet, f.Namespace.Name, cronJob.Name) - Expect(err).NotTo(HaveOccurred()) + Expect(err).NotTo(HaveOccurred(), "Failed to delete CronJob %s in namespace %s", cronJob.Name, f.Namespace.Name) }) // suspended should not schedule jobs @@ -85,7 +85,7 @@ var _ = SIGDescribe("CronJob", func() { t := true cronJob.Spec.Suspend = &t cronJob, err := createCronJob(f.ClientSet, f.Namespace.Name, cronJob) - Expect(err).NotTo(HaveOccurred()) + Expect(err).NotTo(HaveOccurred(), "Failed to create CronJob in namespace %s", f.Namespace.Name) By("Ensuring no jobs are scheduled") err = waitForNoJobs(f.ClientSet, f.Namespace.Name, cronJob.Name, false) @@ -93,12 +93,12 @@ var _ = SIGDescribe("CronJob", func() { By("Ensuring no job exists by listing jobs explicitly") jobs, err := f.ClientSet.BatchV1().Jobs(f.Namespace.Name).List(metav1.ListOptions{}) - Expect(err).NotTo(HaveOccurred()) + Expect(err).NotTo(HaveOccurred(), "Failed to list the CronJobs in namespace %s", f.Namespace.Name) Expect(jobs.Items).To(HaveLen(0)) By("Removing cronjob") err = deleteCronJob(f.ClientSet, f.Namespace.Name, cronJob.Name) - Expect(err).NotTo(HaveOccurred()) + Expect(err).NotTo(HaveOccurred(), "Failed to delete CronJob %s in namespace %s", cronJob.Name, f.Namespace.Name) }) // only single active job is allowed for ForbidConcurrent @@ -107,20 +107,20 @@ var _ = SIGDescribe("CronJob", func() { cronJob := newTestCronJob("forbid", "*/1 * * * ?", batchv1beta1.ForbidConcurrent, sleepCommand, nil) cronJob, err := createCronJob(f.ClientSet, f.Namespace.Name, cronJob) - Expect(err).NotTo(HaveOccurred()) + Expect(err).NotTo(HaveOccurred(), "Failed to create CronJob in namespace %s", f.Namespace.Name) By("Ensuring a job is scheduled") err = waitForActiveJobs(f.ClientSet, f.Namespace.Name, cronJob.Name, 1) - Expect(err).NotTo(HaveOccurred()) + Expect(err).NotTo(HaveOccurred(), "Failed to schedule CronJob %s", cronJob.Name) By("Ensuring exactly one is scheduled") cronJob, err = getCronJob(f.ClientSet, f.Namespace.Name, cronJob.Name) - Expect(err).NotTo(HaveOccurred()) + Expect(err).NotTo(HaveOccurred(), "Failed to get CronJob %s", cronJob.Name) Expect(cronJob.Status.Active).Should(HaveLen(1)) By("Ensuring exactly one running job exists by listing jobs explicitly") jobs, err := f.ClientSet.BatchV1().Jobs(f.Namespace.Name).List(metav1.ListOptions{}) - Expect(err).NotTo(HaveOccurred()) + Expect(err).NotTo(HaveOccurred(), "Failed to list the CronJobs in namespace %s", f.Namespace.Name) activeJobs, _ := filterActiveJobs(jobs) Expect(activeJobs).To(HaveLen(1)) @@ -130,7 +130,7 @@ var _ = SIGDescribe("CronJob", func() { By("Removing cronjob") err = deleteCronJob(f.ClientSet, f.Namespace.Name, cronJob.Name) - Expect(err).NotTo(HaveOccurred()) + Expect(err).NotTo(HaveOccurred(), "Failed to delete CronJob %s in namespace %s", cronJob.Name, f.Namespace.Name) }) // only single active job is allowed for ReplaceConcurrent @@ -139,30 +139,30 @@ var _ = SIGDescribe("CronJob", func() { cronJob := newTestCronJob("replace", "*/1 * * * ?", batchv1beta1.ReplaceConcurrent, sleepCommand, nil) cronJob, err := createCronJob(f.ClientSet, f.Namespace.Name, cronJob) - Expect(err).NotTo(HaveOccurred()) + Expect(err).NotTo(HaveOccurred(), "Failed to create CronJob in namespace %s", f.Namespace.Name) By("Ensuring a job is scheduled") err = waitForActiveJobs(f.ClientSet, f.Namespace.Name, cronJob.Name, 1) - Expect(err).NotTo(HaveOccurred()) + Expect(err).NotTo(HaveOccurred(), "Failed to schedule CronJob %s in namespace %s", cronJob.Name, f.Namespace.Name) By("Ensuring exactly one is scheduled") cronJob, err = getCronJob(f.ClientSet, f.Namespace.Name, cronJob.Name) - Expect(err).NotTo(HaveOccurred()) + Expect(err).NotTo(HaveOccurred(), "Failed to get CronJob %s", cronJob.Name) Expect(cronJob.Status.Active).Should(HaveLen(1)) By("Ensuring exactly one running job exists by listing jobs explicitly") jobs, err := f.ClientSet.BatchV1().Jobs(f.Namespace.Name).List(metav1.ListOptions{}) - Expect(err).NotTo(HaveOccurred()) + Expect(err).NotTo(HaveOccurred(), "Failed to list the jobs in namespace %s", f.Namespace.Name) activeJobs, _ := filterActiveJobs(jobs) Expect(activeJobs).To(HaveLen(1)) By("Ensuring the job is replaced with a new one") err = waitForJobReplaced(f.ClientSet, f.Namespace.Name, jobs.Items[0].Name) - Expect(err).NotTo(HaveOccurred()) + Expect(err).NotTo(HaveOccurred(), "Failed to replace CronJob %s in namespace %s", jobs.Items[0].Name, f.Namespace.Name) By("Removing cronjob") err = deleteCronJob(f.ClientSet, f.Namespace.Name, cronJob.Name) - Expect(err).NotTo(HaveOccurred()) + Expect(err).NotTo(HaveOccurred(), "Failed to delete CronJob %s in namespace %s", cronJob.Name, f.Namespace.Name) }) // shouldn't give us unexpected warnings @@ -171,7 +171,7 @@ var _ = SIGDescribe("CronJob", func() { cronJob := newTestCronJob("concurrent", "*/1 * * * ?", batchv1beta1.AllowConcurrent, nil, nil) cronJob, err := createCronJob(f.ClientSet, f.Namespace.Name, cronJob) - Expect(err).NotTo(HaveOccurred()) + Expect(err).NotTo(HaveOccurred(), "Failed to create CronJob in namespace %s", f.Namespace.Name) By("Ensuring at least two jobs and at least one finished job exists by listing jobs explicitly") err = waitForJobsAtLeast(f.ClientSet, f.Namespace.Name, 2) @@ -185,7 +185,7 @@ var _ = SIGDescribe("CronJob", func() { By("Removing cronjob") err = deleteCronJob(f.ClientSet, f.Namespace.Name, cronJob.Name) - Expect(err).NotTo(HaveOccurred()) + Expect(err).NotTo(HaveOccurred(), "Failed to delete CronJob %s in namespace %s", cronJob.Name, f.Namespace.Name) }) // deleted jobs should be removed from the active list @@ -194,7 +194,7 @@ var _ = SIGDescribe("CronJob", func() { cronJob := newTestCronJob("forbid", "*/1 * * * ?", batchv1beta1.ForbidConcurrent, sleepCommand, nil) cronJob, err := createCronJob(f.ClientSet, f.Namespace.Name, cronJob) - Expect(err).NotTo(HaveOccurred()) + Expect(err).NotTo(HaveOccurred(), "Failed to create CronJob in namespace %s", f.Namespace.Name) By("Ensuring a job is scheduled") err = waitForActiveJobs(f.ClientSet, f.Namespace.Name, cronJob.Name, 1) @@ -250,8 +250,10 @@ var _ = SIGDescribe("CronJob", func() { Expect(len(finishedJobs) == 1).To(BeTrue()) // Job should get deleted when the next job finishes the next minute - By("Ensuring this job does not exist anymore") - err = waitForJobNotExist(f.ClientSet, f.Namespace.Name, finishedJobs[0]) + By("Ensuring this job and its pods does not exist anymore") + err = waitForJobToDisappear(f.ClientSet, f.Namespace.Name, finishedJobs[0]) + Expect(err).NotTo(HaveOccurred()) + err = waitForJobsPodToDisappear(f.ClientSet, f.Namespace.Name, finishedJobs[0]) Expect(err).NotTo(HaveOccurred()) By("Ensuring there is 1 finished job by listing jobs explicitly") @@ -380,8 +382,8 @@ func waitForJobNotActive(c clientset.Interface, ns, cronJobName, jobName string) }) } -// Wait for a job to not exist by listing jobs explicitly. -func waitForJobNotExist(c clientset.Interface, ns string, targetJob *batchv1.Job) error { +// Wait for a job to disappear by listing them explicitly. +func waitForJobToDisappear(c clientset.Interface, ns string, targetJob *batchv1.Job) error { return wait.Poll(framework.Poll, cronJobTimeout, func() (bool, error) { jobs, err := c.BatchV1().Jobs(ns).List(metav1.ListOptions{}) if err != nil { @@ -397,6 +399,18 @@ func waitForJobNotExist(c clientset.Interface, ns string, targetJob *batchv1.Job }) } +// Wait for a pod to disappear by listing them explicitly. +func waitForJobsPodToDisappear(c clientset.Interface, ns string, targetJob *batchv1.Job) error { + return wait.Poll(framework.Poll, cronJobTimeout, func() (bool, error) { + options := metav1.ListOptions{LabelSelector: fmt.Sprintf("controller-uid=%s", targetJob.UID)} + pods, err := c.CoreV1().Pods(ns).List(options) + if err != nil { + return false, err + } + return len(pods.Items) == 0, nil + }) +} + // Wait for a job to be replaced with a new one. func waitForJobReplaced(c clientset.Interface, ns, previousJobName string) error { return wait.Poll(framework.Poll, cronJobTimeout, func() (bool, error) { diff --git a/test/e2e/apps/daemon_set.go b/test/e2e/apps/daemon_set.go index acd62243136..ee4176adc13 100644 --- a/test/e2e/apps/daemon_set.go +++ b/test/e2e/apps/daemon_set.go @@ -35,7 +35,7 @@ import ( podutil "k8s.io/kubernetes/pkg/api/v1/pod" extensionsinternal "k8s.io/kubernetes/pkg/apis/extensions" "k8s.io/kubernetes/pkg/controller/daemon" - schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" + schedulernodeinfo "k8s.io/kubernetes/pkg/scheduler/nodeinfo" "k8s.io/kubernetes/test/e2e/framework" . "github.com/onsi/ginkgo" @@ -639,7 +639,7 @@ func checkAtLeastOneNewPod(c clientset.Interface, ns string, label map[string]st // canScheduleOnNode checks if a given DaemonSet can schedule pods on the given node func canScheduleOnNode(node v1.Node, ds *apps.DaemonSet) bool { newPod := daemon.NewPod(ds, node.Name) - nodeInfo := schedulercache.NewNodeInfo() + nodeInfo := schedulernodeinfo.NewNodeInfo() nodeInfo.SetNode(&node) fit, _, err := daemon.Predicates(newPod, nodeInfo) if err != nil { diff --git a/test/e2e/apps/disruption.go b/test/e2e/apps/disruption.go index 8ae257565fa..22d0e0fef30 100644 --- a/test/e2e/apps/disruption.go +++ b/test/e2e/apps/disruption.go @@ -22,8 +22,9 @@ import ( . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" + + apps "k8s.io/api/apps/v1" "k8s.io/api/core/v1" - extensions "k8s.io/api/extensions/v1beta1" policy "k8s.io/api/policy/v1beta1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/intstr" @@ -310,12 +311,12 @@ func createReplicaSetOrDie(cs kubernetes.Interface, ns string, size int32, exclu } } - rs := &extensions.ReplicaSet{ + rs := &apps.ReplicaSet{ ObjectMeta: metav1.ObjectMeta{ Name: "rs", Namespace: ns, }, - Spec: extensions.ReplicaSetSpec{ + Spec: apps.ReplicaSetSpec{ Replicas: &size, Selector: &metav1.LabelSelector{ MatchLabels: map[string]string{"foo": "bar"}, @@ -331,6 +332,6 @@ func createReplicaSetOrDie(cs kubernetes.Interface, ns string, size int32, exclu }, } - _, err := cs.ExtensionsV1beta1().ReplicaSets(ns).Create(rs) + _, err := cs.AppsV1().ReplicaSets(ns).Create(rs) framework.ExpectNoError(err, "Creating replica set %q in namespace %q", rs.Name, ns) } diff --git a/test/e2e/auth/audit.go b/test/e2e/auth/audit.go index 0bf6b9e197a..d6b07adfcda 100644 --- a/test/e2e/auth/audit.go +++ b/test/e2e/auth/audit.go @@ -54,23 +54,609 @@ var ( patch, _ = json.Marshal(jsonpatch.Patch{}) ) -var _ = SIGDescribe("Advanced Audit", func() { +// TODO: Get rid of [DisabledForLargeClusters] when feature request #53455 is ready. +var _ = SIGDescribe("Advanced Audit [DisabledForLargeClusters]", func() { f := framework.NewDefaultFramework("audit") + var namespace string BeforeEach(func() { framework.SkipUnlessProviderIs("gce") + namespace = f.Namespace.Name }) - // TODO: Get rid of [DisabledForLargeClusters] when feature request #53455 is ready. - It("should audit API calls [DisabledForLargeClusters]", func() { - namespace := f.Namespace.Name + It("should audit API calls to create, get, update, patch, delete, list, watch pods.", func() { + pod := &apiv1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "audit-pod", + }, + Spec: apiv1.PodSpec{ + Containers: []apiv1.Container{{ + Name: "pause", + Image: imageutils.GetPauseImageName(), + }}, + }, + } + updatePod := func(pod *apiv1.Pod) {} + f.PodClient().CreateSync(pod) + + _, err := f.PodClient().Get(pod.Name, metav1.GetOptions{}) + framework.ExpectNoError(err, "failed to get audit-pod") + + podChan, err := f.PodClient().Watch(watchOptions) + framework.ExpectNoError(err, "failed to create watch for pods") + podChan.Stop() + + f.PodClient().Update(pod.Name, updatePod) + + _, err = f.PodClient().List(metav1.ListOptions{}) + framework.ExpectNoError(err, "failed to list pods") + + _, err = f.PodClient().Patch(pod.Name, types.JSONPatchType, patch) + framework.ExpectNoError(err, "failed to patch pod") + + f.PodClient().DeleteSync(pod.Name, &metav1.DeleteOptions{}, framework.DefaultPodDeletionTimeout) + + expectEvents(f, []utils.AuditEvent{ + { + Level: auditinternal.LevelRequestResponse, + Stage: auditinternal.StageResponseComplete, + RequestURI: fmt.Sprintf("/api/v1/namespaces/%s/pods", namespace), + Verb: "create", + Code: 201, + User: auditTestUser, + Resource: "pods", + Namespace: namespace, + RequestObject: true, + ResponseObject: true, + AuthorizeDecision: "allow", + }, { + Level: auditinternal.LevelRequest, + Stage: auditinternal.StageResponseComplete, + RequestURI: fmt.Sprintf("/api/v1/namespaces/%s/pods/audit-pod", namespace), + Verb: "get", + Code: 200, + User: auditTestUser, + Resource: "pods", + Namespace: namespace, + RequestObject: false, + ResponseObject: false, + AuthorizeDecision: "allow", + }, { + Level: auditinternal.LevelRequest, + Stage: auditinternal.StageResponseComplete, + RequestURI: fmt.Sprintf("/api/v1/namespaces/%s/pods", namespace), + Verb: "list", + Code: 200, + User: auditTestUser, + Resource: "pods", + Namespace: namespace, + RequestObject: false, + ResponseObject: false, + AuthorizeDecision: "allow", + }, { + Level: auditinternal.LevelRequest, + Stage: auditinternal.StageResponseStarted, + RequestURI: fmt.Sprintf("/api/v1/namespaces/%s/pods?timeout=%ds&timeoutSeconds=%d&watch=true", namespace, watchTestTimeout, watchTestTimeout), + Verb: "watch", + Code: 200, + User: auditTestUser, + Resource: "pods", + Namespace: namespace, + RequestObject: false, + ResponseObject: false, + AuthorizeDecision: "allow", + }, { + Level: auditinternal.LevelRequest, + Stage: auditinternal.StageResponseComplete, + RequestURI: fmt.Sprintf("/api/v1/namespaces/%s/pods?timeout=%ds&timeoutSeconds=%d&watch=true", namespace, watchTestTimeout, watchTestTimeout), + Verb: "watch", + Code: 200, + User: auditTestUser, + Resource: "pods", + Namespace: namespace, + RequestObject: false, + ResponseObject: false, + AuthorizeDecision: "allow", + }, { + Level: auditinternal.LevelRequestResponse, + Stage: auditinternal.StageResponseComplete, + RequestURI: fmt.Sprintf("/api/v1/namespaces/%s/pods/audit-pod", namespace), + Verb: "update", + Code: 200, + User: auditTestUser, + Resource: "pods", + Namespace: namespace, + RequestObject: true, + ResponseObject: true, + AuthorizeDecision: "allow", + }, { + Level: auditinternal.LevelRequestResponse, + Stage: auditinternal.StageResponseComplete, + RequestURI: fmt.Sprintf("/api/v1/namespaces/%s/pods/audit-pod", namespace), + Verb: "patch", + Code: 200, + User: auditTestUser, + Resource: "pods", + Namespace: namespace, + RequestObject: true, + ResponseObject: true, + AuthorizeDecision: "allow", + }, { + Level: auditinternal.LevelRequestResponse, + Stage: auditinternal.StageResponseComplete, + RequestURI: fmt.Sprintf("/api/v1/namespaces/%s/pods/audit-pod", namespace), + Verb: "delete", + Code: 200, + User: auditTestUser, + Resource: "pods", + Namespace: namespace, + RequestObject: true, + ResponseObject: true, + AuthorizeDecision: "allow", + }, + }) + }) + + It("should audit API calls to create, get, update, patch, delete, list, watch deployments.", func() { + podLabels := map[string]string{"name": "audit-deployment-pod"} + d := framework.NewDeployment("audit-deployment", int32(1), podLabels, "redis", imageutils.GetE2EImage(imageutils.Redis), apps.RecreateDeploymentStrategyType) + + _, err := f.ClientSet.AppsV1().Deployments(namespace).Create(d) + framework.ExpectNoError(err, "failed to create audit-deployment") + + _, err = f.ClientSet.AppsV1().Deployments(namespace).Get(d.Name, metav1.GetOptions{}) + framework.ExpectNoError(err, "failed to get audit-deployment") + + deploymentChan, err := f.ClientSet.AppsV1().Deployments(namespace).Watch(watchOptions) + framework.ExpectNoError(err, "failed to create watch for deployments") + deploymentChan.Stop() + + _, err = f.ClientSet.AppsV1().Deployments(namespace).Update(d) + framework.ExpectNoError(err, "failed to update audit-deployment") + + _, err = f.ClientSet.AppsV1().Deployments(namespace).Patch(d.Name, types.JSONPatchType, patch) + framework.ExpectNoError(err, "failed to patch deployment") + + _, err = f.ClientSet.AppsV1().Deployments(namespace).List(metav1.ListOptions{}) + framework.ExpectNoError(err, "failed to create list deployments") + + err = f.ClientSet.AppsV1().Deployments(namespace).Delete("audit-deployment", &metav1.DeleteOptions{}) + framework.ExpectNoError(err, "failed to delete deployments") + + expectEvents(f, []utils.AuditEvent{ + { + Level: auditinternal.LevelRequestResponse, + Stage: auditinternal.StageResponseComplete, + RequestURI: fmt.Sprintf("/apis/apps/v1/namespaces/%s/deployments", namespace), + Verb: "create", + Code: 201, + User: auditTestUser, + Resource: "deployments", + Namespace: namespace, + RequestObject: true, + ResponseObject: true, + AuthorizeDecision: "allow", + }, { + Level: auditinternal.LevelRequest, + Stage: auditinternal.StageResponseComplete, + RequestURI: fmt.Sprintf("/apis/apps/v1/namespaces/%s/deployments/audit-deployment", namespace), + Verb: "get", + Code: 200, + User: auditTestUser, + Resource: "deployments", + Namespace: namespace, + RequestObject: false, + ResponseObject: false, + AuthorizeDecision: "allow", + }, { + Level: auditinternal.LevelRequest, + Stage: auditinternal.StageResponseComplete, + RequestURI: fmt.Sprintf("/apis/apps/v1/namespaces/%s/deployments", namespace), + Verb: "list", + Code: 200, + User: auditTestUser, + Resource: "deployments", + Namespace: namespace, + RequestObject: false, + ResponseObject: false, + AuthorizeDecision: "allow", + }, { + Level: auditinternal.LevelRequest, + Stage: auditinternal.StageResponseStarted, + RequestURI: fmt.Sprintf("/apis/apps/v1/namespaces/%s/deployments?timeout=%ds&timeoutSeconds=%d&watch=true", namespace, watchTestTimeout, watchTestTimeout), + Verb: "watch", + Code: 200, + User: auditTestUser, + Resource: "deployments", + Namespace: namespace, + RequestObject: false, + ResponseObject: false, + AuthorizeDecision: "allow", + }, { + Level: auditinternal.LevelRequest, + Stage: auditinternal.StageResponseComplete, + RequestURI: fmt.Sprintf("/apis/apps/v1/namespaces/%s/deployments?timeout=%ds&timeoutSeconds=%d&watch=true", namespace, watchTestTimeout, watchTestTimeout), + Verb: "watch", + Code: 200, + User: auditTestUser, + Resource: "deployments", + Namespace: namespace, + RequestObject: false, + ResponseObject: false, + AuthorizeDecision: "allow", + }, { + Level: auditinternal.LevelRequestResponse, + Stage: auditinternal.StageResponseComplete, + RequestURI: fmt.Sprintf("/apis/apps/v1/namespaces/%s/deployments/audit-deployment", namespace), + Verb: "update", + Code: 200, + User: auditTestUser, + Resource: "deployments", + Namespace: namespace, + RequestObject: true, + ResponseObject: true, + AuthorizeDecision: "allow", + }, { + Level: auditinternal.LevelRequestResponse, + Stage: auditinternal.StageResponseComplete, + RequestURI: fmt.Sprintf("/apis/apps/v1/namespaces/%s/deployments/audit-deployment", namespace), + Verb: "patch", + Code: 200, + User: auditTestUser, + Resource: "deployments", + Namespace: namespace, + RequestObject: true, + ResponseObject: true, + AuthorizeDecision: "allow", + }, { + Level: auditinternal.LevelRequestResponse, + Stage: auditinternal.StageResponseComplete, + RequestURI: fmt.Sprintf("/apis/apps/v1/namespaces/%s/deployments/audit-deployment", namespace), + Verb: "delete", + Code: 200, + User: auditTestUser, + Resource: "deployments", + Namespace: namespace, + RequestObject: true, + ResponseObject: true, + AuthorizeDecision: "allow", + }, + }) + }) + + It("should audit API calls to create, get, update, patch, delete, list, watch configmaps.", func() { + configMap := &apiv1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: "audit-configmap", + }, + Data: map[string]string{ + "map-key": "map-value", + }, + } + + _, err := f.ClientSet.CoreV1().ConfigMaps(namespace).Create(configMap) + framework.ExpectNoError(err, "failed to create audit-configmap") + + _, err = f.ClientSet.CoreV1().ConfigMaps(namespace).Get(configMap.Name, metav1.GetOptions{}) + framework.ExpectNoError(err, "failed to get audit-configmap") + + configMapChan, err := f.ClientSet.CoreV1().ConfigMaps(namespace).Watch(watchOptions) + framework.ExpectNoError(err, "failed to create watch for config maps") + configMapChan.Stop() + + _, err = f.ClientSet.CoreV1().ConfigMaps(namespace).Update(configMap) + framework.ExpectNoError(err, "failed to update audit-configmap") + + _, err = f.ClientSet.CoreV1().ConfigMaps(namespace).Patch(configMap.Name, types.JSONPatchType, patch) + framework.ExpectNoError(err, "failed to patch configmap") + + _, err = f.ClientSet.CoreV1().ConfigMaps(namespace).List(metav1.ListOptions{}) + framework.ExpectNoError(err, "failed to list config maps") + + err = f.ClientSet.CoreV1().ConfigMaps(namespace).Delete(configMap.Name, &metav1.DeleteOptions{}) + framework.ExpectNoError(err, "failed to delete audit-configmap") + + expectEvents(f, []utils.AuditEvent{ + { + Level: auditinternal.LevelMetadata, + Stage: auditinternal.StageResponseComplete, + RequestURI: fmt.Sprintf("/api/v1/namespaces/%s/configmaps", namespace), + Verb: "create", + Code: 201, + User: auditTestUser, + Resource: "configmaps", + Namespace: namespace, + RequestObject: false, + ResponseObject: false, + AuthorizeDecision: "allow", + }, { + Level: auditinternal.LevelMetadata, + Stage: auditinternal.StageResponseComplete, + RequestURI: fmt.Sprintf("/api/v1/namespaces/%s/configmaps/audit-configmap", namespace), + Verb: "get", + Code: 200, + User: auditTestUser, + Resource: "configmaps", + Namespace: namespace, + RequestObject: false, + ResponseObject: false, + AuthorizeDecision: "allow", + }, { + Level: auditinternal.LevelMetadata, + Stage: auditinternal.StageResponseComplete, + RequestURI: fmt.Sprintf("/api/v1/namespaces/%s/configmaps", namespace), + Verb: "list", + Code: 200, + User: auditTestUser, + Resource: "configmaps", + Namespace: namespace, + RequestObject: false, + ResponseObject: false, + AuthorizeDecision: "allow", + }, { + Level: auditinternal.LevelMetadata, + Stage: auditinternal.StageResponseStarted, + RequestURI: fmt.Sprintf("/api/v1/namespaces/%s/configmaps?timeout=%ds&timeoutSeconds=%d&watch=true", namespace, watchTestTimeout, watchTestTimeout), + Verb: "watch", + Code: 200, + User: auditTestUser, + Resource: "configmaps", + Namespace: namespace, + RequestObject: false, + ResponseObject: false, + AuthorizeDecision: "allow", + }, { + Level: auditinternal.LevelMetadata, + Stage: auditinternal.StageResponseComplete, + RequestURI: fmt.Sprintf("/api/v1/namespaces/%s/configmaps?timeout=%ds&timeoutSeconds=%d&watch=true", namespace, watchTestTimeout, watchTestTimeout), + Verb: "watch", + Code: 200, + User: auditTestUser, + Resource: "configmaps", + Namespace: namespace, + RequestObject: false, + ResponseObject: false, + AuthorizeDecision: "allow", + }, { + Level: auditinternal.LevelMetadata, + Stage: auditinternal.StageResponseComplete, + RequestURI: fmt.Sprintf("/api/v1/namespaces/%s/configmaps/audit-configmap", namespace), + Verb: "update", + Code: 200, + User: auditTestUser, + Resource: "configmaps", + Namespace: namespace, + RequestObject: false, + ResponseObject: false, + AuthorizeDecision: "allow", + }, { + Level: auditinternal.LevelMetadata, + Stage: auditinternal.StageResponseComplete, + RequestURI: fmt.Sprintf("/api/v1/namespaces/%s/configmaps/audit-configmap", namespace), + Verb: "patch", + Code: 200, + User: auditTestUser, + Resource: "configmaps", + Namespace: namespace, + RequestObject: false, + ResponseObject: false, + AuthorizeDecision: "allow", + }, { + Level: auditinternal.LevelMetadata, + Stage: auditinternal.StageResponseComplete, + RequestURI: fmt.Sprintf("/api/v1/namespaces/%s/configmaps/audit-configmap", namespace), + Verb: "delete", + Code: 200, + User: auditTestUser, + Resource: "configmaps", + Namespace: namespace, + RequestObject: false, + ResponseObject: false, + AuthorizeDecision: "allow", + }, + }) + }) + + It("should audit API calls to create, get, update, patch, delete, list, watch secrets.", func() { + secret := &apiv1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: "audit-secret", + }, + Data: map[string][]byte{ + "top-secret": []byte("foo-bar"), + }, + } + _, err := f.ClientSet.CoreV1().Secrets(namespace).Create(secret) + framework.ExpectNoError(err, "failed to create audit-secret") + + _, err = f.ClientSet.CoreV1().Secrets(namespace).Get(secret.Name, metav1.GetOptions{}) + framework.ExpectNoError(err, "failed to get audit-secret") + + secretChan, err := f.ClientSet.CoreV1().Secrets(namespace).Watch(watchOptions) + framework.ExpectNoError(err, "failed to create watch for secrets") + secretChan.Stop() + + _, err = f.ClientSet.CoreV1().Secrets(namespace).Update(secret) + framework.ExpectNoError(err, "failed to update audit-secret") + + _, err = f.ClientSet.CoreV1().Secrets(namespace).Patch(secret.Name, types.JSONPatchType, patch) + framework.ExpectNoError(err, "failed to patch secret") + + _, err = f.ClientSet.CoreV1().Secrets(namespace).List(metav1.ListOptions{}) + framework.ExpectNoError(err, "failed to list secrets") + + err = f.ClientSet.CoreV1().Secrets(namespace).Delete(secret.Name, &metav1.DeleteOptions{}) + framework.ExpectNoError(err, "failed to delete audit-secret") + + expectEvents(f, []utils.AuditEvent{ + { + Level: auditinternal.LevelMetadata, + Stage: auditinternal.StageResponseComplete, + RequestURI: fmt.Sprintf("/api/v1/namespaces/%s/secrets", namespace), + Verb: "create", + Code: 201, + User: auditTestUser, + Resource: "secrets", + Namespace: namespace, + RequestObject: false, + ResponseObject: false, + AuthorizeDecision: "allow", + }, { + Level: auditinternal.LevelMetadata, + Stage: auditinternal.StageResponseComplete, + RequestURI: fmt.Sprintf("/api/v1/namespaces/%s/secrets/audit-secret", namespace), + Verb: "get", + Code: 200, + User: auditTestUser, + Resource: "secrets", + Namespace: namespace, + RequestObject: false, + ResponseObject: false, + AuthorizeDecision: "allow", + }, { + Level: auditinternal.LevelMetadata, + Stage: auditinternal.StageResponseComplete, + RequestURI: fmt.Sprintf("/api/v1/namespaces/%s/secrets", namespace), + Verb: "list", + Code: 200, + User: auditTestUser, + Resource: "secrets", + Namespace: namespace, + RequestObject: false, + ResponseObject: false, + AuthorizeDecision: "allow", + }, { + Level: auditinternal.LevelMetadata, + Stage: auditinternal.StageResponseStarted, + RequestURI: fmt.Sprintf("/api/v1/namespaces/%s/secrets?timeout=%ds&timeoutSeconds=%d&watch=true", namespace, watchTestTimeout, watchTestTimeout), + Verb: "watch", + Code: 200, + User: auditTestUser, + Resource: "secrets", + Namespace: namespace, + RequestObject: false, + ResponseObject: false, + AuthorizeDecision: "allow", + }, { + Level: auditinternal.LevelMetadata, + Stage: auditinternal.StageResponseComplete, + RequestURI: fmt.Sprintf("/api/v1/namespaces/%s/secrets?timeout=%ds&timeoutSeconds=%d&watch=true", namespace, watchTestTimeout, watchTestTimeout), + Verb: "watch", + Code: 200, + User: auditTestUser, + Resource: "secrets", + Namespace: namespace, + RequestObject: false, + ResponseObject: false, + AuthorizeDecision: "allow", + }, { + Level: auditinternal.LevelMetadata, + Stage: auditinternal.StageResponseComplete, + RequestURI: fmt.Sprintf("/api/v1/namespaces/%s/secrets/audit-secret", namespace), + Verb: "update", + Code: 200, + User: auditTestUser, + Resource: "secrets", + Namespace: namespace, + RequestObject: false, + ResponseObject: false, + AuthorizeDecision: "allow", + }, { + Level: auditinternal.LevelMetadata, + Stage: auditinternal.StageResponseComplete, + RequestURI: fmt.Sprintf("/api/v1/namespaces/%s/secrets/audit-secret", namespace), + Verb: "patch", + Code: 200, + User: auditTestUser, + Resource: "secrets", + Namespace: namespace, + RequestObject: false, + ResponseObject: false, + AuthorizeDecision: "allow", + }, { + Level: auditinternal.LevelMetadata, + Stage: auditinternal.StageResponseComplete, + RequestURI: fmt.Sprintf("/api/v1/namespaces/%s/secrets/audit-secret", namespace), + Verb: "delete", + Code: 200, + User: auditTestUser, + Resource: "secrets", + Namespace: namespace, + RequestObject: false, + ResponseObject: false, + AuthorizeDecision: "allow", + }, + }) + }) + + It("should audit API calls to create and delete custom resource definition.", func() { config, err := framework.LoadConfig() framework.ExpectNoError(err, "failed to load config") apiExtensionClient, err := apiextensionclientset.NewForConfig(config) framework.ExpectNoError(err, "failed to initialize apiExtensionClient") + crd, err = fixtures.CreateNewCustomResourceDefinition(crd, apiExtensionClient, f.DynamicClient) + framework.ExpectNoError(err, "failed to create custom resource definition") + err = fixtures.DeleteCustomResourceDefinition(crd, apiExtensionClient) + framework.ExpectNoError(err, "failed to delete custom resource definition") + + expectEvents(f, []utils.AuditEvent{ + { + Level: auditinternal.LevelRequestResponse, + Stage: auditinternal.StageResponseComplete, + RequestURI: "/apis/apiextensions.k8s.io/v1beta1/customresourcedefinitions", + Verb: "create", + Code: 201, + User: auditTestUser, + Resource: "customresourcedefinitions", + RequestObject: true, + ResponseObject: true, + AuthorizeDecision: "allow", + }, { + Level: auditinternal.LevelMetadata, + Stage: auditinternal.StageResponseComplete, + RequestURI: fmt.Sprintf("/apis/%s/v1beta1/%s", crdNamespace, crdName), + Verb: "create", + Code: 201, + User: auditTestUser, + Resource: crdName, + RequestObject: false, + ResponseObject: false, + AuthorizeDecision: "allow", + }, { + Level: auditinternal.LevelRequestResponse, + Stage: auditinternal.StageResponseComplete, + RequestURI: fmt.Sprintf("/apis/apiextensions.k8s.io/v1beta1/customresourcedefinitions/%s", crd.Name), + Verb: "delete", + Code: 200, + User: auditTestUser, + Resource: "customresourcedefinitions", + RequestObject: false, + ResponseObject: true, + AuthorizeDecision: "allow", + }, { + Level: auditinternal.LevelMetadata, + Stage: auditinternal.StageResponseComplete, + RequestURI: fmt.Sprintf("/apis/%s/v1beta1/%s/setup-instance", crdNamespace, crdName), + Verb: "delete", + Code: 200, + User: auditTestUser, + Resource: crdName, + RequestObject: false, + ResponseObject: false, + AuthorizeDecision: "allow", + }, + }) + }) + + // test authorizer annotations, RBAC is required. + It("should audit API calls to get a pod with unauthorized user.", func() { + if !framework.IsRBACEnabled(f) { + framework.Skipf("RBAC not enabled.") + } + By("Creating a kubernetes client that impersonates an unauthorized anonymous user") - config, err = framework.LoadConfig() + config, err := framework.LoadConfig() framework.ExpectNoError(err) config.Impersonate = restclient.ImpersonationConfig{ UserName: "system:anonymous", @@ -79,655 +665,82 @@ var _ = SIGDescribe("Advanced Audit", func() { anonymousClient, err := clientset.NewForConfig(config) framework.ExpectNoError(err) - testCases := []struct { - action func() - events []utils.AuditEvent - }{ - // Create, get, update, patch, delete, list, watch pods. + _, err = anonymousClient.CoreV1().Pods(namespace).Get("another-audit-pod", metav1.GetOptions{}) + expectForbidden(err) + + expectEvents(f, []utils.AuditEvent{ { - func() { - pod := &apiv1.Pod{ - ObjectMeta: metav1.ObjectMeta{ - Name: "audit-pod", - }, - Spec: apiv1.PodSpec{ - Containers: []apiv1.Container{{ - Name: "pause", - Image: imageutils.GetPauseImageName(), - }}, - }, - } - updatePod := func(pod *apiv1.Pod) {} - - f.PodClient().CreateSync(pod) - - _, err := f.PodClient().Get(pod.Name, metav1.GetOptions{}) - framework.ExpectNoError(err, "failed to get audit-pod") - - podChan, err := f.PodClient().Watch(watchOptions) - framework.ExpectNoError(err, "failed to create watch for pods") - podChan.Stop() - - f.PodClient().Update(pod.Name, updatePod) - - _, err = f.PodClient().List(metav1.ListOptions{}) - framework.ExpectNoError(err, "failed to list pods") - - _, err = f.PodClient().Patch(pod.Name, types.JSONPatchType, patch) - framework.ExpectNoError(err, "failed to patch pod") - - f.PodClient().DeleteSync(pod.Name, &metav1.DeleteOptions{}, framework.DefaultPodDeletionTimeout) - }, - []utils.AuditEvent{ - { - Level: auditinternal.LevelRequestResponse, - Stage: auditinternal.StageResponseComplete, - RequestURI: fmt.Sprintf("/api/v1/namespaces/%s/pods", namespace), - Verb: "create", - Code: 201, - User: auditTestUser, - Resource: "pods", - Namespace: namespace, - RequestObject: true, - ResponseObject: true, - AuthorizeDecision: "allow", - }, { - Level: auditinternal.LevelRequest, - Stage: auditinternal.StageResponseComplete, - RequestURI: fmt.Sprintf("/api/v1/namespaces/%s/pods/audit-pod", namespace), - Verb: "get", - Code: 200, - User: auditTestUser, - Resource: "pods", - Namespace: namespace, - RequestObject: false, - ResponseObject: false, - AuthorizeDecision: "allow", - }, { - Level: auditinternal.LevelRequest, - Stage: auditinternal.StageResponseComplete, - RequestURI: fmt.Sprintf("/api/v1/namespaces/%s/pods", namespace), - Verb: "list", - Code: 200, - User: auditTestUser, - Resource: "pods", - Namespace: namespace, - RequestObject: false, - ResponseObject: false, - AuthorizeDecision: "allow", - }, { - Level: auditinternal.LevelRequest, - Stage: auditinternal.StageResponseStarted, - RequestURI: fmt.Sprintf("/api/v1/namespaces/%s/pods?timeout=%ds&timeoutSeconds=%d&watch=true", namespace, watchTestTimeout, watchTestTimeout), - Verb: "watch", - Code: 200, - User: auditTestUser, - Resource: "pods", - Namespace: namespace, - RequestObject: false, - ResponseObject: false, - AuthorizeDecision: "allow", - }, { - Level: auditinternal.LevelRequest, - Stage: auditinternal.StageResponseComplete, - RequestURI: fmt.Sprintf("/api/v1/namespaces/%s/pods?timeout=%ds&timeoutSeconds=%d&watch=true", namespace, watchTestTimeout, watchTestTimeout), - Verb: "watch", - Code: 200, - User: auditTestUser, - Resource: "pods", - Namespace: namespace, - RequestObject: false, - ResponseObject: false, - AuthorizeDecision: "allow", - }, { - Level: auditinternal.LevelRequestResponse, - Stage: auditinternal.StageResponseComplete, - RequestURI: fmt.Sprintf("/api/v1/namespaces/%s/pods/audit-pod", namespace), - Verb: "update", - Code: 200, - User: auditTestUser, - Resource: "pods", - Namespace: namespace, - RequestObject: true, - ResponseObject: true, - AuthorizeDecision: "allow", - }, { - Level: auditinternal.LevelRequestResponse, - Stage: auditinternal.StageResponseComplete, - RequestURI: fmt.Sprintf("/api/v1/namespaces/%s/pods/audit-pod", namespace), - Verb: "patch", - Code: 200, - User: auditTestUser, - Resource: "pods", - Namespace: namespace, - RequestObject: true, - ResponseObject: true, - AuthorizeDecision: "allow", - }, { - Level: auditinternal.LevelRequestResponse, - Stage: auditinternal.StageResponseComplete, - RequestURI: fmt.Sprintf("/api/v1/namespaces/%s/pods/audit-pod", namespace), - Verb: "delete", - Code: 200, - User: auditTestUser, - Resource: "pods", - Namespace: namespace, - RequestObject: true, - ResponseObject: true, - AuthorizeDecision: "allow", - }, - }, + Level: auditinternal.LevelRequest, + Stage: auditinternal.StageResponseComplete, + RequestURI: fmt.Sprintf("/api/v1/namespaces/%s/pods/another-audit-pod", namespace), + Verb: "get", + Code: 403, + User: auditTestUser, + ImpersonatedUser: "system:anonymous", + ImpersonatedGroups: "system:unauthenticated", + Resource: "pods", + Namespace: namespace, + RequestObject: false, + ResponseObject: false, + AuthorizeDecision: "forbid", }, - // Create, get, update, patch, delete, list, watch deployments. - { - func() { - podLabels := map[string]string{"name": "audit-deployment-pod"} - d := framework.NewDeployment("audit-deployment", int32(1), podLabels, "redis", imageutils.GetE2EImage(imageutils.Redis), apps.RecreateDeploymentStrategyType) - - _, err := f.ClientSet.AppsV1().Deployments(namespace).Create(d) - framework.ExpectNoError(err, "failed to create audit-deployment") - - _, err = f.ClientSet.AppsV1().Deployments(namespace).Get(d.Name, metav1.GetOptions{}) - framework.ExpectNoError(err, "failed to get audit-deployment") - - deploymentChan, err := f.ClientSet.AppsV1().Deployments(namespace).Watch(watchOptions) - framework.ExpectNoError(err, "failed to create watch for deployments") - deploymentChan.Stop() - - _, err = f.ClientSet.AppsV1().Deployments(namespace).Update(d) - framework.ExpectNoError(err, "failed to update audit-deployment") - - _, err = f.ClientSet.AppsV1().Deployments(namespace).Patch(d.Name, types.JSONPatchType, patch) - framework.ExpectNoError(err, "failed to patch deployment") - - _, err = f.ClientSet.AppsV1().Deployments(namespace).List(metav1.ListOptions{}) - framework.ExpectNoError(err, "failed to create list deployments") - - err = f.ClientSet.AppsV1().Deployments(namespace).Delete("audit-deployment", &metav1.DeleteOptions{}) - framework.ExpectNoError(err, "failed to delete deployments") - }, - []utils.AuditEvent{ - { - Level: auditinternal.LevelRequestResponse, - Stage: auditinternal.StageResponseComplete, - RequestURI: fmt.Sprintf("/apis/apps/v1/namespaces/%s/deployments", namespace), - Verb: "create", - Code: 201, - User: auditTestUser, - Resource: "deployments", - Namespace: namespace, - RequestObject: true, - ResponseObject: true, - AuthorizeDecision: "allow", - }, { - Level: auditinternal.LevelRequest, - Stage: auditinternal.StageResponseComplete, - RequestURI: fmt.Sprintf("/apis/apps/v1/namespaces/%s/deployments/audit-deployment", namespace), - Verb: "get", - Code: 200, - User: auditTestUser, - Resource: "deployments", - Namespace: namespace, - RequestObject: false, - ResponseObject: false, - AuthorizeDecision: "allow", - }, { - Level: auditinternal.LevelRequest, - Stage: auditinternal.StageResponseComplete, - RequestURI: fmt.Sprintf("/apis/apps/v1/namespaces/%s/deployments", namespace), - Verb: "list", - Code: 200, - User: auditTestUser, - Resource: "deployments", - Namespace: namespace, - RequestObject: false, - ResponseObject: false, - AuthorizeDecision: "allow", - }, { - Level: auditinternal.LevelRequest, - Stage: auditinternal.StageResponseStarted, - RequestURI: fmt.Sprintf("/apis/apps/v1/namespaces/%s/deployments?timeout=%ds&timeoutSeconds=%d&watch=true", namespace, watchTestTimeout, watchTestTimeout), - Verb: "watch", - Code: 200, - User: auditTestUser, - Resource: "deployments", - Namespace: namespace, - RequestObject: false, - ResponseObject: false, - AuthorizeDecision: "allow", - }, { - Level: auditinternal.LevelRequest, - Stage: auditinternal.StageResponseComplete, - RequestURI: fmt.Sprintf("/apis/apps/v1/namespaces/%s/deployments?timeout=%ds&timeoutSeconds=%d&watch=true", namespace, watchTestTimeout, watchTestTimeout), - Verb: "watch", - Code: 200, - User: auditTestUser, - Resource: "deployments", - Namespace: namespace, - RequestObject: false, - ResponseObject: false, - AuthorizeDecision: "allow", - }, { - Level: auditinternal.LevelRequestResponse, - Stage: auditinternal.StageResponseComplete, - RequestURI: fmt.Sprintf("/apis/apps/v1/namespaces/%s/deployments/audit-deployment", namespace), - Verb: "update", - Code: 200, - User: auditTestUser, - Resource: "deployments", - Namespace: namespace, - RequestObject: true, - ResponseObject: true, - AuthorizeDecision: "allow", - }, { - Level: auditinternal.LevelRequestResponse, - Stage: auditinternal.StageResponseComplete, - RequestURI: fmt.Sprintf("/apis/apps/v1/namespaces/%s/deployments/audit-deployment", namespace), - Verb: "patch", - Code: 200, - User: auditTestUser, - Resource: "deployments", - Namespace: namespace, - RequestObject: true, - ResponseObject: true, - AuthorizeDecision: "allow", - }, { - Level: auditinternal.LevelRequestResponse, - Stage: auditinternal.StageResponseComplete, - RequestURI: fmt.Sprintf("/apis/apps/v1/namespaces/%s/deployments/audit-deployment", namespace), - Verb: "delete", - Code: 200, - User: auditTestUser, - Resource: "deployments", - Namespace: namespace, - RequestObject: true, - ResponseObject: true, - AuthorizeDecision: "allow", - }, - }, - }, - // Create, get, update, patch, delete, list, watch configmaps. - { - func() { - configMap := &apiv1.ConfigMap{ - ObjectMeta: metav1.ObjectMeta{ - Name: "audit-configmap", - }, - Data: map[string]string{ - "map-key": "map-value", - }, - } - - _, err := f.ClientSet.CoreV1().ConfigMaps(namespace).Create(configMap) - framework.ExpectNoError(err, "failed to create audit-configmap") - - _, err = f.ClientSet.CoreV1().ConfigMaps(namespace).Get(configMap.Name, metav1.GetOptions{}) - framework.ExpectNoError(err, "failed to get audit-configmap") - - configMapChan, err := f.ClientSet.CoreV1().ConfigMaps(namespace).Watch(watchOptions) - framework.ExpectNoError(err, "failed to create watch for config maps") - configMapChan.Stop() - - _, err = f.ClientSet.CoreV1().ConfigMaps(namespace).Update(configMap) - framework.ExpectNoError(err, "failed to update audit-configmap") - - _, err = f.ClientSet.CoreV1().ConfigMaps(namespace).Patch(configMap.Name, types.JSONPatchType, patch) - framework.ExpectNoError(err, "failed to patch configmap") - - _, err = f.ClientSet.CoreV1().ConfigMaps(namespace).List(metav1.ListOptions{}) - framework.ExpectNoError(err, "failed to list config maps") - - err = f.ClientSet.CoreV1().ConfigMaps(namespace).Delete(configMap.Name, &metav1.DeleteOptions{}) - framework.ExpectNoError(err, "failed to delete audit-configmap") - }, - []utils.AuditEvent{ - { - Level: auditinternal.LevelMetadata, - Stage: auditinternal.StageResponseComplete, - RequestURI: fmt.Sprintf("/api/v1/namespaces/%s/configmaps", namespace), - Verb: "create", - Code: 201, - User: auditTestUser, - Resource: "configmaps", - Namespace: namespace, - RequestObject: false, - ResponseObject: false, - AuthorizeDecision: "allow", - }, { - Level: auditinternal.LevelMetadata, - Stage: auditinternal.StageResponseComplete, - RequestURI: fmt.Sprintf("/api/v1/namespaces/%s/configmaps/audit-configmap", namespace), - Verb: "get", - Code: 200, - User: auditTestUser, - Resource: "configmaps", - Namespace: namespace, - RequestObject: false, - ResponseObject: false, - AuthorizeDecision: "allow", - }, { - Level: auditinternal.LevelMetadata, - Stage: auditinternal.StageResponseComplete, - RequestURI: fmt.Sprintf("/api/v1/namespaces/%s/configmaps", namespace), - Verb: "list", - Code: 200, - User: auditTestUser, - Resource: "configmaps", - Namespace: namespace, - RequestObject: false, - ResponseObject: false, - AuthorizeDecision: "allow", - }, { - Level: auditinternal.LevelMetadata, - Stage: auditinternal.StageResponseStarted, - RequestURI: fmt.Sprintf("/api/v1/namespaces/%s/configmaps?timeout=%ds&timeoutSeconds=%d&watch=true", namespace, watchTestTimeout, watchTestTimeout), - Verb: "watch", - Code: 200, - User: auditTestUser, - Resource: "configmaps", - Namespace: namespace, - RequestObject: false, - ResponseObject: false, - AuthorizeDecision: "allow", - }, { - Level: auditinternal.LevelMetadata, - Stage: auditinternal.StageResponseComplete, - RequestURI: fmt.Sprintf("/api/v1/namespaces/%s/configmaps?timeout=%ds&timeoutSeconds=%d&watch=true", namespace, watchTestTimeout, watchTestTimeout), - Verb: "watch", - Code: 200, - User: auditTestUser, - Resource: "configmaps", - Namespace: namespace, - RequestObject: false, - ResponseObject: false, - AuthorizeDecision: "allow", - }, { - Level: auditinternal.LevelMetadata, - Stage: auditinternal.StageResponseComplete, - RequestURI: fmt.Sprintf("/api/v1/namespaces/%s/configmaps/audit-configmap", namespace), - Verb: "update", - Code: 200, - User: auditTestUser, - Resource: "configmaps", - Namespace: namespace, - RequestObject: false, - ResponseObject: false, - AuthorizeDecision: "allow", - }, { - Level: auditinternal.LevelMetadata, - Stage: auditinternal.StageResponseComplete, - RequestURI: fmt.Sprintf("/api/v1/namespaces/%s/configmaps/audit-configmap", namespace), - Verb: "patch", - Code: 200, - User: auditTestUser, - Resource: "configmaps", - Namespace: namespace, - RequestObject: false, - ResponseObject: false, - AuthorizeDecision: "allow", - }, { - Level: auditinternal.LevelMetadata, - Stage: auditinternal.StageResponseComplete, - RequestURI: fmt.Sprintf("/api/v1/namespaces/%s/configmaps/audit-configmap", namespace), - Verb: "delete", - Code: 200, - User: auditTestUser, - Resource: "configmaps", - Namespace: namespace, - RequestObject: false, - ResponseObject: false, - AuthorizeDecision: "allow", - }, - }, - }, - // Create, get, update, patch, delete, list, watch secrets. - { - func() { - secret := &apiv1.Secret{ - ObjectMeta: metav1.ObjectMeta{ - Name: "audit-secret", - }, - Data: map[string][]byte{ - "top-secret": []byte("foo-bar"), - }, - } - _, err := f.ClientSet.CoreV1().Secrets(namespace).Create(secret) - framework.ExpectNoError(err, "failed to create audit-secret") - - _, err = f.ClientSet.CoreV1().Secrets(namespace).Get(secret.Name, metav1.GetOptions{}) - framework.ExpectNoError(err, "failed to get audit-secret") - - secretChan, err := f.ClientSet.CoreV1().Secrets(namespace).Watch(watchOptions) - framework.ExpectNoError(err, "failed to create watch for secrets") - secretChan.Stop() - - _, err = f.ClientSet.CoreV1().Secrets(namespace).Update(secret) - framework.ExpectNoError(err, "failed to update audit-secret") - - _, err = f.ClientSet.CoreV1().Secrets(namespace).Patch(secret.Name, types.JSONPatchType, patch) - framework.ExpectNoError(err, "failed to patch secret") - - _, err = f.ClientSet.CoreV1().Secrets(namespace).List(metav1.ListOptions{}) - framework.ExpectNoError(err, "failed to list secrets") - - err = f.ClientSet.CoreV1().Secrets(namespace).Delete(secret.Name, &metav1.DeleteOptions{}) - framework.ExpectNoError(err, "failed to delete audit-secret") - }, - []utils.AuditEvent{ - { - Level: auditinternal.LevelMetadata, - Stage: auditinternal.StageResponseComplete, - RequestURI: fmt.Sprintf("/api/v1/namespaces/%s/secrets", namespace), - Verb: "create", - Code: 201, - User: auditTestUser, - Resource: "secrets", - Namespace: namespace, - RequestObject: false, - ResponseObject: false, - AuthorizeDecision: "allow", - }, { - Level: auditinternal.LevelMetadata, - Stage: auditinternal.StageResponseComplete, - RequestURI: fmt.Sprintf("/api/v1/namespaces/%s/secrets/audit-secret", namespace), - Verb: "get", - Code: 200, - User: auditTestUser, - Resource: "secrets", - Namespace: namespace, - RequestObject: false, - ResponseObject: false, - AuthorizeDecision: "allow", - }, { - Level: auditinternal.LevelMetadata, - Stage: auditinternal.StageResponseComplete, - RequestURI: fmt.Sprintf("/api/v1/namespaces/%s/secrets", namespace), - Verb: "list", - Code: 200, - User: auditTestUser, - Resource: "secrets", - Namespace: namespace, - RequestObject: false, - ResponseObject: false, - AuthorizeDecision: "allow", - }, { - Level: auditinternal.LevelMetadata, - Stage: auditinternal.StageResponseStarted, - RequestURI: fmt.Sprintf("/api/v1/namespaces/%s/secrets?timeout=%ds&timeoutSeconds=%d&watch=true", namespace, watchTestTimeout, watchTestTimeout), - Verb: "watch", - Code: 200, - User: auditTestUser, - Resource: "secrets", - Namespace: namespace, - RequestObject: false, - ResponseObject: false, - AuthorizeDecision: "allow", - }, { - Level: auditinternal.LevelMetadata, - Stage: auditinternal.StageResponseComplete, - RequestURI: fmt.Sprintf("/api/v1/namespaces/%s/secrets?timeout=%ds&timeoutSeconds=%d&watch=true", namespace, watchTestTimeout, watchTestTimeout), - Verb: "watch", - Code: 200, - User: auditTestUser, - Resource: "secrets", - Namespace: namespace, - RequestObject: false, - ResponseObject: false, - AuthorizeDecision: "allow", - }, { - Level: auditinternal.LevelMetadata, - Stage: auditinternal.StageResponseComplete, - RequestURI: fmt.Sprintf("/api/v1/namespaces/%s/secrets/audit-secret", namespace), - Verb: "update", - Code: 200, - User: auditTestUser, - Resource: "secrets", - Namespace: namespace, - RequestObject: false, - ResponseObject: false, - AuthorizeDecision: "allow", - }, { - Level: auditinternal.LevelMetadata, - Stage: auditinternal.StageResponseComplete, - RequestURI: fmt.Sprintf("/api/v1/namespaces/%s/secrets/audit-secret", namespace), - Verb: "patch", - Code: 200, - User: auditTestUser, - Resource: "secrets", - Namespace: namespace, - RequestObject: false, - ResponseObject: false, - AuthorizeDecision: "allow", - }, { - Level: auditinternal.LevelMetadata, - Stage: auditinternal.StageResponseComplete, - RequestURI: fmt.Sprintf("/api/v1/namespaces/%s/secrets/audit-secret", namespace), - Verb: "delete", - Code: 200, - User: auditTestUser, - Resource: "secrets", - Namespace: namespace, - RequestObject: false, - ResponseObject: false, - AuthorizeDecision: "allow", - }, - }, - }, - // Create and delete custom resource definition. - { - func() { - crd, err = fixtures.CreateNewCustomResourceDefinition(crd, apiExtensionClient, f.DynamicClient) - framework.ExpectNoError(err, "failed to create custom resource definition") - fixtures.DeleteCustomResourceDefinition(crd, apiExtensionClient) - }, - []utils.AuditEvent{ - { - Level: auditinternal.LevelRequestResponse, - Stage: auditinternal.StageResponseComplete, - RequestURI: "/apis/apiextensions.k8s.io/v1beta1/customresourcedefinitions", - Verb: "create", - Code: 201, - User: auditTestUser, - Resource: "customresourcedefinitions", - RequestObject: true, - ResponseObject: true, - AuthorizeDecision: "allow", - }, { - Level: auditinternal.LevelMetadata, - Stage: auditinternal.StageResponseComplete, - RequestURI: fmt.Sprintf("/apis/%s/v1beta1/%s", crdNamespace, crdName), - Verb: "create", - Code: 201, - User: auditTestUser, - Resource: crdName, - RequestObject: false, - ResponseObject: false, - AuthorizeDecision: "allow", - }, { - Level: auditinternal.LevelRequestResponse, - Stage: auditinternal.StageResponseComplete, - RequestURI: fmt.Sprintf("/apis/apiextensions.k8s.io/v1beta1/customresourcedefinitions/%s", crd.Name), - Verb: "delete", - Code: 200, - User: auditTestUser, - Resource: "customresourcedefinitions", - RequestObject: false, - ResponseObject: true, - AuthorizeDecision: "allow", - }, { - Level: auditinternal.LevelMetadata, - Stage: auditinternal.StageResponseComplete, - RequestURI: fmt.Sprintf("/apis/%s/v1beta1/%s/setup-instance", crdNamespace, crdName), - Verb: "delete", - Code: 200, - User: auditTestUser, - Resource: crdName, - RequestObject: false, - ResponseObject: false, - AuthorizeDecision: "allow", - }, - }, - }, - } - - // test authorizer annotations, RBAC is required. - annotationTestCases := []struct { - action func() - events []utils.AuditEvent - }{ - - // get a pod with unauthorized user - { - func() { - _, err := anonymousClient.CoreV1().Pods(namespace).Get("another-audit-pod", metav1.GetOptions{}) - expectForbidden(err) - }, - []utils.AuditEvent{ - { - Level: auditinternal.LevelRequest, - Stage: auditinternal.StageResponseComplete, - RequestURI: fmt.Sprintf("/api/v1/namespaces/%s/pods/another-audit-pod", namespace), - Verb: "get", - Code: 403, - User: auditTestUser, - Resource: "pods", - Namespace: namespace, - RequestObject: false, - ResponseObject: false, - AuthorizeDecision: "forbid", - }, - }, - }, - } - - if framework.IsRBACEnabled(f) { - testCases = append(testCases, annotationTestCases...) - } - expectedEvents := []utils.AuditEvent{} - for _, t := range testCases { - t.action() - expectedEvents = append(expectedEvents, t.events...) - } - - // The default flush timeout is 30 seconds, therefore it should be enough to retry once - // to find all expected events. However, we're waiting for 5 minutes to avoid flakes. - pollingInterval := 30 * time.Second - pollingTimeout := 5 * time.Minute - err = wait.Poll(pollingInterval, pollingTimeout, func() (bool, error) { - // Fetch the log stream. - stream, err := f.ClientSet.CoreV1().RESTClient().Get().AbsPath("/logs/kube-apiserver-audit.log").Stream() - if err != nil { - return false, err - } - defer stream.Close() - missing, err := utils.CheckAuditLines(stream, expectedEvents, v1beta1.SchemeGroupVersion) - if err != nil { - framework.Logf("Failed to observe audit events: %v", err) - } else if len(missing) > 0 { - framework.Logf("Events %#v not found!", missing) - } - return len(missing) == 0, nil }) - framework.ExpectNoError(err, "after %v failed to observe audit events", pollingTimeout) }) + + It("should list pods as impersonated user.", func() { + By("Creating a kubernetes client that impersonates an authorized user") + config, err := framework.LoadConfig() + framework.ExpectNoError(err) + config.Impersonate = restclient.ImpersonationConfig{ + UserName: "superman", + Groups: []string{"system:masters"}, + } + impersonatedClient, err := clientset.NewForConfig(config) + framework.ExpectNoError(err) + + _, err = impersonatedClient.CoreV1().Pods(namespace).List(metav1.ListOptions{}) + framework.ExpectNoError(err, "failed to list pods") + + expectEvents(f, []utils.AuditEvent{ + { + Level: auditinternal.LevelRequest, + Stage: auditinternal.StageResponseComplete, + RequestURI: fmt.Sprintf("/api/v1/namespaces/%s/pods", namespace), + Verb: "list", + Code: 200, + User: auditTestUser, + ImpersonatedUser: "superman", + ImpersonatedGroups: "system:masters", + Resource: "pods", + Namespace: namespace, + RequestObject: false, + ResponseObject: false, + AuthorizeDecision: "allow", + }, + }) + }) + }) + +func expectEvents(f *framework.Framework, expectedEvents []utils.AuditEvent) { + // The default flush timeout is 30 seconds, therefore it should be enough to retry once + // to find all expected events. However, we're waiting for 5 minutes to avoid flakes. + pollingInterval := 30 * time.Second + pollingTimeout := 5 * time.Minute + err := wait.Poll(pollingInterval, pollingTimeout, func() (bool, error) { + // Fetch the log stream. + stream, err := f.ClientSet.CoreV1().RESTClient().Get().AbsPath("/logs/kube-apiserver-audit.log").Stream() + if err != nil { + return false, err + } + defer stream.Close() + missing, err := utils.CheckAuditLines(stream, expectedEvents, v1beta1.SchemeGroupVersion) + if err != nil { + framework.Logf("Failed to observe audit events: %v", err) + } else if len(missing) > 0 { + framework.Logf("Events %#v not found!", missing) + } + return len(missing) == 0, nil + }) + framework.ExpectNoError(err, "after %v failed to observe audit events", pollingTimeout) +} diff --git a/test/e2e/autoscaling/BUILD b/test/e2e/autoscaling/BUILD index 3cc66811f42..77d0b849e37 100644 --- a/test/e2e/autoscaling/BUILD +++ b/test/e2e/autoscaling/BUILD @@ -19,9 +19,9 @@ go_library( importpath = "k8s.io/kubernetes/test/e2e/autoscaling", deps = [ "//pkg/apis/core:go_default_library", + "//staging/src/k8s.io/api/apps/v1:go_default_library", "//staging/src/k8s.io/api/autoscaling/v2beta1:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library", - "//staging/src/k8s.io/api/extensions/v1beta1:go_default_library", "//staging/src/k8s.io/api/policy/v1beta1:go_default_library", "//staging/src/k8s.io/api/scheduling/v1beta1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library", diff --git a/test/e2e/autoscaling/cluster_size_autoscaling.go b/test/e2e/autoscaling/cluster_size_autoscaling.go index 2d2f866997d..362f65b08e3 100644 --- a/test/e2e/autoscaling/cluster_size_autoscaling.go +++ b/test/e2e/autoscaling/cluster_size_autoscaling.go @@ -68,7 +68,6 @@ const ( makeSchedulableDelay = 20 * time.Second freshStatusLimit = 20 * time.Second - gkeEndpoint = "https://test-container.sandbox.googleapis.com" gkeUpdateTimeout = 15 * time.Minute gkeNodepoolNameKey = "cloud.google.com/gke-nodepool" @@ -1035,13 +1034,24 @@ func runDrainTest(f *framework.Framework, migSizes map[string]int, namespace str verifyFunction(increasedSize) } +func getGkeApiEndpoint() string { + gkeApiEndpoint := os.Getenv("CLOUDSDK_API_ENDPOINT_OVERRIDES_CONTAINER") + if gkeApiEndpoint == "" { + gkeApiEndpoint = "https://test-container.sandbox.googleapis.com" + } + if strings.HasSuffix(gkeApiEndpoint, "/") { + gkeApiEndpoint = gkeApiEndpoint[:len(gkeApiEndpoint)-1] + } + return gkeApiEndpoint +} + func getGKEURL(apiVersion string, suffix string) string { out, err := execCmd("gcloud", "auth", "print-access-token").Output() framework.ExpectNoError(err) token := strings.Replace(string(out), "\n", "", -1) return fmt.Sprintf("%s/%s/%s?access_token=%s", - gkeEndpoint, + getGkeApiEndpoint(), apiVersion, suffix, token) @@ -1185,6 +1195,11 @@ func executeHTTPRequest(method string, url string, body string) (string, error) return "", err } resp, err := client.Do(req) + if err != nil { + return "", err + } + defer resp.Body.Close() + respBody, err := ioutil.ReadAll(resp.Body) if err != nil { return "", err diff --git a/test/e2e/autoscaling/custom_metrics_stackdriver_autoscaling.go b/test/e2e/autoscaling/custom_metrics_stackdriver_autoscaling.go index 325c3bce439..9fab9a49636 100644 --- a/test/e2e/autoscaling/custom_metrics_stackdriver_autoscaling.go +++ b/test/e2e/autoscaling/custom_metrics_stackdriver_autoscaling.go @@ -22,9 +22,9 @@ import ( "time" gcm "google.golang.org/api/monitoring/v3" + appsv1 "k8s.io/api/apps/v1" as "k8s.io/api/autoscaling/v2beta1" corev1 "k8s.io/api/core/v1" - extensions "k8s.io/api/extensions/v1beta1" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/wait" @@ -219,7 +219,7 @@ type CustomMetricTestCase struct { framework *framework.Framework hpa *as.HorizontalPodAutoscaler kubeClient clientset.Interface - deployment *extensions.Deployment + deployment *appsv1.Deployment pod *corev1.Pod initialReplicas int scaledReplicas int @@ -282,9 +282,9 @@ func (tc *CustomMetricTestCase) Run() { waitForReplicas(tc.deployment.ObjectMeta.Name, tc.framework.Namespace.ObjectMeta.Name, tc.kubeClient, 15*time.Minute, tc.scaledReplicas) } -func createDeploymentToScale(f *framework.Framework, cs clientset.Interface, deployment *extensions.Deployment, pod *corev1.Pod) error { +func createDeploymentToScale(f *framework.Framework, cs clientset.Interface, deployment *appsv1.Deployment, pod *corev1.Pod) error { if deployment != nil { - _, err := cs.Extensions().Deployments(f.Namespace.ObjectMeta.Name).Create(deployment) + _, err := cs.AppsV1().Deployments(f.Namespace.ObjectMeta.Name).Create(deployment) if err != nil { return err } @@ -298,9 +298,9 @@ func createDeploymentToScale(f *framework.Framework, cs clientset.Interface, dep return nil } -func cleanupDeploymentsToScale(f *framework.Framework, cs clientset.Interface, deployment *extensions.Deployment, pod *corev1.Pod) { +func cleanupDeploymentsToScale(f *framework.Framework, cs clientset.Interface, deployment *appsv1.Deployment, pod *corev1.Pod) { if deployment != nil { - _ = cs.Extensions().Deployments(f.Namespace.ObjectMeta.Name).Delete(deployment.ObjectMeta.Name, &metav1.DeleteOptions{}) + _ = cs.AppsV1().Deployments(f.Namespace.ObjectMeta.Name).Delete(deployment.ObjectMeta.Name, &metav1.DeleteOptions{}) } if pod != nil { _ = cs.CoreV1().Pods(f.Namespace.ObjectMeta.Name).Delete(pod.ObjectMeta.Name, &metav1.DeleteOptions{}) @@ -333,7 +333,7 @@ func podsHPA(namespace string, deploymentName string, metricTargets map[string]i MaxReplicas: 3, MinReplicas: &minReplicas, ScaleTargetRef: as.CrossVersionObjectReference{ - APIVersion: "extensions/v1beta1", + APIVersion: "apps/v1", Kind: "Deployment", Name: deploymentName, }, @@ -365,7 +365,7 @@ func objectHPA(namespace string, metricTarget int64) *as.HorizontalPodAutoscaler MaxReplicas: 3, MinReplicas: &minReplicas, ScaleTargetRef: as.CrossVersionObjectReference{ - APIVersion: "extensions/v1beta1", + APIVersion: "apps/v1", Kind: "Deployment", Name: dummyDeploymentName, }, @@ -424,7 +424,7 @@ func externalHPA(namespace string, metricTargets map[string]externalMetricTarget MaxReplicas: 3, MinReplicas: &minReplicas, ScaleTargetRef: as.CrossVersionObjectReference{ - APIVersion: "extensions/v1beta1", + APIVersion: "apps/v1", Kind: "Deployment", Name: dummyDeploymentName, }, @@ -437,7 +437,7 @@ func externalHPA(namespace string, metricTargets map[string]externalMetricTarget func waitForReplicas(deploymentName, namespace string, cs clientset.Interface, timeout time.Duration, desiredReplicas int) { interval := 20 * time.Second err := wait.PollImmediate(interval, timeout, func() (bool, error) { - deployment, err := cs.ExtensionsV1beta1().Deployments(namespace).Get(deploymentName, metav1.GetOptions{}) + deployment, err := cs.AppsV1().Deployments(namespace).Get(deploymentName, metav1.GetOptions{}) if err != nil { framework.Failf("Failed to get replication controller %s: %v", deployment, err) } diff --git a/test/e2e/autoscaling/dns_autoscaling.go b/test/e2e/autoscaling/dns_autoscaling.go index 4f85f110863..92fb14b0c09 100644 --- a/test/e2e/autoscaling/dns_autoscaling.go +++ b/test/e2e/autoscaling/dns_autoscaling.go @@ -292,7 +292,7 @@ func updateDNSScalingConfigMap(c clientset.Interface, configMap *v1.ConfigMap) e func getDNSReplicas(c clientset.Interface) (int, error) { label := labels.SelectorFromSet(labels.Set(map[string]string{ClusterAddonLabelKey: DNSLabelName})) listOpts := metav1.ListOptions{LabelSelector: label.String()} - deployments, err := c.ExtensionsV1beta1().Deployments(metav1.NamespaceSystem).List(listOpts) + deployments, err := c.AppsV1().Deployments(metav1.NamespaceSystem).List(listOpts) if err != nil { return 0, err } diff --git a/test/e2e/common/autoscaling_utils.go b/test/e2e/common/autoscaling_utils.go index fe8b5ab97fc..817e963b0f6 100644 --- a/test/e2e/common/autoscaling_utils.go +++ b/test/e2e/common/autoscaling_utils.go @@ -340,14 +340,14 @@ func (rc *ResourceConsumer) GetReplicas() int { } return int(replicationController.Status.ReadyReplicas) case KindDeployment: - deployment, err := rc.clientSet.ExtensionsV1beta1().Deployments(rc.nsName).Get(rc.name, metav1.GetOptions{}) + deployment, err := rc.clientSet.AppsV1().Deployments(rc.nsName).Get(rc.name, metav1.GetOptions{}) framework.ExpectNoError(err) if deployment == nil { framework.Failf(deploymentIsNil) } return int(deployment.Status.ReadyReplicas) case KindReplicaSet: - rs, err := rc.clientSet.ExtensionsV1beta1().ReplicaSets(rc.nsName).Get(rc.name, metav1.GetOptions{}) + rs, err := rc.clientSet.AppsV1().ReplicaSets(rc.nsName).Get(rc.name, metav1.GetOptions{}) framework.ExpectNoError(err) if rs == nil { framework.Failf(rsIsNil) diff --git a/test/e2e/common/container_probe.go b/test/e2e/common/container_probe.go index d8a8711568a..9988a29919e 100644 --- a/test/e2e/common/container_probe.go +++ b/test/e2e/common/container_probe.go @@ -20,7 +20,7 @@ import ( "fmt" "time" - "k8s.io/api/core/v1" + v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/intstr" "k8s.io/apimachinery/pkg/util/uuid" @@ -204,13 +204,12 @@ var _ = framework.KubeDescribe("Probing container", func() { }, 1, defaultObservationTimeout) }) - // Slow by design (5 min) /* Release : v1.9 Testname: Pod liveness probe, using http endpoint, multiple restarts (slow) Description: A Pod is created with liveness probe on http endpoint /healthz. The http handler on the /healthz will return a http error after 10 seconds since the Pod is started. This MUST result in liveness check failure. The Pod MUST now be killed and restarted incrementing restart count to 1. The liveness probe must fail again after restart once the http handler for /healthz enpoind on the Pod returns an http error after 10 seconds from the start. Restart counts MUST increment everytime health check fails, measure upto 5 restart. */ - framework.ConformanceIt("should have monotonically increasing restart count [Slow][NodeConformance]", func() { + framework.ConformanceIt("should have monotonically increasing restart count [NodeConformance]", func() { runLivenessTest(f, &v1.Pod{ ObjectMeta: metav1.ObjectMeta{ Name: "liveness-http", diff --git a/test/e2e/common/host_path.go b/test/e2e/common/host_path.go index 2728b6e4c32..fef81301803 100644 --- a/test/e2e/common/host_path.go +++ b/test/e2e/common/host_path.go @@ -49,7 +49,7 @@ var _ = Describe("[sig-storage] HostPath", func() { source := &v1.HostPathVolumeSource{ Path: "/tmp", } - pod := testPodWithHostVol(volumePath, source) + pod := testPodWithHostVol(volumePath, source, false) pod.Spec.Containers[0].Args = []string{ fmt.Sprintf("--fs_type=%v", volumePath), @@ -67,7 +67,7 @@ var _ = Describe("[sig-storage] HostPath", func() { source := &v1.HostPathVolumeSource{ Path: "/tmp", } - pod := testPodWithHostVol(volumePath, source) + pod := testPodWithHostVol(volumePath, source, true) pod.Spec.Containers[0].Args = []string{ fmt.Sprintf("--new_file_0644=%v", filePath), @@ -96,7 +96,7 @@ var _ = Describe("[sig-storage] HostPath", func() { source := &v1.HostPathVolumeSource{ Path: "/tmp", } - pod := testPodWithHostVol(volumePath, source) + pod := testPodWithHostVol(volumePath, source, true) // Write the file in the subPath from container 0 container := &pod.Spec.Containers[0] @@ -135,9 +135,8 @@ func mount(source *v1.HostPathVolumeSource) []v1.Volume { } //TODO: To merge this with the emptyDir tests, we can make source a lambda. -func testPodWithHostVol(path string, source *v1.HostPathVolumeSource) *v1.Pod { +func testPodWithHostVol(path string, source *v1.HostPathVolumeSource, privileged bool) *v1.Pod { podName := "pod-host-path-test" - privileged := true return &v1.Pod{ TypeMeta: metav1.TypeMeta{ diff --git a/test/e2e/common/runtime.go b/test/e2e/common/runtime.go index 69b7bbf82f2..7fdb3215896 100644 --- a/test/e2e/common/runtime.go +++ b/test/e2e/common/runtime.go @@ -96,11 +96,6 @@ while true; do sleep 1; done Container: testContainer, RestartPolicy: testCase.RestartPolicy, Volumes: testVolumes, - PodSecurityContext: &v1.PodSecurityContext{ - SELinuxOptions: &v1.SELinuxOptions{ - Level: "s0", - }, - }, } terminateContainer.Create() defer terminateContainer.Delete() diff --git a/test/e2e/framework/BUILD b/test/e2e/framework/BUILD index 6a1be393003..ab4868a01d5 100644 --- a/test/e2e/framework/BUILD +++ b/test/e2e/framework/BUILD @@ -65,8 +65,8 @@ go_library( "//pkg/kubelet/util/format:go_default_library", "//pkg/master/ports:go_default_library", "//pkg/scheduler/algorithm/predicates:go_default_library", - "//pkg/scheduler/cache:go_default_library", "//pkg/scheduler/metrics:go_default_library", + "//pkg/scheduler/nodeinfo:go_default_library", "//pkg/security/podsecuritypolicy/seccomp:go_default_library", "//pkg/ssh:go_default_library", "//pkg/util/system:go_default_library", diff --git a/test/e2e/framework/ingress/BUILD b/test/e2e/framework/ingress/BUILD index f991757f1c1..fcccf5b6c8b 100644 --- a/test/e2e/framework/ingress/BUILD +++ b/test/e2e/framework/ingress/BUILD @@ -6,6 +6,7 @@ go_library( importpath = "k8s.io/kubernetes/test/e2e/framework/ingress", visibility = ["//visibility:public"], deps = [ + "//staging/src/k8s.io/api/apps/v1:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library", "//staging/src/k8s.io/api/extensions/v1beta1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library", diff --git a/test/e2e/framework/ingress/ingress_utils.go b/test/e2e/framework/ingress/ingress_utils.go index 0cb68dc4e9a..1c230ada96c 100644 --- a/test/e2e/framework/ingress/ingress_utils.go +++ b/test/e2e/framework/ingress/ingress_utils.go @@ -34,9 +34,10 @@ import ( "strings" "time" + compute "google.golang.org/api/compute/v1" "k8s.io/klog" - compute "google.golang.org/api/compute/v1" + apps "k8s.io/api/apps/v1" "k8s.io/api/core/v1" extensions "k8s.io/api/extensions/v1beta1" apierrs "k8s.io/apimachinery/pkg/api/errors" @@ -896,12 +897,12 @@ func generateBacksideHTTPSServiceSpec() *v1.Service { } } -func generateBacksideHTTPSDeploymentSpec() *extensions.Deployment { - return &extensions.Deployment{ +func generateBacksideHTTPSDeploymentSpec() *apps.Deployment { + return &apps.Deployment{ ObjectMeta: metav1.ObjectMeta{ Name: "echoheaders-https", }, - Spec: extensions.DeploymentSpec{ + Spec: apps.DeploymentSpec{ Selector: &metav1.LabelSelector{MatchLabels: map[string]string{ "app": "echoheaders-https", }}, @@ -929,8 +930,8 @@ func generateBacksideHTTPSDeploymentSpec() *extensions.Deployment { } // SetUpBacksideHTTPSIngress sets up deployment, service and ingress with backside HTTPS configured. -func (j *IngressTestJig) SetUpBacksideHTTPSIngress(cs clientset.Interface, namespace string, staticIPName string) (*extensions.Deployment, *v1.Service, *extensions.Ingress, error) { - deployCreated, err := cs.ExtensionsV1beta1().Deployments(namespace).Create(generateBacksideHTTPSDeploymentSpec()) +func (j *IngressTestJig) SetUpBacksideHTTPSIngress(cs clientset.Interface, namespace string, staticIPName string) (*apps.Deployment, *v1.Service, *extensions.Ingress, error) { + deployCreated, err := cs.AppsV1().Deployments(namespace).Create(generateBacksideHTTPSDeploymentSpec()) if err != nil { return nil, nil, nil, err } @@ -953,7 +954,7 @@ func (j *IngressTestJig) SetUpBacksideHTTPSIngress(cs clientset.Interface, names } // DeleteTestResource deletes given deployment, service and ingress. -func (j *IngressTestJig) DeleteTestResource(cs clientset.Interface, deploy *extensions.Deployment, svc *v1.Service, ing *extensions.Ingress) []error { +func (j *IngressTestJig) DeleteTestResource(cs clientset.Interface, deploy *apps.Deployment, svc *v1.Service, ing *extensions.Ingress) []error { var errs []error if ing != nil { if err := j.runDelete(ing); err != nil { @@ -966,7 +967,7 @@ func (j *IngressTestJig) DeleteTestResource(cs clientset.Interface, deploy *exte } } if deploy != nil { - if err := cs.ExtensionsV1beta1().Deployments(deploy.Namespace).Delete(deploy.Name, nil); err != nil { + if err := cs.AppsV1().Deployments(deploy.Namespace).Delete(deploy.Name, nil); err != nil { errs = append(errs, fmt.Errorf("error while deleting deployment %s/%s: %v", deploy.Namespace, deploy.Name, err)) } } diff --git a/test/e2e/framework/nodes_util.go b/test/e2e/framework/nodes_util.go index 9bafaeec74a..60e238185f4 100644 --- a/test/e2e/framework/nodes_util.go +++ b/test/e2e/framework/nodes_util.go @@ -66,7 +66,7 @@ func etcdUpgradeGCE(target_storage, target_version string) error { os.Environ(), "TEST_ETCD_VERSION="+target_version, "STORAGE_BACKEND="+target_storage, - "TEST_ETCD_IMAGE=3.2.24-1") + "TEST_ETCD_IMAGE=3.3.10-0") _, _, err := RunCmdEnv(env, gceUpgradeScript(), "-l", "-M") return err @@ -106,7 +106,7 @@ func masterUpgradeGCE(rawV string, enableKubeProxyDaemonSet bool) error { env = append(env, "TEST_ETCD_VERSION="+TestContext.EtcdUpgradeVersion, "STORAGE_BACKEND="+TestContext.EtcdUpgradeStorage, - "TEST_ETCD_IMAGE=3.2.24-1") + "TEST_ETCD_IMAGE=3.3.10-0") } else { // In e2e tests, we skip the confirmation prompt about // implicit etcd upgrades to simulate the user entering "y". diff --git a/test/e2e/framework/psp_util.go b/test/e2e/framework/psp_util.go index 82363ed04f6..e211d4ef66f 100644 --- a/test/e2e/framework/psp_util.go +++ b/test/e2e/framework/psp_util.go @@ -78,7 +78,7 @@ func PrivilegedPSP(name string) *policy.PodSecurityPolicy { func IsPodSecurityPolicyEnabled(f *Framework) bool { isPSPEnabledOnce.Do(func() { - psps, err := f.ClientSet.ExtensionsV1beta1().PodSecurityPolicies().List(metav1.ListOptions{}) + psps, err := f.ClientSet.PolicyV1beta1().PodSecurityPolicies().List(metav1.ListOptions{}) if err != nil { Logf("Error listing PodSecurityPolicies; assuming PodSecurityPolicy is disabled: %v", err) isPSPEnabled = false @@ -103,7 +103,7 @@ func CreatePrivilegedPSPBinding(f *Framework, namespace string) { } // Create the privileged PSP & role privilegedPSPOnce.Do(func() { - _, err := f.ClientSet.ExtensionsV1beta1().PodSecurityPolicies().Get( + _, err := f.ClientSet.PolicyV1beta1().PodSecurityPolicies().Get( podSecurityPolicyPrivileged, metav1.GetOptions{}) if !apierrs.IsNotFound(err) { // Privileged PSP was already created. diff --git a/test/e2e/framework/rs_util.go b/test/e2e/framework/rs_util.go index f206dc89fca..cfdf0975ad5 100644 --- a/test/e2e/framework/rs_util.go +++ b/test/e2e/framework/rs_util.go @@ -130,7 +130,7 @@ func NewReplicaSet(name, namespace string, replicas int32, podLabels map[string] return &apps.ReplicaSet{ TypeMeta: metav1.TypeMeta{ Kind: "ReplicaSet", - APIVersion: "extensions/v1beta1", + APIVersion: "apps/v1", }, ObjectMeta: metav1.ObjectMeta{ Namespace: namespace, diff --git a/test/e2e/framework/service_util.go b/test/e2e/framework/service_util.go index 9a30001760c..394958d0f68 100644 --- a/test/e2e/framework/service_util.go +++ b/test/e2e/framework/service_util.go @@ -25,7 +25,7 @@ import ( "strings" "time" - "k8s.io/api/core/v1" + v1 "k8s.io/api/core/v1" policyv1beta1 "k8s.io/api/policy/v1beta1" "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -109,6 +109,14 @@ type ServiceTestJig struct { Labels map[string]string } +// PodNode is a pod-node pair indicating which node a given pod is running on +type PodNode struct { + // Pod represents pod name + Pod string + // Node represents node name + Node string +} + // NewServiceTestJig allocates and inits a new ServiceTestJig. func NewServiceTestJig(client clientset.Interface, name string) *ServiceTestJig { j := &ServiceTestJig{} @@ -348,6 +356,25 @@ func PickNodeIP(c clientset.Interface) string { return ip } +// PodNodePairs return PodNode pairs for all pods in a namespace +func PodNodePairs(c clientset.Interface, ns string) ([]PodNode, error) { + var result []PodNode + + podList, err := c.CoreV1().Pods(ns).List(metav1.ListOptions{}) + if err != nil { + return result, err + } + + for _, pod := range podList.Items { + result = append(result, PodNode{ + Pod: pod.Name, + Node: pod.Spec.NodeName, + }) + } + + return result, nil +} + // GetEndpointNodes returns a map of nodenames:external-ip on which the // endpoints of the given Service are running. func (j *ServiceTestJig) GetEndpointNodes(svc *v1.Service) map[string][]string { diff --git a/test/e2e/framework/test_context.go b/test/e2e/framework/test_context.go index 6db3b4685df..58df02d4371 100644 --- a/test/e2e/framework/test_context.go +++ b/test/e2e/framework/test_context.go @@ -344,7 +344,8 @@ func createKubeConfig(clientCfg *restclient.Config) *clientcmdapi.Config { config := clientcmdapi.NewConfig() credentials := clientcmdapi.NewAuthInfo() - credentials.TokenFile = "/var/run/secrets/kubernetes.io/serviceaccount/token" + credentials.Token = clientCfg.BearerToken + credentials.TokenFile = clientCfg.BearerTokenFile credentials.ClientCertificate = clientCfg.TLSClientConfig.CertFile if len(credentials.ClientCertificate) == 0 { credentials.ClientCertificateData = clientCfg.TLSClientConfig.CertData diff --git a/test/e2e/framework/util.go b/test/e2e/framework/util.go index 970801a8bde..3749fa68eed 100644 --- a/test/e2e/framework/util.go +++ b/test/e2e/framework/util.go @@ -91,7 +91,7 @@ import ( "k8s.io/kubernetes/pkg/kubelet/util/format" "k8s.io/kubernetes/pkg/master/ports" "k8s.io/kubernetes/pkg/scheduler/algorithm/predicates" - schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" + schedulernodeinfo "k8s.io/kubernetes/pkg/scheduler/nodeinfo" sshutil "k8s.io/kubernetes/pkg/ssh" "k8s.io/kubernetes/pkg/util/system" taintutils "k8s.io/kubernetes/pkg/util/taints" @@ -286,95 +286,99 @@ func FailfWithOffset(offset int, format string, args ...interface{}) { ginkgowrapper.Fail(nowStamp()+": "+msg, 1+offset) } -func Skipf(format string, args ...interface{}) { +func skipInternalf(caller int, format string, args ...interface{}) { msg := fmt.Sprintf(format, args...) log("INFO", msg) - ginkgowrapper.Skip(nowStamp() + ": " + msg) + ginkgowrapper.Skip(msg, caller+1) +} + +func Skipf(format string, args ...interface{}) { + skipInternalf(1, format, args...) } func SkipUnlessNodeCountIsAtLeast(minNodeCount int) { if TestContext.CloudConfig.NumNodes < minNodeCount { - Skipf("Requires at least %d nodes (not %d)", minNodeCount, TestContext.CloudConfig.NumNodes) + skipInternalf(1, "Requires at least %d nodes (not %d)", minNodeCount, TestContext.CloudConfig.NumNodes) } } func SkipUnlessNodeCountIsAtMost(maxNodeCount int) { if TestContext.CloudConfig.NumNodes > maxNodeCount { - Skipf("Requires at most %d nodes (not %d)", maxNodeCount, TestContext.CloudConfig.NumNodes) + skipInternalf(1, "Requires at most %d nodes (not %d)", maxNodeCount, TestContext.CloudConfig.NumNodes) } } func SkipUnlessAtLeast(value int, minValue int, message string) { if value < minValue { - Skipf(message) + skipInternalf(1, message) } } func SkipIfProviderIs(unsupportedProviders ...string) { if ProviderIs(unsupportedProviders...) { - Skipf("Not supported for providers %v (found %s)", unsupportedProviders, TestContext.Provider) + skipInternalf(1, "Not supported for providers %v (found %s)", unsupportedProviders, TestContext.Provider) } } func SkipUnlessLocalEphemeralStorageEnabled() { if !utilfeature.DefaultFeatureGate.Enabled(features.LocalStorageCapacityIsolation) { - Skipf("Only supported when %v feature is enabled", features.LocalStorageCapacityIsolation) + skipInternalf(1, "Only supported when %v feature is enabled", features.LocalStorageCapacityIsolation) } } func SkipUnlessSSHKeyPresent() { if _, err := GetSigner(TestContext.Provider); err != nil { - Skipf("No SSH Key for provider %s: '%v'", TestContext.Provider, err) + skipInternalf(1, "No SSH Key for provider %s: '%v'", TestContext.Provider, err) } } func SkipUnlessProviderIs(supportedProviders ...string) { if !ProviderIs(supportedProviders...) { - Skipf("Only supported for providers %v (not %s)", supportedProviders, TestContext.Provider) + skipInternalf(1, "Only supported for providers %v (not %s)", supportedProviders, TestContext.Provider) } } func SkipUnlessMultizone(c clientset.Interface) { zones, err := GetClusterZones(c) if err != nil { - Skipf("Error listing cluster zones") + skipInternalf(1, "Error listing cluster zones") } if zones.Len() <= 1 { - Skipf("Requires more than one zone") + skipInternalf(1, "Requires more than one zone") } } func SkipIfMultizone(c clientset.Interface) { zones, err := GetClusterZones(c) if err != nil { - Skipf("Error listing cluster zones") + skipInternalf(1, "Error listing cluster zones") } if zones.Len() > 1 { - Skipf("Requires at most one zone") + skipInternalf(1, "Requires at most one zone") } } func SkipUnlessClusterMonitoringModeIs(supportedMonitoring ...string) { if !ClusterMonitoringModeIs(supportedMonitoring...) { - Skipf("Only next monitoring modes are supported %v (not %s)", supportedMonitoring, TestContext.ClusterMonitoringMode) + skipInternalf(1, "Only next monitoring modes are supported %v (not %s)", supportedMonitoring, TestContext.ClusterMonitoringMode) } } func SkipUnlessPrometheusMonitoringIsEnabled(supportedMonitoring ...string) { if !TestContext.EnablePrometheusMonitoring { - Skipf("Skipped because prometheus monitoring is not enabled") + skipInternalf(1, "Skipped because prometheus monitoring is not enabled") } } func SkipUnlessMasterOSDistroIs(supportedMasterOsDistros ...string) { if !MasterOSDistroIs(supportedMasterOsDistros...) { - Skipf("Only supported for master OS distro %v (not %s)", supportedMasterOsDistros, TestContext.MasterOSDistro) + skipInternalf(1, "Only supported for master OS distro %v (not %s)", supportedMasterOsDistros, TestContext.MasterOSDistro) } } func SkipUnlessNodeOSDistroIs(supportedNodeOsDistros ...string) { if !NodeOSDistroIs(supportedNodeOsDistros...) { - Skipf("Only supported for node OS distro %v (not %s)", supportedNodeOsDistros, TestContext.NodeOSDistro) + skipInternalf(1, "Only supported for node OS distro %v (not %s)", supportedNodeOsDistros, TestContext.NodeOSDistro) } } @@ -389,21 +393,21 @@ func SkipUnlessSecretExistsAfterWait(c clientset.Interface, name, namespace stri } return true, nil }) != nil { - Skipf("Secret %v in namespace %v did not exist after timeout of %v", name, namespace, timeout) + skipInternalf(1, "Secret %v in namespace %v did not exist after timeout of %v", name, namespace, timeout) } Logf("Secret %v in namespace %v found after duration %v", name, namespace, time.Since(start)) } func SkipUnlessTaintBasedEvictionsEnabled() { if !utilfeature.DefaultFeatureGate.Enabled(features.TaintBasedEvictions) { - Skipf("Only supported when %v feature is enabled", features.TaintBasedEvictions) + skipInternalf(1, "Only supported when %v feature is enabled", features.TaintBasedEvictions) } } func SkipIfContainerRuntimeIs(runtimes ...string) { for _, runtime := range runtimes { if runtime == TestContext.ContainerRuntime { - Skipf("Not supported under container runtime %s", runtime) + skipInternalf(1, "Not supported under container runtime %s", runtime) } } } @@ -414,7 +418,7 @@ func RunIfContainerRuntimeIs(runtimes ...string) { return } } - Skipf("Skipped because container runtime %q is not in %s", TestContext.ContainerRuntime, runtimes) + skipInternalf(1, "Skipped because container runtime %q is not in %s", TestContext.ContainerRuntime, runtimes) } func RunIfSystemSpecNameIs(names ...string) { @@ -423,7 +427,7 @@ func RunIfSystemSpecNameIs(names ...string) { return } } - Skipf("Skipped because system spec name %q is not in %v", TestContext.SystemSpecName, names) + skipInternalf(1, "Skipped because system spec name %q is not in %v", TestContext.SystemSpecName, names) } func ProviderIs(providers ...string) bool { @@ -497,7 +501,7 @@ func SkipUnlessServerVersionGTE(v *utilversion.Version, c discovery.ServerVersio Failf("Failed to get server version: %v", err) } if !gte { - Skipf("Not supported for server versions before %q", v) + skipInternalf(1, "Not supported for server versions before %q", v) } } @@ -507,7 +511,7 @@ func SkipIfMissingResource(dynamicClient dynamic.Interface, gvr schema.GroupVers if err != nil { // not all resources support list, so we ignore those if apierrs.IsMethodNotSupported(err) || apierrs.IsNotFound(err) || apierrs.IsForbidden(err) { - Skipf("Could not find %s resource, skipping test: %#v", gvr, err) + skipInternalf(1, "Could not find %s resource, skipping test: %#v", gvr, err) } Failf("Unexpected error getting %v: %v", gvr, err) } @@ -662,7 +666,7 @@ func WaitForPodsRunningReady(c clientset.Interface, ns string, minPods, allowedN replicaOk += rc.Status.ReadyReplicas } - rsList, err := c.ExtensionsV1beta1().ReplicaSets(ns).List(metav1.ListOptions{}) + rsList, err := c.AppsV1().ReplicaSets(ns).List(metav1.ListOptions{}) if err != nil { Logf("Error getting replication sets in namespace %q: %v", ns, err) if testutils.IsRetryableAPIError(err) { @@ -1052,6 +1056,25 @@ func WaitForPersistentVolumeClaimsPhase(phase v1.PersistentVolumeClaimPhase, c c return fmt.Errorf("PersistentVolumeClaims %v not all in phase %s within %v", pvcNames, phase, timeout) } +// findAvailableNamespaceName random namespace name starting with baseName. +func findAvailableNamespaceName(baseName string, c clientset.Interface) (string, error) { + var name string + err := wait.PollImmediate(Poll, 30*time.Second, func() (bool, error) { + name = fmt.Sprintf("%v-%v", baseName, randomSuffix()) + _, err := c.CoreV1().Namespaces().Get(name, metav1.GetOptions{}) + if err == nil { + // Already taken + return false, nil + } + if apierrs.IsNotFound(err) { + return true, nil + } + Logf("Unexpected error while getting namespace: %v", err) + return false, nil + }) + return name, err +} + // CreateTestingNS should be used by every test, note that we append a common prefix to the provided test name. // Please see NewFramework instead of using this directly. func CreateTestingNS(baseName string, c clientset.Interface, labels map[string]string) (*v1.Namespace, error) { @@ -1060,11 +1083,19 @@ func CreateTestingNS(baseName string, c clientset.Interface, labels map[string]s } labels["e2e-run"] = string(RunId) + // We don't use ObjectMeta.GenerateName feature, as in case of API call + // failure we don't know whether the namespace was created and what is its + // name. + name, err := findAvailableNamespaceName(baseName, c) + if err != nil { + return nil, err + } + namespaceObj := &v1.Namespace{ ObjectMeta: metav1.ObjectMeta{ - GenerateName: fmt.Sprintf("e2e-tests-%v-", baseName), - Namespace: "", - Labels: labels, + Name: name, + Namespace: "", + Labels: labels, }, Status: v1.NamespaceStatus{}, } @@ -1294,6 +1325,7 @@ func hasRemainingContent(c clientset.Interface, dynamicClient dynamic.Interface, if err != nil { return false, err } + resources = discovery.FilteredBy(discovery.SupportsAllVerbs{Verbs: []string{"list", "delete"}}, resources) groupVersionResources, err := discovery.GroupVersionResources(resources) if err != nil { return false, err @@ -1916,7 +1948,7 @@ func SkipUnlessKubectlVersionGTE(v *utilversion.Version) { Failf("Failed to get kubectl version: %v", err) } if !gte { - Skipf("Not supported for kubectl versions before %q", v) + skipInternalf(1, "Not supported for kubectl versions before %q", v) } } @@ -2655,7 +2687,7 @@ func isNodeUntainted(node *v1.Node) bool { }, }, } - nodeInfo := schedulercache.NewNodeInfo() + nodeInfo := schedulernodeinfo.NewNodeInfo() nodeInfo.SetNode(node) fit, _, err := predicates.PodToleratesNodeTaints(fakePod, nil, nodeInfo) if err != nil { @@ -2734,7 +2766,7 @@ func WaitForAllNodesSchedulable(c clientset.Interface, timeout time.Duration) er // However, we only allow non-ready nodes with some specific reasons. if len(notSchedulable) > 0 { // In large clusters, log them only every 10th pass. - if len(nodes.Items) >= largeClusterThreshold && attempt%10 == 0 { + if len(nodes.Items) < largeClusterThreshold || attempt%10 == 0 { Logf("Unschedulable nodes:") for i := range notSchedulable { Logf("-> %s Ready=%t Network=%t Taints=%v", @@ -3061,11 +3093,11 @@ func getRuntimeObjectForKind(c clientset.Interface, kind schema.GroupKind, ns, n case api.Kind("ReplicationController"): return c.CoreV1().ReplicationControllers(ns).Get(name, metav1.GetOptions{}) case extensionsinternal.Kind("ReplicaSet"), appsinternal.Kind("ReplicaSet"): - return c.ExtensionsV1beta1().ReplicaSets(ns).Get(name, metav1.GetOptions{}) + return c.AppsV1().ReplicaSets(ns).Get(name, metav1.GetOptions{}) case extensionsinternal.Kind("Deployment"), appsinternal.Kind("Deployment"): - return c.ExtensionsV1beta1().Deployments(ns).Get(name, metav1.GetOptions{}) + return c.AppsV1().Deployments(ns).Get(name, metav1.GetOptions{}) case extensionsinternal.Kind("DaemonSet"): - return c.ExtensionsV1beta1().DaemonSets(ns).Get(name, metav1.GetOptions{}) + return c.AppsV1().DaemonSets(ns).Get(name, metav1.GetOptions{}) case batchinternal.Kind("Job"): return c.BatchV1().Jobs(ns).Get(name, metav1.GetOptions{}) default: @@ -3079,10 +3111,16 @@ func getSelectorFromRuntimeObject(obj runtime.Object) (labels.Selector, error) { return labels.SelectorFromSet(typed.Spec.Selector), nil case *extensions.ReplicaSet: return metav1.LabelSelectorAsSelector(typed.Spec.Selector) + case *apps.ReplicaSet: + return metav1.LabelSelectorAsSelector(typed.Spec.Selector) case *extensions.Deployment: return metav1.LabelSelectorAsSelector(typed.Spec.Selector) + case *apps.Deployment: + return metav1.LabelSelectorAsSelector(typed.Spec.Selector) case *extensions.DaemonSet: return metav1.LabelSelectorAsSelector(typed.Spec.Selector) + case *apps.DaemonSet: + return metav1.LabelSelectorAsSelector(typed.Spec.Selector) case *batch.Job: return metav1.LabelSelectorAsSelector(typed.Spec.Selector) default: @@ -3102,13 +3140,25 @@ func getReplicasFromRuntimeObject(obj runtime.Object) (int32, error) { return *typed.Spec.Replicas, nil } return 0, nil + case *apps.ReplicaSet: + if typed.Spec.Replicas != nil { + return *typed.Spec.Replicas, nil + } + return 0, nil case *extensions.Deployment: if typed.Spec.Replicas != nil { return *typed.Spec.Replicas, nil } return 0, nil + case *apps.Deployment: + if typed.Spec.Replicas != nil { + return *typed.Spec.Replicas, nil + } + return 0, nil case *extensions.DaemonSet: return 0, nil + case *apps.DaemonSet: + return 0, nil case *batch.Job: // TODO: currently we use pause pods so that's OK. When we'll want to switch to Pods // that actually finish we need a better way to do this. @@ -3601,44 +3651,43 @@ func DeletePodOrFail(c clientset.Interface, ns, name string) { // GetSigner returns an ssh.Signer for the provider ("gce", etc.) that can be // used to SSH to their nodes. func GetSigner(provider string) (ssh.Signer, error) { - // Get the directory in which SSH keys are located. - keydir := filepath.Join(os.Getenv("HOME"), ".ssh") - // Select the key itself to use. When implementing more providers here, // please also add them to any SSH tests that are disabled because of signer // support. keyfile := "" - key := "" switch provider { case "gce", "gke", "kubemark": - keyfile = "google_compute_engine" - case "aws": - // If there is an env. variable override, use that. - aws_keyfile := os.Getenv("AWS_SSH_KEY") - if len(aws_keyfile) != 0 { - return sshutil.MakePrivateKeySignerFromFile(aws_keyfile) + keyfile = os.Getenv("GCE_SSH_KEY") + if keyfile == "" { + keyfile = "google_compute_engine" + } + case "aws", "eks": + keyfile = os.Getenv("AWS_SSH_KEY") + if keyfile == "" { + keyfile = "kube_aws_rsa" } - // Otherwise revert to home dir - keyfile = "kube_aws_rsa" case "local", "vsphere": - keyfile = os.Getenv("LOCAL_SSH_KEY") // maybe? - if len(keyfile) == 0 { + keyfile = os.Getenv("LOCAL_SSH_KEY") + if keyfile == "" { keyfile = "id_rsa" } case "skeleton": keyfile = os.Getenv("KUBE_SSH_KEY") - if len(keyfile) == 0 { + if keyfile == "" { keyfile = "id_rsa" } default: return nil, fmt.Errorf("GetSigner(...) not implemented for %s", provider) } - if len(key) == 0 { - key = filepath.Join(keydir, keyfile) + // Respect absolute paths for keys given by user, fallback to assuming + // relative paths are in ~/.ssh + if !filepath.IsAbs(keyfile) { + keydir := filepath.Join(os.Getenv("HOME"), ".ssh") + keyfile = filepath.Join(keydir, keyfile) } - return sshutil.MakePrivateKeySignerFromFile(key) + return sshutil.MakePrivateKeySignerFromFile(keyfile) } // CheckPodsRunningReady returns whether all pods whose names are listed in diff --git a/test/e2e/instrumentation/logging/OWNERS b/test/e2e/instrumentation/logging/OWNERS index 1a6a1d51b32..c76a20b5677 100644 --- a/test/e2e/instrumentation/logging/OWNERS +++ b/test/e2e/instrumentation/logging/OWNERS @@ -1,6 +1,8 @@ reviewers: - coffeepac + - monotek - piosz approvers: - coffeepac + - monotek - piosz diff --git a/test/e2e/instrumentation/monitoring/BUILD b/test/e2e/instrumentation/monitoring/BUILD index 5c7b4b27149..5fae723aa8e 100644 --- a/test/e2e/instrumentation/monitoring/BUILD +++ b/test/e2e/instrumentation/monitoring/BUILD @@ -19,8 +19,8 @@ go_library( ], importpath = "k8s.io/kubernetes/test/e2e/instrumentation/monitoring", deps = [ + "//staging/src/k8s.io/api/apps/v1:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library", - "//staging/src/k8s.io/api/extensions/v1beta1:go_default_library", "//staging/src/k8s.io/api/rbac/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/resource:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", diff --git a/test/e2e/instrumentation/monitoring/custom_metrics_deployments.go b/test/e2e/instrumentation/monitoring/custom_metrics_deployments.go index 3c59f6e4889..636b6e86514 100644 --- a/test/e2e/instrumentation/monitoring/custom_metrics_deployments.go +++ b/test/e2e/instrumentation/monitoring/custom_metrics_deployments.go @@ -20,13 +20,14 @@ import ( "fmt" "strings" + "os/exec" + gcm "google.golang.org/api/monitoring/v3" + appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" - extensions "k8s.io/api/extensions/v1beta1" rbac "k8s.io/api/rbac/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/kubernetes/test/e2e/framework" - "os/exec" ) var ( @@ -71,7 +72,7 @@ type CustomMetricContainerSpec struct { // SimpleStackdriverExporterDeployment is a Deployment of simple application that exports a metric of // fixed value to Stackdriver in a loop. -func SimpleStackdriverExporterDeployment(name, namespace string, replicas int32, metricValue int64) *extensions.Deployment { +func SimpleStackdriverExporterDeployment(name, namespace string, replicas int32, metricValue int64) *appsv1.Deployment { return StackdriverExporterDeployment(name, namespace, replicas, []CustomMetricContainerSpec{ { @@ -86,18 +87,18 @@ func SimpleStackdriverExporterDeployment(name, namespace string, replicas int32, // an arbitrary amount of metrics of fixed value to Stackdriver in a loop. Each metric // is exposed by a different container in one pod. // The metric names and values are configured via the containers parameter. -func StackdriverExporterDeployment(name, namespace string, replicas int32, containers []CustomMetricContainerSpec) *extensions.Deployment { +func StackdriverExporterDeployment(name, namespace string, replicas int32, containers []CustomMetricContainerSpec) *appsv1.Deployment { podSpec := corev1.PodSpec{Containers: []corev1.Container{}} for _, containerSpec := range containers { podSpec.Containers = append(podSpec.Containers, stackdriverExporterContainerSpec(containerSpec.Name, namespace, containerSpec.MetricName, containerSpec.MetricValue)) } - return &extensions.Deployment{ + return &appsv1.Deployment{ ObjectMeta: metav1.ObjectMeta{ Name: name, Namespace: namespace, }, - Spec: extensions.DeploymentSpec{ + Spec: appsv1.DeploymentSpec{ Selector: &metav1.LabelSelector{ MatchLabels: map[string]string{"name": name}, }, @@ -175,13 +176,13 @@ func stackdriverExporterContainerSpec(name string, namespace string, metricName // PrometheusExporterDeployment is a Deployment of simple application with two containers // one exposing a metric in prometheus format and second a prometheus-to-sd container // that scrapes the metric and pushes it to stackdriver. -func PrometheusExporterDeployment(name, namespace string, replicas int32, metricValue int64) *extensions.Deployment { - return &extensions.Deployment{ +func PrometheusExporterDeployment(name, namespace string, replicas int32, metricValue int64) *appsv1.Deployment { + return &appsv1.Deployment{ ObjectMeta: metav1.ObjectMeta{ Name: name, Namespace: namespace, }, - Spec: extensions.DeploymentSpec{ + Spec: appsv1.DeploymentSpec{ Selector: &metav1.LabelSelector{ MatchLabels: map[string]string{"name": name}, }, diff --git a/test/e2e/kubectl/kubectl.go b/test/e2e/kubectl/kubectl.go index 3d23c49cbf2..72926eb0d17 100644 --- a/test/e2e/kubectl/kubectl.go +++ b/test/e2e/kubectl/kubectl.go @@ -1424,7 +1424,7 @@ metadata: By("running the image " + nginxImage) framework.RunKubectlOrDie("run", dName, "--image="+nginxImage, "--generator=deployment/v1beta1", nsFlag) By("verifying the deployment " + dName + " was created") - d, err := c.ExtensionsV1beta1().Deployments(ns).Get(dName, metav1.GetOptions{}) + d, err := c.AppsV1().Deployments(ns).Get(dName, metav1.GetOptions{}) if err != nil { framework.Failf("Failed getting deployment %s: %v", dName, err) } diff --git a/test/e2e/network/BUILD b/test/e2e/network/BUILD index 663a2e5d6e9..a1987d8644c 100644 --- a/test/e2e/network/BUILD +++ b/test/e2e/network/BUILD @@ -34,7 +34,6 @@ go_library( "//pkg/apis/core:go_default_library", "//pkg/client/clientset_generated/internalclientset:go_default_library", "//pkg/cloudprovider/providers/gce:go_default_library", - "//pkg/cloudprovider/providers/gce/cloud:go_default_library", "//pkg/controller/endpoint:go_default_library", "//pkg/kubelet/apis:go_default_library", "//pkg/master/ports:go_default_library", @@ -68,6 +67,7 @@ go_library( "//test/images/net/nat:go_default_library", "//test/utils:go_default_library", "//test/utils/image:go_default_library", + "//vendor/github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud:go_default_library", "//vendor/github.com/onsi/ginkgo:go_default_library", "//vendor/github.com/onsi/gomega:go_default_library", "//vendor/google.golang.org/api/compute/v0.alpha:go_default_library", diff --git a/test/e2e/network/dns_common.go b/test/e2e/network/dns_common.go index ca1dc35283d..c93c431a3cd 100644 --- a/test/e2e/network/dns_common.go +++ b/test/e2e/network/dns_common.go @@ -22,9 +22,9 @@ import ( "strings" "time" + "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/fields" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/util/intstr" @@ -494,7 +494,7 @@ func createProbeCommand(namesToResolve []string, hostEntries []string, ptrLookup // createTargetedProbeCommand returns a command line that performs a DNS lookup for a specific record type func createTargetedProbeCommand(nameToResolve string, lookup string, fileNamePrefix string) (string, string) { fileName := fmt.Sprintf("%s_udp@%s", fileNamePrefix, nameToResolve) - probeCmd := fmt.Sprintf("dig +short +tries=12 +norecurse %s %s > /results/%s", nameToResolve, lookup, fileName) + probeCmd := fmt.Sprintf("dig +short +tries=12 %s %s > /results/%s", nameToResolve, lookup, fileName) return probeCmd, fileName } diff --git a/test/e2e/network/firewall.go b/test/e2e/network/firewall.go index ee3839f16d2..32e4c1ace1c 100644 --- a/test/e2e/network/firewall.go +++ b/test/e2e/network/firewall.go @@ -131,7 +131,7 @@ var _ = SIGDescribe("Firewall rule", func() { // Send requests from outside of the cluster because internal traffic is whitelisted By("Accessing the external service ip from outside, all non-master nodes should be reached") - Expect(framework.TestHitNodesFromOutside(svcExternalIP, gce.FirewallTestHttpPort, gce.FirewallTimeoutDefault, nodesSet)).NotTo(HaveOccurred()) + Expect(framework.TestHitNodesFromOutside(svcExternalIP, gce.FirewallTestHttpPort, framework.LoadBalancerCreateTimeoutDefault, nodesSet)).NotTo(HaveOccurred()) // Check if there are overlapping tags on the firewall that extend beyond just the vms in our cluster // by removing the tag on one vm and make sure it doesn't get any traffic. This is an imperfect @@ -151,11 +151,11 @@ var _ = SIGDescribe("Firewall rule", func() { nodesSet.Insert(nodesNames[0]) gce.SetInstanceTags(cloudConfig, nodesNames[0], zone, removedTags) // Make sure traffic is recovered before exit - Expect(framework.TestHitNodesFromOutside(svcExternalIP, gce.FirewallTestHttpPort, gce.FirewallTimeoutDefault, nodesSet)).NotTo(HaveOccurred()) + Expect(framework.TestHitNodesFromOutside(svcExternalIP, gce.FirewallTestHttpPort, framework.LoadBalancerCreateTimeoutDefault, nodesSet)).NotTo(HaveOccurred()) }() By("Accessing serivce through the external ip and examine got no response from the node without tags") - Expect(framework.TestHitNodesFromOutsideWithCount(svcExternalIP, gce.FirewallTestHttpPort, gce.FirewallTimeoutDefault, nodesSet, 15)).NotTo(HaveOccurred()) + Expect(framework.TestHitNodesFromOutsideWithCount(svcExternalIP, gce.FirewallTestHttpPort, framework.LoadBalancerCreateTimeoutDefault, nodesSet, 15)).NotTo(HaveOccurred()) }) It("should have correct firewall rules for e2e cluster", func() { diff --git a/test/e2e/network/ingress.go b/test/e2e/network/ingress.go index 6a9a98b5485..96815c9dd9d 100644 --- a/test/e2e/network/ingress.go +++ b/test/e2e/network/ingress.go @@ -562,11 +562,11 @@ var _ = SIGDescribe("Loadbalancing: L7", func() { It("should sync endpoints to NEG", func() { name := "hostname" scaleAndValidateNEG := func(num int) { - scale, err := f.ClientSet.ExtensionsV1beta1().Deployments(ns).GetScale(name, metav1.GetOptions{}) + scale, err := f.ClientSet.AppsV1().Deployments(ns).GetScale(name, metav1.GetOptions{}) Expect(err).NotTo(HaveOccurred()) if scale.Spec.Replicas != int32(num) { scale.Spec.Replicas = int32(num) - _, err = f.ClientSet.ExtensionsV1beta1().Deployments(ns).UpdateScale(name, scale) + _, err = f.ClientSet.AppsV1().Deployments(ns).UpdateScale(name, scale) Expect(err).NotTo(HaveOccurred()) } wait.Poll(10*time.Second, ingress.NEGUpdateTimeout, func() (bool, error) { @@ -611,10 +611,10 @@ var _ = SIGDescribe("Loadbalancing: L7", func() { Expect(usingNEG).To(BeTrue()) By(fmt.Sprintf("Scale backend replicas to %d", replicas)) - scale, err := f.ClientSet.ExtensionsV1beta1().Deployments(ns).GetScale(name, metav1.GetOptions{}) + scale, err := f.ClientSet.AppsV1().Deployments(ns).GetScale(name, metav1.GetOptions{}) Expect(err).NotTo(HaveOccurred()) scale.Spec.Replicas = int32(replicas) - _, err = f.ClientSet.ExtensionsV1beta1().Deployments(ns).UpdateScale(name, scale) + _, err = f.ClientSet.AppsV1().Deployments(ns).UpdateScale(name, scale) Expect(err).NotTo(HaveOccurred()) wait.Poll(10*time.Second, framework.LoadBalancerPollTimeout, func() (bool, error) { res, err := jig.GetDistinctResponseFromIngress() @@ -625,17 +625,17 @@ var _ = SIGDescribe("Loadbalancing: L7", func() { }) By("Trigger rolling update and observe service disruption") - deploy, err := f.ClientSet.ExtensionsV1beta1().Deployments(ns).Get(name, metav1.GetOptions{}) + deploy, err := f.ClientSet.AppsV1().Deployments(ns).Get(name, metav1.GetOptions{}) Expect(err).NotTo(HaveOccurred()) // trigger by changing graceful termination period to 60 seconds gracePeriod := int64(60) deploy.Spec.Template.Spec.TerminationGracePeriodSeconds = &gracePeriod - _, err = f.ClientSet.ExtensionsV1beta1().Deployments(ns).Update(deploy) + _, err = f.ClientSet.AppsV1().Deployments(ns).Update(deploy) Expect(err).NotTo(HaveOccurred()) wait.Poll(10*time.Second, framework.LoadBalancerPollTimeout, func() (bool, error) { res, err := jig.GetDistinctResponseFromIngress() Expect(err).NotTo(HaveOccurred()) - deploy, err := f.ClientSet.ExtensionsV1beta1().Deployments(ns).Get(name, metav1.GetOptions{}) + deploy, err := f.ClientSet.AppsV1().Deployments(ns).Get(name, metav1.GetOptions{}) Expect(err).NotTo(HaveOccurred()) if int(deploy.Status.UpdatedReplicas) == replicas { if res.Len() == replicas { @@ -657,11 +657,11 @@ var _ = SIGDescribe("Loadbalancing: L7", func() { expectedKeys := []int32{80, 443} scaleAndValidateExposedNEG := func(num int) { - scale, err := f.ClientSet.ExtensionsV1beta1().Deployments(ns).GetScale(name, metav1.GetOptions{}) + scale, err := f.ClientSet.AppsV1().Deployments(ns).GetScale(name, metav1.GetOptions{}) Expect(err).NotTo(HaveOccurred()) if scale.Spec.Replicas != int32(num) { scale.Spec.Replicas = int32(num) - _, err = f.ClientSet.ExtensionsV1beta1().Deployments(ns).UpdateScale(name, scale) + _, err = f.ClientSet.AppsV1().Deployments(ns).UpdateScale(name, scale) Expect(err).NotTo(HaveOccurred()) } wait.Poll(10*time.Second, ingress.NEGUpdateTimeout, func() (bool, error) { diff --git a/test/e2e/network/network_tiers.go b/test/e2e/network/network_tiers.go index c102d52e3d3..459be2b2cf4 100644 --- a/test/e2e/network/network_tiers.go +++ b/test/e2e/network/network_tiers.go @@ -23,12 +23,12 @@ import ( computealpha "google.golang.org/api/compute/v0.alpha" - "k8s.io/api/core/v1" + "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud" + v1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/util/wait" clientset "k8s.io/client-go/kubernetes" cloudprovider "k8s.io/cloud-provider" gcecloud "k8s.io/kubernetes/pkg/cloudprovider/providers/gce" - "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud" "k8s.io/kubernetes/test/e2e/framework" "k8s.io/kubernetes/test/e2e/framework/providers/gce" diff --git a/test/e2e/network/scale/BUILD b/test/e2e/network/scale/BUILD index f99c7d97ade..5bfd0cee49c 100644 --- a/test/e2e/network/scale/BUILD +++ b/test/e2e/network/scale/BUILD @@ -6,6 +6,7 @@ go_library( importpath = "k8s.io/kubernetes/test/e2e/network/scale", visibility = ["//visibility:public"], deps = [ + "//staging/src/k8s.io/api/apps/v1:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library", "//staging/src/k8s.io/api/extensions/v1beta1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", diff --git a/test/e2e/network/scale/ingress.go b/test/e2e/network/scale/ingress.go index ce8d43c5ca5..a570321f3a2 100644 --- a/test/e2e/network/scale/ingress.go +++ b/test/e2e/network/scale/ingress.go @@ -22,6 +22,7 @@ import ( "sync" "time" + apps "k8s.io/api/apps/v1" "k8s.io/api/core/v1" extensions "k8s.io/api/extensions/v1beta1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -71,7 +72,7 @@ type IngressScaleFramework struct { NumIngressesTest []int OutputFile string - ScaleTestDeploy *extensions.Deployment + ScaleTestDeploy *apps.Deployment ScaleTestSvcs []*v1.Service ScaleTestIngs []*extensions.Ingress @@ -147,7 +148,7 @@ func (f *IngressScaleFramework) CleanupScaleTest() []error { } if f.ScaleTestDeploy != nil { f.Logger.Infof("Cleaning up deployment %s...", f.ScaleTestDeploy.Name) - if err := f.Clientset.ExtensionsV1beta1().Deployments(f.ScaleTestDeploy.Namespace).Delete(f.ScaleTestDeploy.Name, nil); err != nil { + if err := f.Clientset.AppsV1().Deployments(f.ScaleTestDeploy.Namespace).Delete(f.ScaleTestDeploy.Name, nil); err != nil { errs = append(errs, fmt.Errorf("Error while delting deployment %s/%s: %v", f.ScaleTestDeploy.Namespace, f.ScaleTestDeploy.Name, err)) } } @@ -166,7 +167,7 @@ func (f *IngressScaleFramework) RunScaleTest() []error { testDeploy := generateScaleTestBackendDeploymentSpec(scaleTestNumBackends) f.Logger.Infof("Creating deployment %s...", testDeploy.Name) - testDeploy, err := f.Jig.Client.ExtensionsV1beta1().Deployments(f.Namespace).Create(testDeploy) + testDeploy, err := f.Jig.Client.AppsV1().Deployments(f.Namespace).Create(testDeploy) if err != nil { errs = append(errs, fmt.Errorf("Failed to create deployment %s: %v", testDeploy.Name, err)) return errs @@ -436,12 +437,12 @@ func generateScaleTestServiceSpec(suffix string) *v1.Service { } } -func generateScaleTestBackendDeploymentSpec(numReplicas int32) *extensions.Deployment { - return &extensions.Deployment{ +func generateScaleTestBackendDeploymentSpec(numReplicas int32) *apps.Deployment { + return &apps.Deployment{ ObjectMeta: metav1.ObjectMeta{ Name: scaleTestBackendName, }, - Spec: extensions.DeploymentSpec{ + Spec: apps.DeploymentSpec{ Replicas: &numReplicas, Selector: &metav1.LabelSelector{MatchLabels: scaleTestLabels}, Template: v1.PodTemplateSpec{ diff --git a/test/e2e/network/service.go b/test/e2e/network/service.go index a1b85257b8a..c1bbdb52801 100644 --- a/test/e2e/network/service.go +++ b/test/e2e/network/service.go @@ -27,7 +27,7 @@ import ( compute "google.golang.org/api/compute/v1" - "k8s.io/api/core/v1" + v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/util/intstr" @@ -1687,6 +1687,67 @@ var _ = SIGDescribe("Services", func() { svc.Spec.ExternalTrafficPolicy = v1.ServiceExternalTrafficPolicyTypeCluster execAffinityTestForLBService(f, cs, svc, true) }) + + It("should implement service.kubernetes.io/service-proxy-name", func() { + // this test uses framework.NodeSSHHosts that does not work if a Node only reports LegacyHostIP + framework.SkipUnlessProviderIs(framework.ProvidersWithSSH...) + // this test does not work if the Node does not support SSH Key + framework.SkipUnlessSSHKeyPresent() + + ns := f.Namespace.Name + numPods, servicePort := 3, defaultServeHostnameServicePort + serviceProxyNameLabels := map[string]string{"service.kubernetes.io/service-proxy-name": "foo-bar"} + + // We will create 2 services to test creating services in both states and also dynamic updates + // svcDisabled: Created with the label, will always be disabled. We create this early and + // test again late to make sure it never becomes available. + // svcToggled: Created without the label then the label is toggled verifying reachability at each step. + + By("creating service-disabled in namespace " + ns) + svcDisabled := getServeHostnameService("service-disabled") + svcDisabled.ObjectMeta.Labels = serviceProxyNameLabels + _, svcDisabledIP, err := framework.StartServeHostnameService(cs, internalClientset, svcDisabled, ns, numPods) + Expect(err).NotTo(HaveOccurred()) + + By("creating service in namespace " + ns) + svcToggled := getServeHostnameService("service") + podToggledNames, svcToggledIP, err := framework.StartServeHostnameService(cs, internalClientset, svcToggled, ns, numPods) + Expect(err).NotTo(HaveOccurred()) + + jig := framework.NewServiceTestJig(cs, svcToggled.ObjectMeta.Name) + + hosts, err := framework.NodeSSHHosts(cs) + Expect(err).NotTo(HaveOccurred()) + if len(hosts) == 0 { + framework.Failf("No ssh-able nodes") + } + host := hosts[0] + + By("verifying service is up") + framework.ExpectNoError(framework.VerifyServeHostnameServiceUp(cs, ns, host, podToggledNames, svcToggledIP, servicePort)) + + By("verifying service-disabled is not up") + framework.ExpectNoError(framework.VerifyServeHostnameServiceDown(cs, host, svcDisabledIP, servicePort)) + + By("adding service-proxy-name label") + jig.UpdateServiceOrFail(ns, svcToggled.ObjectMeta.Name, func(svc *v1.Service) { + svc.ObjectMeta.Labels = serviceProxyNameLabels + }) + + By("verifying service is not up") + framework.ExpectNoError(framework.VerifyServeHostnameServiceDown(cs, host, svcToggledIP, servicePort)) + + By("removing service-proxy-name annotation") + jig.UpdateServiceOrFail(ns, svcToggled.ObjectMeta.Name, func(svc *v1.Service) { + svc.ObjectMeta.Labels = nil + }) + + By("verifying service is up") + framework.ExpectNoError(framework.VerifyServeHostnameServiceUp(cs, ns, host, podToggledNames, svcToggledIP, servicePort)) + + By("verifying service-disabled is still not up") + framework.ExpectNoError(framework.VerifyServeHostnameServiceDown(cs, host, svcDisabledIP, servicePort)) + }) }) // TODO: Get rid of [DisabledForLargeClusters] tag when issue #56138 is fixed. @@ -2111,6 +2172,8 @@ func execAffinityTestForLBService(f *framework.Framework, cs clientset.Interface svc = jig.WaitForLoadBalancerOrFail(ns, serviceName, framework.LoadBalancerCreateTimeoutDefault) jig.SanityCheckService(svc, v1.ServiceTypeLoadBalancer) defer func() { + podNodePairs, err := framework.PodNodePairs(cs, ns) + framework.Logf("[pod,node] pairs: %+v; err: %v", podNodePairs, err) framework.StopServeHostnameService(cs, ns, serviceName) lb := cloudprovider.DefaultLoadBalancerName(svc) framework.Logf("cleaning load balancer resource for %s", lb) diff --git a/test/e2e/scalability/BUILD b/test/e2e/scalability/BUILD index a87ebd8c347..0d7e0e47f69 100644 --- a/test/e2e/scalability/BUILD +++ b/test/e2e/scalability/BUILD @@ -3,6 +3,7 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library") go_library( name = "go_default_library", srcs = [ + "common.go", "density.go", "framework.go", "load.go", diff --git a/test/e2e/scalability/common.go b/test/e2e/scalability/common.go new file mode 100644 index 00000000000..4fac86cb03d --- /dev/null +++ b/test/e2e/scalability/common.go @@ -0,0 +1,24 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package scalability + +import "time" + +const ( + // UnreadyNodeToleration denotes time the node can be unreachable/not ready. + UnreadyNodeToleration = 15 * time.Minute +) diff --git a/test/e2e/scalability/density.go b/test/e2e/scalability/density.go index 3d4d9a6e21e..9a2e64256c3 100644 --- a/test/e2e/scalability/density.go +++ b/test/e2e/scalability/density.go @@ -637,7 +637,11 @@ var _ = SIGDescribe("Density", func() { // Since all RCs are created at the same time, timeout for each config // has to assume that it will be run at the very end. podThroughput := 20 - timeout := time.Duration(totalPods/podThroughput)*time.Second + 3*time.Minute + timeout := time.Duration(totalPods/podThroughput) * time.Second + if timeout < UnreadyNodeToleration { + timeout = UnreadyNodeToleration + } + timeout += 3 * time.Minute // createClients is defined in load.go clients, internalClients, scalesClients, err := createClients(numberOfCollections) framework.ExpectNoError(err) @@ -688,6 +692,19 @@ var _ = SIGDescribe("Density", func() { SecretNames: secretNames, ConfigMapNames: configMapNames, ServiceAccountTokenProjections: itArg.svcacctTokenProjectionsPerPod, + Tolerations: []v1.Toleration{ + { + Key: "node.kubernetes.io/not-ready", + Operator: v1.TolerationOpExists, + Effect: v1.TaintEffectNoExecute, + TolerationSeconds: func(i int64) *int64 { return &i }(int64(UnreadyNodeToleration / time.Second)), + }, { + Key: "node.kubernetes.io/unreachable", + Operator: v1.TolerationOpExists, + Effect: v1.TaintEffectNoExecute, + TolerationSeconds: func(i int64) *int64 { return &i }(int64(UnreadyNodeToleration / time.Second)), + }, + }, } switch itArg.kind { case api.Kind("ReplicationController"): diff --git a/test/e2e/scalability/load.go b/test/e2e/scalability/load.go index 78d3d45c55c..5e2a95e2d9c 100644 --- a/test/e2e/scalability/load.go +++ b/test/e2e/scalability/load.go @@ -541,7 +541,7 @@ func GenerateConfigsForGroup( InternalClient: nil, // this will be overwritten later Name: groupName + "-" + strconv.Itoa(i), Namespace: namespace, - Timeout: 10 * time.Minute, + Timeout: UnreadyNodeToleration, Image: image, Command: command, Replicas: size, @@ -551,6 +551,19 @@ func GenerateConfigsForGroup( ConfigMapNames: configMapNames, // Define a label to group every 2 RCs into one service. Labels: map[string]string{svcLabelKey: groupName + "-" + strconv.Itoa((i+1)/2)}, + Tolerations: []v1.Toleration{ + { + Key: "node.kubernetes.io/not-ready", + Operator: v1.TolerationOpExists, + Effect: v1.TaintEffectNoExecute, + TolerationSeconds: func(i int64) *int64 { return &i }(int64(UnreadyNodeToleration / time.Second)), + }, { + Key: "node.kubernetes.io/unreachable", + Operator: v1.TolerationOpExists, + Effect: v1.TaintEffectNoExecute, + TolerationSeconds: func(i int64) *int64 { return &i }(int64(UnreadyNodeToleration / time.Second)), + }, + }, } if kind == randomKind { diff --git a/test/e2e/scheduling/BUILD b/test/e2e/scheduling/BUILD index 33eaa147b54..9d58bc67694 100644 --- a/test/e2e/scheduling/BUILD +++ b/test/e2e/scheduling/BUILD @@ -11,7 +11,6 @@ go_library( "predicates.go", "preemption.go", "priorities.go", - "resource_quota.go", "taint_based_evictions.go", "taints.go", "ubernetes_lite.go", @@ -24,12 +23,10 @@ go_library( "//pkg/apis/extensions:go_default_library", "//pkg/apis/scheduling:go_default_library", "//pkg/kubelet/apis:go_default_library", - "//pkg/quota/v1/evaluator/core:go_default_library", "//pkg/scheduler/algorithm/priorities/util:go_default_library", "//pkg/scheduler/api:go_default_library", "//staging/src/k8s.io/api/apps/v1:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library", - "//staging/src/k8s.io/api/extensions/v1beta1:go_default_library", "//staging/src/k8s.io/api/scheduling/v1beta1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/resource:go_default_library", diff --git a/test/e2e/storage/BUILD b/test/e2e/storage/BUILD index 118c3a259ba..37e6ae2e1c5 100644 --- a/test/e2e/storage/BUILD +++ b/test/e2e/storage/BUILD @@ -41,7 +41,6 @@ go_library( "//pkg/volume/util:go_default_library", "//staging/src/k8s.io/api/apps/v1:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library", - "//staging/src/k8s.io/api/extensions/v1beta1:go_default_library", "//staging/src/k8s.io/api/policy/v1beta1:go_default_library", "//staging/src/k8s.io/api/rbac/v1beta1:go_default_library", "//staging/src/k8s.io/api/storage/v1:go_default_library", diff --git a/test/e2e/storage/csi_volumes.go b/test/e2e/storage/csi_volumes.go index dd9a25806a7..5c5477119c2 100644 --- a/test/e2e/storage/csi_volumes.go +++ b/test/e2e/storage/csi_volumes.go @@ -43,11 +43,11 @@ import ( ) // List of testDrivers to be executed in below loop -var csiTestDrivers = []func() drivers.TestDriver{ +var csiTestDrivers = []func(config testsuites.TestConfig) testsuites.TestDriver{ drivers.InitHostPathCSIDriver, drivers.InitGcePDCSIDriver, drivers.InitGcePDExternalCSIDriver, - drivers.InitHostV0PathCSIDriver, + drivers.InitHostPathV0CSIDriver, } // List of testSuites to be executed in below loop @@ -81,7 +81,11 @@ var _ = utils.SIGDescribe("CSI Volumes", func() { cancel context.CancelFunc cs clientset.Interface ns *v1.Namespace - config framework.VolumeTestConfig + // Common configuration options for each driver. + config = testsuites.TestConfig{ + Framework: f, + Prefix: "csi", + } ) BeforeEach(func() { @@ -89,10 +93,7 @@ var _ = utils.SIGDescribe("CSI Volumes", func() { cancel = c cs = f.ClientSet ns = f.Namespace - config = framework.VolumeTestConfig{ - Namespace: ns.Name, - Prefix: "csi", - } + // Debugging of the following tests heavily depends on the log output // of the different containers. Therefore include all of that in log // files (when using --report-dir, as in the CI) or the output stream @@ -125,22 +126,24 @@ var _ = utils.SIGDescribe("CSI Volumes", func() { }) for _, initDriver := range csiTestDrivers { - curDriver := initDriver() - Context(drivers.GetDriverNameWithFeatureTags(curDriver), func() { - driver := curDriver - + curDriver := initDriver(config) + curConfig := curDriver.GetDriverInfo().Config + Context(testsuites.GetDriverNameWithFeatureTags(curDriver), func() { BeforeEach(func() { + // Reset config. The driver might have modified its copy + // in a previous test. + curDriver.GetDriverInfo().Config = curConfig + // setupDriver - drivers.SetCommonDriverParameters(driver, f, config) - driver.CreateDriver() + curDriver.CreateDriver() }) AfterEach(func() { // Cleanup driver - driver.CleanupDriver() + curDriver.CleanupDriver() }) - testsuites.RunTestSuite(f, config, driver, csiTestSuites, csiTunePattern) + testsuites.RunTestSuite(f, curDriver, csiTestSuites, csiTunePattern) }) } @@ -149,14 +152,17 @@ var _ = utils.SIGDescribe("CSI Volumes", func() { var ( cs clientset.Interface csics csiclient.Interface - driver drivers.TestDriver + driver testsuites.TestDriver ) BeforeEach(func() { cs = f.ClientSet csics = f.CSIClientSet - driver = drivers.InitHostPathCSIDriver() - drivers.SetCommonDriverParameters(driver, f, config) + config := testsuites.TestConfig{ + Framework: f, + Prefix: "csi-attach", + } + driver = drivers.InitHostPathCSIDriver(config) driver.CreateDriver() }) @@ -193,7 +199,7 @@ var _ = utils.SIGDescribe("CSI Volumes", func() { test := t It(test.name, func() { if test.driverExists { - csiDriver := createCSIDriver(csics, drivers.GetUniqueDriverName(driver), test.driverAttachable) + csiDriver := createCSIDriver(csics, testsuites.GetUniqueDriverName(driver), test.driverAttachable) if csiDriver != nil { defer csics.CsiV1alpha1().CSIDrivers().Delete(csiDriver.Name, nil) } @@ -201,7 +207,7 @@ var _ = utils.SIGDescribe("CSI Volumes", func() { By("Creating pod") var sc *storagev1.StorageClass - if dDriver, ok := driver.(drivers.DynamicPVTestDriver); ok { + if dDriver, ok := driver.(testsuites.DynamicPVTestDriver); ok { sc = dDriver.GetDynamicProvisionStorageClass("") } nodeName := driver.GetDriverInfo().Config.ClientNodeName diff --git a/test/e2e/storage/detach_mounted.go b/test/e2e/storage/detach_mounted.go index 5c944b541fb..4ee571e8cfb 100644 --- a/test/e2e/storage/detach_mounted.go +++ b/test/e2e/storage/detach_mounted.go @@ -64,7 +64,7 @@ var _ = utils.SIGDescribe("Detaching volumes", func() { }) It("should not work when mount is in progress", func() { - driver := "attachable-with-long-format" + driver := "attachable-with-long-mount" driverInstallAs := driver + "-" + suffix By(fmt.Sprintf("installing flexvolume %s on node %s as %s", path.Join(driverDir, driver), node.Name, driverInstallAs)) diff --git a/test/e2e/storage/drivers/BUILD b/test/e2e/storage/drivers/BUILD index 487e0f21866..da57c59f188 100644 --- a/test/e2e/storage/drivers/BUILD +++ b/test/e2e/storage/drivers/BUILD @@ -3,7 +3,6 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library") go_library( name = "go_default_library", srcs = [ - "base.go", "csi.go", "csi_objects.go", "in_tree.go", @@ -24,6 +23,7 @@ go_library( "//staging/src/k8s.io/client-go/kubernetes:go_default_library", "//test/e2e/framework:go_default_library", "//test/e2e/storage/testpatterns:go_default_library", + "//test/e2e/storage/testsuites:go_default_library", "//test/e2e/storage/utils:go_default_library", "//test/e2e/storage/vsphere:go_default_library", "//test/utils/image:go_default_library", diff --git a/test/e2e/storage/drivers/csi.go b/test/e2e/storage/drivers/csi.go index d58faa46f35..357ef2318ce 100644 --- a/test/e2e/storage/drivers/csi.go +++ b/test/e2e/storage/drivers/csi.go @@ -44,74 +44,42 @@ import ( "k8s.io/apimachinery/pkg/util/sets" "k8s.io/kubernetes/test/e2e/framework" "k8s.io/kubernetes/test/e2e/storage/testpatterns" + "k8s.io/kubernetes/test/e2e/storage/testsuites" "k8s.io/kubernetes/test/e2e/storage/utils" ) // hostpathCSI type hostpathCSIDriver struct { cleanup func() - driverInfo DriverInfo + driverInfo testsuites.DriverInfo + manifests []string } -var _ TestDriver = &hostpathCSIDriver{} -var _ DynamicPVTestDriver = &hostpathCSIDriver{} - -// InitHostPathCSIDriver returns hostpathCSIDriver that implements TestDriver interface -func InitHostPathCSIDriver() TestDriver { +func initHostPathCSIDriver(name string, config testsuites.TestConfig, manifests ...string) testsuites.TestDriver { return &hostpathCSIDriver{ - driverInfo: DriverInfo{ - Name: "csi-hostpath", + driverInfo: testsuites.DriverInfo{ + Name: name, FeatureTag: "", MaxFileSize: testpatterns.FileSizeMedium, SupportedFsType: sets.NewString( "", // Default fsType ), - Capabilities: map[Capability]bool{ - CapPersistence: true, + Capabilities: map[testsuites.Capability]bool{ + testsuites.CapPersistence: true, }, + + Config: config, }, + manifests: manifests, } } -func (h *hostpathCSIDriver) GetDriverInfo() *DriverInfo { - return &h.driverInfo -} +var _ testsuites.TestDriver = &hostpathCSIDriver{} +var _ testsuites.DynamicPVTestDriver = &hostpathCSIDriver{} -func (h *hostpathCSIDriver) SkipUnsupportedTest(pattern testpatterns.TestPattern) { -} - -func (h *hostpathCSIDriver) GetDynamicProvisionStorageClass(fsType string) *storagev1.StorageClass { - provisioner := GetUniqueDriverName(h) - parameters := map[string]string{} - ns := h.driverInfo.Framework.Namespace.Name - suffix := fmt.Sprintf("%s-sc", provisioner) - - return getStorageClass(provisioner, parameters, nil, ns, suffix) -} - -func (h *hostpathCSIDriver) CreateDriver() { - By("deploying csi hostpath driver") - f := h.driverInfo.Framework - cs := f.ClientSet - - // pods should be scheduled on the node - nodes := framework.GetReadySchedulableNodesOrDie(cs) - node := nodes.Items[rand.Intn(len(nodes.Items))] - h.driverInfo.Config.ClientNodeName = node.Name - h.driverInfo.Config.ServerNodeName = node.Name - - // TODO (?): the storage.csi.image.version and storage.csi.image.registry - // settings are ignored for this test. We could patch the image definitions. - o := utils.PatchCSIOptions{ - OldDriverName: h.driverInfo.Name, - NewDriverName: GetUniqueDriverName(h), - DriverContainerName: "hostpath", - ProvisionerContainerName: "csi-provisioner", - NodeName: h.driverInfo.Config.ServerNodeName, - } - cleanup, err := h.driverInfo.Framework.CreateFromManifests(func(item interface{}) error { - return utils.PatchCSIDeployment(h.driverInfo.Framework, o, item) - }, +// InitHostPathCSIDriver returns hostpathCSIDriver that implements TestDriver interface +func InitHostPathCSIDriver(config testsuites.TestConfig) testsuites.TestDriver { + return initHostPathCSIDriver("csi-hostpath", config, "test/e2e/testing-manifests/storage-csi/driver-registrar/rbac.yaml", "test/e2e/testing-manifests/storage-csi/external-attacher/rbac.yaml", "test/e2e/testing-manifests/storage-csi/external-provisioner/rbac.yaml", @@ -120,84 +88,67 @@ func (h *hostpathCSIDriver) CreateDriver() { "test/e2e/testing-manifests/storage-csi/hostpath/hostpath/csi-hostpathplugin.yaml", "test/e2e/testing-manifests/storage-csi/hostpath/hostpath/e2e-test-rbac.yaml", ) - h.cleanup = cleanup - if err != nil { - framework.Failf("deploying csi hostpath driver: %v", err) - } } -func (h *hostpathCSIDriver) CleanupDriver() { - if h.cleanup != nil { - By("uninstalling csi hostpath driver") - h.cleanup() - } -} - -// hostpathV0CSIDriver -type hostpathV0CSIDriver struct { - cleanup func() - driverInfo DriverInfo -} - -var _ TestDriver = &hostpathV0CSIDriver{} -var _ DynamicPVTestDriver = &hostpathV0CSIDriver{} - -// InitHostPathV0CSIDriver returns hostpathV0CSIDriver that implements TestDriver interface -func InitHostV0PathCSIDriver() TestDriver { - return &hostpathV0CSIDriver{ - driverInfo: DriverInfo{ - Name: "csi-hostpath-v0", - FeatureTag: "", - MaxFileSize: testpatterns.FileSizeMedium, - SupportedFsType: sets.NewString( - "", // Default fsType - ), - Capabilities: map[Capability]bool{ - CapPersistence: true, - }, - }, - } -} - -func (h *hostpathV0CSIDriver) GetDriverInfo() *DriverInfo { +func (h *hostpathCSIDriver) GetDriverInfo() *testsuites.DriverInfo { return &h.driverInfo } -func (h *hostpathV0CSIDriver) SkipUnsupportedTest(pattern testpatterns.TestPattern) { +func (h *hostpathCSIDriver) SkipUnsupportedTest(pattern testpatterns.TestPattern) { } -func (h *hostpathV0CSIDriver) GetDynamicProvisionStorageClass(fsType string) *storagev1.StorageClass { - provisioner := GetUniqueDriverName(h) +func (h *hostpathCSIDriver) GetDynamicProvisionStorageClass(fsType string) *storagev1.StorageClass { + provisioner := testsuites.GetUniqueDriverName(h) parameters := map[string]string{} - ns := h.driverInfo.Framework.Namespace.Name + ns := h.driverInfo.Config.Framework.Namespace.Name suffix := fmt.Sprintf("%s-sc", provisioner) - return getStorageClass(provisioner, parameters, nil, ns, suffix) + return testsuites.GetStorageClass(provisioner, parameters, nil, ns, suffix) } -func (h *hostpathV0CSIDriver) CreateDriver() { - By("deploying csi hostpath v0 driver") - f := h.driverInfo.Framework +func (h *hostpathCSIDriver) GetClaimSize() string { + return "5Gi" +} + +func (h *hostpathCSIDriver) CreateDriver() { + By(fmt.Sprintf("deploying %s driver", h.driverInfo.Name)) + f := h.driverInfo.Config.Framework cs := f.ClientSet - // pods should be scheduled on the node + // The hostpath CSI driver only works when everything runs on the same node. nodes := framework.GetReadySchedulableNodesOrDie(cs) - node := nodes.Items[rand.Intn(len(nodes.Items))] - h.driverInfo.Config.ClientNodeName = node.Name - h.driverInfo.Config.ServerNodeName = node.Name + nodeName := nodes.Items[rand.Intn(len(nodes.Items))].Name + h.driverInfo.Config.ClientNodeName = nodeName // TODO (?): the storage.csi.image.version and storage.csi.image.registry // settings are ignored for this test. We could patch the image definitions. o := utils.PatchCSIOptions{ OldDriverName: h.driverInfo.Name, - NewDriverName: GetUniqueDriverName(h), + NewDriverName: testsuites.GetUniqueDriverName(h), DriverContainerName: "hostpath", - ProvisionerContainerName: "csi-provisioner-v0", - NodeName: h.driverInfo.Config.ServerNodeName, + ProvisionerContainerName: "csi-provisioner", + NodeName: nodeName, } - cleanup, err := h.driverInfo.Framework.CreateFromManifests(func(item interface{}) error { - return utils.PatchCSIDeployment(h.driverInfo.Framework, o, item) + cleanup, err := h.driverInfo.Config.Framework.CreateFromManifests(func(item interface{}) error { + return utils.PatchCSIDeployment(h.driverInfo.Config.Framework, o, item) }, + h.manifests...) + h.cleanup = cleanup + if err != nil { + framework.Failf("deploying %s driver: %v", h.driverInfo.Name, err) + } +} + +func (h *hostpathCSIDriver) CleanupDriver() { + if h.cleanup != nil { + By(fmt.Sprintf("uninstalling %s driver", h.driverInfo.Name)) + h.cleanup() + } +} + +// InitHostPathV0CSIDriver returns a variant of hostpathCSIDriver with different manifests. +func InitHostPathV0CSIDriver(config testsuites.TestConfig) testsuites.TestDriver { + return initHostPathCSIDriver("csi-hostpath-v0", config, "test/e2e/testing-manifests/storage-csi/driver-registrar/rbac.yaml", "test/e2e/testing-manifests/storage-csi/external-attacher/rbac.yaml", "test/e2e/testing-manifests/storage-csi/external-provisioner/rbac.yaml", @@ -206,32 +157,21 @@ func (h *hostpathV0CSIDriver) CreateDriver() { "test/e2e/testing-manifests/storage-csi/hostpath/hostpath-v0/csi-hostpathplugin.yaml", "test/e2e/testing-manifests/storage-csi/hostpath/hostpath-v0/e2e-test-rbac.yaml", ) - h.cleanup = cleanup - if err != nil { - framework.Failf("deploying csi hostpath v0 driver: %v", err) - } -} - -func (h *hostpathV0CSIDriver) CleanupDriver() { - if h.cleanup != nil { - By("uninstalling csi hostpath v0 driver") - h.cleanup() - } } // gce-pd type gcePDCSIDriver struct { cleanup func() - driverInfo DriverInfo + driverInfo testsuites.DriverInfo } -var _ TestDriver = &gcePDCSIDriver{} -var _ DynamicPVTestDriver = &gcePDCSIDriver{} +var _ testsuites.TestDriver = &gcePDCSIDriver{} +var _ testsuites.DynamicPVTestDriver = &gcePDCSIDriver{} // InitGcePDCSIDriver returns gcePDCSIDriver that implements TestDriver interface -func InitGcePDCSIDriver() TestDriver { +func InitGcePDCSIDriver(config testsuites.TestConfig) testsuites.TestDriver { return &gcePDCSIDriver{ - driverInfo: DriverInfo{ + driverInfo: testsuites.DriverInfo{ Name: "pd.csi.storage.gke.io", FeatureTag: "[Serial]", MaxFileSize: testpatterns.FileSizeMedium, @@ -242,33 +182,39 @@ func InitGcePDCSIDriver() TestDriver { "ext4", "xfs", ), - Capabilities: map[Capability]bool{ - CapPersistence: true, - CapFsGroup: true, - CapExec: true, + Capabilities: map[testsuites.Capability]bool{ + testsuites.CapPersistence: true, + testsuites.CapFsGroup: true, + testsuites.CapExec: true, }, + + Config: config, }, } } -func (g *gcePDCSIDriver) GetDriverInfo() *DriverInfo { +func (g *gcePDCSIDriver) GetDriverInfo() *testsuites.DriverInfo { return &g.driverInfo } func (g *gcePDCSIDriver) SkipUnsupportedTest(pattern testpatterns.TestPattern) { - f := g.driverInfo.Framework + f := g.driverInfo.Config.Framework framework.SkipUnlessProviderIs("gce", "gke") framework.SkipIfMultizone(f.ClientSet) } func (g *gcePDCSIDriver) GetDynamicProvisionStorageClass(fsType string) *storagev1.StorageClass { - ns := g.driverInfo.Framework.Namespace.Name + ns := g.driverInfo.Config.Framework.Namespace.Name provisioner := g.driverInfo.Name suffix := fmt.Sprintf("%s-sc", g.driverInfo.Name) parameters := map[string]string{"type": "pd-standard"} - return getStorageClass(provisioner, parameters, nil, ns, suffix) + return testsuites.GetStorageClass(provisioner, parameters, nil, ns, suffix) +} + +func (g *gcePDCSIDriver) GetClaimSize() string { + return "5Gi" } func (g *gcePDCSIDriver) CreateDriver() { @@ -281,13 +227,13 @@ func (g *gcePDCSIDriver) CreateDriver() { // These are the options which would have to be used: // o := utils.PatchCSIOptions{ // OldDriverName: g.driverInfo.Name, - // NewDriverName: GetUniqueDriverName(g), + // NewDriverName: testsuites.GetUniqueDriverName(g), // DriverContainerName: "gce-driver", // ProvisionerContainerName: "csi-external-provisioner", // } - createGCESecrets(g.driverInfo.Framework.ClientSet, g.driverInfo.Config) + createGCESecrets(g.driverInfo.Config.Framework.ClientSet, g.driverInfo.Config.Framework.Namespace.Name) - cleanup, err := g.driverInfo.Framework.CreateFromManifests(nil, + cleanup, err := g.driverInfo.Config.Framework.CreateFromManifests(nil, "test/e2e/testing-manifests/storage-csi/driver-registrar/rbac.yaml", "test/e2e/testing-manifests/storage-csi/external-attacher/rbac.yaml", "test/e2e/testing-manifests/storage-csi/external-provisioner/rbac.yaml", @@ -310,17 +256,18 @@ func (g *gcePDCSIDriver) CleanupDriver() { // gcePd-external type gcePDExternalCSIDriver struct { - driverInfo DriverInfo + driverInfo testsuites.DriverInfo } -var _ TestDriver = &gcePDExternalCSIDriver{} -var _ DynamicPVTestDriver = &gcePDExternalCSIDriver{} +var _ testsuites.TestDriver = &gcePDExternalCSIDriver{} +var _ testsuites.DynamicPVTestDriver = &gcePDExternalCSIDriver{} // InitGcePDExternalCSIDriver returns gcePDExternalCSIDriver that implements TestDriver interface -func InitGcePDExternalCSIDriver() TestDriver { +func InitGcePDExternalCSIDriver(config testsuites.TestConfig) testsuites.TestDriver { return &gcePDExternalCSIDriver{ - driverInfo: DriverInfo{ + driverInfo: testsuites.DriverInfo{ Name: "pd.csi.storage.gke.io", + // TODO(#70258): this is temporary until we can figure out how to make e2e tests a library FeatureTag: "[Feature: gcePD-external]", MaxFileSize: testpatterns.FileSizeMedium, @@ -331,32 +278,38 @@ func InitGcePDExternalCSIDriver() TestDriver { "ext4", "xfs", ), - Capabilities: map[Capability]bool{ - CapPersistence: true, - CapFsGroup: true, - CapExec: true, + Capabilities: map[testsuites.Capability]bool{ + testsuites.CapPersistence: true, + testsuites.CapFsGroup: true, + testsuites.CapExec: true, }, + + Config: config, }, } } -func (g *gcePDExternalCSIDriver) GetDriverInfo() *DriverInfo { +func (g *gcePDExternalCSIDriver) GetDriverInfo() *testsuites.DriverInfo { return &g.driverInfo } func (g *gcePDExternalCSIDriver) SkipUnsupportedTest(pattern testpatterns.TestPattern) { framework.SkipUnlessProviderIs("gce", "gke") - framework.SkipIfMultizone(g.driverInfo.Framework.ClientSet) + framework.SkipIfMultizone(g.driverInfo.Config.Framework.ClientSet) } func (g *gcePDExternalCSIDriver) GetDynamicProvisionStorageClass(fsType string) *storagev1.StorageClass { - ns := g.driverInfo.Framework.Namespace.Name + ns := g.driverInfo.Config.Framework.Namespace.Name provisioner := g.driverInfo.Name suffix := fmt.Sprintf("%s-sc", g.driverInfo.Name) parameters := map[string]string{"type": "pd-standard"} - return getStorageClass(provisioner, parameters, nil, ns, suffix) + return testsuites.GetStorageClass(provisioner, parameters, nil, ns, suffix) +} + +func (g *gcePDExternalCSIDriver) GetClaimSize() string { + return "5Gi" } func (g *gcePDExternalCSIDriver) CreateDriver() { diff --git a/test/e2e/storage/drivers/csi_objects.go b/test/e2e/storage/drivers/csi_objects.go index 1a4c2af592f..9960da8add4 100644 --- a/test/e2e/storage/drivers/csi_objects.go +++ b/test/e2e/storage/drivers/csi_objects.go @@ -80,7 +80,7 @@ func shredFile(filePath string) { // createGCESecrets downloads the GCP IAM Key for the default compute service account // and puts it in a secret for the GCE PD CSI Driver to consume -func createGCESecrets(client clientset.Interface, config framework.VolumeTestConfig) { +func createGCESecrets(client clientset.Interface, ns string) { saEnv := "E2E_GOOGLE_APPLICATION_CREDENTIALS" saFile := fmt.Sprintf("/tmp/%s/cloud-sa.json", string(uuid.NewUUID())) @@ -107,7 +107,7 @@ func createGCESecrets(client clientset.Interface, config framework.VolumeTestCon s := &v1.Secret{ ObjectMeta: metav1.ObjectMeta{ Name: "cloud-sa", - Namespace: config.Namespace, + Namespace: ns, }, Type: v1.SecretTypeOpaque, Data: map[string][]byte{ @@ -115,7 +115,7 @@ func createGCESecrets(client clientset.Interface, config framework.VolumeTestCon }, } - _, err = client.CoreV1().Secrets(config.Namespace).Create(s) + _, err = client.CoreV1().Secrets(ns).Create(s) if !apierrors.IsAlreadyExists(err) { framework.ExpectNoError(err, "Failed to create Secret %v", s.GetName()) } diff --git a/test/e2e/storage/drivers/in_tree.go b/test/e2e/storage/drivers/in_tree.go index cc73bd81a4c..728ab69794f 100644 --- a/test/e2e/storage/drivers/in_tree.go +++ b/test/e2e/storage/drivers/in_tree.go @@ -55,6 +55,7 @@ import ( kubeletapis "k8s.io/kubernetes/pkg/kubelet/apis" "k8s.io/kubernetes/test/e2e/framework" "k8s.io/kubernetes/test/e2e/storage/testpatterns" + "k8s.io/kubernetes/test/e2e/storage/testsuites" "k8s.io/kubernetes/test/e2e/storage/utils" vspheretest "k8s.io/kubernetes/test/e2e/storage/vsphere" imageutils "k8s.io/kubernetes/test/utils/image" @@ -65,7 +66,7 @@ type nfsDriver struct { externalProvisionerPod *v1.Pod externalPluginName string - driverInfo DriverInfo + driverInfo testsuites.DriverInfo } type nfsTestResource struct { @@ -73,16 +74,16 @@ type nfsTestResource struct { serverPod *v1.Pod } -var _ TestDriver = &nfsDriver{} -var _ PreprovisionedVolumeTestDriver = &nfsDriver{} -var _ InlineVolumeTestDriver = &nfsDriver{} -var _ PreprovisionedPVTestDriver = &nfsDriver{} -var _ DynamicPVTestDriver = &nfsDriver{} +var _ testsuites.TestDriver = &nfsDriver{} +var _ testsuites.PreprovisionedVolumeTestDriver = &nfsDriver{} +var _ testsuites.InlineVolumeTestDriver = &nfsDriver{} +var _ testsuites.PreprovisionedPVTestDriver = &nfsDriver{} +var _ testsuites.DynamicPVTestDriver = &nfsDriver{} // InitNFSDriver returns nfsDriver that implements TestDriver interface -func InitNFSDriver() TestDriver { +func InitNFSDriver(config testsuites.TestConfig) testsuites.TestDriver { return &nfsDriver{ - driverInfo: DriverInfo{ + driverInfo: testsuites.DriverInfo{ Name: "nfs", MaxFileSize: testpatterns.FileSizeLarge, SupportedFsType: sets.NewString( @@ -90,15 +91,17 @@ func InitNFSDriver() TestDriver { ), SupportedMountOption: sets.NewString("proto=tcp", "relatime"), RequiredMountOption: sets.NewString("vers=4.1"), - Capabilities: map[Capability]bool{ - CapPersistence: true, - CapExec: true, + Capabilities: map[testsuites.Capability]bool{ + testsuites.CapPersistence: true, + testsuites.CapExec: true, }, + + Config: config, }, } } -func (n *nfsDriver) GetDriverInfo() *DriverInfo { +func (n *nfsDriver) GetDriverInfo() *testsuites.DriverInfo { return &n.driverInfo } @@ -132,14 +135,18 @@ func (n *nfsDriver) GetPersistentVolumeSource(readOnly bool, fsType string, test func (n *nfsDriver) GetDynamicProvisionStorageClass(fsType string) *storagev1.StorageClass { provisioner := n.externalPluginName parameters := map[string]string{"mountOptions": "vers=4.1"} - ns := n.driverInfo.Framework.Namespace.Name + ns := n.driverInfo.Config.Framework.Namespace.Name suffix := fmt.Sprintf("%s-sc", n.driverInfo.Name) - return getStorageClass(provisioner, parameters, nil, ns, suffix) + return testsuites.GetStorageClass(provisioner, parameters, nil, ns, suffix) +} + +func (n *nfsDriver) GetClaimSize() string { + return "5Gi" } func (n *nfsDriver) CreateDriver() { - f := n.driverInfo.Framework + f := n.driverInfo.Config.Framework cs := f.ClientSet ns := f.Namespace n.externalPluginName = fmt.Sprintf("example.com/nfs-%s", ns.Name) @@ -159,7 +166,7 @@ func (n *nfsDriver) CreateDriver() { } func (n *nfsDriver) CleanupDriver() { - f := n.driverInfo.Framework + f := n.driverInfo.Config.Framework cs := f.ClientSet ns := f.Namespace @@ -169,7 +176,7 @@ func (n *nfsDriver) CleanupDriver() { } func (n *nfsDriver) CreateVolume(volType testpatterns.TestVolType) interface{} { - f := n.driverInfo.Framework + f := n.driverInfo.Config.Framework cs := f.ClientSet ns := f.Namespace @@ -181,7 +188,7 @@ func (n *nfsDriver) CreateVolume(volType testpatterns.TestVolType) interface{} { fallthrough case testpatterns.PreprovisionedPV: config, serverPod, serverIP := framework.NewNFSServer(cs, ns.Name, []string{}) - n.driverInfo.Config = config + n.driverInfo.Config.ServerConfig = &config return &nfsTestResource{ serverIP: serverIP, serverPod: serverPod, @@ -195,7 +202,7 @@ func (n *nfsDriver) CreateVolume(volType testpatterns.TestVolType) interface{} { } func (n *nfsDriver) DeleteVolume(volType testpatterns.TestVolType, testResource interface{}) { - f := n.driverInfo.Framework + f := n.driverInfo.Config.Framework ntr, ok := testResource.(*nfsTestResource) Expect(ok).To(BeTrue(), "Failed to cast test resource to NFS Test Resource") @@ -214,7 +221,7 @@ func (n *nfsDriver) DeleteVolume(volType testpatterns.TestVolType, testResource // Gluster type glusterFSDriver struct { - driverInfo DriverInfo + driverInfo testsuites.DriverInfo } type glusterTestResource struct { @@ -222,29 +229,31 @@ type glusterTestResource struct { serverPod *v1.Pod } -var _ TestDriver = &glusterFSDriver{} -var _ PreprovisionedVolumeTestDriver = &glusterFSDriver{} -var _ InlineVolumeTestDriver = &glusterFSDriver{} -var _ PreprovisionedPVTestDriver = &glusterFSDriver{} +var _ testsuites.TestDriver = &glusterFSDriver{} +var _ testsuites.PreprovisionedVolumeTestDriver = &glusterFSDriver{} +var _ testsuites.InlineVolumeTestDriver = &glusterFSDriver{} +var _ testsuites.PreprovisionedPVTestDriver = &glusterFSDriver{} // InitGlusterFSDriver returns glusterFSDriver that implements TestDriver interface -func InitGlusterFSDriver() TestDriver { +func InitGlusterFSDriver(config testsuites.TestConfig) testsuites.TestDriver { return &glusterFSDriver{ - driverInfo: DriverInfo{ + driverInfo: testsuites.DriverInfo{ Name: "gluster", MaxFileSize: testpatterns.FileSizeMedium, SupportedFsType: sets.NewString( "", // Default fsType ), - Capabilities: map[Capability]bool{ - CapPersistence: true, - CapExec: true, + Capabilities: map[testsuites.Capability]bool{ + testsuites.CapPersistence: true, + testsuites.CapExec: true, }, + + Config: config, }, } } -func (g *glusterFSDriver) GetDriverInfo() *DriverInfo { +func (g *glusterFSDriver) GetDriverInfo() *testsuites.DriverInfo { return &g.driverInfo } @@ -292,12 +301,12 @@ func (g *glusterFSDriver) CleanupDriver() { } func (g *glusterFSDriver) CreateVolume(volType testpatterns.TestVolType) interface{} { - f := g.driverInfo.Framework + f := g.driverInfo.Config.Framework cs := f.ClientSet ns := f.Namespace config, serverPod, _ := framework.NewGlusterfsServer(cs, ns.Name) - g.driverInfo.Config = config + g.driverInfo.Config.ServerConfig = &config return &glusterTestResource{ prefix: config.Prefix, serverPod: serverPod, @@ -305,7 +314,7 @@ func (g *glusterFSDriver) CreateVolume(volType testpatterns.TestVolType) interfa } func (g *glusterFSDriver) DeleteVolume(volType testpatterns.TestVolType, testResource interface{}) { - f := g.driverInfo.Framework + f := g.driverInfo.Config.Framework cs := f.ClientSet ns := f.Namespace @@ -332,22 +341,22 @@ func (g *glusterFSDriver) DeleteVolume(volType testpatterns.TestVolType, testRes // iSCSI // The iscsiadm utility and iscsi target kernel modules must be installed on all nodes. type iSCSIDriver struct { - driverInfo DriverInfo + driverInfo testsuites.DriverInfo } type iSCSITestResource struct { serverPod *v1.Pod serverIP string } -var _ TestDriver = &iSCSIDriver{} -var _ PreprovisionedVolumeTestDriver = &iSCSIDriver{} -var _ InlineVolumeTestDriver = &iSCSIDriver{} -var _ PreprovisionedPVTestDriver = &iSCSIDriver{} +var _ testsuites.TestDriver = &iSCSIDriver{} +var _ testsuites.PreprovisionedVolumeTestDriver = &iSCSIDriver{} +var _ testsuites.InlineVolumeTestDriver = &iSCSIDriver{} +var _ testsuites.PreprovisionedPVTestDriver = &iSCSIDriver{} // InitISCSIDriver returns iSCSIDriver that implements TestDriver interface -func InitISCSIDriver() TestDriver { +func InitISCSIDriver(config testsuites.TestConfig) testsuites.TestDriver { return &iSCSIDriver{ - driverInfo: DriverInfo{ + driverInfo: testsuites.DriverInfo{ Name: "iscsi", FeatureTag: "[Feature:Volumes]", MaxFileSize: testpatterns.FileSizeMedium, @@ -358,17 +367,19 @@ func InitISCSIDriver() TestDriver { //"ext3", "ext4", ), - Capabilities: map[Capability]bool{ - CapPersistence: true, - CapFsGroup: true, - CapBlock: true, - CapExec: true, + Capabilities: map[testsuites.Capability]bool{ + testsuites.CapPersistence: true, + testsuites.CapFsGroup: true, + testsuites.CapBlock: true, + testsuites.CapExec: true, }, + + Config: config, }, } } -func (i *iSCSIDriver) GetDriverInfo() *DriverInfo { +func (i *iSCSIDriver) GetDriverInfo() *testsuites.DriverInfo { return &i.driverInfo } @@ -419,12 +430,12 @@ func (i *iSCSIDriver) CleanupDriver() { } func (i *iSCSIDriver) CreateVolume(volType testpatterns.TestVolType) interface{} { - f := i.driverInfo.Framework + f := i.driverInfo.Config.Framework cs := f.ClientSet ns := f.Namespace config, serverPod, serverIP := framework.NewISCSIServer(cs, ns.Name) - i.driverInfo.Config = config + i.driverInfo.Config.ServerConfig = &config return &iSCSITestResource{ serverPod: serverPod, serverIP: serverIP, @@ -432,7 +443,7 @@ func (i *iSCSIDriver) CreateVolume(volType testpatterns.TestVolType) interface{} } func (i *iSCSIDriver) DeleteVolume(volType testpatterns.TestVolType, testResource interface{}) { - f := i.driverInfo.Framework + f := i.driverInfo.Config.Framework itr, ok := testResource.(*iSCSITestResource) Expect(ok).To(BeTrue(), "Failed to cast test resource to iSCSI Test Resource") @@ -442,7 +453,7 @@ func (i *iSCSIDriver) DeleteVolume(volType testpatterns.TestVolType, testResourc // Ceph RBD type rbdDriver struct { - driverInfo DriverInfo + driverInfo testsuites.DriverInfo } type rbdTestResource struct { @@ -451,15 +462,15 @@ type rbdTestResource struct { secret *v1.Secret } -var _ TestDriver = &rbdDriver{} -var _ PreprovisionedVolumeTestDriver = &rbdDriver{} -var _ InlineVolumeTestDriver = &rbdDriver{} -var _ PreprovisionedPVTestDriver = &rbdDriver{} +var _ testsuites.TestDriver = &rbdDriver{} +var _ testsuites.PreprovisionedVolumeTestDriver = &rbdDriver{} +var _ testsuites.InlineVolumeTestDriver = &rbdDriver{} +var _ testsuites.PreprovisionedPVTestDriver = &rbdDriver{} // InitRbdDriver returns rbdDriver that implements TestDriver interface -func InitRbdDriver() TestDriver { +func InitRbdDriver(config testsuites.TestConfig) testsuites.TestDriver { return &rbdDriver{ - driverInfo: DriverInfo{ + driverInfo: testsuites.DriverInfo{ Name: "rbd", FeatureTag: "[Feature:Volumes]", MaxFileSize: testpatterns.FileSizeMedium, @@ -470,17 +481,19 @@ func InitRbdDriver() TestDriver { //"ext3", "ext4", ), - Capabilities: map[Capability]bool{ - CapPersistence: true, - CapFsGroup: true, - CapBlock: true, - CapExec: true, + Capabilities: map[testsuites.Capability]bool{ + testsuites.CapPersistence: true, + testsuites.CapFsGroup: true, + testsuites.CapBlock: true, + testsuites.CapExec: true, }, + + Config: config, }, } } -func (r *rbdDriver) GetDriverInfo() *DriverInfo { +func (r *rbdDriver) GetDriverInfo() *testsuites.DriverInfo { return &r.driverInfo } @@ -510,7 +523,7 @@ func (r *rbdDriver) GetVolumeSource(readOnly bool, fsType string, testResource i } func (r *rbdDriver) GetPersistentVolumeSource(readOnly bool, fsType string, testResource interface{}) *v1.PersistentVolumeSource { - f := r.driverInfo.Framework + f := r.driverInfo.Config.Framework ns := f.Namespace rtr, ok := testResource.(*rbdTestResource) @@ -542,12 +555,12 @@ func (r *rbdDriver) CleanupDriver() { } func (r *rbdDriver) CreateVolume(volType testpatterns.TestVolType) interface{} { - f := r.driverInfo.Framework + f := r.driverInfo.Config.Framework cs := f.ClientSet ns := f.Namespace config, serverPod, secret, serverIP := framework.NewRBDServer(cs, ns.Name) - r.driverInfo.Config = config + r.driverInfo.Config.ServerConfig = &config return &rbdTestResource{ serverPod: serverPod, serverIP: serverIP, @@ -556,7 +569,7 @@ func (r *rbdDriver) CreateVolume(volType testpatterns.TestVolType) interface{} { } func (r *rbdDriver) DeleteVolume(volType testpatterns.TestVolType, testResource interface{}) { - f := r.driverInfo.Framework + f := r.driverInfo.Config.Framework rtr, ok := testResource.(*rbdTestResource) Expect(ok).To(BeTrue(), "Failed to cast test resource to RBD Test Resource") @@ -570,7 +583,7 @@ type cephFSDriver struct { serverPod *v1.Pod secret *v1.Secret - driverInfo DriverInfo + driverInfo testsuites.DriverInfo } type cephTestResource struct { @@ -579,30 +592,32 @@ type cephTestResource struct { secret *v1.Secret } -var _ TestDriver = &cephFSDriver{} -var _ PreprovisionedVolumeTestDriver = &cephFSDriver{} -var _ InlineVolumeTestDriver = &cephFSDriver{} -var _ PreprovisionedPVTestDriver = &cephFSDriver{} +var _ testsuites.TestDriver = &cephFSDriver{} +var _ testsuites.PreprovisionedVolumeTestDriver = &cephFSDriver{} +var _ testsuites.InlineVolumeTestDriver = &cephFSDriver{} +var _ testsuites.PreprovisionedPVTestDriver = &cephFSDriver{} // InitCephFSDriver returns cephFSDriver that implements TestDriver interface -func InitCephFSDriver() TestDriver { +func InitCephFSDriver(config testsuites.TestConfig) testsuites.TestDriver { return &cephFSDriver{ - driverInfo: DriverInfo{ + driverInfo: testsuites.DriverInfo{ Name: "ceph", FeatureTag: "[Feature:Volumes]", MaxFileSize: testpatterns.FileSizeMedium, SupportedFsType: sets.NewString( "", // Default fsType ), - Capabilities: map[Capability]bool{ - CapPersistence: true, - CapExec: true, + Capabilities: map[testsuites.Capability]bool{ + testsuites.CapPersistence: true, + testsuites.CapExec: true, }, + + Config: config, }, } } -func (c *cephFSDriver) GetDriverInfo() *DriverInfo { +func (c *cephFSDriver) GetDriverInfo() *testsuites.DriverInfo { return &c.driverInfo } @@ -626,7 +641,7 @@ func (c *cephFSDriver) GetVolumeSource(readOnly bool, fsType string, testResourc } func (c *cephFSDriver) GetPersistentVolumeSource(readOnly bool, fsType string, testResource interface{}) *v1.PersistentVolumeSource { - f := c.driverInfo.Framework + f := c.driverInfo.Config.Framework ns := f.Namespace ctr, ok := testResource.(*cephTestResource) @@ -652,12 +667,12 @@ func (c *cephFSDriver) CleanupDriver() { } func (c *cephFSDriver) CreateVolume(volType testpatterns.TestVolType) interface{} { - f := c.driverInfo.Framework + f := c.driverInfo.Config.Framework cs := f.ClientSet ns := f.Namespace config, serverPod, secret, serverIP := framework.NewRBDServer(cs, ns.Name) - c.driverInfo.Config = config + c.driverInfo.Config.ServerConfig = &config return &cephTestResource{ serverPod: serverPod, serverIP: serverIP, @@ -666,7 +681,7 @@ func (c *cephFSDriver) CreateVolume(volType testpatterns.TestVolType) interface{ } func (c *cephFSDriver) DeleteVolume(volType testpatterns.TestVolType, testResource interface{}) { - f := c.driverInfo.Framework + f := c.driverInfo.Config.Framework ctr, ok := testResource.(*cephTestResource) Expect(ok).To(BeTrue(), "Failed to cast test resource to Ceph Test Resource") @@ -678,30 +693,32 @@ func (c *cephFSDriver) DeleteVolume(volType testpatterns.TestVolType, testResour type hostPathDriver struct { node v1.Node - driverInfo DriverInfo + driverInfo testsuites.DriverInfo } -var _ TestDriver = &hostPathDriver{} -var _ PreprovisionedVolumeTestDriver = &hostPathDriver{} -var _ InlineVolumeTestDriver = &hostPathDriver{} +var _ testsuites.TestDriver = &hostPathDriver{} +var _ testsuites.PreprovisionedVolumeTestDriver = &hostPathDriver{} +var _ testsuites.InlineVolumeTestDriver = &hostPathDriver{} // InitHostPathDriver returns hostPathDriver that implements TestDriver interface -func InitHostPathDriver() TestDriver { +func InitHostPathDriver(config testsuites.TestConfig) testsuites.TestDriver { return &hostPathDriver{ - driverInfo: DriverInfo{ + driverInfo: testsuites.DriverInfo{ Name: "hostPath", MaxFileSize: testpatterns.FileSizeMedium, SupportedFsType: sets.NewString( "", // Default fsType ), - Capabilities: map[Capability]bool{ - CapPersistence: true, + Capabilities: map[testsuites.Capability]bool{ + testsuites.CapPersistence: true, }, + + Config: config, }, } } -func (h *hostPathDriver) GetDriverInfo() *DriverInfo { +func (h *hostPathDriver) GetDriverInfo() *testsuites.DriverInfo { return &h.driverInfo } @@ -727,7 +744,7 @@ func (h *hostPathDriver) CleanupDriver() { } func (h *hostPathDriver) CreateVolume(volType testpatterns.TestVolType) interface{} { - f := h.driverInfo.Framework + f := h.driverInfo.Config.Framework cs := f.ClientSet // pods should be scheduled on the node @@ -744,7 +761,7 @@ func (h *hostPathDriver) DeleteVolume(volType testpatterns.TestVolType, testReso type hostPathSymlinkDriver struct { node v1.Node - driverInfo DriverInfo + driverInfo testsuites.DriverInfo } type hostPathSymlinkTestResource struct { @@ -753,27 +770,29 @@ type hostPathSymlinkTestResource struct { prepPod *v1.Pod } -var _ TestDriver = &hostPathSymlinkDriver{} -var _ PreprovisionedVolumeTestDriver = &hostPathSymlinkDriver{} -var _ InlineVolumeTestDriver = &hostPathSymlinkDriver{} +var _ testsuites.TestDriver = &hostPathSymlinkDriver{} +var _ testsuites.PreprovisionedVolumeTestDriver = &hostPathSymlinkDriver{} +var _ testsuites.InlineVolumeTestDriver = &hostPathSymlinkDriver{} // InitHostPathSymlinkDriver returns hostPathSymlinkDriver that implements TestDriver interface -func InitHostPathSymlinkDriver() TestDriver { +func InitHostPathSymlinkDriver(config testsuites.TestConfig) testsuites.TestDriver { return &hostPathSymlinkDriver{ - driverInfo: DriverInfo{ + driverInfo: testsuites.DriverInfo{ Name: "hostPathSymlink", MaxFileSize: testpatterns.FileSizeMedium, SupportedFsType: sets.NewString( "", // Default fsType ), - Capabilities: map[Capability]bool{ - CapPersistence: true, + Capabilities: map[testsuites.Capability]bool{ + testsuites.CapPersistence: true, }, + + Config: config, }, } } -func (h *hostPathSymlinkDriver) GetDriverInfo() *DriverInfo { +func (h *hostPathSymlinkDriver) GetDriverInfo() *testsuites.DriverInfo { return &h.driverInfo } @@ -802,7 +821,7 @@ func (h *hostPathSymlinkDriver) CleanupDriver() { } func (h *hostPathSymlinkDriver) CreateVolume(volType testpatterns.TestVolType) interface{} { - f := h.driverInfo.Framework + f := h.driverInfo.Config.Framework cs := f.ClientSet sourcePath := fmt.Sprintf("/tmp/%v", f.Namespace.Name) @@ -870,7 +889,7 @@ func (h *hostPathSymlinkDriver) CreateVolume(volType testpatterns.TestVolType) i } func (h *hostPathSymlinkDriver) DeleteVolume(volType testpatterns.TestVolType, testResource interface{}) { - f := h.driverInfo.Framework + f := h.driverInfo.Config.Framework htr, ok := testResource.(*hostPathSymlinkTestResource) Expect(ok).To(BeTrue(), "Failed to cast test resource to Hostpath Symlink Test Resource") @@ -890,30 +909,32 @@ func (h *hostPathSymlinkDriver) DeleteVolume(volType testpatterns.TestVolType, t // emptydir type emptydirDriver struct { - driverInfo DriverInfo + driverInfo testsuites.DriverInfo } -var _ TestDriver = &emptydirDriver{} -var _ PreprovisionedVolumeTestDriver = &emptydirDriver{} -var _ InlineVolumeTestDriver = &emptydirDriver{} +var _ testsuites.TestDriver = &emptydirDriver{} +var _ testsuites.PreprovisionedVolumeTestDriver = &emptydirDriver{} +var _ testsuites.InlineVolumeTestDriver = &emptydirDriver{} // InitEmptydirDriver returns emptydirDriver that implements TestDriver interface -func InitEmptydirDriver() TestDriver { +func InitEmptydirDriver(config testsuites.TestConfig) testsuites.TestDriver { return &emptydirDriver{ - driverInfo: DriverInfo{ + driverInfo: testsuites.DriverInfo{ Name: "emptydir", MaxFileSize: testpatterns.FileSizeMedium, SupportedFsType: sets.NewString( "", // Default fsType ), - Capabilities: map[Capability]bool{ - CapExec: true, + Capabilities: map[testsuites.Capability]bool{ + testsuites.CapExec: true, }, + + Config: config, }, } } -func (e *emptydirDriver) GetDriverInfo() *DriverInfo { +func (e *emptydirDriver) GetDriverInfo() *testsuites.DriverInfo { return &e.driverInfo } @@ -949,7 +970,7 @@ func (e *emptydirDriver) CleanupDriver() { // and that the usual OpenStack authentication env. variables are set // (OS_USERNAME, OS_PASSWORD, OS_TENANT_NAME at least). type cinderDriver struct { - driverInfo DriverInfo + driverInfo testsuites.DriverInfo } type cinderTestResource struct { @@ -957,32 +978,34 @@ type cinderTestResource struct { volumeID string } -var _ TestDriver = &cinderDriver{} -var _ PreprovisionedVolumeTestDriver = &cinderDriver{} -var _ InlineVolumeTestDriver = &cinderDriver{} -var _ PreprovisionedPVTestDriver = &cinderDriver{} -var _ DynamicPVTestDriver = &cinderDriver{} +var _ testsuites.TestDriver = &cinderDriver{} +var _ testsuites.PreprovisionedVolumeTestDriver = &cinderDriver{} +var _ testsuites.InlineVolumeTestDriver = &cinderDriver{} +var _ testsuites.PreprovisionedPVTestDriver = &cinderDriver{} +var _ testsuites.DynamicPVTestDriver = &cinderDriver{} // InitCinderDriver returns cinderDriver that implements TestDriver interface -func InitCinderDriver() TestDriver { +func InitCinderDriver(config testsuites.TestConfig) testsuites.TestDriver { return &cinderDriver{ - driverInfo: DriverInfo{ + driverInfo: testsuites.DriverInfo{ Name: "cinder", MaxFileSize: testpatterns.FileSizeMedium, SupportedFsType: sets.NewString( "", // Default fsType "ext3", ), - Capabilities: map[Capability]bool{ - CapPersistence: true, - CapFsGroup: true, - CapExec: true, + Capabilities: map[testsuites.Capability]bool{ + testsuites.CapPersistence: true, + testsuites.CapFsGroup: true, + testsuites.CapExec: true, }, + + Config: config, }, } } -func (c *cinderDriver) GetDriverInfo() *DriverInfo { +func (c *cinderDriver) GetDriverInfo() *testsuites.DriverInfo { return &c.driverInfo } @@ -1028,10 +1051,14 @@ func (c *cinderDriver) GetDynamicProvisionStorageClass(fsType string) *storagev1 if fsType != "" { parameters["fsType"] = fsType } - ns := c.driverInfo.Framework.Namespace.Name + ns := c.driverInfo.Config.Framework.Namespace.Name suffix := fmt.Sprintf("%s-sc", c.driverInfo.Name) - return getStorageClass(provisioner, parameters, nil, ns, suffix) + return testsuites.GetStorageClass(provisioner, parameters, nil, ns, suffix) +} + +func (c *cinderDriver) GetClaimSize() string { + return "5Gi" } func (c *cinderDriver) CreateDriver() { @@ -1041,7 +1068,7 @@ func (c *cinderDriver) CleanupDriver() { } func (c *cinderDriver) CreateVolume(volType testpatterns.TestVolType) interface{} { - f := c.driverInfo.Framework + f := c.driverInfo.Config.Framework ns := f.Namespace // We assume that namespace.Name is a random string @@ -1106,23 +1133,23 @@ func deleteCinderVolume(name string) error { // GCE type gcePdDriver struct { - driverInfo DriverInfo + driverInfo testsuites.DriverInfo } type gcePdTestResource struct { volumeName string } -var _ TestDriver = &gcePdDriver{} -var _ PreprovisionedVolumeTestDriver = &gcePdDriver{} -var _ InlineVolumeTestDriver = &gcePdDriver{} -var _ PreprovisionedPVTestDriver = &gcePdDriver{} -var _ DynamicPVTestDriver = &gcePdDriver{} +var _ testsuites.TestDriver = &gcePdDriver{} +var _ testsuites.PreprovisionedVolumeTestDriver = &gcePdDriver{} +var _ testsuites.InlineVolumeTestDriver = &gcePdDriver{} +var _ testsuites.PreprovisionedPVTestDriver = &gcePdDriver{} +var _ testsuites.DynamicPVTestDriver = &gcePdDriver{} // InitGceDriver returns gcePdDriver that implements TestDriver interface -func InitGcePdDriver() TestDriver { +func InitGcePdDriver(config testsuites.TestConfig) testsuites.TestDriver { return &gcePdDriver{ - driverInfo: DriverInfo{ + driverInfo: testsuites.DriverInfo{ Name: "gcepd", MaxFileSize: testpatterns.FileSizeMedium, SupportedFsType: sets.NewString( @@ -1133,17 +1160,19 @@ func InitGcePdDriver() TestDriver { "xfs", ), SupportedMountOption: sets.NewString("debug", "nouid32"), - Capabilities: map[Capability]bool{ - CapPersistence: true, - CapFsGroup: true, - CapBlock: true, - CapExec: true, + Capabilities: map[testsuites.Capability]bool{ + testsuites.CapPersistence: true, + testsuites.CapFsGroup: true, + testsuites.CapBlock: true, + testsuites.CapExec: true, }, + + Config: config, }, } } -func (g *gcePdDriver) GetDriverInfo() *DriverInfo { +func (g *gcePdDriver) GetDriverInfo() *testsuites.DriverInfo { return &g.driverInfo } @@ -1190,10 +1219,14 @@ func (g *gcePdDriver) GetDynamicProvisionStorageClass(fsType string) *storagev1. if fsType != "" { parameters["fsType"] = fsType } - ns := g.driverInfo.Framework.Namespace.Name + ns := g.driverInfo.Config.Framework.Namespace.Name suffix := fmt.Sprintf("%s-sc", g.driverInfo.Name) - return getStorageClass(provisioner, parameters, nil, ns, suffix) + return testsuites.GetStorageClass(provisioner, parameters, nil, ns, suffix) +} + +func (h *gcePdDriver) GetClaimSize() string { + return "5Gi" } func (g *gcePdDriver) CreateDriver() { @@ -1206,7 +1239,7 @@ func (g *gcePdDriver) CreateVolume(volType testpatterns.TestVolType) interface{} if volType == testpatterns.InlineVolume { // PD will be created in framework.TestContext.CloudConfig.Zone zone, // so pods should be also scheduled there. - g.driverInfo.Config.NodeSelector = map[string]string{ + g.driverInfo.Config.ClientNodeSelector = map[string]string{ kubeletapis.LabelZoneFailureDomain: framework.TestContext.CloudConfig.Zone, } } @@ -1226,7 +1259,7 @@ func (g *gcePdDriver) DeleteVolume(volType testpatterns.TestVolType, testResourc // vSphere type vSphereDriver struct { - driverInfo DriverInfo + driverInfo testsuites.DriverInfo } type vSphereTestResource struct { @@ -1234,31 +1267,33 @@ type vSphereTestResource struct { nodeInfo *vspheretest.NodeInfo } -var _ TestDriver = &vSphereDriver{} -var _ PreprovisionedVolumeTestDriver = &vSphereDriver{} -var _ InlineVolumeTestDriver = &vSphereDriver{} -var _ PreprovisionedPVTestDriver = &vSphereDriver{} -var _ DynamicPVTestDriver = &vSphereDriver{} +var _ testsuites.TestDriver = &vSphereDriver{} +var _ testsuites.PreprovisionedVolumeTestDriver = &vSphereDriver{} +var _ testsuites.InlineVolumeTestDriver = &vSphereDriver{} +var _ testsuites.PreprovisionedPVTestDriver = &vSphereDriver{} +var _ testsuites.DynamicPVTestDriver = &vSphereDriver{} // InitVSphereDriver returns vSphereDriver that implements TestDriver interface -func InitVSphereDriver() TestDriver { +func InitVSphereDriver(config testsuites.TestConfig) testsuites.TestDriver { return &vSphereDriver{ - driverInfo: DriverInfo{ + driverInfo: testsuites.DriverInfo{ Name: "vSphere", MaxFileSize: testpatterns.FileSizeMedium, SupportedFsType: sets.NewString( "", // Default fsType "ext4", ), - Capabilities: map[Capability]bool{ - CapPersistence: true, - CapFsGroup: true, - CapExec: true, + Capabilities: map[testsuites.Capability]bool{ + testsuites.CapPersistence: true, + testsuites.CapFsGroup: true, + testsuites.CapExec: true, }, + + Config: config, }, } } -func (v *vSphereDriver) GetDriverInfo() *DriverInfo { +func (v *vSphereDriver) GetDriverInfo() *testsuites.DriverInfo { return &v.driverInfo } @@ -1312,10 +1347,14 @@ func (v *vSphereDriver) GetDynamicProvisionStorageClass(fsType string) *storagev if fsType != "" { parameters["fsType"] = fsType } - ns := v.driverInfo.Framework.Namespace.Name + ns := v.driverInfo.Config.Framework.Namespace.Name suffix := fmt.Sprintf("%s-sc", v.driverInfo.Name) - return getStorageClass(provisioner, parameters, nil, ns, suffix) + return testsuites.GetStorageClass(provisioner, parameters, nil, ns, suffix) +} + +func (v *vSphereDriver) GetClaimSize() string { + return "5Gi" } func (v *vSphereDriver) CreateDriver() { @@ -1325,7 +1364,7 @@ func (v *vSphereDriver) CleanupDriver() { } func (v *vSphereDriver) CreateVolume(volType testpatterns.TestVolType) interface{} { - f := v.driverInfo.Framework + f := v.driverInfo.Config.Framework vspheretest.Bootstrap(f) nodeInfo := vspheretest.GetReadySchedulableRandomNodeInfo() volumePath, err := nodeInfo.VSphere.CreateVolume(&vspheretest.VolumeOptions{}, nodeInfo.DataCenterRef) @@ -1345,40 +1384,42 @@ func (v *vSphereDriver) DeleteVolume(volType testpatterns.TestVolType, testResou // Azure type azureDriver struct { - driverInfo DriverInfo + driverInfo testsuites.DriverInfo } type azureTestResource struct { volumeName string } -var _ TestDriver = &azureDriver{} -var _ PreprovisionedVolumeTestDriver = &azureDriver{} -var _ InlineVolumeTestDriver = &azureDriver{} -var _ PreprovisionedPVTestDriver = &azureDriver{} -var _ DynamicPVTestDriver = &azureDriver{} +var _ testsuites.TestDriver = &azureDriver{} +var _ testsuites.PreprovisionedVolumeTestDriver = &azureDriver{} +var _ testsuites.InlineVolumeTestDriver = &azureDriver{} +var _ testsuites.PreprovisionedPVTestDriver = &azureDriver{} +var _ testsuites.DynamicPVTestDriver = &azureDriver{} // InitAzureDriver returns azureDriver that implements TestDriver interface -func InitAzureDriver() TestDriver { +func InitAzureDriver(config testsuites.TestConfig) testsuites.TestDriver { return &azureDriver{ - driverInfo: DriverInfo{ + driverInfo: testsuites.DriverInfo{ Name: "azure", MaxFileSize: testpatterns.FileSizeMedium, SupportedFsType: sets.NewString( "", // Default fsType "ext4", ), - Capabilities: map[Capability]bool{ - CapPersistence: true, - CapFsGroup: true, - CapBlock: true, - CapExec: true, + Capabilities: map[testsuites.Capability]bool{ + testsuites.CapPersistence: true, + testsuites.CapFsGroup: true, + testsuites.CapBlock: true, + testsuites.CapExec: true, }, + + Config: config, }, } } -func (a *azureDriver) GetDriverInfo() *DriverInfo { +func (a *azureDriver) GetDriverInfo() *testsuites.DriverInfo { return &a.driverInfo } @@ -1430,10 +1471,14 @@ func (a *azureDriver) GetDynamicProvisionStorageClass(fsType string) *storagev1. if fsType != "" { parameters["fsType"] = fsType } - ns := a.driverInfo.Framework.Namespace.Name + ns := a.driverInfo.Config.Framework.Namespace.Name suffix := fmt.Sprintf("%s-sc", a.driverInfo.Name) - return getStorageClass(provisioner, parameters, nil, ns, suffix) + return testsuites.GetStorageClass(provisioner, parameters, nil, ns, suffix) +} + +func (a *azureDriver) GetClaimSize() string { + return "5Gi" } func (a *azureDriver) CreateDriver() { @@ -1462,21 +1507,21 @@ func (a *azureDriver) DeleteVolume(volType testpatterns.TestVolType, testResourc type awsDriver struct { volumeName string - driverInfo DriverInfo + driverInfo testsuites.DriverInfo } -var _ TestDriver = &awsDriver{} +var _ testsuites.TestDriver = &awsDriver{} // TODO: Fix authorization error in attach operation and uncomment below -//var _ PreprovisionedVolumeTestDriver = &awsDriver{} -//var _ InlineVolumeTestDriver = &awsDriver{} -//var _ PreprovisionedPVTestDriver = &awsDriver{} -var _ DynamicPVTestDriver = &awsDriver{} +//var _ testsuites.PreprovisionedVolumeTestDriver = &awsDriver{} +//var _ testsuites.InlineVolumeTestDriver = &awsDriver{} +//var _ testsuites.PreprovisionedPVTestDriver = &awsDriver{} +var _ testsuites.DynamicPVTestDriver = &awsDriver{} // InitAwsDriver returns awsDriver that implements TestDriver interface -func InitAwsDriver() TestDriver { +func InitAwsDriver(config testsuites.TestConfig) testsuites.TestDriver { return &awsDriver{ - driverInfo: DriverInfo{ + driverInfo: testsuites.DriverInfo{ Name: "aws", MaxFileSize: testpatterns.FileSizeMedium, SupportedFsType: sets.NewString( @@ -1484,17 +1529,19 @@ func InitAwsDriver() TestDriver { "ext3", ), SupportedMountOption: sets.NewString("debug", "nouid32"), - Capabilities: map[Capability]bool{ - CapPersistence: true, - CapFsGroup: true, - CapBlock: true, - CapExec: true, + Capabilities: map[testsuites.Capability]bool{ + testsuites.CapPersistence: true, + testsuites.CapFsGroup: true, + testsuites.CapBlock: true, + testsuites.CapExec: true, }, + + Config: config, }, } } -func (a *awsDriver) GetDriverInfo() *DriverInfo { +func (a *awsDriver) GetDriverInfo() *testsuites.DriverInfo { return &a.driverInfo } @@ -1537,10 +1584,14 @@ func (a *awsDriver) GetDynamicProvisionStorageClass(fsType string) *storagev1.St if fsType != "" { parameters["fsType"] = fsType } - ns := a.driverInfo.Framework.Namespace.Name + ns := a.driverInfo.Config.Framework.Namespace.Name suffix := fmt.Sprintf("%s-sc", a.driverInfo.Name) - return getStorageClass(provisioner, parameters, nil, ns, suffix) + return testsuites.GetStorageClass(provisioner, parameters, nil, ns, suffix) +} + +func (a *awsDriver) GetClaimSize() string { + return "5Gi" } func (a *awsDriver) CreateDriver() { diff --git a/test/e2e/storage/empty_dir_wrapper.go b/test/e2e/storage/empty_dir_wrapper.go index 845ce1c7cde..87c3a4fc4c4 100644 --- a/test/e2e/storage/empty_dir_wrapper.go +++ b/test/e2e/storage/empty_dir_wrapper.go @@ -20,7 +20,7 @@ import ( "fmt" "strconv" - "k8s.io/api/core/v1" + v1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/intstr" @@ -179,10 +179,9 @@ var _ = utils.SIGDescribe("EmptyDir wrapper volumes", func() { /* Release : v1.13 Testname: EmptyDir Wrapper Volume, ConfigMap volumes, no race - Description: Slow by design [~180 Seconds]. - Create 50 ConfigMaps Volumes and 5 replicas of pod with these ConfigMapvolumes mounted. Pod MUST NOT fail waiting for Volumes. + Description: Create 50 ConfigMaps Volumes and 5 replicas of pod with these ConfigMapvolumes mounted. Pod MUST NOT fail waiting for Volumes. */ - framework.ConformanceIt("should not cause race condition when used for configmaps [Serial] [Slow]", func() { + framework.ConformanceIt("should not cause race condition when used for configmaps [Serial]", func() { configMapNames := createConfigmapsForRace(f) defer deleteConfigMaps(f, configMapNames) volumes, volumeMounts := makeConfigMapVolumes(configMapNames) diff --git a/test/e2e/storage/in_tree_volumes.go b/test/e2e/storage/in_tree_volumes.go index 603876150b5..7769a329fd7 100644 --- a/test/e2e/storage/in_tree_volumes.go +++ b/test/e2e/storage/in_tree_volumes.go @@ -18,7 +18,6 @@ package storage import ( . "github.com/onsi/ginkgo" - "k8s.io/api/core/v1" "k8s.io/kubernetes/test/e2e/framework" "k8s.io/kubernetes/test/e2e/storage/drivers" "k8s.io/kubernetes/test/e2e/storage/testpatterns" @@ -27,7 +26,7 @@ import ( ) // List of testDrivers to be executed in below loop -var testDrivers = []func() drivers.TestDriver{ +var testDrivers = []func(config testsuites.TestConfig) testsuites.TestDriver{ drivers.InitNFSDriver, drivers.InitGlusterFSDriver, drivers.InitISCSIDriver, @@ -61,35 +60,32 @@ var _ = utils.SIGDescribe("In-tree Volumes", func() { f := framework.NewDefaultFramework("volumes") var ( - ns *v1.Namespace - config framework.VolumeTestConfig + // Common configuration options for all drivers. + config = testsuites.TestConfig{ + Framework: f, + Prefix: "in-tree", + } ) - BeforeEach(func() { - ns = f.Namespace - config = framework.VolumeTestConfig{ - Namespace: ns.Name, - Prefix: "volume", - } - }) - for _, initDriver := range testDrivers { - curDriver := initDriver() - Context(drivers.GetDriverNameWithFeatureTags(curDriver), func() { - driver := curDriver - + curDriver := initDriver(config) + curConfig := curDriver.GetDriverInfo().Config + Context(testsuites.GetDriverNameWithFeatureTags(curDriver), func() { BeforeEach(func() { + // Reset config. The driver might have modified its copy + // in a previous test. + curDriver.GetDriverInfo().Config = curConfig + // setupDriver - drivers.SetCommonDriverParameters(driver, f, config) - driver.CreateDriver() + curDriver.CreateDriver() }) AfterEach(func() { // Cleanup driver - driver.CleanupDriver() + curDriver.CleanupDriver() }) - testsuites.RunTestSuite(f, config, driver, testSuites, intreeTunePattern) + testsuites.RunTestSuite(f, curDriver, testSuites, intreeTunePattern) }) } }) diff --git a/test/e2e/storage/persistent_volumes-local.go b/test/e2e/storage/persistent_volumes-local.go index aa55bf287d6..fadb462c3fe 100644 --- a/test/e2e/storage/persistent_volumes-local.go +++ b/test/e2e/storage/persistent_volumes-local.go @@ -31,7 +31,6 @@ import ( appsv1 "k8s.io/api/apps/v1" "k8s.io/api/core/v1" - extv1beta1 "k8s.io/api/extensions/v1beta1" rbacv1beta1 "k8s.io/api/rbac/v1beta1" storagev1 "k8s.io/api/storage/v1" "k8s.io/apimachinery/pkg/api/resource" @@ -1627,15 +1626,15 @@ func createProvisionerDaemonset(config *localTestConfig) { provisionerPrivileged := true mountProp := v1.MountPropagationHostToContainer - provisioner := &extv1beta1.DaemonSet{ + provisioner := &appsv1.DaemonSet{ TypeMeta: metav1.TypeMeta{ Kind: "DaemonSet", - APIVersion: "extensions/v1beta1", + APIVersion: "apps/v1", }, ObjectMeta: metav1.ObjectMeta{ Name: daemonSetName, }, - Spec: extv1beta1.DaemonSetSpec{ + Spec: appsv1.DaemonSetSpec{ Selector: &metav1.LabelSelector{ MatchLabels: map[string]string{"app": "local-volume-provisioner"}, }, @@ -1708,7 +1707,7 @@ func createProvisionerDaemonset(config *localTestConfig) { }, }, } - _, err := config.client.ExtensionsV1beta1().DaemonSets(config.ns).Create(provisioner) + _, err := config.client.AppsV1().DaemonSets(config.ns).Create(provisioner) Expect(err).NotTo(HaveOccurred()) kind := schema.GroupKind{Group: "extensions", Kind: "DaemonSet"} @@ -1732,12 +1731,12 @@ func findProvisionerDaemonsetPodName(config *localTestConfig) string { } func deleteProvisionerDaemonset(config *localTestConfig) { - ds, err := config.client.ExtensionsV1beta1().DaemonSets(config.ns).Get(daemonSetName, metav1.GetOptions{}) + ds, err := config.client.AppsV1().DaemonSets(config.ns).Get(daemonSetName, metav1.GetOptions{}) if ds == nil { return } - err = config.client.ExtensionsV1beta1().DaemonSets(config.ns).Delete(daemonSetName, nil) + err = config.client.AppsV1().DaemonSets(config.ns).Delete(daemonSetName, nil) Expect(err).NotTo(HaveOccurred()) err = wait.PollImmediate(time.Second, time.Minute, func() (bool, error) { diff --git a/test/e2e/storage/pv_protection.go b/test/e2e/storage/pv_protection.go index 44865d1d026..d94aa6effe3 100644 --- a/test/e2e/storage/pv_protection.go +++ b/test/e2e/storage/pv_protection.go @@ -85,7 +85,7 @@ var _ = utils.SIGDescribe("PV Protection", func() { By("Checking that PV Protection finalizer is set") pv, err = client.CoreV1().PersistentVolumes().Get(pv.Name, metav1.GetOptions{}) Expect(err).NotTo(HaveOccurred(), "While getting PV status") - Expect(slice.ContainsString(pv.ObjectMeta.Finalizers, volumeutil.PVProtectionFinalizer, nil)).To(BeTrue()) + Expect(slice.ContainsString(pv.ObjectMeta.Finalizers, volumeutil.PVProtectionFinalizer, nil)).To(BeTrue(), "PV Protection finalizer(%v) is not set in %v", volumeutil.PVProtectionFinalizer, pv.ObjectMeta.Finalizers) }) AfterEach(func() { diff --git a/test/e2e/storage/pvc_protection.go b/test/e2e/storage/pvc_protection.go index af6ed9c1281..5c2868dc088 100644 --- a/test/e2e/storage/pvc_protection.go +++ b/test/e2e/storage/pvc_protection.go @@ -64,7 +64,7 @@ var _ = utils.SIGDescribe("PVC Protection", func() { By("Checking that PVC Protection finalizer is set") pvc, err = client.CoreV1().PersistentVolumeClaims(pvc.Namespace).Get(pvc.Name, metav1.GetOptions{}) Expect(err).NotTo(HaveOccurred(), "While getting PVC status") - Expect(slice.ContainsString(pvc.ObjectMeta.Finalizers, volumeutil.PVCProtectionFinalizer, nil)).To(BeTrue()) + Expect(slice.ContainsString(pvc.ObjectMeta.Finalizers, volumeutil.PVCProtectionFinalizer, nil)).To(BeTrue(), "PVC Protection finalizer(%v) is not set in %v", volumeutil.PVCProtectionFinalizer, pvc.ObjectMeta.Finalizers) }) AfterEach(func() { diff --git a/test/e2e/storage/testsuites/BUILD b/test/e2e/storage/testsuites/BUILD index 800a19f6093..0ea47b1c697 100644 --- a/test/e2e/storage/testsuites/BUILD +++ b/test/e2e/storage/testsuites/BUILD @@ -4,8 +4,10 @@ go_library( name = "go_default_library", srcs = [ "base.go", + "driveroperations.go", "provisioning.go", "subpath.go", + "testdriver.go", "volume_io.go", "volumemode.go", "volumes.go", @@ -20,10 +22,10 @@ go_library( "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/errors:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/rand:go_default_library", + "//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library", "//staging/src/k8s.io/client-go/kubernetes:go_default_library", "//test/e2e/framework:go_default_library", - "//test/e2e/storage/drivers:go_default_library", "//test/e2e/storage/testpatterns:go_default_library", "//test/e2e/storage/utils:go_default_library", "//test/utils/image:go_default_library", diff --git a/test/e2e/storage/testsuites/base.go b/test/e2e/storage/testsuites/base.go index 8d4f084989f..8638a90cfe1 100644 --- a/test/e2e/storage/testsuites/base.go +++ b/test/e2e/storage/testsuites/base.go @@ -30,7 +30,6 @@ import ( utilerrors "k8s.io/apimachinery/pkg/util/errors" clientset "k8s.io/client-go/kubernetes" "k8s.io/kubernetes/test/e2e/framework" - "k8s.io/kubernetes/test/e2e/storage/drivers" "k8s.io/kubernetes/test/e2e/storage/testpatterns" ) @@ -39,9 +38,9 @@ type TestSuite interface { // getTestSuiteInfo returns the TestSuiteInfo for this TestSuite getTestSuiteInfo() TestSuiteInfo // skipUnsupportedTest skips the test if this TestSuite is not suitable to be tested with the combination of TestPattern and TestDriver - skipUnsupportedTest(testpatterns.TestPattern, drivers.TestDriver) + skipUnsupportedTest(testpatterns.TestPattern, TestDriver) // execTest executes test of the testpattern for the driver - execTest(drivers.TestDriver, testpatterns.TestPattern) + execTest(TestDriver, testpatterns.TestPattern) } // TestSuiteInfo represents a set of parameters for TestSuite @@ -55,9 +54,9 @@ type TestSuiteInfo struct { type TestResource interface { // setupResource sets up test resources to be used for the tests with the // combination of TestDriver and TestPattern - setupResource(drivers.TestDriver, testpatterns.TestPattern) + setupResource(TestDriver, testpatterns.TestPattern) // cleanupResource clean up the test resources created in SetupResource - cleanupResource(drivers.TestDriver, testpatterns.TestPattern) + cleanupResource(TestDriver, testpatterns.TestPattern) } func getTestNameStr(suite TestSuite, pattern testpatterns.TestPattern) string { @@ -66,7 +65,7 @@ func getTestNameStr(suite TestSuite, pattern testpatterns.TestPattern) string { } // RunTestSuite runs all testpatterns of all testSuites for a driver -func RunTestSuite(f *framework.Framework, config framework.VolumeTestConfig, driver drivers.TestDriver, tsInits []func() TestSuite, tunePatternFunc func([]testpatterns.TestPattern) []testpatterns.TestPattern) { +func RunTestSuite(f *framework.Framework, driver TestDriver, tsInits []func() TestSuite, tunePatternFunc func([]testpatterns.TestPattern) []testpatterns.TestPattern) { for _, testSuiteInit := range tsInits { suite := testSuiteInit() patterns := tunePatternFunc(suite.getTestSuiteInfo().testPatterns) @@ -84,18 +83,18 @@ func RunTestSuite(f *framework.Framework, config framework.VolumeTestConfig, dri // 2. Check if fsType is supported by driver // 3. Check with driver specific logic // 4. Check with testSuite specific logic -func skipUnsupportedTest(suite TestSuite, driver drivers.TestDriver, pattern testpatterns.TestPattern) { +func skipUnsupportedTest(suite TestSuite, driver TestDriver, pattern testpatterns.TestPattern) { dInfo := driver.GetDriverInfo() // 1. Check if Whether volType is supported by driver from its interface var isSupported bool switch pattern.VolType { case testpatterns.InlineVolume: - _, isSupported = driver.(drivers.InlineVolumeTestDriver) + _, isSupported = driver.(InlineVolumeTestDriver) case testpatterns.PreprovisionedPV: - _, isSupported = driver.(drivers.PreprovisionedPVTestDriver) + _, isSupported = driver.(PreprovisionedPVTestDriver) case testpatterns.DynamicPV: - _, isSupported = driver.(drivers.DynamicPVTestDriver) + _, isSupported = driver.(DynamicPVTestDriver) default: isSupported = false } @@ -121,7 +120,7 @@ func skipUnsupportedTest(suite TestSuite, driver drivers.TestDriver, pattern tes // See volume_io.go or volumes.go in test/e2e/storage/testsuites/ for how to use this resource. // Also, see subpath.go in the same directory for how to extend and use it. type genericVolumeTestResource struct { - driver drivers.TestDriver + driver TestDriver volType string volSource *v1.VolumeSource pvc *v1.PersistentVolumeClaim @@ -134,27 +133,27 @@ type genericVolumeTestResource struct { var _ TestResource = &genericVolumeTestResource{} // setupResource sets up genericVolumeTestResource -func (r *genericVolumeTestResource) setupResource(driver drivers.TestDriver, pattern testpatterns.TestPattern) { +func (r *genericVolumeTestResource) setupResource(driver TestDriver, pattern testpatterns.TestPattern) { r.driver = driver dInfo := driver.GetDriverInfo() - f := dInfo.Framework + f := dInfo.Config.Framework cs := f.ClientSet fsType := pattern.FsType volType := pattern.VolType // Create volume for pre-provisioned volume tests - r.driverTestResource = drivers.CreateVolume(driver, volType) + r.driverTestResource = CreateVolume(driver, volType) switch volType { case testpatterns.InlineVolume: framework.Logf("Creating resource for inline volume") - if iDriver, ok := driver.(drivers.InlineVolumeTestDriver); ok { + if iDriver, ok := driver.(InlineVolumeTestDriver); ok { r.volSource = iDriver.GetVolumeSource(false, fsType, r.driverTestResource) r.volType = dInfo.Name } case testpatterns.PreprovisionedPV: framework.Logf("Creating resource for pre-provisioned PV") - if pDriver, ok := driver.(drivers.PreprovisionedPVTestDriver); ok { + if pDriver, ok := driver.(PreprovisionedPVTestDriver); ok { pvSource := pDriver.GetPersistentVolumeSource(false, fsType, r.driverTestResource) if pvSource != nil { r.volSource, r.pv, r.pvc = createVolumeSourceWithPVCPV(f, dInfo.Name, pvSource, false) @@ -163,8 +162,8 @@ func (r *genericVolumeTestResource) setupResource(driver drivers.TestDriver, pat } case testpatterns.DynamicPV: framework.Logf("Creating resource for dynamic PV") - if dDriver, ok := driver.(drivers.DynamicPVTestDriver); ok { - claimSize := "5Gi" + if dDriver, ok := driver.(DynamicPVTestDriver); ok { + claimSize := dDriver.GetClaimSize() r.sc = dDriver.GetDynamicProvisionStorageClass(fsType) By("creating a StorageClass " + r.sc.Name) @@ -188,9 +187,9 @@ func (r *genericVolumeTestResource) setupResource(driver drivers.TestDriver, pat } // cleanupResource cleans up genericVolumeTestResource -func (r *genericVolumeTestResource) cleanupResource(driver drivers.TestDriver, pattern testpatterns.TestPattern) { +func (r *genericVolumeTestResource) cleanupResource(driver TestDriver, pattern testpatterns.TestPattern) { dInfo := driver.GetDriverInfo() - f := dInfo.Framework + f := dInfo.Config.Framework volType := pattern.VolType if r.pvc != nil || r.pv != nil { @@ -222,7 +221,7 @@ func (r *genericVolumeTestResource) cleanupResource(driver drivers.TestDriver, p } // Cleanup volume for pre-provisioned volume tests - drivers.DeleteVolume(driver, volType, r.driverTestResource) + DeleteVolume(driver, volType, r.driverTestResource) } func createVolumeSourceWithPVCPV( @@ -324,3 +323,24 @@ func deleteStorageClass(cs clientset.Interface, className string) { Expect(err).NotTo(HaveOccurred()) } } + +// convertTestConfig returns a framework test config with the +// parameters specified for the testsuite or (if available) the +// dynamically created config for the volume server. +// +// This is done because TestConfig is the public API for +// the testsuites package whereas framework.VolumeTestConfig is merely +// an implementation detail. It contains fields that have no effect, +// which makes it unsuitable for use in the testsuits public API. +func convertTestConfig(in *TestConfig) framework.VolumeTestConfig { + if in.ServerConfig != nil { + return *in.ServerConfig + } + + return framework.VolumeTestConfig{ + Namespace: in.Framework.Namespace.Name, + Prefix: in.Prefix, + ClientNodeName: in.ClientNodeName, + NodeSelector: in.ClientNodeSelector, + } +} diff --git a/test/e2e/storage/testsuites/driveroperations.go b/test/e2e/storage/testsuites/driveroperations.go new file mode 100644 index 00000000000..1e233b48387 --- /dev/null +++ b/test/e2e/storage/testsuites/driveroperations.go @@ -0,0 +1,101 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package testsuites + +import ( + "fmt" + + storagev1 "k8s.io/api/storage/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/kubernetes/test/e2e/framework" + "k8s.io/kubernetes/test/e2e/storage/testpatterns" +) + +// GetDriverNameWithFeatureTags returns driver name with feature tags +// For example) +// - [Driver: nfs] +// - [Driver: rbd][Feature:Volumes] +func GetDriverNameWithFeatureTags(driver TestDriver) string { + dInfo := driver.GetDriverInfo() + + return fmt.Sprintf("[Driver: %s]%s", dInfo.Name, dInfo.FeatureTag) +} + +// CreateVolume creates volume for test unless dynamicPV test +func CreateVolume(driver TestDriver, volType testpatterns.TestVolType) interface{} { + switch volType { + case testpatterns.InlineVolume: + fallthrough + case testpatterns.PreprovisionedPV: + if pDriver, ok := driver.(PreprovisionedVolumeTestDriver); ok { + return pDriver.CreateVolume(volType) + } + case testpatterns.DynamicPV: + // No need to create volume + default: + framework.Failf("Invalid volType specified: %v", volType) + } + return nil +} + +// DeleteVolume deletes volume for test unless dynamicPV test +func DeleteVolume(driver TestDriver, volType testpatterns.TestVolType, testResource interface{}) { + switch volType { + case testpatterns.InlineVolume: + fallthrough + case testpatterns.PreprovisionedPV: + if pDriver, ok := driver.(PreprovisionedVolumeTestDriver); ok { + pDriver.DeleteVolume(volType, testResource) + } + case testpatterns.DynamicPV: + // No need to delete volume + default: + framework.Failf("Invalid volType specified: %v", volType) + } +} + +// GetStorageClass constructs a new StorageClass instance +// with a unique name that is based on namespace + suffix. +func GetStorageClass( + provisioner string, + parameters map[string]string, + bindingMode *storagev1.VolumeBindingMode, + ns string, + suffix string, +) *storagev1.StorageClass { + if bindingMode == nil { + defaultBindingMode := storagev1.VolumeBindingImmediate + bindingMode = &defaultBindingMode + } + return &storagev1.StorageClass{ + TypeMeta: metav1.TypeMeta{ + Kind: "StorageClass", + }, + ObjectMeta: metav1.ObjectMeta{ + // Name must be unique, so let's base it on namespace name + Name: ns + "-" + suffix, + }, + Provisioner: provisioner, + Parameters: parameters, + VolumeBindingMode: bindingMode, + } +} + +// GetUniqueDriverName returns unique driver name that can be used parallelly in tests +func GetUniqueDriverName(driver TestDriver) string { + return fmt.Sprintf("%s-%s", driver.GetDriverInfo().Name, driver.GetDriverInfo().Config.Framework.UniqueName) +} diff --git a/test/e2e/storage/testsuites/provisioning.go b/test/e2e/storage/testsuites/provisioning.go index ba9f8d025b3..527218d23ca 100644 --- a/test/e2e/storage/testsuites/provisioning.go +++ b/test/e2e/storage/testsuites/provisioning.go @@ -31,7 +31,6 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" clientset "k8s.io/client-go/kubernetes" "k8s.io/kubernetes/test/e2e/framework" - "k8s.io/kubernetes/test/e2e/storage/drivers" "k8s.io/kubernetes/test/e2e/storage/testpatterns" imageutils "k8s.io/kubernetes/test/utils/image" ) @@ -74,10 +73,10 @@ func (p *provisioningTestSuite) getTestSuiteInfo() TestSuiteInfo { return p.tsInfo } -func (p *provisioningTestSuite) skipUnsupportedTest(pattern testpatterns.TestPattern, driver drivers.TestDriver) { +func (p *provisioningTestSuite) skipUnsupportedTest(pattern testpatterns.TestPattern, driver TestDriver) { } -func createProvisioningTestInput(driver drivers.TestDriver, pattern testpatterns.TestPattern) (provisioningTestResource, provisioningTestInput) { +func createProvisioningTestInput(driver TestDriver, pattern testpatterns.TestPattern) (provisioningTestResource, provisioningTestInput) { // Setup test resource for driver and testpattern resource := provisioningTestResource{} resource.setupResource(driver, pattern) @@ -87,7 +86,7 @@ func createProvisioningTestInput(driver drivers.TestDriver, pattern testpatterns ClaimSize: resource.claimSize, ExpectedSize: resource.claimSize, }, - cs: driver.GetDriverInfo().Framework.ClientSet, + cs: driver.GetDriverInfo().Config.Framework.ClientSet, pvc: resource.pvc, sc: resource.sc, dInfo: driver.GetDriverInfo(), @@ -100,7 +99,7 @@ func createProvisioningTestInput(driver drivers.TestDriver, pattern testpatterns return resource, input } -func (p *provisioningTestSuite) execTest(driver drivers.TestDriver, pattern testpatterns.TestPattern) { +func (p *provisioningTestSuite) execTest(driver TestDriver, pattern testpatterns.TestPattern) { Context(getTestNameStr(p, pattern), func() { var ( resource provisioningTestResource @@ -132,7 +131,7 @@ func (p *provisioningTestSuite) execTest(driver drivers.TestDriver, pattern test } type provisioningTestResource struct { - driver drivers.TestDriver + driver TestDriver claimSize string sc *storage.StorageClass @@ -141,18 +140,18 @@ type provisioningTestResource struct { var _ TestResource = &provisioningTestResource{} -func (p *provisioningTestResource) setupResource(driver drivers.TestDriver, pattern testpatterns.TestPattern) { +func (p *provisioningTestResource) setupResource(driver TestDriver, pattern testpatterns.TestPattern) { // Setup provisioningTest resource switch pattern.VolType { case testpatterns.DynamicPV: - if dDriver, ok := driver.(drivers.DynamicPVTestDriver); ok { + if dDriver, ok := driver.(DynamicPVTestDriver); ok { p.sc = dDriver.GetDynamicProvisionStorageClass("") if p.sc == nil { framework.Skipf("Driver %q does not define Dynamic Provision StorageClass - skipping", driver.GetDriverInfo().Name) } p.driver = driver - p.claimSize = "5Gi" - p.pvc = getClaim(p.claimSize, driver.GetDriverInfo().Framework.Namespace.Name) + p.claimSize = dDriver.GetClaimSize() + p.pvc = getClaim(p.claimSize, driver.GetDriverInfo().Config.Framework.Namespace.Name) p.pvc.Spec.StorageClassName = &p.sc.Name framework.Logf("In creating storage class object and pvc object for driver - sc: %v, pvc: %v", p.sc, p.pvc) } @@ -161,7 +160,7 @@ func (p *provisioningTestResource) setupResource(driver drivers.TestDriver, patt } } -func (p *provisioningTestResource) cleanupResource(driver drivers.TestDriver, pattern testpatterns.TestPattern) { +func (p *provisioningTestResource) cleanupResource(driver TestDriver, pattern testpatterns.TestPattern) { } type provisioningTestInput struct { @@ -169,7 +168,7 @@ type provisioningTestInput struct { cs clientset.Interface pvc *v1.PersistentVolumeClaim sc *storage.StorageClass - dInfo *drivers.DriverInfo + dInfo *DriverInfo } func testProvisioning(input *provisioningTestInput) { @@ -187,7 +186,7 @@ func testProvisioning(input *provisioningTestInput) { }) It("should create and delete block persistent volumes", func() { - if !input.dInfo.Capabilities[drivers.CapBlock] { + if !input.dInfo.Capabilities[CapBlock] { framework.Skipf("Driver %q does not support BlockVolume - skipping", input.dInfo.Name) } block := v1.PersistentVolumeBlock diff --git a/test/e2e/storage/testsuites/subpath.go b/test/e2e/storage/testsuites/subpath.go index 66e1985c9ce..f7343b680c5 100644 --- a/test/e2e/storage/testsuites/subpath.go +++ b/test/e2e/storage/testsuites/subpath.go @@ -22,12 +22,11 @@ import ( "regexp" "strings" - "k8s.io/api/core/v1" + v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/rand" "k8s.io/apimachinery/pkg/util/wait" "k8s.io/kubernetes/test/e2e/framework" - "k8s.io/kubernetes/test/e2e/storage/drivers" "k8s.io/kubernetes/test/e2e/storage/testpatterns" "k8s.io/kubernetes/test/e2e/storage/utils" imageutils "k8s.io/kubernetes/test/utils/image" @@ -72,13 +71,13 @@ func (s *subPathTestSuite) getTestSuiteInfo() TestSuiteInfo { return s.tsInfo } -func (s *subPathTestSuite) skipUnsupportedTest(pattern testpatterns.TestPattern, driver drivers.TestDriver) { +func (s *subPathTestSuite) skipUnsupportedTest(pattern testpatterns.TestPattern, driver TestDriver) { } func createSubPathTestInput(pattern testpatterns.TestPattern, resource subPathTestResource) subPathTestInput { driver := resource.driver dInfo := driver.GetDriverInfo() - f := dInfo.Framework + f := dInfo.Config.Framework subPath := f.Namespace.Name subPathDir := filepath.Join(volumePath, subPath) @@ -95,7 +94,7 @@ func createSubPathTestInput(pattern testpatterns.TestPattern, resource subPathTe } } -func (s *subPathTestSuite) execTest(driver drivers.TestDriver, pattern testpatterns.TestPattern) { +func (s *subPathTestSuite) execTest(driver TestDriver, pattern testpatterns.TestPattern) { Context(getTestNameStr(s, pattern), func() { var ( resource subPathTestResource @@ -137,10 +136,10 @@ type subPathTestResource struct { var _ TestResource = &subPathTestResource{} -func (s *subPathTestResource) setupResource(driver drivers.TestDriver, pattern testpatterns.TestPattern) { +func (s *subPathTestResource) setupResource(driver TestDriver, pattern testpatterns.TestPattern) { s.driver = driver dInfo := s.driver.GetDriverInfo() - f := dInfo.Framework + f := dInfo.Config.Framework fsType := pattern.FsType volType := pattern.VolType @@ -150,7 +149,7 @@ func (s *subPathTestResource) setupResource(driver drivers.TestDriver, pattern t // Setup subPath test dependent resource switch volType { case testpatterns.InlineVolume: - if iDriver, ok := driver.(drivers.InlineVolumeTestDriver); ok { + if iDriver, ok := driver.(InlineVolumeTestDriver); ok { s.roVolSource = iDriver.GetVolumeSource(true, fsType, s.genericVolumeTestResource.driverTestResource) } case testpatterns.PreprovisionedPV: @@ -175,16 +174,16 @@ func (s *subPathTestResource) setupResource(driver drivers.TestDriver, pattern t config := dInfo.Config s.pod = SubpathTestPod(f, subPath, s.volType, s.volSource, true) s.pod.Spec.NodeName = config.ClientNodeName - s.pod.Spec.NodeSelector = config.NodeSelector + s.pod.Spec.NodeSelector = config.ClientNodeSelector s.formatPod = volumeFormatPod(f, s.volSource) s.formatPod.Spec.NodeName = config.ClientNodeName - s.formatPod.Spec.NodeSelector = config.NodeSelector + s.formatPod.Spec.NodeSelector = config.ClientNodeSelector } -func (s *subPathTestResource) cleanupResource(driver drivers.TestDriver, pattern testpatterns.TestPattern) { +func (s *subPathTestResource) cleanupResource(driver TestDriver, pattern testpatterns.TestPattern) { dInfo := driver.GetDriverInfo() - f := dInfo.Framework + f := dInfo.Config.Framework // Cleanup subPath test dependent resource By("Deleting pod") @@ -247,7 +246,7 @@ func testSubPath(input *subPathTestInput) { setInitCommand(input.pod, fmt.Sprintf("ln -s /bin %s", input.subPathDir)) // Pod should fail - testPodFailSubpath(input.f, input.pod) + testPodFailSubpath(input.f, input.pod, false) }) It("should fail if subpath file is outside the volume [Slow]", func() { @@ -255,7 +254,7 @@ func testSubPath(input *subPathTestInput) { setInitCommand(input.pod, fmt.Sprintf("ln -s /bin/sh %s", input.subPathDir)) // Pod should fail - testPodFailSubpath(input.f, input.pod) + testPodFailSubpath(input.f, input.pod, false) }) It("should fail if non-existent subpath is outside the volume [Slow]", func() { @@ -263,7 +262,7 @@ func testSubPath(input *subPathTestInput) { setInitCommand(input.pod, fmt.Sprintf("ln -s /bin/notanexistingpath %s", input.subPathDir)) // Pod should fail - testPodFailSubpath(input.f, input.pod) + testPodFailSubpath(input.f, input.pod, false) }) It("should fail if subpath with backstepping is outside the volume [Slow]", func() { @@ -271,7 +270,7 @@ func testSubPath(input *subPathTestInput) { setInitCommand(input.pod, fmt.Sprintf("ln -s ../ %s", input.subPathDir)) // Pod should fail - testPodFailSubpath(input.f, input.pod) + testPodFailSubpath(input.f, input.pod, false) }) It("should support creating multiple subpath from same volumes [Slow]", func() { @@ -361,6 +360,49 @@ func testSubPath(input *subPathTestInput) { testReadFile(input.f, input.filePathInSubpath, input.pod, 0) }) + It("should verify container cannot write to subpath readonly volumes", func() { + if input.roVol == nil { + framework.Skipf("Volume type %v doesn't support readOnly source", input.volType) + } + + // Format the volume while it's writable + formatVolume(input.f, input.formatPod) + + // Set volume source to read only + input.pod.Spec.Volumes[0].VolumeSource = *input.roVol + + // Write the file in the volume from container 0 + setWriteCommand(input.subPathDir, &input.pod.Spec.Containers[0]) + + // Pod should fail + testPodFailSubpath(input.f, input.pod, true) + }) + + It("should be able to unmount after the subpath directory is deleted", func() { + // Change volume container to busybox so we can exec later + input.pod.Spec.Containers[1].Image = imageutils.GetE2EImage(imageutils.BusyBox) + input.pod.Spec.Containers[1].Command = []string{"/bin/sh", "-ec", "sleep 100000"} + + By(fmt.Sprintf("Creating pod %s", input.pod.Name)) + pod, err := input.f.ClientSet.CoreV1().Pods(input.f.Namespace.Name).Create(input.pod) + Expect(err).ToNot(HaveOccurred(), "while creating pod") + defer func() { + By(fmt.Sprintf("Deleting pod %s", pod.Name)) + framework.DeletePodWithWait(input.f, input.f.ClientSet, pod) + }() + + // Wait for pod to be running + err = framework.WaitForPodRunningInNamespace(input.f.ClientSet, pod) + Expect(err).ToNot(HaveOccurred(), "while waiting for pod to be running") + + // Exec into container that mounted the volume, delete subpath directory + rmCmd := fmt.Sprintf("rm -rf %s", input.subPathDir) + _, err = podContainerExec(pod, 1, rmCmd) + Expect(err).ToNot(HaveOccurred(), "while removing subpath directory") + + // Delete pod (from defer) and wait for it to be successfully deleted + }) + // TODO: add a test case for the same disk with two partitions } @@ -575,11 +617,11 @@ func testReadFile(f *framework.Framework, file string, pod *v1.Pod, containerInd Expect(err).NotTo(HaveOccurred(), "while deleting pod") } -func testPodFailSubpath(f *framework.Framework, pod *v1.Pod) { - testPodFailSubpathError(f, pod, "subPath") +func testPodFailSubpath(f *framework.Framework, pod *v1.Pod, allowContainerTerminationError bool) { + testPodFailSubpathError(f, pod, "subPath", allowContainerTerminationError) } -func testPodFailSubpathError(f *framework.Framework, pod *v1.Pod, errorMsg string) { +func testPodFailSubpathError(f *framework.Framework, pod *v1.Pod, errorMsg string, allowContainerTerminationError bool) { By(fmt.Sprintf("Creating pod %s", pod.Name)) pod, err := f.ClientSet.CoreV1().Pods(f.Namespace.Name).Create(pod) Expect(err).ToNot(HaveOccurred(), "while creating pod") @@ -587,7 +629,7 @@ func testPodFailSubpathError(f *framework.Framework, pod *v1.Pod, errorMsg strin framework.DeletePodWithWait(f, f.ClientSet, pod) }() By("Checking for subpath error in container status") - err = waitForPodSubpathError(f, pod) + err = waitForPodSubpathError(f, pod, allowContainerTerminationError) Expect(err).NotTo(HaveOccurred(), "while waiting for subpath failure") } @@ -602,7 +644,7 @@ func findSubpathContainerName(pod *v1.Pod) string { return "" } -func waitForPodSubpathError(f *framework.Framework, pod *v1.Pod) error { +func waitForPodSubpathError(f *framework.Framework, pod *v1.Pod, allowContainerTerminationError bool) error { subpathContainerName := findSubpathContainerName(pod) if subpathContainerName == "" { return fmt.Errorf("failed to find container that uses subpath") @@ -620,6 +662,9 @@ func waitForPodSubpathError(f *framework.Framework, pod *v1.Pod) error { case status.State.Running != nil: return false, fmt.Errorf("subpath container unexpectedly became running") case status.State.Terminated != nil: + if status.State.Terminated.ExitCode != 0 && allowContainerTerminationError { + return true, nil + } return false, fmt.Errorf("subpath container unexpectedly terminated") case status.State.Waiting != nil: if status.State.Waiting.Reason == "CreateContainerConfigError" && diff --git a/test/e2e/storage/drivers/base.go b/test/e2e/storage/testsuites/testdriver.go similarity index 59% rename from test/e2e/storage/drivers/base.go rename to test/e2e/storage/testsuites/testdriver.go index 95d6b263c33..beb8ea1a429 100644 --- a/test/e2e/storage/drivers/base.go +++ b/test/e2e/storage/testsuites/testdriver.go @@ -14,14 +14,11 @@ See the License for the specific language governing permissions and limitations under the License. */ -package drivers +package testsuites import ( - "fmt" - "k8s.io/api/core/v1" storagev1 "k8s.io/api/storage/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/sets" "k8s.io/kubernetes/test/e2e/framework" "k8s.io/kubernetes/test/e2e/storage/testpatterns" @@ -74,6 +71,11 @@ type DynamicPVTestDriver interface { // It will set fsType to the StorageClass, if TestDriver supports it. // It will return nil, if the TestDriver doesn't support it. GetDynamicProvisionStorageClass(fsType string) *storagev1.StorageClass + + // GetClaimSize returns the size of the volume that is to be provisioned ("5Gi", "1Mi"). + // The size must be chosen so that the resulting volume is large enough for all + // enabled tests and within the range supported by the underlying storage. + GetClaimSize() string } // Capability represents a feature that a volume plugin supports @@ -97,95 +99,35 @@ type DriverInfo struct { RequiredMountOption sets.String // Map of string for required mount option (Optional) Capabilities map[Capability]bool // Map that represents plugin capabilities - // Parameters below will be set inside test loop by using SetCommonDriverParameters. - // Drivers that implement TestDriver is required to set all the above parameters - // and return DriverInfo on GetDriverInfo() call. - Framework *framework.Framework // Framework for the test - Config framework.VolumeTestConfig // VolumeTestConfig for thet test + Config TestConfig // Test configuration for the current test. } -// GetDriverNameWithFeatureTags returns driver name with feature tags -// For example) -// - [Driver: nfs] -// - [Driver: rbd][Feature:Volumes] -func GetDriverNameWithFeatureTags(driver TestDriver) string { - dInfo := driver.GetDriverInfo() +// TestConfig represents parameters that control test execution. +// They can still be modified after defining tests, for example +// in a BeforeEach or when creating the driver. +type TestConfig struct { + // Some short word that gets inserted into dynamically + // generated entities (pods, paths) as first part of the name + // to make debugging easier. Can be the same for different + // tests inside the test suite. + Prefix string - return fmt.Sprintf("[Driver: %s]%s", dInfo.Name, dInfo.FeatureTag) -} - -// CreateVolume creates volume for test unless dynamicPV test -func CreateVolume(driver TestDriver, volType testpatterns.TestVolType) interface{} { - switch volType { - case testpatterns.InlineVolume: - fallthrough - case testpatterns.PreprovisionedPV: - if pDriver, ok := driver.(PreprovisionedVolumeTestDriver); ok { - return pDriver.CreateVolume(volType) - } - case testpatterns.DynamicPV: - // No need to create volume - default: - framework.Failf("Invalid volType specified: %v", volType) - } - return nil -} - -// DeleteVolume deletes volume for test unless dynamicPV test -func DeleteVolume(driver TestDriver, volType testpatterns.TestVolType, testResource interface{}) { - switch volType { - case testpatterns.InlineVolume: - fallthrough - case testpatterns.PreprovisionedPV: - if pDriver, ok := driver.(PreprovisionedVolumeTestDriver); ok { - pDriver.DeleteVolume(volType, testResource) - } - case testpatterns.DynamicPV: - // No need to delete volume - default: - framework.Failf("Invalid volType specified: %v", volType) - } -} - -// SetCommonDriverParameters sets a common driver parameters to TestDriver -// This function is intended to be called in BeforeEach() inside test loop. -func SetCommonDriverParameters( - driver TestDriver, - f *framework.Framework, - config framework.VolumeTestConfig, -) { - dInfo := driver.GetDriverInfo() - - dInfo.Framework = f - dInfo.Config = config -} - -func getStorageClass( - provisioner string, - parameters map[string]string, - bindingMode *storagev1.VolumeBindingMode, - ns string, - suffix string, -) *storagev1.StorageClass { - if bindingMode == nil { - defaultBindingMode := storagev1.VolumeBindingImmediate - bindingMode = &defaultBindingMode - } - return &storagev1.StorageClass{ - TypeMeta: metav1.TypeMeta{ - Kind: "StorageClass", - }, - ObjectMeta: metav1.ObjectMeta{ - // Name must be unique, so let's base it on namespace name - Name: ns + "-" + suffix, - }, - Provisioner: provisioner, - Parameters: parameters, - VolumeBindingMode: bindingMode, - } -} - -// GetUniqueDriverName returns unique driver name that can be used parallelly in tests -func GetUniqueDriverName(driver TestDriver) string { - return fmt.Sprintf("%s-%s", driver.GetDriverInfo().Name, driver.GetDriverInfo().Framework.UniqueName) + // The framework instance allocated for the current test. + Framework *framework.Framework + + // If non-empty, then pods using a volume will be scheduled + // onto the node with this name. Otherwise Kubernetes will + // pick a node. + ClientNodeName string + + // Some tests also support scheduling pods onto nodes with + // these label/value pairs. As not all tests use this field, + // a driver that absolutely needs the pods on a specific + // node must use ClientNodeName. + ClientNodeSelector map[string]string + + // Some test drivers initialize a storage server. This is + // the configuration that then has to be used to run tests. + // The values above are ignored for such tests. + ServerConfig *framework.VolumeTestConfig } diff --git a/test/e2e/storage/testsuites/volume_io.go b/test/e2e/storage/testsuites/volume_io.go index 3b291517778..ad32f84fa5f 100644 --- a/test/e2e/storage/testsuites/volume_io.go +++ b/test/e2e/storage/testsuites/volume_io.go @@ -35,7 +35,6 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" clientset "k8s.io/client-go/kubernetes" "k8s.io/kubernetes/test/e2e/framework" - "k8s.io/kubernetes/test/e2e/storage/drivers" "k8s.io/kubernetes/test/e2e/storage/testpatterns" "k8s.io/kubernetes/test/e2e/storage/utils" ) @@ -75,14 +74,14 @@ func (t *volumeIOTestSuite) getTestSuiteInfo() TestSuiteInfo { return t.tsInfo } -func (t *volumeIOTestSuite) skipUnsupportedTest(pattern testpatterns.TestPattern, driver drivers.TestDriver) { +func (t *volumeIOTestSuite) skipUnsupportedTest(pattern testpatterns.TestPattern, driver TestDriver) { } func createVolumeIOTestInput(pattern testpatterns.TestPattern, resource genericVolumeTestResource) volumeIOTestInput { var fsGroup *int64 driver := resource.driver dInfo := driver.GetDriverInfo() - f := dInfo.Framework + f := dInfo.Config.Framework fileSizes := createFileSizes(dInfo.MaxFileSize) volSource := resource.volSource @@ -90,7 +89,7 @@ func createVolumeIOTestInput(pattern testpatterns.TestPattern, resource genericV framework.Skipf("Driver %q does not define volumeSource - skipping", dInfo.Name) } - if dInfo.Capabilities[drivers.CapFsGroup] { + if dInfo.Capabilities[CapFsGroup] { fsGroupVal := int64(1234) fsGroup = &fsGroupVal } @@ -98,7 +97,7 @@ func createVolumeIOTestInput(pattern testpatterns.TestPattern, resource genericV return volumeIOTestInput{ f: f, name: dInfo.Name, - config: dInfo.Config, + config: &dInfo.Config, volSource: *volSource, testFile: fmt.Sprintf("%s_io_test_%s", dInfo.Name, f.Namespace.Name), podSec: v1.PodSecurityContext{ @@ -108,7 +107,7 @@ func createVolumeIOTestInput(pattern testpatterns.TestPattern, resource genericV } } -func (t *volumeIOTestSuite) execTest(driver drivers.TestDriver, pattern testpatterns.TestPattern) { +func (t *volumeIOTestSuite) execTest(driver TestDriver, pattern testpatterns.TestPattern) { Context(getTestNameStr(t, pattern), func() { var ( resource genericVolumeTestResource @@ -143,7 +142,7 @@ func (t *volumeIOTestSuite) execTest(driver drivers.TestDriver, pattern testpatt type volumeIOTestInput struct { f *framework.Framework name string - config framework.VolumeTestConfig + config *TestConfig volSource v1.VolumeSource testFile string podSec v1.PodSecurityContext @@ -155,7 +154,7 @@ func execTestVolumeIO(input *volumeIOTestInput) { f := input.f cs := f.ClientSet - err := testVolumeIO(f, cs, input.config, input.volSource, &input.podSec, input.testFile, input.fileSizes) + err := testVolumeIO(f, cs, convertTestConfig(input.config), input.volSource, &input.podSec, input.testFile, input.fileSizes) Expect(err).NotTo(HaveOccurred()) }) } diff --git a/test/e2e/storage/testsuites/volumemode.go b/test/e2e/storage/testsuites/volumemode.go index 94bef7508d9..03eb2a43b09 100644 --- a/test/e2e/storage/testsuites/volumemode.go +++ b/test/e2e/storage/testsuites/volumemode.go @@ -27,7 +27,6 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" utilerrors "k8s.io/apimachinery/pkg/util/errors" "k8s.io/kubernetes/test/e2e/framework" - "k8s.io/kubernetes/test/e2e/storage/drivers" "k8s.io/kubernetes/test/e2e/storage/testpatterns" "k8s.io/kubernetes/test/e2e/storage/utils" ) @@ -62,13 +61,13 @@ func (t *volumeModeTestSuite) getTestSuiteInfo() TestSuiteInfo { return t.tsInfo } -func (t *volumeModeTestSuite) skipUnsupportedTest(pattern testpatterns.TestPattern, driver drivers.TestDriver) { +func (t *volumeModeTestSuite) skipUnsupportedTest(pattern testpatterns.TestPattern, driver TestDriver) { } func createVolumeModeTestInput(pattern testpatterns.TestPattern, resource volumeModeTestResource) volumeModeTestInput { driver := resource.driver dInfo := driver.GetDriverInfo() - f := dInfo.Framework + f := dInfo.Config.Framework return volumeModeTestInput{ f: f, @@ -78,13 +77,13 @@ func createVolumeModeTestInput(pattern testpatterns.TestPattern, resource volume testVolType: pattern.VolType, nodeName: dInfo.Config.ClientNodeName, volMode: pattern.VolMode, - isBlockSupported: dInfo.Capabilities[drivers.CapBlock], + isBlockSupported: dInfo.Capabilities[CapBlock], } } -func getVolumeModeTestFunc(pattern testpatterns.TestPattern, driver drivers.TestDriver) func(*volumeModeTestInput) { +func getVolumeModeTestFunc(pattern testpatterns.TestPattern, driver TestDriver) func(*volumeModeTestInput) { dInfo := driver.GetDriverInfo() - isBlockSupported := dInfo.Capabilities[drivers.CapBlock] + isBlockSupported := dInfo.Capabilities[CapBlock] volMode := pattern.VolMode volType := pattern.VolType @@ -105,7 +104,7 @@ func getVolumeModeTestFunc(pattern testpatterns.TestPattern, driver drivers.Test return nil } -func (t *volumeModeTestSuite) execTest(driver drivers.TestDriver, pattern testpatterns.TestPattern) { +func (t *volumeModeTestSuite) execTest(driver TestDriver, pattern testpatterns.TestPattern) { Context(getTestNameStr(t, pattern), func() { var ( resource volumeModeTestResource @@ -141,7 +140,7 @@ func (t *volumeModeTestSuite) execTest(driver drivers.TestDriver, pattern testpa } type volumeModeTestResource struct { - driver drivers.TestDriver + driver TestDriver sc *storagev1.StorageClass pvc *v1.PersistentVolumeClaim @@ -152,10 +151,10 @@ type volumeModeTestResource struct { var _ TestResource = &volumeModeTestResource{} -func (s *volumeModeTestResource) setupResource(driver drivers.TestDriver, pattern testpatterns.TestPattern) { +func (s *volumeModeTestResource) setupResource(driver TestDriver, pattern testpatterns.TestPattern) { s.driver = driver dInfo := driver.GetDriverInfo() - f := dInfo.Framework + f := dInfo.Config.Framework ns := f.Namespace fsType := pattern.FsType volBindMode := storagev1.VolumeBindingImmediate @@ -168,7 +167,7 @@ func (s *volumeModeTestResource) setupResource(driver drivers.TestDriver, patter ) // Create volume for pre-provisioned volume tests - s.driverTestResource = drivers.CreateVolume(driver, volType) + s.driverTestResource = CreateVolume(driver, volType) switch volType { case testpatterns.PreprovisionedPV: @@ -177,7 +176,7 @@ func (s *volumeModeTestResource) setupResource(driver drivers.TestDriver, patter } else if volMode == v1.PersistentVolumeFilesystem { scName = fmt.Sprintf("%s-%s-sc-for-file", ns.Name, dInfo.Name) } - if pDriver, ok := driver.(drivers.PreprovisionedPVTestDriver); ok { + if pDriver, ok := driver.(PreprovisionedPVTestDriver); ok { pvSource = pDriver.GetPersistentVolumeSource(false, fsType, s.driverTestResource) if pvSource == nil { framework.Skipf("Driver %q does not define PersistentVolumeSource - skipping", dInfo.Name) @@ -189,14 +188,14 @@ func (s *volumeModeTestResource) setupResource(driver drivers.TestDriver, patter s.pvc = framework.MakePersistentVolumeClaim(pvcConfig, ns.Name) } case testpatterns.DynamicPV: - if dDriver, ok := driver.(drivers.DynamicPVTestDriver); ok { + if dDriver, ok := driver.(DynamicPVTestDriver); ok { s.sc = dDriver.GetDynamicProvisionStorageClass(fsType) if s.sc == nil { framework.Skipf("Driver %q does not define Dynamic Provision StorageClass - skipping", dInfo.Name) } s.sc.VolumeBindingMode = &volBindMode - claimSize := "5Gi" + claimSize := dDriver.GetClaimSize() s.pvc = getClaim(claimSize, ns.Name) s.pvc.Spec.StorageClassName = &s.sc.Name s.pvc.Spec.VolumeMode = &volMode @@ -206,9 +205,9 @@ func (s *volumeModeTestResource) setupResource(driver drivers.TestDriver, patter } } -func (s *volumeModeTestResource) cleanupResource(driver drivers.TestDriver, pattern testpatterns.TestPattern) { +func (s *volumeModeTestResource) cleanupResource(driver TestDriver, pattern testpatterns.TestPattern) { dInfo := driver.GetDriverInfo() - f := dInfo.Framework + f := dInfo.Config.Framework cs := f.ClientSet ns := f.Namespace volType := pattern.VolType @@ -224,7 +223,7 @@ func (s *volumeModeTestResource) cleanupResource(driver drivers.TestDriver, patt } // Cleanup volume for pre-provisioned volume tests - drivers.DeleteVolume(driver, volType, s.driverTestResource) + DeleteVolume(driver, volType, s.driverTestResource) } type volumeModeTestInput struct { diff --git a/test/e2e/storage/testsuites/volumes.go b/test/e2e/storage/testsuites/volumes.go index 8189187fc6f..1d890e085a9 100644 --- a/test/e2e/storage/testsuites/volumes.go +++ b/test/e2e/storage/testsuites/volumes.go @@ -31,7 +31,6 @@ import ( "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/kubernetes/test/e2e/framework" - "k8s.io/kubernetes/test/e2e/storage/drivers" "k8s.io/kubernetes/test/e2e/storage/testpatterns" imageutils "k8s.io/kubernetes/test/utils/image" ) @@ -73,19 +72,19 @@ func (t *volumesTestSuite) getTestSuiteInfo() TestSuiteInfo { return t.tsInfo } -func (t *volumesTestSuite) skipUnsupportedTest(pattern testpatterns.TestPattern, driver drivers.TestDriver) { +func (t *volumesTestSuite) skipUnsupportedTest(pattern testpatterns.TestPattern, driver TestDriver) { } -func skipPersistenceTest(driver drivers.TestDriver) { +func skipPersistenceTest(driver TestDriver) { dInfo := driver.GetDriverInfo() - if !dInfo.Capabilities[drivers.CapPersistence] { + if !dInfo.Capabilities[CapPersistence] { framework.Skipf("Driver %q does not provide persistency - skipping", dInfo.Name) } } -func skipExecTest(driver drivers.TestDriver) { +func skipExecTest(driver TestDriver) { dInfo := driver.GetDriverInfo() - if !dInfo.Capabilities[drivers.CapExec] { + if !dInfo.Capabilities[CapExec] { framework.Skipf("Driver %q does not support exec - skipping", dInfo.Name) } } @@ -94,14 +93,14 @@ func createVolumesTestInput(pattern testpatterns.TestPattern, resource genericVo var fsGroup *int64 driver := resource.driver dInfo := driver.GetDriverInfo() - f := dInfo.Framework + f := dInfo.Config.Framework volSource := resource.volSource if volSource == nil { framework.Skipf("Driver %q does not define volumeSource - skipping", dInfo.Name) } - if dInfo.Capabilities[drivers.CapFsGroup] { + if dInfo.Capabilities[CapFsGroup] { fsGroupVal := int64(1234) fsGroup = &fsGroupVal } @@ -109,7 +108,7 @@ func createVolumesTestInput(pattern testpatterns.TestPattern, resource genericVo return volumesTestInput{ f: f, name: dInfo.Name, - config: dInfo.Config, + config: &dInfo.Config, fsGroup: fsGroup, resource: resource, tests: []framework.VolumeTest{ @@ -124,7 +123,7 @@ func createVolumesTestInput(pattern testpatterns.TestPattern, resource genericVo } } -func (t *volumesTestSuite) execTest(driver drivers.TestDriver, pattern testpatterns.TestPattern) { +func (t *volumesTestSuite) execTest(driver TestDriver, pattern testpatterns.TestPattern) { Context(getTestNameStr(t, pattern), func() { var ( resource genericVolumeTestResource @@ -159,7 +158,7 @@ func (t *volumesTestSuite) execTest(driver drivers.TestDriver, pattern testpatte type volumesTestInput struct { f *framework.Framework name string - config framework.VolumeTestConfig + config *TestConfig fsGroup *int64 tests []framework.VolumeTest resource genericVolumeTestResource @@ -169,23 +168,29 @@ func testVolumes(input *volumesTestInput) { It("should be mountable", func() { f := input.f cs := f.ClientSet - defer framework.VolumeTestCleanup(f, input.config) + defer framework.VolumeTestCleanup(f, convertTestConfig(input.config)) skipPersistenceTest(input.resource.driver) volumeTest := input.tests - framework.InjectHtml(cs, input.config, volumeTest[0].Volume, volumeTest[0].ExpectedContent) - framework.TestVolumeClient(cs, input.config, input.fsGroup, input.tests) + config := convertTestConfig(input.config) + framework.InjectHtml(cs, config, volumeTest[0].Volume, volumeTest[0].ExpectedContent) + framework.TestVolumeClient(cs, config, input.fsGroup, input.tests) }) It("should allow exec of files on the volume", func() { f := input.f skipExecTest(input.resource.driver) - testScriptInPod(f, input.resource.volType, input.resource.volSource) + testScriptInPod(f, input.resource.volType, input.resource.volSource, input.resource.driver.GetDriverInfo().Config.ClientNodeSelector) }) } -func testScriptInPod(f *framework.Framework, volumeType string, source *v1.VolumeSource) { +func testScriptInPod( + f *framework.Framework, + volumeType string, + source *v1.VolumeSource, + nodeSelector map[string]string) { + const ( volPath = "/vol1" volName = "vol1" @@ -221,6 +226,7 @@ func testScriptInPod(f *framework.Framework, volumeType string, source *v1.Volum }, }, RestartPolicy: v1.RestartPolicyNever, + NodeSelector: nodeSelector, }, } By(fmt.Sprintf("Creating pod %s", pod.Name)) diff --git a/test/e2e/storage/vsphere/config.go b/test/e2e/storage/vsphere/config.go index 07a608ae701..98f3feb0c35 100644 --- a/test/e2e/storage/vsphere/config.go +++ b/test/e2e/storage/vsphere/config.go @@ -19,10 +19,11 @@ package vsphere import ( "errors" "fmt" - "gopkg.in/gcfg.v1" "io" - "k8s.io/kubernetes/test/e2e/framework" "os" + + "gopkg.in/gcfg.v1" + "k8s.io/kubernetes/test/e2e/framework" ) const ( @@ -147,7 +148,7 @@ func populateInstanceMap(cfg *ConfigFile) (map[string]*VSphere, error) { vcConfig.Password = cfg.Global.Password } if vcConfig.Username == "" { - msg := fmt.Sprintf("vcConfig.User is empty for vc %s!", vcServer) + msg := fmt.Sprintf("vcConfig.Username is empty for vc %s!", vcServer) framework.Logf(msg) return nil, errors.New(msg) } diff --git a/test/e2e/storage/vsphere/pvc_label_selector.go b/test/e2e/storage/vsphere/pvc_label_selector.go index 21eb3d5b1e4..3de1e2bbcf4 100644 --- a/test/e2e/storage/vsphere/pvc_label_selector.go +++ b/test/e2e/storage/vsphere/pvc_label_selector.go @@ -105,9 +105,8 @@ var _ = utils.SIGDescribe("PersistentVolumes [Feature:LabelSelector]", func() { }) func testSetupVSpherePVClabelselector(c clientset.Interface, nodeInfo *NodeInfo, ns string, ssdlabels map[string]string, vvollabels map[string]string) (volumePath string, pv_ssd *v1.PersistentVolume, pvc_ssd *v1.PersistentVolumeClaim, pvc_vvol *v1.PersistentVolumeClaim, err error) { - volumePath = "" By("creating vmdk") - Expect(err).NotTo(HaveOccurred()) + volumePath = "" volumePath, err = nodeInfo.VSphere.CreateVolume(&VolumeOptions{}, nodeInfo.DataCenterRef) if err != nil { return diff --git a/test/e2e/storage/vsphere/vsphere_volume_node_poweroff.go b/test/e2e/storage/vsphere/vsphere_volume_node_poweroff.go index a105d4c765f..a79699b6f09 100644 --- a/test/e2e/storage/vsphere/vsphere_volume_node_poweroff.go +++ b/test/e2e/storage/vsphere/vsphere_volume_node_poweroff.go @@ -95,7 +95,7 @@ var _ = utils.SIGDescribe("Node Poweroff [Feature:vsphere] [Slow] [Disruptive]", By("Creating a Deployment") deployment, err := framework.CreateDeployment(client, int32(1), map[string]string{"test": "app"}, nil, namespace, pvclaims, "") Expect(err).NotTo(HaveOccurred(), fmt.Sprintf("Failed to create Deployment with err: %v", err)) - defer client.ExtensionsV1beta1().Deployments(namespace).Delete(deployment.Name, &metav1.DeleteOptions{}) + defer client.AppsV1().Deployments(namespace).Delete(deployment.Name, &metav1.DeleteOptions{}) By("Get pod from the deployement") podList, err := framework.GetPodsForDeployment(client, deployment) diff --git a/test/e2e/testing-manifests/flexvolume/attachable-with-long-format b/test/e2e/testing-manifests/flexvolume/attachable-with-long-mount similarity index 100% rename from test/e2e/testing-manifests/flexvolume/attachable-with-long-format rename to test/e2e/testing-manifests/flexvolume/attachable-with-long-mount diff --git a/test/e2e/testing-manifests/flexvolume/dummy-attachable b/test/e2e/testing-manifests/flexvolume/dummy-attachable index 2c47faaf3fe..ed9e73e7a01 100755 --- a/test/e2e/testing-manifests/flexvolume/dummy-attachable +++ b/test/e2e/testing-manifests/flexvolume/dummy-attachable @@ -81,8 +81,6 @@ domountdevice() { unmountdevice() { debug "unmountdevice $@" - MNTDEVICE=$2 - validateMountDeviceOrDie "$MNTDEVICE" "unmountdevice" MNTPATH=$1 rm "${MNTPATH}/index.html" >/dev/null 2>&1 umount ${MNTPATH} >/dev/null 2>&1 diff --git a/test/e2e/testing-manifests/guestbook/frontend-deployment.yaml.in b/test/e2e/testing-manifests/guestbook/frontend-deployment.yaml.in index 6cbd92fe717..de9ceccedea 100644 --- a/test/e2e/testing-manifests/guestbook/frontend-deployment.yaml.in +++ b/test/e2e/testing-manifests/guestbook/frontend-deployment.yaml.in @@ -1,9 +1,13 @@ -apiVersion: extensions/v1beta1 +apiVersion: apps/v1 kind: Deployment metadata: name: frontend spec: replicas: 3 + selector: + matchLabels: + app: guestbook + tier: frontend template: metadata: labels: diff --git a/test/e2e/testing-manifests/guestbook/redis-master-deployment.yaml.in b/test/e2e/testing-manifests/guestbook/redis-master-deployment.yaml.in index 6de8c5590ff..1f6a674ab57 100644 --- a/test/e2e/testing-manifests/guestbook/redis-master-deployment.yaml.in +++ b/test/e2e/testing-manifests/guestbook/redis-master-deployment.yaml.in @@ -1,9 +1,14 @@ -apiVersion: extensions/v1beta1 +apiVersion: apps/v1 kind: Deployment metadata: name: redis-master spec: replicas: 1 + selector: + matchLabels: + app: redis + role: master + tier: backend template: metadata: labels: diff --git a/test/e2e/testing-manifests/guestbook/redis-slave-deployment.yaml.in b/test/e2e/testing-manifests/guestbook/redis-slave-deployment.yaml.in index 38210542007..46775a82306 100644 --- a/test/e2e/testing-manifests/guestbook/redis-slave-deployment.yaml.in +++ b/test/e2e/testing-manifests/guestbook/redis-slave-deployment.yaml.in @@ -1,9 +1,14 @@ -apiVersion: extensions/v1beta1 +apiVersion: apps/v1 kind: Deployment metadata: name: redis-slave spec: replicas: 2 + selector: + matchLabels: + app: redis + role: slave + tier: backend template: metadata: labels: diff --git a/test/e2e/testing-manifests/ingress/http2/rc.yaml b/test/e2e/testing-manifests/ingress/http2/rc.yaml index d60c984ed4d..c6d411ed32f 100644 --- a/test/e2e/testing-manifests/ingress/http2/rc.yaml +++ b/test/e2e/testing-manifests/ingress/http2/rc.yaml @@ -1,9 +1,12 @@ -apiVersion: extensions/v1beta1 +apiVersion: apps/v1 kind: Deployment metadata: name: echoheaders spec: replicas: 1 + selector: + matchLabels: + app: echoheaders template: metadata: labels: diff --git a/test/e2e/testing-manifests/ingress/neg-clusterip/rc.yaml b/test/e2e/testing-manifests/ingress/neg-clusterip/rc.yaml index 32938b628ba..8d4ceefed47 100644 --- a/test/e2e/testing-manifests/ingress/neg-clusterip/rc.yaml +++ b/test/e2e/testing-manifests/ingress/neg-clusterip/rc.yaml @@ -1,4 +1,4 @@ -apiVersion: extensions/v1beta1 +apiVersion: apps/v1 kind: Deployment metadata: labels: @@ -6,6 +6,9 @@ metadata: name: hostname spec: minReadySeconds: 60 + selector: + matchLabels: + run: hostname template: metadata: labels: diff --git a/test/e2e/testing-manifests/ingress/neg-exposed/rc.yaml b/test/e2e/testing-manifests/ingress/neg-exposed/rc.yaml index 6ee21b2add4..a98f398b7e7 100644 --- a/test/e2e/testing-manifests/ingress/neg-exposed/rc.yaml +++ b/test/e2e/testing-manifests/ingress/neg-exposed/rc.yaml @@ -1,10 +1,13 @@ -apiVersion: extensions/v1beta1 +apiVersion: apps/v1 kind: Deployment metadata: labels: run: hostname name: hostname spec: + selector: + matchLabels: + run: hostname template: metadata: labels: diff --git a/test/e2e/testing-manifests/ingress/neg/rc.yaml b/test/e2e/testing-manifests/ingress/neg/rc.yaml index 32938b628ba..8d4ceefed47 100644 --- a/test/e2e/testing-manifests/ingress/neg/rc.yaml +++ b/test/e2e/testing-manifests/ingress/neg/rc.yaml @@ -1,4 +1,4 @@ -apiVersion: extensions/v1beta1 +apiVersion: apps/v1 kind: Deployment metadata: labels: @@ -6,6 +6,9 @@ metadata: name: hostname spec: minReadySeconds: 60 + selector: + matchLabels: + run: hostname template: metadata: labels: diff --git a/test/e2e/testing-manifests/storage-csi/OWNERS b/test/e2e/testing-manifests/storage-csi/OWNERS new file mode 100644 index 00000000000..46424783f87 --- /dev/null +++ b/test/e2e/testing-manifests/storage-csi/OWNERS @@ -0,0 +1,18 @@ +approvers: +- saad-ali +- rootfs +- gnufied +- jingxu97 +- jsafrane +- msau42 +reviewers: +- saad-ali +- rootfs +- gnufied +- jingxu97 +- jsafrane +- msau42 +- jeffvance +- copejon +- verult +- davidz627 diff --git a/test/e2e/testing-manifests/storage-csi/hostpath/hostpath-v0/csi-hostpath-attacher.yaml b/test/e2e/testing-manifests/storage-csi/hostpath/hostpath-v0/csi-hostpath-attacher.yaml index 5598a161d07..3febb17544a 100644 --- a/test/e2e/testing-manifests/storage-csi/hostpath/hostpath-v0/csi-hostpath-attacher.yaml +++ b/test/e2e/testing-manifests/storage-csi/hostpath/hostpath-v0/csi-hostpath-attacher.yaml @@ -30,7 +30,7 @@ spec: serviceAccountName: csi-attacher containers: - name: csi-attacher - image: gcr.io/gke-release/csi-attacher:v0.4.1-gke.0 + image: quay.io/k8scsi/csi-attacher:v0.4.1 args: - --v=5 - --csi-address=$(ADDRESS) diff --git a/test/e2e/testing-manifests/storage-csi/hostpath/hostpath-v0/csi-hostpath-provisioner.yaml b/test/e2e/testing-manifests/storage-csi/hostpath/hostpath-v0/csi-hostpath-provisioner.yaml index 4c2b58a08f6..a7fefb5c516 100644 --- a/test/e2e/testing-manifests/storage-csi/hostpath/hostpath-v0/csi-hostpath-provisioner.yaml +++ b/test/e2e/testing-manifests/storage-csi/hostpath/hostpath-v0/csi-hostpath-provisioner.yaml @@ -29,8 +29,8 @@ spec: spec: serviceAccountName: csi-provisioner containers: - - name: csi-provisioner-v0 - image: gcr.io/gke-release/csi-provisioner:v0.4.1-gke.0 + - name: csi-provisioner + image: quay.io/k8scsi/csi-provisioner:v0.4.1 args: - "--provisioner=csi-hostpath-v0" - "--csi-address=$(ADDRESS)" diff --git a/test/e2e/testing-manifests/storage-csi/hostpath/hostpath-v0/csi-hostpathplugin.yaml b/test/e2e/testing-manifests/storage-csi/hostpath/hostpath-v0/csi-hostpathplugin.yaml index a8f34832d1d..2af3382adbd 100644 --- a/test/e2e/testing-manifests/storage-csi/hostpath/hostpath-v0/csi-hostpathplugin.yaml +++ b/test/e2e/testing-manifests/storage-csi/hostpath/hostpath-v0/csi-hostpathplugin.yaml @@ -15,7 +15,7 @@ spec: hostNetwork: true containers: - name: driver-registrar - image: gcr.io/gke-release/csi-driver-registrar:v0.4.1-gke.0 + image: quay.io/k8scsi/driver-registrar:v0.4.1 args: - --v=5 - --csi-address=/csi/csi.sock diff --git a/test/e2e/testing-manifests/storage-csi/hostpath/hostpath/csi-hostpath-attacher.yaml b/test/e2e/testing-manifests/storage-csi/hostpath/hostpath/csi-hostpath-attacher.yaml index dc2d4c4b7e8..2839731a4be 100644 --- a/test/e2e/testing-manifests/storage-csi/hostpath/hostpath/csi-hostpath-attacher.yaml +++ b/test/e2e/testing-manifests/storage-csi/hostpath/hostpath/csi-hostpath-attacher.yaml @@ -30,7 +30,7 @@ spec: serviceAccountName: csi-attacher containers: - name: csi-attacher - image: gcr.io/gke-release/csi-attacher:v1.0.0-gke.0 + image: quay.io/k8scsi/csi-attacher:v1.0.1 args: - --v=5 - --csi-address=$(ADDRESS) diff --git a/test/e2e/testing-manifests/storage-csi/hostpath/hostpath/csi-hostpath-provisioner.yaml b/test/e2e/testing-manifests/storage-csi/hostpath/hostpath/csi-hostpath-provisioner.yaml index 4f117e11284..12aca8ca494 100644 --- a/test/e2e/testing-manifests/storage-csi/hostpath/hostpath/csi-hostpath-provisioner.yaml +++ b/test/e2e/testing-manifests/storage-csi/hostpath/hostpath/csi-hostpath-provisioner.yaml @@ -30,7 +30,7 @@ spec: serviceAccountName: csi-provisioner containers: - name: csi-provisioner - image: gcr.io/gke-release/csi-provisioner:v1.0.0-gke.0 + image: quay.io/k8scsi/csi-provisioner:v1.0.1 args: - "--provisioner=csi-hostpath" - "--csi-address=$(ADDRESS)" diff --git a/test/e2e/testing-manifests/storage-csi/hostpath/hostpath/csi-hostpathplugin.yaml b/test/e2e/testing-manifests/storage-csi/hostpath/hostpath/csi-hostpathplugin.yaml index 237b759a1c3..8b01fe981cb 100644 --- a/test/e2e/testing-manifests/storage-csi/hostpath/hostpath/csi-hostpathplugin.yaml +++ b/test/e2e/testing-manifests/storage-csi/hostpath/hostpath/csi-hostpathplugin.yaml @@ -15,7 +15,7 @@ spec: hostNetwork: true containers: - name: driver-registrar - image: gcr.io/gke-release/csi-driver-registrar:v1.0.1-gke.0 + image: quay.io/k8scsi/csi-node-driver-registrar:v1.0.1 args: - --v=5 - --csi-address=/csi/csi.sock @@ -33,7 +33,7 @@ spec: - mountPath: /registration name: registration-dir - name: hostpath - image: quay.io/k8scsi/hostpathplugin:v1.0.0 + image: quay.io/k8scsi/hostpathplugin:v1.0.1 args: - "--v=5" - "--endpoint=$(CSI_ENDPOINT)" diff --git a/test/e2e/upgrades/BUILD b/test/e2e/upgrades/BUILD index 9eca273c31d..08cc96d9184 100644 --- a/test/e2e/upgrades/BUILD +++ b/test/e2e/upgrades/BUILD @@ -25,6 +25,7 @@ go_library( importpath = "k8s.io/kubernetes/test/e2e/upgrades", deps = [ "//pkg/kubelet/sysctl:go_default_library", + "//staging/src/k8s.io/api/apps/v1:go_default_library", "//staging/src/k8s.io/api/autoscaling/v1:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library", "//staging/src/k8s.io/api/extensions/v1beta1:go_default_library", diff --git a/test/e2e/upgrades/apps/BUILD b/test/e2e/upgrades/apps/BUILD index aa85076116d..bc0e5810898 100644 --- a/test/e2e/upgrades/apps/BUILD +++ b/test/e2e/upgrades/apps/BUILD @@ -21,7 +21,6 @@ go_library( "//staging/src/k8s.io/api/apps/v1:go_default_library", "//staging/src/k8s.io/api/batch/v1:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library", - "//staging/src/k8s.io/api/extensions/v1beta1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/labels:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/types:go_default_library", diff --git a/test/e2e/upgrades/apps/daemonsets.go b/test/e2e/upgrades/apps/daemonsets.go index 35037003891..c008c8db143 100644 --- a/test/e2e/upgrades/apps/daemonsets.go +++ b/test/e2e/upgrades/apps/daemonsets.go @@ -17,24 +17,22 @@ limitations under the License. package upgrades import ( + . "github.com/onsi/ginkgo" + + apps "k8s.io/api/apps/v1" + "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/util/wait" "k8s.io/kubernetes/pkg/controller" - - "k8s.io/api/core/v1" - - extensions "k8s.io/api/extensions/v1beta1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/kubernetes/test/e2e/framework" "k8s.io/kubernetes/test/e2e/upgrades" - - . "github.com/onsi/ginkgo" ) // DaemonSetUpgradeTest tests that a DaemonSet is running before and after // a cluster upgrade. type DaemonSetUpgradeTest struct { - daemonSet *extensions.DaemonSet + daemonSet *apps.DaemonSet } func (DaemonSetUpgradeTest) Name() string { return "[sig-apps] daemonset-upgrade" } @@ -47,12 +45,12 @@ func (t *DaemonSetUpgradeTest) Setup(f *framework.Framework) { ns := f.Namespace - t.daemonSet = &extensions.DaemonSet{ + t.daemonSet = &apps.DaemonSet{ ObjectMeta: metav1.ObjectMeta{ Namespace: ns.Name, Name: daemonSetName, }, - Spec: extensions.DaemonSetSpec{ + Spec: apps.DaemonSetSpec{ Template: v1.PodTemplateSpec{ ObjectMeta: metav1.ObjectMeta{ Labels: labelSet, @@ -72,7 +70,7 @@ func (t *DaemonSetUpgradeTest) Setup(f *framework.Framework) { By("Creating a DaemonSet") var err error - if t.daemonSet, err = f.ClientSet.ExtensionsV1beta1().DaemonSets(ns.Name).Create(t.daemonSet); err != nil { + if t.daemonSet, err = f.ClientSet.AppsV1().DaemonSets(ns.Name).Create(t.daemonSet); err != nil { framework.Failf("unable to create test DaemonSet %s: %v", t.daemonSet.Name, err) } @@ -168,7 +166,7 @@ func checkDaemonPodOnNodes(f *framework.Framework, namespace string, labelSet ma } func checkDaemonStatus(f *framework.Framework, namespace string, dsName string) (bool, error) { - ds, err := f.ClientSet.ExtensionsV1beta1().DaemonSets(namespace).Get(dsName, metav1.GetOptions{}) + ds, err := f.ClientSet.AppsV1().DaemonSets(namespace).Get(dsName, metav1.GetOptions{}) if err != nil { return false, err } diff --git a/test/e2e/upgrades/kube_proxy_migration.go b/test/e2e/upgrades/kube_proxy_migration.go index e4c11c34ce3..3faa0271ee6 100644 --- a/test/e2e/upgrades/kube_proxy_migration.go +++ b/test/e2e/upgrades/kube_proxy_migration.go @@ -20,8 +20,8 @@ import ( "fmt" "time" + apps "k8s.io/api/apps/v1" "k8s.io/api/core/v1" - extensions "k8s.io/api/extensions/v1beta1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/util/wait" @@ -213,8 +213,8 @@ func getKubeProxyStaticPods(c clientset.Interface) (*v1.PodList, error) { return c.CoreV1().Pods(metav1.NamespaceSystem).List(listOpts) } -func getKubeProxyDaemonSet(c clientset.Interface) (*extensions.DaemonSetList, error) { +func getKubeProxyDaemonSet(c clientset.Interface) (*apps.DaemonSetList, error) { label := labels.SelectorFromSet(labels.Set(map[string]string{clusterAddonLabelKey: kubeProxyLabelName})) listOpts := metav1.ListOptions{LabelSelector: label.String()} - return c.ExtensionsV1beta1().DaemonSets(metav1.NamespaceSystem).List(listOpts) + return c.AppsV1().DaemonSets(metav1.NamespaceSystem).List(listOpts) } diff --git a/test/e2e_node/node_problem_detector_linux.go b/test/e2e_node/node_problem_detector_linux.go index 64aa7ac7207..36a63193c9e 100644 --- a/test/e2e_node/node_problem_detector_linux.go +++ b/test/e2e_node/node_problem_detector_linux.go @@ -22,7 +22,6 @@ import ( "fmt" "os" "path" - "syscall" "time" "k8s.io/api/core/v1" @@ -34,6 +33,7 @@ import ( clientset "k8s.io/client-go/kubernetes" coreclientset "k8s.io/client-go/kubernetes/typed/core/v1" nodeutil "k8s.io/kubernetes/pkg/api/v1/node" + "k8s.io/kubernetes/pkg/kubelet/util" "k8s.io/kubernetes/test/e2e/framework" . "github.com/onsi/ginkgo" @@ -97,8 +97,11 @@ var _ = framework.KubeDescribe("NodeProblemDetector [NodeFeature:NodeProblemDete BeforeEach(func() { By("Calculate Lookback duration") var err error - nodeTime, bootTime, err = getNodeTime() + + nodeTime = time.Now() + bootTime, err = util.GetBootTime() Expect(err).To(BeNil()) + // Set lookback duration longer than node up time. // Assume the test won't take more than 1 hour, in fact it usually only takes 90 seconds. lookback = nodeTime.Sub(bootTime) + time.Hour @@ -387,24 +390,6 @@ func injectLog(file string, timestamp time.Time, log string, num int) error { return nil } -// getNodeTime gets node boot time and current time. -func getNodeTime() (time.Time, time.Time, error) { - // Get node current time. - nodeTime := time.Now() - - // Get system uptime. - var info syscall.Sysinfo_t - if err := syscall.Sysinfo(&info); err != nil { - return time.Time{}, time.Time{}, err - } - // Get node boot time. NOTE that because we get node current time before uptime, the boot time - // calculated will be a little earlier than the real boot time. This won't affect the correctness - // of the test result. - bootTime := nodeTime.Add(-time.Duration(info.Uptime) * time.Second) - - return nodeTime, bootTime, nil -} - // verifyEvents verifies there are num specific events generated func verifyEvents(e coreclientset.EventInterface, options metav1.ListOptions, num int, reason, message string) error { events, err := e.List(options) diff --git a/test/fixtures/doc-yaml/admin/daemon.yaml b/test/fixtures/doc-yaml/admin/daemon.yaml index c5cd14a5921..c7a5547c761 100644 --- a/test/fixtures/doc-yaml/admin/daemon.yaml +++ b/test/fixtures/doc-yaml/admin/daemon.yaml @@ -1,8 +1,11 @@ -apiVersion: extensions/v1beta1 +apiVersion: apps/v1 kind: DaemonSet metadata: name: prometheus-node-exporter spec: + selector: + matchLabels: + daemon: prom-node-exp template: metadata: name: prometheus-node-exporter diff --git a/test/fixtures/doc-yaml/user-guide/deployment.yaml b/test/fixtures/doc-yaml/user-guide/deployment.yaml index 98e614ceb2e..f6a90428b61 100644 --- a/test/fixtures/doc-yaml/user-guide/deployment.yaml +++ b/test/fixtures/doc-yaml/user-guide/deployment.yaml @@ -1,4 +1,4 @@ -apiVersion: extensions/v1beta1 +apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment diff --git a/test/fixtures/doc-yaml/user-guide/replicaset/redis-slave.yaml b/test/fixtures/doc-yaml/user-guide/replicaset/redis-slave.yaml index 5c470d2ef6a..ca2f826f86d 100644 --- a/test/fixtures/doc-yaml/user-guide/replicaset/redis-slave.yaml +++ b/test/fixtures/doc-yaml/user-guide/replicaset/redis-slave.yaml @@ -1,23 +1,20 @@ -apiVersion: extensions/v1beta1 +apiVersion: apps/v1 kind: ReplicaSet metadata: name: redis-slave - # these labels can be applied automatically - # from the labels in the pod template if not set - # labels: - # app: redis - # role: slave - # tier: backend + labels: + app: redis + role: slave + tier: backend spec: # this replicas value is default # modify it according to your case replicas: 2 - # selector can be applied automatically - # from the labels in the pod template if not set - # selector: - # app: guestbook - # role: slave - # tier: backend + selector: + matchLabels: + app: redis + role: slave + tier: backend template: metadata: labels: diff --git a/test/fixtures/pkg/kubectl/cmd/apply/deploy-clientside.yaml b/test/fixtures/pkg/kubectl/cmd/apply/deploy-clientside.yaml index b3aa9071c4b..4261fb09b96 100644 --- a/test/fixtures/pkg/kubectl/cmd/apply/deploy-clientside.yaml +++ b/test/fixtures/pkg/kubectl/cmd/apply/deploy-clientside.yaml @@ -1,8 +1,13 @@ -apiVersion: extensions/v1beta1 +apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment + labels: + name: nginx spec: + selector: + matchLabels: + name: nginx strategy: type: Recreate rollingUpdate: null diff --git a/test/fixtures/pkg/kubectl/cmd/apply/deploy-serverside.yaml b/test/fixtures/pkg/kubectl/cmd/apply/deploy-serverside.yaml index 566b18ab2c8..664b87fd770 100644 --- a/test/fixtures/pkg/kubectl/cmd/apply/deploy-serverside.yaml +++ b/test/fixtures/pkg/kubectl/cmd/apply/deploy-serverside.yaml @@ -1,9 +1,9 @@ -apiVersion: extensions/v1beta1 +apiVersion: apps/v1 kind: Deployment metadata: annotations: deployment.kubernetes.io/revision: "1" - kubectl.kubernetes.io/last-applied-configuration: '{"kind":"Deployment","apiVersion":"extensions/v1beta1","metadata":{"name":"nginx-deployment","creationTimestamp":null},"spec":{"template":{"metadata":{"creationTimestamp":null,"labels":{"name":"nginx"}},"spec":{"containers":[{"name":"nginx","image":"nginx","resources":{}}]}},"strategy":{}},"status":{}}' + kubectl.kubernetes.io/last-applied-configuration: '{"kind":"Deployment","apiVersion":"apps/v1","metadata":{"name":"nginx-deployment","creationTimestamp":null,"labels":{"name":"nginx"}},"spec":{"selector":{"matchLabels":{"name":"nginx"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"name":"nginx"}},"spec":{"containers":[{"name":"nginx","image":"nginx","resources":{}}]}},"strategy":{}},"status":{}}' creationTimestamp: "2016-10-24T22:15:06Z" generation: 6 labels: diff --git a/test/fixtures/pkg/kubectl/cmd/convert/v1HPA.yaml b/test/fixtures/pkg/kubectl/cmd/convert/v1HPA.yaml index de7efbde371..f3f1ef5d4f9 100644 --- a/test/fixtures/pkg/kubectl/cmd/convert/v1HPA.yaml +++ b/test/fixtures/pkg/kubectl/cmd/convert/v1HPA.yaml @@ -4,7 +4,7 @@ metadata: name: php-apache spec: scaleTargetRef: - apiVersion: apps/v1beta1 + apiVersion: apps/v1 kind: Deployment name: php-apache minReplicas: 1 diff --git a/test/fixtures/pkg/kubectl/cmd/convert/v2beta1HPA.yaml b/test/fixtures/pkg/kubectl/cmd/convert/v2beta1HPA.yaml index 8247b24dcd2..88a5dc7001a 100644 --- a/test/fixtures/pkg/kubectl/cmd/convert/v2beta1HPA.yaml +++ b/test/fixtures/pkg/kubectl/cmd/convert/v2beta1HPA.yaml @@ -4,7 +4,7 @@ metadata: name: php-apache spec: scaleTargetRef: - apiVersion: apps/v1beta1 + apiVersion: apps/v1 kind: Deployment name: php-apache minReplicas: 1 diff --git a/test/images/Makefile b/test/images/Makefile index 089c2696de9..977889533b9 100644 --- a/test/images/Makefile +++ b/test/images/Makefile @@ -17,7 +17,7 @@ include ../../hack/make-rules/Makefile.manifest REGISTRY ?= gcr.io/kubernetes-e2e-test-images GOARM=7 QEMUVERSION=v2.9.1 -GOLANG_VERSION=1.11.2 +GOLANG_VERSION=1.11.4 export ifndef WHAT diff --git a/test/images/apparmor-loader/example-daemon.yaml b/test/images/apparmor-loader/example-daemon.yaml index f7df03804b4..7a558a480f2 100644 --- a/test/images/apparmor-loader/example-daemon.yaml +++ b/test/images/apparmor-loader/example-daemon.yaml @@ -1,13 +1,18 @@ # The example DaemonSet demonstrating how the profile loader can be deployed onto a cluster to # automatically load AppArmor profiles from a ConfigMap. -apiVersion: extensions/v1beta1 +apiVersion: apps/v1 kind: DaemonSet metadata: name: apparmor-loader # Namespace must match that of the ConfigMap. namespace: apparmor + labels: + daemon: apparmor-loader spec: + selector: + matchLabels: + daemon: apparmor-loader template: metadata: name: apparmor-loader diff --git a/test/images/metadata-concealment/VERSION b/test/images/metadata-concealment/VERSION index 524cb55242b..5625e59da88 100644 --- a/test/images/metadata-concealment/VERSION +++ b/test/images/metadata-concealment/VERSION @@ -1 +1 @@ -1.1.1 +1.2 diff --git a/test/images/metadata-concealment/check_metadata_concealment.go b/test/images/metadata-concealment/check_metadata_concealment.go index 4749e907ddd..f6e4345cd1c 100644 --- a/test/images/metadata-concealment/check_metadata_concealment.go +++ b/test/images/metadata-concealment/check_metadata_concealment.go @@ -40,9 +40,13 @@ var ( "http://metadata.google.internal/computeMetadata/v1/", // Service account token endpoints. "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token", - // Params that contain 'recursive' as substring. - "http://metadata.google.internal/computeMetadata/v1/instance/?nonrecursive=true", - "http://metadata.google.internal/computeMetadata/v1/instance/?something=other&nonrecursive=true", + // Permitted recursive query to SA endpoint. + "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/?recursive=true", + // Known query params. + "http://metadata.google.internal/computeMetadata/v1/instance/tags?alt=text", + "http://metadata.google.internal/computeMetadata/v1/instance/tags?wait_for_change=false", + "http://metadata.google.internal/computeMetadata/v1/instance/tags?wait_for_change=true&timeout_sec=0", + "http://metadata.google.internal/computeMetadata/v1/instance/tags?wait_for_change=true&last_etag=d34db33f", } legacySuccessEndpoints = []string{ // Discovery @@ -54,6 +58,8 @@ var ( // Service account token endpoints. "http://metadata.google.internal/0.1/meta-data/service-accounts/default/acquire", "http://metadata.google.internal/computeMetadata/v1beta1/instance/service-accounts/default/token", + // Known query params. + "http://metadata.google.internal/0.1/meta-data/service-accounts/default/acquire?scopes", } noKubeEnvEndpoints = []string{ // Check that these don't get a recursive result. @@ -72,10 +78,12 @@ var ( "http://metadata.google.internal/0.1/meta-data/service-accounts/default/identity", "http://metadata.google.internal/computeMetadata/v1beta1/instance/service-accounts/default/identity", "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/identity", - // Recursive. + // Forbidden recursive queries. "http://metadata.google.internal/computeMetadata/v1/instance/?recursive=true", - "http://metadata.google.internal/computeMetadata/v1/instance/?something=other&recursive=true", - "http://metadata.google.internal/computeMetadata/v1/instance/?recursive=true&something=other", + "http://metadata.google.internal/computeMetadata/v1/instance/?%72%65%63%75%72%73%69%76%65=true", // url-encoded + // Unknown query param key. + "http://metadata.google.internal/computeMetadata/v1/instance/?something=else", + "http://metadata.google.internal/computeMetadata/v1/instance/?unknown", // Other. "http://metadata.google.internal/computeMetadata/v1/instance/attributes//kube-env", "http://metadata.google.internal/computeMetadata/v1/instance/attributes/../attributes/kube-env", @@ -96,7 +104,7 @@ func main() { } } for _, e := range noKubeEnvEndpoints { - if err := checkURL(e, h, 200, "", "kube-env"); err != nil { + if err := checkURL(e, h, 403, "", "kube-env"); err != nil { log.Printf("Wrong response for %v: %v", e, err) success = 1 } diff --git a/test/integration/apiserver/BUILD b/test/integration/apiserver/BUILD index 165b8181010..39754df01d3 100644 --- a/test/integration/apiserver/BUILD +++ b/test/integration/apiserver/BUILD @@ -27,10 +27,10 @@ go_test( "//pkg/master:go_default_library", "//pkg/printers:go_default_library", "//pkg/printers/internalversion:go_default_library", + "//staging/src/k8s.io/api/apps/v1:go_default_library", "//staging/src/k8s.io/api/auditregistration/v1alpha1:go_default_library", "//staging/src/k8s.io/api/batch/v2alpha1:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library", - "//staging/src/k8s.io/api/extensions/v1beta1:go_default_library", "//staging/src/k8s.io/api/rbac/v1alpha1:go_default_library", "//staging/src/k8s.io/api/scheduling/v1beta1:go_default_library", "//staging/src/k8s.io/api/settings/v1alpha1:go_default_library", diff --git a/test/integration/apiserver/apiserver_test.go b/test/integration/apiserver/apiserver_test.go index 19d90e35149..48fbcdbd0ed 100644 --- a/test/integration/apiserver/apiserver_test.go +++ b/test/integration/apiserver/apiserver_test.go @@ -26,8 +26,8 @@ import ( "reflect" "testing" + apps "k8s.io/api/apps/v1" "k8s.io/api/core/v1" - "k8s.io/api/extensions/v1beta1" "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -87,17 +87,18 @@ func path(resource, namespace, name string) string { return testapi.Extensions.ResourcePath(resource, namespace, name) } -func newRS(namespace string) *v1beta1.ReplicaSet { - return &v1beta1.ReplicaSet{ +func newRS(namespace string) *apps.ReplicaSet { + return &apps.ReplicaSet{ TypeMeta: metav1.TypeMeta{ Kind: "ReplicaSet", - APIVersion: "extensions/v1beta1", + APIVersion: "apps/v1", }, ObjectMeta: metav1.ObjectMeta{ Namespace: namespace, GenerateName: "apiserver-test", }, - Spec: v1beta1.ReplicaSetSpec{ + Spec: apps.ReplicaSetSpec{ + Selector: &metav1.LabelSelector{MatchLabels: map[string]string{"name": "test"}}, Template: v1.PodTemplateSpec{ ObjectMeta: metav1.ObjectMeta{ Labels: map[string]string{"name": "test"}, @@ -131,7 +132,7 @@ func Test202StatusCode(t *testing.T) { ns := framework.CreateTestingNamespace("status-code", s, t) defer framework.DeleteTestingNamespace(ns, s, t) - rsClient := clientSet.ExtensionsV1beta1().ReplicaSets(ns.Name) + rsClient := clientSet.AppsV1().ReplicaSets(ns.Name) // 1. Create the resource without any finalizer and then delete it without setting DeleteOptions. // Verify that server returns 200 in this case. @@ -179,7 +180,7 @@ func TestAPIListChunking(t *testing.T) { ns := framework.CreateTestingNamespace("list-paging", s, t) defer framework.DeleteTestingNamespace(ns, s, t) - rsClient := clientSet.ExtensionsV1beta1().ReplicaSets(ns.Name) + rsClient := clientSet.AppsV1().ReplicaSets(ns.Name) for i := 0; i < 4; i++ { rs := newRS(ns.Name) @@ -228,7 +229,7 @@ func TestAPIListChunking(t *testing.T) { } var names []string if err := meta.EachListItem(listObj, func(obj runtime.Object) error { - rs := obj.(*v1beta1.ReplicaSet) + rs := obj.(*apps.ReplicaSet) names = append(names, rs.Name) return nil }); err != nil { diff --git a/test/integration/auth/BUILD b/test/integration/auth/BUILD index fcadaf9217d..cd8db061f9e 100644 --- a/test/integration/auth/BUILD +++ b/test/integration/auth/BUILD @@ -79,7 +79,9 @@ go_test( "//staging/src/k8s.io/apiserver/plugin/pkg/authenticator/token/tokentest:go_default_library", "//staging/src/k8s.io/apiserver/plugin/pkg/authenticator/token/webhook:go_default_library", "//staging/src/k8s.io/client-go/kubernetes:go_default_library", + "//staging/src/k8s.io/client-go/listers/core/v1:go_default_library", "//staging/src/k8s.io/client-go/rest:go_default_library", + "//staging/src/k8s.io/client-go/tools/cache:go_default_library", "//staging/src/k8s.io/client-go/tools/clientcmd/api/v1:go_default_library", "//staging/src/k8s.io/client-go/tools/watch:go_default_library", "//staging/src/k8s.io/client-go/transport:go_default_library", diff --git a/test/integration/auth/svcaccttoken_test.go b/test/integration/auth/svcaccttoken_test.go index 65fcbba58c3..0963ffeea4c 100644 --- a/test/integration/auth/svcaccttoken_test.go +++ b/test/integration/auth/svcaccttoken_test.go @@ -39,6 +39,8 @@ import ( utilfeature "k8s.io/apiserver/pkg/util/feature" utilfeaturetesting "k8s.io/apiserver/pkg/util/feature/testing" clientset "k8s.io/client-go/kubernetes" + v1listers "k8s.io/client-go/listers/core/v1" + "k8s.io/client-go/tools/cache" certutil "k8s.io/client-go/util/cert" "k8s.io/kubernetes/pkg/apis/core" serviceaccountgetter "k8s.io/kubernetes/pkg/controller/serviceaccount" @@ -83,7 +85,18 @@ func TestServiceAccountTokenCreate(t *testing.T) { iss, []interface{}{&pk}, aud, - serviceaccount.NewValidator(serviceaccountgetter.NewGetterFromClient(gcs)), + serviceaccount.NewValidator(serviceaccountgetter.NewGetterFromClient( + gcs, + v1listers.NewSecretLister(newIndexer(func(namespace, name string) (interface{}, error) { + return gcs.CoreV1().Secrets(namespace).Get(name, metav1.GetOptions{}) + })), + v1listers.NewServiceAccountLister(newIndexer(func(namespace, name string) (interface{}, error) { + return gcs.CoreV1().ServiceAccounts(namespace).Get(name, metav1.GetOptions{}) + })), + v1listers.NewPodLister(newIndexer(func(namespace, name string) (interface{}, error) { + return gcs.CoreV1().Pods(namespace).Get(name, metav1.GetOptions{}) + })), + )), ), ) tokenGenerator, err := serviceaccount.JWTTokenGenerator(iss, sk) @@ -683,3 +696,23 @@ func createDeleteSecret(t *testing.T, cs clientset.Interface, sec *v1.Secret) (* } } } + +func newIndexer(get func(namespace, name string) (interface{}, error)) cache.Indexer { + return &fakeIndexer{get: get} +} + +type fakeIndexer struct { + cache.Indexer + get func(namespace, name string) (interface{}, error) +} + +func (f *fakeIndexer) GetByKey(key string) (interface{}, bool, error) { + parts := strings.SplitN(key, "/", 2) + namespace := parts[0] + name := "" + if len(parts) == 2 { + name = parts[1] + } + obj, err := f.get(namespace, name) + return obj, err == nil, err +} diff --git a/test/integration/daemonset/daemonset_test.go b/test/integration/daemonset/daemonset_test.go index f73cbe93a9b..7b686906deb 100644 --- a/test/integration/daemonset/daemonset_test.go +++ b/test/integration/daemonset/daemonset_test.go @@ -112,7 +112,6 @@ func setupScheduler( PdbInformer: informerFactory.Policy().V1beta1().PodDisruptionBudgets(), StorageClassInformer: informerFactory.Storage().V1().StorageClasses(), HardPodAffinitySymmetricWeight: v1.DefaultHardPodAffinitySymmetricWeight, - EnableEquivalenceClassCache: false, DisablePreemption: false, PercentageOfNodesToScore: 100, }) @@ -279,7 +278,7 @@ func newNode(name string, label map[string]string) *v1.Node { ObjectMeta: metav1.ObjectMeta{ Name: name, Labels: label, - Namespace: metav1.NamespaceDefault, + Namespace: metav1.NamespaceNone, }, Status: v1.NodeStatus{ Conditions: []v1.NodeCondition{{Type: v1.NodeReady, Status: v1.ConditionTrue}}, diff --git a/test/integration/deployment/deployment_test.go b/test/integration/deployment/deployment_test.go index 6d0190e3f13..86d5aeeaa69 100644 --- a/test/integration/deployment/deployment_test.go +++ b/test/integration/deployment/deployment_test.go @@ -109,7 +109,9 @@ func TestNewDeployment(t *testing.T) { } } -// Deployments should support roll out, roll back, and roll over +// Deployments should support roll out, roll back, and roll over. +// TODO: drop the rollback portions of this test when extensions/v1beta1 is no longer served +// and rollback endpoint is no longer supported. func TestDeploymentRollingUpdate(t *testing.T) { s, closeFn, rm, dc, informers, c := dcSetup(t) defer closeFn() @@ -239,6 +241,7 @@ func TestDeploymentSelectorImmutability(t *testing.T) { } // test to ensure extensions/v1beta1 selector is mutable + // TODO: drop the extensions/v1beta1 portion of this test when extensions/v1beta1 is no longer served newSelectorLabels := map[string]string{"name_extensions_v1beta1": "test_extensions_v1beta1"} deploymentExtensionsV1beta1, err := c.ExtensionsV1beta1().Deployments(ns.Name).Get(name, metav1.GetOptions{}) if err != nil { @@ -553,6 +556,7 @@ func TestDeploymentHashCollision(t *testing.T) { } // Deployment supports rollback even when there's old replica set without revision. +// TODO: drop this test when extensions/v1beta1 is no longer served func TestRollbackDeploymentRSNoRevision(t *testing.T) { s, closeFn, rm, dc, informers, c := dcSetup(t) defer closeFn() @@ -1252,12 +1256,12 @@ func TestGeneralReplicaSetAdoption(t *testing.T) { // with Controller=false, the deployment should add a second OwnerReference (ControllerRef) pointing to itself // with Controller=true var falseVar = false - ownerReference := metav1.OwnerReference{UID: uuid.NewUUID(), APIVersion: "apps/v1beta1", Kind: "StatefulSet", Name: deploymentName, Controller: &falseVar} + ownerReference := metav1.OwnerReference{UID: uuid.NewUUID(), APIVersion: "apps/v1", Kind: "StatefulSet", Name: deploymentName, Controller: &falseVar} testRSControllerRefPatch(t, tester, rs, &ownerReference, 2) // When the only OwnerReference of the RS points to the deployment with Controller=false, // the deployment should set Controller=true for the only OwnerReference - ownerReference = metav1.OwnerReference{UID: tester.deployment.UID, APIVersion: "extensions/v1beta1", Kind: "Deployment", Name: deploymentName, Controller: &falseVar} + ownerReference = metav1.OwnerReference{UID: tester.deployment.UID, APIVersion: "apps/v1", Kind: "Deployment", Name: deploymentName, Controller: &falseVar} testRSControllerRefPatch(t, tester, rs, &ownerReference, 1) } diff --git a/test/integration/deployment/util.go b/test/integration/deployment/util.go index 3dd73425ff8..dc2b3a13f1c 100644 --- a/test/integration/deployment/util.go +++ b/test/integration/deployment/util.go @@ -105,7 +105,7 @@ func newReplicaSet(name, ns string, replicas int32) *apps.ReplicaSet { return &apps.ReplicaSet{ TypeMeta: metav1.TypeMeta{ Kind: "ReplicaSet", - APIVersion: "extensions/v1beta1", + APIVersion: "apps/v1", }, ObjectMeta: metav1.ObjectMeta{ Namespace: ns, diff --git a/test/integration/etcd/data.go b/test/integration/etcd/data.go index 686b704634a..201c4efdc54 100644 --- a/test/integration/etcd/data.go +++ b/test/integration/etcd/data.go @@ -211,10 +211,18 @@ func GetEtcdStorageData() map[schema.GroupVersionResource]StorageData { }, // -- + // k8s.io/kubernetes/pkg/apis/coordination/v1 + gvr("coordination.k8s.io", "v1", "leases"): { + Stub: `{"metadata": {"name": "leasev1"}, "spec": {"holderIdentity": "holder", "leaseDurationSeconds": 5}}`, + ExpectedEtcdPath: "/registry/leases/etcdstoragepathtestnamespace/leasev1", + ExpectedGVK: gvkP("coordination.k8s.io", "v1beta1", "Lease"), + }, + // -- + // k8s.io/kubernetes/pkg/apis/coordination/v1beta1 gvr("coordination.k8s.io", "v1beta1", "leases"): { - Stub: `{"metadata": {"name": "lease1"}, "spec": {"holderIdentity": "holder", "leaseDurationSeconds": 5}}`, - ExpectedEtcdPath: "/registry/leases/etcdstoragepathtestnamespace/lease1", + Stub: `{"metadata": {"name": "leasev1beta1"}, "spec": {"holderIdentity": "holder", "leaseDurationSeconds": 5}}`, + ExpectedEtcdPath: "/registry/leases/etcdstoragepathtestnamespace/leasev1beta1", }, // -- diff --git a/test/integration/etcd/server.go b/test/integration/etcd/server.go index d86534ba292..8c433618014 100644 --- a/test/integration/etcd/server.go +++ b/test/integration/etcd/server.go @@ -74,7 +74,7 @@ func StartRealMasterOrDie(t *testing.T) *Master { kubeAPIServerOptions.InsecureServing.BindPort = 0 kubeAPIServerOptions.SecureServing.Listener = listener kubeAPIServerOptions.SecureServing.ServerCert.CertDirectory = certDir - kubeAPIServerOptions.Etcd.StorageConfig.ServerList = []string{framework.GetEtcdURL()} + kubeAPIServerOptions.Etcd.StorageConfig.Transport.ServerList = []string{framework.GetEtcdURL()} kubeAPIServerOptions.Etcd.DefaultStorageMediaType = runtime.ContentTypeJSON // force json we can easily interpret the result in etcd kubeAPIServerOptions.ServiceClusterIPRange = *defaultServiceClusterIPRange kubeAPIServerOptions.Authorization.Modes = []string{"RBAC"} @@ -88,7 +88,7 @@ func StartRealMasterOrDie(t *testing.T) *Master { } // get etcd client before starting API server - rawClient, kvClient, err := integration.GetEtcdClients(completedOptions.Etcd.StorageConfig) + rawClient, kvClient, err := integration.GetEtcdClients(completedOptions.Etcd.StorageConfig.Transport) if err != nil { t.Fatal(err) } diff --git a/test/integration/evictions/evictions_test.go b/test/integration/evictions/evictions_test.go index 4a88a07181e..640e285da52 100644 --- a/test/integration/evictions/evictions_test.go +++ b/test/integration/evictions/evictions_test.go @@ -86,7 +86,7 @@ func TestConcurrentEvictionRequests(t *testing.T) { } } - waitToObservePods(t, informers.Core().V1().Pods().Informer(), numOfEvictions) + waitToObservePods(t, informers.Core().V1().Pods().Informer(), numOfEvictions, v1.PodRunning) pdb := newPDB() if _, err := clientSet.Policy().PodDisruptionBudgets(ns.Name).Create(pdb); err != nil { @@ -193,18 +193,21 @@ func TestTerminalPodEviction(t *testing.T) { if _, err := clientSet.CoreV1().Pods(ns.Name).Create(pod); err != nil { t.Errorf("Failed to create pod: %v", err) } + addPodConditionSucceeded(pod) if _, err := clientSet.CoreV1().Pods(ns.Name).UpdateStatus(pod); err != nil { t.Fatal(err) } - waitToObservePods(t, informers.Core().V1().Pods().Informer(), 1) + waitToObservePods(t, informers.Core().V1().Pods().Informer(), 1, v1.PodSucceeded) pdb := newPDB() if _, err := clientSet.Policy().PodDisruptionBudgets(ns.Name).Create(pdb); err != nil { t.Errorf("Failed to create PodDisruptionBudget: %v", err) } + waitPDBStable(t, clientSet, 1, ns.Name, pdb.Name) + pdbList, err := clientSet.Policy().PodDisruptionBudgets(ns.Name).List(metav1.ListOptions{}) if err != nil { t.Fatalf("Error while listing pod disruption budget") @@ -330,9 +333,9 @@ func rmSetup(t *testing.T) (*httptest.Server, framework.CloseFunc, *disruption.D informers.Core().V1().Pods(), informers.Policy().V1beta1().PodDisruptionBudgets(), informers.Core().V1().ReplicationControllers(), - informers.Extensions().V1beta1().ReplicaSets(), - informers.Extensions().V1beta1().Deployments(), - informers.Apps().V1beta1().StatefulSets(), + informers.Apps().V1().ReplicaSets(), + informers.Apps().V1().Deployments(), + informers.Apps().V1().StatefulSets(), clientset.NewForConfigOrDie(restclient.AddUserAgent(&config, "disruption-controller")), ) return s, closeFn, rm, informers, clientSet @@ -341,13 +344,19 @@ func rmSetup(t *testing.T) (*httptest.Server, framework.CloseFunc, *disruption.D // wait for the podInformer to observe the pods. Call this function before // running the RS controller to prevent the rc manager from creating new pods // rather than adopting the existing ones. -func waitToObservePods(t *testing.T, podInformer cache.SharedIndexInformer, podNum int) { +func waitToObservePods(t *testing.T, podInformer cache.SharedIndexInformer, podNum int, phase v1.PodPhase) { if err := wait.PollImmediate(2*time.Second, 60*time.Second, func() (bool, error) { objects := podInformer.GetIndexer().List() - if len(objects) == podNum { - return true, nil + if len(objects) != podNum { + return false, nil } - return false, nil + for _, obj := range objects { + pod := obj.(*v1.Pod) + if pod.Status.Phase != phase { + return false, nil + } + } + return true, nil }); err != nil { t.Fatal(err) } diff --git a/test/integration/examples/apiserver_test.go b/test/integration/examples/apiserver_test.go index 994a304bf25..e5119fd6bed 100644 --- a/test/integration/examples/apiserver_test.go +++ b/test/integration/examples/apiserver_test.go @@ -98,7 +98,7 @@ func TestAggregatedAPIServer(t *testing.T) { kubeAPIServerOptions.SecureServing.BindAddress = net.ParseIP("127.0.0.1") kubeAPIServerOptions.SecureServing.ServerCert.CertDirectory = certDir kubeAPIServerOptions.InsecureServing.BindPort = 0 - kubeAPIServerOptions.Etcd.StorageConfig.ServerList = []string{framework.GetEtcdURL()} + kubeAPIServerOptions.Etcd.StorageConfig.Transport.ServerList = []string{framework.GetEtcdURL()} kubeAPIServerOptions.ServiceClusterIPRange = *defaultServiceClusterIPRange kubeAPIServerOptions.Authentication.RequestHeader.UsernameHeaders = []string{"X-Remote-User"} kubeAPIServerOptions.Authentication.RequestHeader.GroupHeaders = []string{"X-Remote-Group"} diff --git a/test/integration/examples/setup_test.go b/test/integration/examples/setup_test.go index be388126ed5..3c9f2becb79 100644 --- a/test/integration/examples/setup_test.go +++ b/test/integration/examples/setup_test.go @@ -89,7 +89,7 @@ func startTestServer(t *testing.T, stopCh <-chan struct{}, setup TestServerSetup kubeAPIServerOptions.SecureServing.ServerCert.CertDirectory = certDir kubeAPIServerOptions.InsecureServing.BindPort = 0 kubeAPIServerOptions.Etcd.StorageConfig.Prefix = path.Join("/", uuid.New(), "registry") - kubeAPIServerOptions.Etcd.StorageConfig.ServerList = []string{framework.GetEtcdURL()} + kubeAPIServerOptions.Etcd.StorageConfig.Transport.ServerList = []string{framework.GetEtcdURL()} kubeAPIServerOptions.ServiceClusterIPRange = *defaultServiceClusterIPRange kubeAPIServerOptions.Authentication.RequestHeader.UsernameHeaders = []string{"X-Remote-User"} kubeAPIServerOptions.Authentication.RequestHeader.GroupHeaders = []string{"X-Remote-Group"} diff --git a/test/integration/framework/etcd.go b/test/integration/framework/etcd.go index 18ae79904d5..5756c3e6a4c 100644 --- a/test/integration/framework/etcd.go +++ b/test/integration/framework/etcd.go @@ -106,6 +106,8 @@ func startEtcd() (func(), error) { GetEtcdURL(), "--listen-peer-urls", "http://127.0.0.1:0", + "--log-package-levels", + "*=DEBUG", ) cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr diff --git a/test/integration/framework/master_utils.go b/test/integration/framework/master_utils.go index b8b4bbd24bd..78e46c89f41 100644 --- a/test/integration/framework/master_utils.go +++ b/test/integration/framework/master_utils.go @@ -17,10 +17,12 @@ limitations under the License. package framework import ( + "flag" "net" "net/http" "net/http/httptest" "path" + "strconv" "time" "github.com/go-openapi/spec" @@ -130,6 +132,13 @@ func startMasterOrDie(masterConfig *master.Config, incomingServer *httptest.Serv var m *master.Master var s *httptest.Server + // Ensure we log at least level 4 + v := flag.Lookup("v").Value + level, _ := strconv.Atoi(v.String()) + if level < 4 { + v.Set("4") + } + if incomingServer != nil { s = incomingServer } else { @@ -248,7 +257,7 @@ func NewMasterConfig() *master.Config { // prefix code, so please don't change without ensuring // sufficient coverage in other ways. etcdOptions := options.NewEtcdOptions(storagebackend.NewDefaultConfig(uuid.New(), nil)) - etcdOptions.StorageConfig.ServerList = []string{GetEtcdURL()} + etcdOptions.StorageConfig.Transport.ServerList = []string{GetEtcdURL()} info, _ := runtime.SerializerInfoForMediaType(legacyscheme.Codecs.SupportedMediaTypes(), runtime.ContentTypeJSON) ns := NewSingleContentTypeSerializer(legacyscheme.Scheme, info) @@ -347,7 +356,7 @@ func RunAMasterUsingServer(masterConfig *master.Config, s *httptest.Server, mast // SharedEtcd creates a storage config for a shared etcd instance, with a unique prefix. func SharedEtcd() *storagebackend.Config { cfg := storagebackend.NewDefaultConfig(path.Join(uuid.New(), "registry"), nil) - cfg.ServerList = []string{GetEtcdURL()} + cfg.Transport.ServerList = []string{GetEtcdURL()} return cfg } diff --git a/test/integration/ipamperf/BUILD b/test/integration/ipamperf/BUILD index 52b0889b6a7..e26a4c4e076 100644 --- a/test/integration/ipamperf/BUILD +++ b/test/integration/ipamperf/BUILD @@ -47,8 +47,6 @@ go_library( ], importpath = "k8s.io/kubernetes/test/integration/ipamperf", deps = [ - "//pkg/cloudprovider/providers/gce/cloud:go_default_library", - "//pkg/cloudprovider/providers/gce/cloud/meta:go_default_library", "//pkg/controller/nodeipam/ipam:go_default_library", "//pkg/controller/nodeipam/ipam/cidrset:go_default_library", "//pkg/controller/util/node:go_default_library", @@ -63,6 +61,8 @@ go_library( "//staging/src/k8s.io/client-go/tools/cache:go_default_library", "//staging/src/k8s.io/cloud-provider:go_default_library", "//test/integration/util:go_default_library", + "//vendor/github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud:go_default_library", + "//vendor/github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/meta:go_default_library", "//vendor/google.golang.org/api/compute/v0.beta:go_default_library", "//vendor/google.golang.org/api/compute/v1:go_default_library", "//vendor/k8s.io/klog:go_default_library", diff --git a/test/integration/ipamperf/cloud.go b/test/integration/ipamperf/cloud.go index c7cb10ec10f..63c4681ee1b 100644 --- a/test/integration/ipamperf/cloud.go +++ b/test/integration/ipamperf/cloud.go @@ -21,10 +21,10 @@ import ( "net" "sync" + "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud" + "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/meta" beta "google.golang.org/api/compute/v0.beta" ga "google.golang.org/api/compute/v1" - "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud" - "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta" "k8s.io/kubernetes/pkg/controller/nodeipam/ipam/cidrset" "k8s.io/kubernetes/test/integration/util" ) diff --git a/test/integration/master/BUILD b/test/integration/master/BUILD index bb7c8cc979b..9355baf1113 100644 --- a/test/integration/master/BUILD +++ b/test/integration/master/BUILD @@ -22,7 +22,6 @@ go_test( tags = ["integration"], deps = [ "//cmd/kube-apiserver/app/testing:go_default_library", - "//pkg/api/testapi:go_default_library", "//pkg/apis/core:go_default_library", "//pkg/client/clientset_generated/internalclientset:go_default_library", "//pkg/master:go_default_library", diff --git a/test/integration/master/synthetic_master_test.go b/test/integration/master/synthetic_master_test.go index de3f9f29333..d40b98e3cad 100644 --- a/test/integration/master/synthetic_master_test.go +++ b/test/integration/master/synthetic_master_test.go @@ -24,6 +24,7 @@ import ( "net" "net/http" "os" + "path" "strconv" "strings" "sync" @@ -47,7 +48,6 @@ import ( clientsetv1 "k8s.io/client-go/kubernetes" clienttypedv1 "k8s.io/client-go/kubernetes/typed/core/v1" restclient "k8s.io/client-go/rest" - "k8s.io/kubernetes/pkg/api/testapi" api "k8s.io/kubernetes/pkg/apis/core" clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" "k8s.io/kubernetes/pkg/master" @@ -298,7 +298,7 @@ func TestObjectSizeResponses(t *testing.T) { _, s, closeFn := framework.RunAMaster(nil) defer closeFn() - client := clientsetv1.NewForConfigOrDie(&restclient.Config{Host: s.URL, ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Groups[api.GroupName].GroupVersion()}}) + client := clientsetv1.NewForConfigOrDie(&restclient.Config{Host: s.URL}) const DeploymentMegabyteSize = 100000 const DeploymentTwoMegabyteSize = 1000000 @@ -403,7 +403,7 @@ var deploymentExtensions string = ` var deploymentApps string = ` { - "apiVersion": "apps/v1beta1", + "apiVersion": "apps/v1", "kind": "Deployment", "metadata": { "name": "test-deployment2", @@ -411,6 +411,11 @@ var deploymentApps string = ` }, "spec": { "replicas": 1, + "selector": { + "matchLabels": { + "app": "nginx0" + } + }, "template": { "metadata": { "labels": { @@ -429,19 +434,31 @@ var deploymentApps string = ` ` func autoscalingPath(resource, namespace, name string) string { - return testapi.Autoscaling.ResourcePath(resource, namespace, name) + if namespace != "" { + namespace = path.Join("namespaces", namespace) + } + return path.Join("/apis/autoscaling/v1", namespace, resource, name) } func batchPath(resource, namespace, name string) string { - return testapi.Batch.ResourcePath(resource, namespace, name) + if namespace != "" { + namespace = path.Join("namespaces", namespace) + } + return path.Join("/apis/batch/v1", namespace, resource, name) } func extensionsPath(resource, namespace, name string) string { - return testapi.Extensions.ResourcePath(resource, namespace, name) + if namespace != "" { + namespace = path.Join("namespaces", namespace) + } + return path.Join("/apis/extensions/v1beta1", namespace, resource, name) } func appsPath(resource, namespace, name string) string { - return testapi.Apps.ResourcePath(resource, namespace, name) + if namespace != "" { + namespace = path.Join("namespaces", namespace) + } + return path.Join("/apis/apps/v1", namespace, resource, name) } func TestAutoscalingGroupBackwardCompatibility(t *testing.T) { @@ -457,7 +474,7 @@ func TestAutoscalingGroupBackwardCompatibility(t *testing.T) { expectedVersion string }{ {"POST", autoscalingPath("horizontalpodautoscalers", metav1.NamespaceDefault, ""), hpaV1, integration.Code201, ""}, - {"GET", autoscalingPath("horizontalpodautoscalers", metav1.NamespaceDefault, ""), "", integration.Code200, testapi.Autoscaling.GroupVersion().String()}, + {"GET", autoscalingPath("horizontalpodautoscalers", metav1.NamespaceDefault, ""), "", integration.Code200, "autoscaling/v1"}, } for _, r := range requests { @@ -503,14 +520,15 @@ func TestAppsGroupBackwardCompatibility(t *testing.T) { }{ // Post to extensions endpoint and get back from both: extensions and apps {"POST", extensionsPath("deployments", metav1.NamespaceDefault, ""), deploymentExtensions, integration.Code201, ""}, - {"GET", extensionsPath("deployments", metav1.NamespaceDefault, "test-deployment1"), "", integration.Code200, testapi.Extensions.GroupVersion().String()}, - {"GET", appsPath("deployments", metav1.NamespaceDefault, "test-deployment1"), "", integration.Code200, testapi.Apps.GroupVersion().String()}, - {"DELETE", extensionsPath("deployments", metav1.NamespaceDefault, "test-deployment1"), "", integration.Code200, testapi.Extensions.GroupVersion().String()}, + {"GET", extensionsPath("deployments", metav1.NamespaceDefault, "test-deployment1"), "", integration.Code200, "extensions/v1beta1"}, + {"GET", appsPath("deployments", metav1.NamespaceDefault, "test-deployment1"), "", integration.Code200, "apps/v1"}, + {"DELETE", extensionsPath("deployments", metav1.NamespaceDefault, "test-deployment1"), "", integration.Code200, "extensions/v1beta1"}, // Post to apps endpoint and get back from both: apps and extensions {"POST", appsPath("deployments", metav1.NamespaceDefault, ""), deploymentApps, integration.Code201, ""}, - {"GET", appsPath("deployments", metav1.NamespaceDefault, "test-deployment2"), "", integration.Code200, testapi.Apps.GroupVersion().String()}, - {"GET", extensionsPath("deployments", metav1.NamespaceDefault, "test-deployment2"), "", integration.Code200, testapi.Extensions.GroupVersion().String()}, - {"DELETE", appsPath("deployments", metav1.NamespaceDefault, "test-deployment2"), "", integration.Code200, testapi.Apps.GroupVersion().String()}, + {"GET", appsPath("deployments", metav1.NamespaceDefault, "test-deployment2"), "", integration.Code200, "apps/v1"}, + {"GET", extensionsPath("deployments", metav1.NamespaceDefault, "test-deployment2"), "", integration.Code200, "extensions/v1beta1"}, + // set propagationPolicy=Orphan to force the object to be returned so we can check the apiVersion (otherwise, we just get a status object back) + {"DELETE", appsPath("deployments", metav1.NamespaceDefault, "test-deployment2") + "?propagationPolicy=Orphan", "", integration.Code200, "apps/v1"}, } for _, r := range requests { @@ -624,7 +642,7 @@ func TestMasterService(t *testing.T) { _, s, closeFn := framework.RunAMaster(framework.NewIntegrationTestMasterConfig()) defer closeFn() - client := clientset.NewForConfigOrDie(&restclient.Config{Host: s.URL, ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Groups[api.GroupName].GroupVersion()}}) + client := clientset.NewForConfigOrDie(&restclient.Config{Host: s.URL}) err := wait.Poll(time.Second, time.Minute, func() (bool, error) { svcList, err := client.Core().Services(metav1.NamespaceDefault).List(metav1.ListOptions{}) @@ -666,7 +684,7 @@ func TestServiceAlloc(t *testing.T) { _, s, closeFn := framework.RunAMaster(cfg) defer closeFn() - client := clientset.NewForConfigOrDie(&restclient.Config{Host: s.URL, ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Groups[api.GroupName].GroupVersion()}}) + client := clientset.NewForConfigOrDie(&restclient.Config{Host: s.URL}) svc := func(i int) *api.Service { return &api.Service{ diff --git a/test/integration/master/transformation_testcase.go b/test/integration/master/transformation_testcase.go index 3778b514cff..50d5c1ab5bd 100644 --- a/test/integration/master/transformation_testcase.go +++ b/test/integration/master/transformation_testcase.go @@ -228,7 +228,7 @@ func (e *transformTest) createSecret(name, namespace string) (*corev1.Secret, er } func (e *transformTest) readRawRecordFromETCD(path string) (*clientv3.GetResponse, error) { - _, etcdClient, err := integration.GetEtcdClients(e.kubeAPIServer.ServerOpts.Etcd.StorageConfig) + _, etcdClient, err := integration.GetEtcdClients(e.kubeAPIServer.ServerOpts.Etcd.StorageConfig.Transport) if err != nil { return nil, fmt.Errorf("failed to create etcd client: %v", err) } diff --git a/test/integration/replicaset/replicaset_test.go b/test/integration/replicaset/replicaset_test.go index 53854ec0fe1..0a5ae21642b 100644 --- a/test/integration/replicaset/replicaset_test.go +++ b/test/integration/replicaset/replicaset_test.go @@ -335,7 +335,7 @@ func setPodsReadyCondition(t *testing.T, clientSet clientset.Interface, pods *v1 func testScalingUsingScaleSubresource(t *testing.T, c clientset.Interface, rs *apps.ReplicaSet, replicas int32) { ns := rs.Namespace - rsClient := c.ExtensionsV1beta1().ReplicaSets(ns) + rsClient := c.AppsV1().ReplicaSets(ns) newRS, err := rsClient.Get(rs.Name, metav1.GetOptions{}) if err != nil { t.Fatalf("Failed to obtain rs %s: %v", rs.Name, err) @@ -471,6 +471,7 @@ func TestRSSelectorImmutability(t *testing.T) { createRSsPods(t, clientSet, []*apps.ReplicaSet{rs}, []*v1.Pod{}) // test to ensure extensions/v1beta1 selector is mutable + // TODO: remove the extensions/v1beta1 portion of the test once we stop serving extensions/v1beta1 newSelectorLabels := map[string]string{"changed_name_extensions_v1beta1": "changed_test_extensions_v1beta1"} rsExt, err := clientSet.ExtensionsV1beta1().ReplicaSets(ns.Name).Get(rs.Name, metav1.GetOptions{}) if err != nil { @@ -637,7 +638,7 @@ func TestOverlappingRSs(t *testing.T) { // Expect both RSs have .status.replicas = .spec.replicas for i := 0; i < 2; i++ { - newRS, err := c.ExtensionsV1beta1().ReplicaSets(ns.Name).Get(fmt.Sprintf("rs-%d", i+1), metav1.GetOptions{}) + newRS, err := c.AppsV1().ReplicaSets(ns.Name).Get(fmt.Sprintf("rs-%d", i+1), metav1.GetOptions{}) if err != nil { t.Fatalf("failed to obtain rs rs-%d: %v", i+1, err) } @@ -795,7 +796,7 @@ func TestReadyAndAvailableReplicas(t *testing.T) { // by setting LastTransitionTime to more than 3600 seconds ago setPodsReadyCondition(t, c, thirdPodList, v1.ConditionTrue, time.Now().Add(-120*time.Minute)) - rsClient := c.ExtensionsV1beta1().ReplicaSets(ns.Name) + rsClient := c.AppsV1().ReplicaSets(ns.Name) if err := wait.PollImmediate(interval, timeout, func() (bool, error) { newRS, err := rsClient.Get(rs.Name, metav1.GetOptions{}) if err != nil { diff --git a/test/integration/scheduler/BUILD b/test/integration/scheduler/BUILD index bce32d144b5..c9ad35323b8 100644 --- a/test/integration/scheduler/BUILD +++ b/test/integration/scheduler/BUILD @@ -12,6 +12,7 @@ go_test( srcs = [ "extender_test.go", "main_test.go", + "plugin_test.go", "predicates_test.go", "preemption_test.go", "priorities_test.go", @@ -25,18 +26,19 @@ go_test( "//cmd/kube-scheduler/app:go_default_library", "//cmd/kube-scheduler/app/config:go_default_library", "//pkg/api/legacyscheme:go_default_library", + "//pkg/api/v1/pod:go_default_library", "//pkg/controller/nodelifecycle:go_default_library", "//pkg/controller/volume/persistentvolume:go_default_library", "//pkg/controller/volume/persistentvolume/options:go_default_library", "//pkg/features:go_default_library", "//pkg/scheduler:go_default_library", - "//pkg/scheduler/algorithm:go_default_library", "//pkg/scheduler/algorithm/predicates:go_default_library", "//pkg/scheduler/algorithmprovider:go_default_library", "//pkg/scheduler/api:go_default_library", "//pkg/scheduler/apis/config:go_default_library", - "//pkg/scheduler/cache:go_default_library", "//pkg/scheduler/factory:go_default_library", + "//pkg/scheduler/nodeinfo:go_default_library", + "//pkg/scheduler/plugins/v1alpha1:go_default_library", "//pkg/volume:go_default_library", "//pkg/volume/testing:go_default_library", "//plugin/pkg/admission/podtolerationrestriction:go_default_library", @@ -91,11 +93,11 @@ go_library( "//pkg/api/v1/pod:go_default_library", "//pkg/controller:go_default_library", "//pkg/controller/disruption:go_default_library", - "//pkg/features:go_default_library", "//pkg/scheduler:go_default_library", "//pkg/scheduler/algorithmprovider:go_default_library", "//pkg/scheduler/api:go_default_library", "//pkg/scheduler/factory:go_default_library", + "//pkg/scheduler/plugins/v1alpha1:go_default_library", "//pkg/util/taints:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library", "//staging/src/k8s.io/api/policy/v1beta1:go_default_library", @@ -107,8 +109,6 @@ go_library( "//staging/src/k8s.io/apimachinery/pkg/util/uuid:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library", "//staging/src/k8s.io/apiserver/pkg/admission:go_default_library", - "//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library", - "//staging/src/k8s.io/apiserver/pkg/util/feature/testing:go_default_library", "//staging/src/k8s.io/client-go/informers:go_default_library", "//staging/src/k8s.io/client-go/informers/core/v1:go_default_library", "//staging/src/k8s.io/client-go/kubernetes:go_default_library", diff --git a/test/integration/scheduler/plugin_test.go b/test/integration/scheduler/plugin_test.go new file mode 100644 index 00000000000..a2bcba025f5 --- /dev/null +++ b/test/integration/scheduler/plugin_test.go @@ -0,0 +1,269 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package scheduler + +import ( + "fmt" + "testing" + "time" + + "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/util/wait" + plugins "k8s.io/kubernetes/pkg/scheduler/plugins/v1alpha1" +) + +// StatefulMultipointExample is an example plugin that is executed at multiple extension points. +// This plugin is stateful. It receives arguments at initialization (NewMultipointPlugin) +// and changes its state when it is executed. +type TesterPlugin struct { + numReserveCalled int + numPrebindCalled int + failReserve bool + failPrebind bool + rejectPrebind bool +} + +var _ = plugins.ReservePlugin(&TesterPlugin{}) +var _ = plugins.PrebindPlugin(&TesterPlugin{}) + +// Name returns name of the plugin. +func (tp *TesterPlugin) Name() string { + return "tester-plugin" +} + +// Reserve is a test function that returns an error or nil, depending on the +// value of "failReserve". +func (tp *TesterPlugin) Reserve(ps plugins.PluginSet, pod *v1.Pod, nodeName string) error { + tp.numReserveCalled++ + if tp.failReserve { + return fmt.Errorf("injecting failure for pod %v", pod.Name) + } + return nil +} + +// Prebind is a test function that returns (true, nil) or errors for testing. +func (tp *TesterPlugin) Prebind(ps plugins.PluginSet, pod *v1.Pod, nodeName string) (bool, error) { + var err error = nil + tp.numPrebindCalled++ + if tp.failPrebind { + err = fmt.Errorf("injecting failure for pod %v", pod.Name) + } + if tp.rejectPrebind { + return false, err + } + return true, err +} + +// TestPluginSet is a plugin set used for testing purposes. +type TestPluginSet struct { + data *plugins.PluginData + reservePlugins []plugins.ReservePlugin + prebindPlugins []plugins.PrebindPlugin +} + +var _ = plugins.PluginSet(&TestPluginSet{}) + +// ReservePlugins returns a slice of default reserve plugins. +func (r *TestPluginSet) ReservePlugins() []plugins.ReservePlugin { + return r.reservePlugins +} + +// PrebindPlugins returns a slice of default prebind plugins. +func (r *TestPluginSet) PrebindPlugins() []plugins.PrebindPlugin { + return r.prebindPlugins +} + +// Data returns a pointer to PluginData. +func (r *TestPluginSet) Data() *plugins.PluginData { + return r.data +} + +// TestReservePlugin tests invocation of reserve plugins. +func TestReservePlugin(t *testing.T) { + // Create a plugin set for testing. Register only a reserve plugin. + testerPlugin := &TesterPlugin{} + testPluginSet := &TestPluginSet{ + data: &plugins.PluginData{ + Ctx: plugins.NewPluginContext(), + }, + reservePlugins: []plugins.ReservePlugin{testerPlugin}, + } + + // Create the master and the scheduler with the test plugin set. + context := initTestSchedulerWithOptions(t, + initTestMaster(t, "reserve-plugin", nil), + false, nil, testPluginSet, false, time.Second) + defer cleanupTest(t, context) + + cs := context.clientSet + // Add a few nodes. + _, err := createNodes(cs, "test-node", nil, 2) + if err != nil { + t.Fatalf("Cannot create nodes: %v", err) + } + + for _, fail := range []bool{false, true} { + testerPlugin.failReserve = fail + // Create a best effort pod. + pod, err := createPausePod(cs, + initPausePod(cs, &pausePodConfig{Name: "test-pod", Namespace: context.ns.Name})) + if err != nil { + t.Errorf("Error while creating a test pod: %v", err) + } + + if fail { + if err = wait.Poll(10*time.Millisecond, 30*time.Second, podSchedulingError(cs, pod.Namespace, pod.Name)); err != nil { + t.Errorf("Didn't expected the pod to be scheduled. error: %v", err) + } + } else { + if err = waitForPodToSchedule(cs, pod); err != nil { + t.Errorf("Expected the pod to be scheduled. error: %v", err) + } + } + + if testerPlugin.numReserveCalled == 0 { + t.Errorf("Expected the reserve plugin to be called.") + } + + cleanupPods(cs, t, []*v1.Pod{pod}) + } +} + +// TestPrebindPlugin tests invocation of prebind plugins. +func TestPrebindPlugin(t *testing.T) { + // Create a plugin set for testing. Register only a prebind plugin. + testerPlugin := &TesterPlugin{} + testPluginSet := &TestPluginSet{ + data: &plugins.PluginData{ + Ctx: plugins.NewPluginContext(), + }, + prebindPlugins: []plugins.PrebindPlugin{testerPlugin}, + } + + // Create the master and the scheduler with the test plugin set. + context := initTestSchedulerWithOptions(t, + initTestMaster(t, "prebind-plugin", nil), + false, nil, testPluginSet, false, time.Second) + defer cleanupTest(t, context) + + cs := context.clientSet + // Add a few nodes. + _, err := createNodes(cs, "test-node", nil, 2) + if err != nil { + t.Fatalf("Cannot create nodes: %v", err) + } + + tests := []struct { + fail bool + reject bool + }{ + { + fail: false, + reject: false, + }, + { + fail: true, + reject: false, + }, + { + fail: false, + reject: true, + }, + { + fail: true, + reject: true, + }, + } + + for i, test := range tests { + testerPlugin.failPrebind = test.fail + testerPlugin.rejectPrebind = test.reject + // Create a best effort pod. + pod, err := createPausePod(cs, + initPausePod(cs, &pausePodConfig{Name: "test-pod", Namespace: context.ns.Name})) + if err != nil { + t.Errorf("Error while creating a test pod: %v", err) + } + + if test.fail { + if err = wait.Poll(10*time.Millisecond, 30*time.Second, podSchedulingError(cs, pod.Namespace, pod.Name)); err != nil { + t.Errorf("test #%v: Expected a scheduling error, but didn't get it. error: %v", i, err) + } + } else { + if test.reject { + if err = waitForPodUnschedulable(cs, pod); err != nil { + t.Errorf("test #%v: Didn't expected the pod to be scheduled. error: %v", i, err) + } + } else { + if err = waitForPodToSchedule(cs, pod); err != nil { + t.Errorf("test #%v: Expected the pod to be scheduled. error: %v", i, err) + } + } + } + + if testerPlugin.numPrebindCalled == 0 { + t.Errorf("Expected the prebind plugin to be called.") + } + + cleanupPods(cs, t, []*v1.Pod{pod}) + } +} + +// TestContextCleanup tests that data inserted in the pluginContext is removed +// after a scheduling cycle is over. +func TestContextCleanup(t *testing.T) { + // Create a plugin set for testing. + testerPlugin := &TesterPlugin{} + testPluginSet := &TestPluginSet{ + data: &plugins.PluginData{ + Ctx: plugins.NewPluginContext(), + }, + reservePlugins: []plugins.ReservePlugin{testerPlugin}, + prebindPlugins: []plugins.PrebindPlugin{testerPlugin}, + } + + // Create the master and the scheduler with the test plugin set. + context := initTestSchedulerWithOptions(t, + initTestMaster(t, "plugin-context-cleanup", nil), + false, nil, testPluginSet, false, time.Second) + defer cleanupTest(t, context) + + cs := context.clientSet + // Add a few nodes. + _, err := createNodes(cs, "test-node", nil, 2) + if err != nil { + t.Fatalf("Cannot create nodes: %v", err) + } + + // Insert something in the plugin context. + testPluginSet.Data().Ctx.Write("test", "foo") + + // Create and schedule a best effort pod. + pod, err := runPausePod(cs, + initPausePod(cs, &pausePodConfig{Name: "test-pod", Namespace: context.ns.Name})) + if err != nil { + t.Errorf("Error while creating or scheduling a test pod: %v", err) + } + + // Make sure the data inserted in the plugin context is removed. + _, err = testPluginSet.Data().Ctx.Read("test") + if err == nil || err.Error() != plugins.NotFound { + t.Errorf("Expected the plugin context to be cleaned up after a scheduling cycle. error: %v", err) + } + + cleanupPods(cs, t, []*v1.Pod{pod}) +} diff --git a/test/integration/scheduler/preemption_test.go b/test/integration/scheduler/preemption_test.go index ffa0e4237ea..70b590b4793 100644 --- a/test/integration/scheduler/preemption_test.go +++ b/test/integration/scheduler/preemption_test.go @@ -33,6 +33,7 @@ import ( utilfeature "k8s.io/apiserver/pkg/util/feature" utilfeaturetesting "k8s.io/apiserver/pkg/util/feature/testing" clientset "k8s.io/client-go/kubernetes" + podutil "k8s.io/kubernetes/pkg/api/v1/pod" "k8s.io/kubernetes/pkg/features" _ "k8s.io/kubernetes/pkg/scheduler/algorithmprovider" testutils "k8s.io/kubernetes/test/utils" @@ -73,7 +74,7 @@ func TestPreemption(t *testing.T) { defaultPodRes := &v1.ResourceRequirements{Requests: v1.ResourceList{ v1.ResourceCPU: *resource.NewMilliQuantity(100, resource.DecimalSI), - v1.ResourceMemory: *resource.NewQuantity(100, resource.BinarySI)}, + v1.ResourceMemory: *resource.NewQuantity(100, resource.DecimalSI)}, } tests := []struct { @@ -91,7 +92,7 @@ func TestPreemption(t *testing.T) { Priority: &lowPriority, Resources: &v1.ResourceRequirements{Requests: v1.ResourceList{ v1.ResourceCPU: *resource.NewMilliQuantity(400, resource.DecimalSI), - v1.ResourceMemory: *resource.NewQuantity(200, resource.BinarySI)}, + v1.ResourceMemory: *resource.NewQuantity(200, resource.DecimalSI)}, }, }), }, @@ -101,7 +102,7 @@ func TestPreemption(t *testing.T) { Priority: &highPriority, Resources: &v1.ResourceRequirements{Requests: v1.ResourceList{ v1.ResourceCPU: *resource.NewMilliQuantity(300, resource.DecimalSI), - v1.ResourceMemory: *resource.NewQuantity(200, resource.BinarySI)}, + v1.ResourceMemory: *resource.NewQuantity(200, resource.DecimalSI)}, }, }), preemptedPodIndexes: map[int]struct{}{0: {}}, @@ -237,7 +238,7 @@ func TestPreemption(t *testing.T) { nodeRes := &v1.ResourceList{ v1.ResourcePods: *resource.NewQuantity(32, resource.DecimalSI), v1.ResourceCPU: *resource.NewMilliQuantity(500, resource.DecimalSI), - v1.ResourceMemory: *resource.NewQuantity(500, resource.BinarySI), + v1.ResourceMemory: *resource.NewQuantity(500, resource.DecimalSI), } node, err := createNode(context.clientSet, "node1", nodeRes) if err != nil { @@ -313,7 +314,7 @@ func TestDisablePreemption(t *testing.T) { Priority: &lowPriority, Resources: &v1.ResourceRequirements{Requests: v1.ResourceList{ v1.ResourceCPU: *resource.NewMilliQuantity(400, resource.DecimalSI), - v1.ResourceMemory: *resource.NewQuantity(200, resource.BinarySI)}, + v1.ResourceMemory: *resource.NewQuantity(200, resource.DecimalSI)}, }, }), }, @@ -323,7 +324,7 @@ func TestDisablePreemption(t *testing.T) { Priority: &highPriority, Resources: &v1.ResourceRequirements{Requests: v1.ResourceList{ v1.ResourceCPU: *resource.NewMilliQuantity(300, resource.DecimalSI), - v1.ResourceMemory: *resource.NewQuantity(200, resource.BinarySI)}, + v1.ResourceMemory: *resource.NewQuantity(200, resource.DecimalSI)}, }, }), }, @@ -333,7 +334,7 @@ func TestDisablePreemption(t *testing.T) { nodeRes := &v1.ResourceList{ v1.ResourcePods: *resource.NewQuantity(32, resource.DecimalSI), v1.ResourceCPU: *resource.NewMilliQuantity(500, resource.DecimalSI), - v1.ResourceMemory: *resource.NewQuantity(500, resource.BinarySI), + v1.ResourceMemory: *resource.NewQuantity(500, resource.DecimalSI), } _, err := createNode(context.clientSet, "node1", nodeRes) if err != nil { @@ -375,7 +376,7 @@ func TestDisablePreemption(t *testing.T) { func mkPriorityPodWithGrace(tc *TestContext, name string, priority int32, grace int64) *v1.Pod { defaultPodRes := &v1.ResourceRequirements{Requests: v1.ResourceList{ v1.ResourceCPU: *resource.NewMilliQuantity(100, resource.DecimalSI), - v1.ResourceMemory: *resource.NewQuantity(100, resource.BinarySI)}, + v1.ResourceMemory: *resource.NewQuantity(100, resource.DecimalSI)}, } pod := initPausePod(tc.clientSet, &pausePodConfig{ Name: name, @@ -420,7 +421,7 @@ func TestPreemptionStarvation(t *testing.T) { Priority: &highPriority, Resources: &v1.ResourceRequirements{Requests: v1.ResourceList{ v1.ResourceCPU: *resource.NewMilliQuantity(300, resource.DecimalSI), - v1.ResourceMemory: *resource.NewQuantity(200, resource.BinarySI)}, + v1.ResourceMemory: *resource.NewQuantity(200, resource.DecimalSI)}, }, }), }, @@ -430,7 +431,7 @@ func TestPreemptionStarvation(t *testing.T) { nodeRes := &v1.ResourceList{ v1.ResourcePods: *resource.NewQuantity(32, resource.DecimalSI), v1.ResourceCPU: *resource.NewMilliQuantity(500, resource.DecimalSI), - v1.ResourceMemory: *resource.NewQuantity(500, resource.BinarySI), + v1.ResourceMemory: *resource.NewQuantity(500, resource.DecimalSI), } _, err := createNode(context.clientSet, "node1", nodeRes) if err != nil { @@ -490,6 +491,119 @@ func TestPreemptionStarvation(t *testing.T) { } } +// TestPreemptionRaces tests that other scheduling events and operations do not +// race with the preemption process. +func TestPreemptionRaces(t *testing.T) { + // Initialize scheduler. + context := initTest(t, "preemption-race") + defer cleanupTest(t, context) + cs := context.clientSet + + tests := []struct { + description string + numInitialPods int // Pods created and executed before running preemptor + numAdditionalPods int // Pods created after creating the preemptor + numRepetitions int // Repeat the tests to check races + preemptor *v1.Pod + }{ + { + // This test ensures that while the preempting pod is waiting for the victims + // terminate, other lower priority pods are not scheduled in the room created + // after preemption and while the higher priority pods is not scheduled yet. + description: "ensures that other pods are not scheduled while preemptor is being marked as nominated (issue #72124)", + numInitialPods: 2, + numAdditionalPods: 50, + numRepetitions: 10, + preemptor: initPausePod(cs, &pausePodConfig{ + Name: "preemptor-pod", + Namespace: context.ns.Name, + Priority: &highPriority, + Resources: &v1.ResourceRequirements{Requests: v1.ResourceList{ + v1.ResourceCPU: *resource.NewMilliQuantity(4900, resource.DecimalSI), + v1.ResourceMemory: *resource.NewQuantity(4900, resource.DecimalSI)}, + }, + }), + }, + } + + // Create a node with some resources and a label. + nodeRes := &v1.ResourceList{ + v1.ResourcePods: *resource.NewQuantity(100, resource.DecimalSI), + v1.ResourceCPU: *resource.NewMilliQuantity(5000, resource.DecimalSI), + v1.ResourceMemory: *resource.NewQuantity(5000, resource.DecimalSI), + } + _, err := createNode(context.clientSet, "node1", nodeRes) + if err != nil { + t.Fatalf("Error creating nodes: %v", err) + } + + for _, test := range tests { + if test.numRepetitions <= 0 { + test.numRepetitions = 1 + } + for n := 0; n < test.numRepetitions; n++ { + initialPods := make([]*v1.Pod, test.numInitialPods) + additionalPods := make([]*v1.Pod, test.numAdditionalPods) + // Create and run existingPods. + for i := 0; i < test.numInitialPods; i++ { + initialPods[i], err = createPausePod(cs, mkPriorityPodWithGrace(context, fmt.Sprintf("rpod-%v", i), mediumPriority, 0)) + if err != nil { + t.Fatalf("Test [%v]: Error creating pause pod: %v", test.description, err) + } + } + // make sure that initial Pods are all scheduled. + for _, p := range initialPods { + if err := waitForPodToSchedule(cs, p); err != nil { + t.Fatalf("Pod %v/%v didn't get scheduled: %v", p.Namespace, p.Name, err) + } + } + // Create the preemptor. + klog.Info("Creating the preemptor pod...") + preemptor, err := createPausePod(cs, test.preemptor) + if err != nil { + t.Errorf("Error while creating the preempting pod: %v", err) + } + + klog.Info("Creating additional pods...") + for i := 0; i < test.numAdditionalPods; i++ { + additionalPods[i], err = createPausePod(cs, mkPriorityPodWithGrace(context, fmt.Sprintf("ppod-%v", i), mediumPriority, 0)) + if err != nil { + t.Fatalf("Test [%v]: Error creating pending pod: %v", test.description, err) + } + } + // Check that the preemptor pod gets nominated node name. + if err := waitForNominatedNodeName(cs, preemptor); err != nil { + t.Errorf("Test [%v]: NominatedNodeName annotation was not set for pod %v/%v: %v", test.description, preemptor.Namespace, preemptor.Name, err) + } + // Make sure that preemptor is scheduled after preemptions. + if err := waitForPodToScheduleWithTimeout(cs, preemptor, 60*time.Second); err != nil { + t.Errorf("Preemptor pod %v didn't get scheduled: %v", preemptor.Name, err) + } + + klog.Info("Check unschedulable pods still exists and were never scheduled...") + for _, p := range additionalPods { + pod, err := cs.CoreV1().Pods(p.Namespace).Get(p.Name, metav1.GetOptions{}) + if err != nil { + t.Errorf("Error in getting Pod %v/%v info: %v", p.Namespace, p.Name, err) + } + if len(pod.Spec.NodeName) > 0 { + t.Errorf("Pod %v/%v is already scheduled", p.Namespace, p.Name) + } + _, cond := podutil.GetPodCondition(&pod.Status, v1.PodScheduled) + if cond != nil && cond.Status != v1.ConditionFalse { + t.Errorf("Pod %v/%v is no longer unschedulable: %v", p.Namespace, p.Name, err) + } + } + // Cleanup + klog.Info("Cleaning up all pods...") + allPods := additionalPods + allPods = append(allPods, initialPods...) + allPods = append(allPods, preemptor) + cleanupPods(cs, t, allPods) + } + } +} + // TestNominatedNodeCleanUp checks that when there are nominated pods on a // node and a higher priority pod is nominated to run on the node, the nominated // node name of the lower priority pods is cleared. @@ -515,7 +629,7 @@ func TestNominatedNodeCleanUp(t *testing.T) { nodeRes := &v1.ResourceList{ v1.ResourcePods: *resource.NewQuantity(32, resource.DecimalSI), v1.ResourceCPU: *resource.NewMilliQuantity(500, resource.DecimalSI), - v1.ResourceMemory: *resource.NewQuantity(500, resource.BinarySI), + v1.ResourceMemory: *resource.NewQuantity(500, resource.DecimalSI), } _, err := createNode(context.clientSet, "node1", nodeRes) if err != nil { @@ -543,7 +657,7 @@ func TestNominatedNodeCleanUp(t *testing.T) { Priority: &mediumPriority, Resources: &v1.ResourceRequirements{Requests: v1.ResourceList{ v1.ResourceCPU: *resource.NewMilliQuantity(400, resource.DecimalSI), - v1.ResourceMemory: *resource.NewQuantity(400, resource.BinarySI)}, + v1.ResourceMemory: *resource.NewQuantity(400, resource.DecimalSI)}, }, }) medPriPod, err := createPausePod(cs, podConf) @@ -561,7 +675,7 @@ func TestNominatedNodeCleanUp(t *testing.T) { Priority: &highPriority, Resources: &v1.ResourceRequirements{Requests: v1.ResourceList{ v1.ResourceCPU: *resource.NewMilliQuantity(300, resource.DecimalSI), - v1.ResourceMemory: *resource.NewQuantity(200, resource.BinarySI)}, + v1.ResourceMemory: *resource.NewQuantity(200, resource.DecimalSI)}, }, }) highPriPod, err := createPausePod(cs, podConf) @@ -626,12 +740,12 @@ func TestPDBInPreemption(t *testing.T) { defaultPodRes := &v1.ResourceRequirements{Requests: v1.ResourceList{ v1.ResourceCPU: *resource.NewMilliQuantity(100, resource.DecimalSI), - v1.ResourceMemory: *resource.NewQuantity(100, resource.BinarySI)}, + v1.ResourceMemory: *resource.NewQuantity(100, resource.DecimalSI)}, } defaultNodeRes := &v1.ResourceList{ v1.ResourcePods: *resource.NewQuantity(32, resource.DecimalSI), v1.ResourceCPU: *resource.NewMilliQuantity(500, resource.DecimalSI), - v1.ResourceMemory: *resource.NewQuantity(500, resource.BinarySI), + v1.ResourceMemory: *resource.NewQuantity(500, resource.DecimalSI), } type nodeConfig struct { @@ -683,7 +797,7 @@ func TestPDBInPreemption(t *testing.T) { Priority: &highPriority, Resources: &v1.ResourceRequirements{Requests: v1.ResourceList{ v1.ResourceCPU: *resource.NewMilliQuantity(300, resource.DecimalSI), - v1.ResourceMemory: *resource.NewQuantity(200, resource.BinarySI)}, + v1.ResourceMemory: *resource.NewQuantity(200, resource.DecimalSI)}, }, }), preemptedPodIndexes: map[int]struct{}{2: {}}, @@ -721,7 +835,7 @@ func TestPDBInPreemption(t *testing.T) { Priority: &highPriority, Resources: &v1.ResourceRequirements{Requests: v1.ResourceList{ v1.ResourceCPU: *resource.NewMilliQuantity(500, resource.DecimalSI), - v1.ResourceMemory: *resource.NewQuantity(200, resource.BinarySI)}, + v1.ResourceMemory: *resource.NewQuantity(200, resource.DecimalSI)}, }, }), preemptedPodIndexes: map[int]struct{}{1: {}}, @@ -801,7 +915,7 @@ func TestPDBInPreemption(t *testing.T) { Priority: &highPriority, Resources: &v1.ResourceRequirements{Requests: v1.ResourceList{ v1.ResourceCPU: *resource.NewMilliQuantity(500, resource.DecimalSI), - v1.ResourceMemory: *resource.NewQuantity(400, resource.BinarySI)}, + v1.ResourceMemory: *resource.NewQuantity(400, resource.DecimalSI)}, }, }), // The third node is chosen because PDB is not violated for node 3 and the victims have lower priority than node-2. diff --git a/test/integration/scheduler/scheduler_test.go b/test/integration/scheduler/scheduler_test.go index 3f7938bb5ff..42a496c1cf1 100644 --- a/test/integration/scheduler/scheduler_test.go +++ b/test/integration/scheduler/scheduler_test.go @@ -40,12 +40,12 @@ import ( schedulerappconfig "k8s.io/kubernetes/cmd/kube-scheduler/app/config" "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/scheduler" - "k8s.io/kubernetes/pkg/scheduler/algorithm" + "k8s.io/kubernetes/pkg/scheduler/algorithm/predicates" _ "k8s.io/kubernetes/pkg/scheduler/algorithmprovider" schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" kubeschedulerconfig "k8s.io/kubernetes/pkg/scheduler/apis/config" - schedulercache "k8s.io/kubernetes/pkg/scheduler/cache" "k8s.io/kubernetes/pkg/scheduler/factory" + schedulernodeinfo "k8s.io/kubernetes/pkg/scheduler/nodeinfo" "k8s.io/kubernetes/test/integration/framework" ) @@ -56,19 +56,19 @@ type nodeStateManager struct { makeUnSchedulable nodeMutationFunc } -func PredicateOne(pod *v1.Pod, meta algorithm.PredicateMetadata, nodeInfo *schedulercache.NodeInfo) (bool, []algorithm.PredicateFailureReason, error) { +func PredicateOne(pod *v1.Pod, meta predicates.PredicateMetadata, nodeInfo *schedulernodeinfo.NodeInfo) (bool, []predicates.PredicateFailureReason, error) { return true, nil, nil } -func PredicateTwo(pod *v1.Pod, meta algorithm.PredicateMetadata, nodeInfo *schedulercache.NodeInfo) (bool, []algorithm.PredicateFailureReason, error) { +func PredicateTwo(pod *v1.Pod, meta predicates.PredicateMetadata, nodeInfo *schedulernodeinfo.NodeInfo) (bool, []predicates.PredicateFailureReason, error) { return true, nil, nil } -func PriorityOne(pod *v1.Pod, nodeNameToInfo map[string]*schedulercache.NodeInfo, nodes []*v1.Node) (schedulerapi.HostPriorityList, error) { +func PriorityOne(pod *v1.Pod, nodeNameToInfo map[string]*schedulernodeinfo.NodeInfo, nodes []*v1.Node) (schedulerapi.HostPriorityList, error) { return []schedulerapi.HostPriority{}, nil } -func PriorityTwo(pod *v1.Pod, nodeNameToInfo map[string]*schedulercache.NodeInfo, nodes []*v1.Node) (schedulerapi.HostPriorityList, error) { +func PriorityTwo(pod *v1.Pod, nodeNameToInfo map[string]*schedulernodeinfo.NodeInfo, nodes []*v1.Node) (schedulerapi.HostPriorityList, error) { return []schedulerapi.HostPriority{}, nil } diff --git a/test/integration/scheduler/taint_test.go b/test/integration/scheduler/taint_test.go index bdcd0b4a08b..ee10f1f1231 100644 --- a/test/integration/scheduler/taint_test.go +++ b/test/integration/scheduler/taint_test.go @@ -94,8 +94,7 @@ func TestTaintNodeByCondition(t *testing.T) { informers.Coordination().V1beta1().Leases(), informers.Core().V1().Pods(), informers.Core().V1().Nodes(), - informers.Extensions().V1beta1().DaemonSets(), - nil, // CloudProvider + informers.Apps().V1().DaemonSets(), cs, time.Hour, // Node monitor grace period time.Second, // Node startup grace period diff --git a/test/integration/scheduler/util.go b/test/integration/scheduler/util.go index 71875405ee6..c35502376d9 100644 --- a/test/integration/scheduler/util.go +++ b/test/integration/scheduler/util.go @@ -33,8 +33,6 @@ import ( "k8s.io/apimachinery/pkg/util/uuid" "k8s.io/apimachinery/pkg/util/wait" "k8s.io/apiserver/pkg/admission" - utilfeature "k8s.io/apiserver/pkg/util/feature" - utilfeaturetesting "k8s.io/apiserver/pkg/util/feature/testing" "k8s.io/client-go/informers" coreinformers "k8s.io/client-go/informers/core/v1" clientset "k8s.io/client-go/kubernetes" @@ -46,11 +44,11 @@ import ( podutil "k8s.io/kubernetes/pkg/api/v1/pod" "k8s.io/kubernetes/pkg/controller" "k8s.io/kubernetes/pkg/controller/disruption" - "k8s.io/kubernetes/pkg/features" "k8s.io/kubernetes/pkg/scheduler" _ "k8s.io/kubernetes/pkg/scheduler/algorithmprovider" schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" "k8s.io/kubernetes/pkg/scheduler/factory" + plugins "k8s.io/kubernetes/pkg/scheduler/plugins/v1alpha1" taintutils "k8s.io/kubernetes/pkg/util/taints" "k8s.io/kubernetes/test/integration/framework" imageutils "k8s.io/kubernetes/test/utils/image" @@ -90,7 +88,6 @@ func createConfiguratorWithPodInformer( PdbInformer: informerFactory.Policy().V1beta1().PodDisruptionBudgets(), StorageClassInformer: informerFactory.Storage().V1().StorageClasses(), HardPodAffinitySymmetricWeight: v1.DefaultHardPodAffinitySymmetricWeight, - EnableEquivalenceClassCache: utilfeature.DefaultFeatureGate.Enabled(features.EnableEquivalenceClassCache), DisablePreemption: false, PercentageOfNodesToScore: schedulerapi.DefaultPercentageOfNodesToScore, BindTimeoutSeconds: 600, @@ -148,7 +145,7 @@ func initTestScheduler( ) *TestContext { // Pod preemption is enabled by default scheduler configuration, but preemption only happens when PodPriority // feature gate is enabled at the same time. - return initTestSchedulerWithOptions(t, context, setPodInformer, policy, false, true, time.Second) + return initTestSchedulerWithOptions(t, context, setPodInformer, policy, nil, false, time.Second) } // initTestSchedulerWithOptions initializes a test environment and creates a scheduler with default @@ -158,17 +155,10 @@ func initTestSchedulerWithOptions( context *TestContext, setPodInformer bool, policy *schedulerapi.Policy, + pluginSet plugins.PluginSet, disablePreemption bool, - disableEquivalenceCache bool, resyncPeriod time.Duration, ) *TestContext { - if !disableEquivalenceCache { - defer utilfeaturetesting.SetFeatureGateDuringTest( - t, - utilfeature.DefaultFeatureGate, - features.EnableEquivalenceClassCache, true)() - } - // 1. Create scheduler context.informerFactory = informers.NewSharedInformerFactory(context.clientSet, resyncPeriod) @@ -205,6 +195,11 @@ func initTestSchedulerWithOptions( controller.WaitForCacheSync("scheduler", context.schedulerConfig.StopEverything, podInformer.Informer().HasSynced) } + // Set pluginSet if provided. DefaultPluginSet is used if this is not specified. + if pluginSet != nil { + context.schedulerConfig.PluginSet = pluginSet + } + eventBroadcaster := record.NewBroadcaster() context.schedulerConfig.Recorder = eventBroadcaster.NewRecorder( legacyscheme.Scheme, @@ -236,9 +231,9 @@ func initDisruptionController(context *TestContext) *disruption.DisruptionContro informers.Core().V1().Pods(), informers.Policy().V1beta1().PodDisruptionBudgets(), informers.Core().V1().ReplicationControllers(), - informers.Extensions().V1beta1().ReplicaSets(), - informers.Extensions().V1beta1().Deployments(), - informers.Apps().V1beta1().StatefulSets(), + informers.Apps().V1().ReplicaSets(), + informers.Apps().V1().Deployments(), + informers.Apps().V1().StatefulSets(), context.clientSet) informers.Start(context.schedulerConfig.StopEverything) @@ -257,7 +252,7 @@ func initTest(t *testing.T, nsPrefix string) *TestContext { // configuration but with pod preemption disabled. func initTestDisablePreemption(t *testing.T, nsPrefix string) *TestContext { return initTestSchedulerWithOptions( - t, initTestMaster(t, nsPrefix, nil), true, nil, true, true, time.Second) + t, initTestMaster(t, nsPrefix, nil), true, nil, nil, true, time.Second) } // cleanupTest deletes the scheduler and the test namespace. It should be called @@ -587,6 +582,17 @@ func podScheduled(c clientset.Interface, podNamespace, podName string) wait.Cond } } +// podUnschedulable returns a condition function that returns true if the given pod +// gets unschedulable status. +func podSchedulableCondition(c clientset.Interface, podNamespace, podName string) (*v1.PodCondition, error) { + pod, err := c.CoreV1().Pods(podNamespace).Get(podName, metav1.GetOptions{}) + if err != nil { + return nil, err + } + _, cond := podutil.GetPodCondition(&pod.Status, v1.PodScheduled) + return cond, nil +} + // podUnschedulable returns a condition function that returns true if the given pod // gets unschedulable status. func podUnschedulable(c clientset.Interface, podNamespace, podName string) wait.ConditionFunc { @@ -605,6 +611,25 @@ func podUnschedulable(c clientset.Interface, podNamespace, podName string) wait. } } +// podSchedulingError returns a condition function that returns true if the given pod +// gets unschedulable status for reasons other than "Unschedulable". The scheduler +// records such reasons in case of error. +func podSchedulingError(c clientset.Interface, podNamespace, podName string) wait.ConditionFunc { + return func() (bool, error) { + pod, err := c.CoreV1().Pods(podNamespace).Get(podName, metav1.GetOptions{}) + if errors.IsNotFound(err) { + return false, nil + } + if err != nil { + // This could be a connection error so we want to retry. + return false, nil + } + _, cond := podutil.GetPodCondition(&pod.Status, v1.PodScheduled) + return cond != nil && cond.Status == v1.ConditionFalse && + cond.Reason != v1.PodReasonUnschedulable, nil + } +} + // waitForPodToScheduleWithTimeout waits for a pod to get scheduled and returns // an error if it does not scheduled within the given timeout. func waitForPodToScheduleWithTimeout(cs clientset.Interface, pod *v1.Pod, timeout time.Duration) error { @@ -696,7 +721,7 @@ func cleanupPods(cs clientset.Interface, t *testing.T, pods []*v1.Pod) { } } for _, p := range pods { - if err := wait.Poll(time.Second, wait.ForeverTestTimeout, + if err := wait.Poll(time.Millisecond, wait.ForeverTestTimeout, podDeleted(cs, p.Namespace, p.Name)); err != nil { t.Errorf("error while waiting for pod %v/%v to get deleted: %v", p.Namespace, p.Name, err) } diff --git a/test/integration/scheduler/volume_binding_test.go b/test/integration/scheduler/volume_binding_test.go index 114e23ae67c..58b4c538985 100644 --- a/test/integration/scheduler/volume_binding_test.go +++ b/test/integration/scheduler/volume_binding_test.go @@ -97,9 +97,8 @@ type testPVC struct { } func TestVolumeBinding(t *testing.T) { - defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.VolumeScheduling, true)() defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.PersistentLocalVolumes, true)() - config := setupCluster(t, "volume-scheduling-", 2, 0, 0, true) + config := setupCluster(t, "volume-scheduling-", 2, 0, 0) defer config.teardown() cases := map[string]struct { @@ -268,9 +267,8 @@ func TestVolumeBinding(t *testing.T) { // TestVolumeBindingRescheduling tests scheduler will retry scheduling when needed. func TestVolumeBindingRescheduling(t *testing.T) { - defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.VolumeScheduling, true)() defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.PersistentLocalVolumes, true)() - config := setupCluster(t, "volume-scheduling-", 2, 0, 0, true) + config := setupCluster(t, "volume-scheduling-", 2, 0, 0) defer config.teardown() storageClassName := "local-storage" @@ -412,9 +410,8 @@ func TestVolumeBindingDynamicStressSlow(t *testing.T) { } func testVolumeBindingStress(t *testing.T, schedulerResyncPeriod time.Duration, dynamic bool, provisionDelaySeconds int) { - defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.VolumeScheduling, true)() defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.PersistentLocalVolumes, true)() - config := setupCluster(t, "volume-binding-stress-", 1, schedulerResyncPeriod, provisionDelaySeconds, true) + config := setupCluster(t, "volume-binding-stress-", 1, schedulerResyncPeriod, provisionDelaySeconds) defer config.teardown() // Set max volume limit to the number of PVCs the test will create @@ -502,10 +499,8 @@ func testVolumeBindingStress(t *testing.T, schedulerResyncPeriod time.Duration, } func testVolumeBindingWithAffinity(t *testing.T, anti bool, numNodes, numPods, numPVsFirstNode int) { - defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.VolumeScheduling, true)() defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.PersistentLocalVolumes, true)() - // TODO: disable equivalence cache until kubernetes/kubernetes#67680 is fixed - config := setupCluster(t, "volume-pod-affinity-", numNodes, 0, 0, true) + config := setupCluster(t, "volume-pod-affinity-", numNodes, 0, 0) defer config.teardown() pods := []*v1.Pod{} @@ -630,9 +625,8 @@ func TestVolumeBindingWithAffinity(t *testing.T) { } func TestPVAffinityConflict(t *testing.T) { - defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.VolumeScheduling, true)() defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.PersistentLocalVolumes, true)() - config := setupCluster(t, "volume-scheduling-", 3, 0, 0, true) + config := setupCluster(t, "volume-scheduling-", 3, 0, 0) defer config.teardown() pv := makePV("local-pv", classImmediate, "", "", node1) @@ -691,9 +685,8 @@ func TestPVAffinityConflict(t *testing.T) { } func TestVolumeProvision(t *testing.T) { - defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.VolumeScheduling, true)() defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.PersistentLocalVolumes, true)() - config := setupCluster(t, "volume-scheduling", 1, 0, 0, true) + config := setupCluster(t, "volume-scheduling", 1, 0, 0) defer config.teardown() cases := map[string]struct { @@ -831,7 +824,6 @@ func TestVolumeProvision(t *testing.T) { // on provision failure. func TestRescheduleProvisioning(t *testing.T) { // Set feature gates - defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.VolumeScheduling, true)() controllerCh := make(chan struct{}) context := initTestMaster(t, "reschedule-volume-provision", nil) @@ -889,9 +881,8 @@ func TestRescheduleProvisioning(t *testing.T) { } } -func setupCluster(t *testing.T, nsName string, numberOfNodes int, resyncPeriod time.Duration, provisionDelaySeconds int, disableEquivalenceCache bool) *testConfig { - context := initTestSchedulerWithOptions(t, initTestMaster(t, nsName, nil), false, nil, false, disableEquivalenceCache, resyncPeriod) - +func setupCluster(t *testing.T, nsName string, numberOfNodes int, resyncPeriod time.Duration, provisionDelaySeconds int) *testConfig { + context := initTestSchedulerWithOptions(t, initTestMaster(t, nsName, nil), false, nil, nil, false, resyncPeriod) clientset := context.clientSet ns := context.ns.Name diff --git a/test/integration/scheduler_perf/scheduler_bench_test.go b/test/integration/scheduler_perf/scheduler_bench_test.go index 85af9567234..818eb9a9819 100644 --- a/test/integration/scheduler_perf/scheduler_bench_test.go +++ b/test/integration/scheduler_perf/scheduler_bench_test.go @@ -43,6 +43,7 @@ func BenchmarkScheduling(b *testing.B) { {nodes: 100, existingPods: 1000, minPods: 100}, {nodes: 1000, existingPods: 0, minPods: 100}, {nodes: 1000, existingPods: 1000, minPods: 100}, + {nodes: 5000, existingPods: 1000, minPods: 1000}, } setupStrategy := testutils.NewSimpleWithControllerCreatePodStrategy("rc1") testStrategy := testutils.NewSimpleWithControllerCreatePodStrategy("rc2") @@ -62,6 +63,7 @@ func BenchmarkSchedulingPodAntiAffinity(b *testing.B) { {nodes: 500, existingPods: 250, minPods: 250}, {nodes: 500, existingPods: 5000, minPods: 250}, {nodes: 1000, existingPods: 1000, minPods: 500}, + {nodes: 5000, existingPods: 1000, minPods: 1000}, } // The setup strategy creates pods with no affinity rules. setupStrategy := testutils.NewSimpleWithControllerCreatePodStrategy("setup") @@ -86,6 +88,7 @@ func BenchmarkSchedulingPodAffinity(b *testing.B) { {nodes: 500, existingPods: 250, minPods: 250}, {nodes: 500, existingPods: 5000, minPods: 250}, {nodes: 1000, existingPods: 1000, minPods: 500}, + {nodes: 5000, existingPods: 1000, minPods: 1000}, } // The setup strategy creates pods with no affinity rules. setupStrategy := testutils.NewSimpleWithControllerCreatePodStrategy("setup") @@ -112,6 +115,7 @@ func BenchmarkSchedulingNodeAffinity(b *testing.B) { {nodes: 500, existingPods: 250, minPods: 250}, {nodes: 500, existingPods: 5000, minPods: 250}, {nodes: 1000, existingPods: 1000, minPods: 500}, + {nodes: 5000, existingPods: 1000, minPods: 1000}, } // The setup strategy creates pods with no affinity rules. setupStrategy := testutils.NewSimpleWithControllerCreatePodStrategy("setup") diff --git a/test/integration/serviceaccount/service_account_test.go b/test/integration/serviceaccount/service_account_test.go index 5139911db66..70f4aceaf9c 100644 --- a/test/integration/serviceaccount/service_account_test.go +++ b/test/integration/serviceaccount/service_account_test.go @@ -363,6 +363,10 @@ func startServiceAccountTestServer(t *testing.T) (*clientset.Clientset, restclie // TODO: remove rootClient after we refactor pkg/admission to use the clientset. rootClientset := clientset.NewForConfigOrDie(&restclient.Config{Host: apiServer.URL, ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}, BearerToken: rootToken}) externalRootClientset := kubernetes.NewForConfigOrDie(&restclient.Config{Host: apiServer.URL, ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}, BearerToken: rootToken}) + + externalInformers := informers.NewSharedInformerFactory(externalRootClientset, controller.NoResyncPeriodFunc()) + informers := informers.NewSharedInformerFactory(rootClientset, controller.NoResyncPeriodFunc()) + // Set up two authenticators: // 1. A token authenticator that maps the rootToken to the "root" user // 2. A ServiceAccountToken authenticator that validates ServiceAccount tokens @@ -373,7 +377,12 @@ func startServiceAccountTestServer(t *testing.T) (*clientset.Clientset, restclie return nil, false, nil }) serviceAccountKey, _ := rsa.GenerateKey(rand.Reader, 2048) - serviceAccountTokenGetter := serviceaccountcontroller.NewGetterFromClient(rootClientset) + serviceAccountTokenGetter := serviceaccountcontroller.NewGetterFromClient( + rootClientset, + externalInformers.Core().V1().Secrets().Lister(), + externalInformers.Core().V1().ServiceAccounts().Lister(), + externalInformers.Core().V1().Pods().Lister(), + ) serviceAccountTokenAuth := serviceaccount.JWTTokenAuthenticator(serviceaccount.LegacyIssuer, []interface{}{&serviceAccountKey.PublicKey}, nil, serviceaccount.NewLegacyValidator(true, serviceAccountTokenGetter)) authenticator := union.New( bearertoken.New(rootTokenAuth), @@ -418,9 +427,7 @@ func startServiceAccountTestServer(t *testing.T) (*clientset.Clientset, restclie // Set up admission plugin to auto-assign serviceaccounts to pods serviceAccountAdmission := serviceaccountadmission.NewServiceAccount() serviceAccountAdmission.SetExternalKubeClientSet(externalRootClientset) - externalInformers := informers.NewSharedInformerFactory(externalRootClientset, controller.NoResyncPeriodFunc()) serviceAccountAdmission.SetExternalKubeInformerFactory(externalInformers) - informers := informers.NewSharedInformerFactory(rootClientset, controller.NoResyncPeriodFunc()) masterConfig := framework.NewMasterConfig() masterConfig.GenericConfig.EnableIndex = true diff --git a/test/integration/util/BUILD b/test/integration/util/BUILD index 5bd8b0bb804..add700c8058 100644 --- a/test/integration/util/BUILD +++ b/test/integration/util/BUILD @@ -15,18 +15,16 @@ go_library( deps = [ "//pkg/api/legacyscheme:go_default_library", "//pkg/cloudprovider/providers/gce:go_default_library", - "//pkg/cloudprovider/providers/gce/cloud:go_default_library", - "//pkg/features:go_default_library", "//pkg/scheduler:go_default_library", "//pkg/scheduler/api:go_default_library", "//pkg/scheduler/factory:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library", - "//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library", "//staging/src/k8s.io/client-go/informers:go_default_library", "//staging/src/k8s.io/client-go/kubernetes:go_default_library", "//staging/src/k8s.io/client-go/kubernetes/typed/core/v1:go_default_library", "//staging/src/k8s.io/client-go/tools/record:go_default_library", "//test/integration/framework:go_default_library", + "//vendor/github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud:go_default_library", "//vendor/golang.org/x/oauth2:go_default_library", "//vendor/k8s.io/klog:go_default_library", ], diff --git a/test/integration/util/cloud.go b/test/integration/util/cloud.go index 0d018a4e96f..c701a5410b3 100644 --- a/test/integration/util/cloud.go +++ b/test/integration/util/cloud.go @@ -19,9 +19,9 @@ package util import ( "time" + "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud" "golang.org/x/oauth2" "k8s.io/kubernetes/pkg/cloudprovider/providers/gce" - "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud" ) const ( diff --git a/test/integration/util/util.go b/test/integration/util/util.go index 4137429ec45..939815747be 100644 --- a/test/integration/util/util.go +++ b/test/integration/util/util.go @@ -21,14 +21,12 @@ import ( "net/http/httptest" "k8s.io/api/core/v1" - utilfeature "k8s.io/apiserver/pkg/util/feature" "k8s.io/client-go/informers" clientset "k8s.io/client-go/kubernetes" clientv1core "k8s.io/client-go/kubernetes/typed/core/v1" "k8s.io/client-go/tools/record" "k8s.io/klog" "k8s.io/kubernetes/pkg/api/legacyscheme" - "k8s.io/kubernetes/pkg/features" "k8s.io/kubernetes/pkg/scheduler" schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" "k8s.io/kubernetes/pkg/scheduler/factory" @@ -94,6 +92,7 @@ func createSchedulerConfigurator( informerFactory informers.SharedInformerFactory, stopCh <-chan struct{}, ) factory.Configurator { + return factory.NewConfigFactory(&factory.ConfigFactoryArgs{ SchedulerName: v1.DefaultSchedulerName, Client: clientSet, @@ -108,7 +107,6 @@ func createSchedulerConfigurator( PdbInformer: informerFactory.Policy().V1beta1().PodDisruptionBudgets(), StorageClassInformer: informerFactory.Storage().V1().StorageClasses(), HardPodAffinitySymmetricWeight: v1.DefaultHardPodAffinitySymmetricWeight, - EnableEquivalenceClassCache: utilfeature.DefaultFeatureGate.Enabled(features.EnableEquivalenceClassCache), DisablePreemption: false, PercentageOfNodesToScore: schedulerapi.DefaultPercentageOfNodesToScore, StopCh: stopCh, diff --git a/test/integration/utils.go b/test/integration/utils.go index 5eb72c86553..533948c6326 100644 --- a/test/integration/utils.go +++ b/test/integration/utils.go @@ -67,7 +67,7 @@ func WaitForPodToDisappear(podClient coreclient.PodInterface, podName string, in }) } -func GetEtcdClients(config storagebackend.Config) (*clientv3.Client, clientv3.KV, error) { +func GetEtcdClients(config storagebackend.TransportConfig) (*clientv3.Client, clientv3.KV, error) { tlsInfo := transport.TLSInfo{ CertFile: config.CertFile, KeyFile: config.KeyFile, diff --git a/test/kubemark/resources/kube_dns_template.yaml b/test/kubemark/resources/kube_dns_template.yaml index 8d812023f09..02c2a68a2e5 100644 --- a/test/kubemark/resources/kube_dns_template.yaml +++ b/test/kubemark/resources/kube_dns_template.yaml @@ -36,7 +36,7 @@ metadata: labels: addonmanager.kubernetes.io/mode: EnsureExists --- -apiVersion: extensions/v1beta1 +apiVersion: apps/v1 kind: Deployment metadata: name: kube-dns diff --git a/test/kubemark/resources/start-kubemark-master.sh b/test/kubemark/resources/start-kubemark-master.sh index 4f0aae5e258..9b813b19a18 100755 --- a/test/kubemark/resources/start-kubemark-master.sh +++ b/test/kubemark/resources/start-kubemark-master.sh @@ -489,11 +489,11 @@ function compute-etcd-events-params { function compute-kube-apiserver-params { local params="${APISERVER_TEST_ARGS:-}" params+=" --insecure-bind-address=0.0.0.0" + params+=" --etcd-servers=${ETCD_SERVERS:-http://127.0.0.1:2379}" if [[ -z "${ETCD_SERVERS:-}" ]]; then - params+=" --etcd-servers=http://127.0.0.1:2379" - params+=" --etcd-servers-overrides=/events#${EVENT_STORE_URL}" - else - params+=" --etcd-servers=${ETCD_SERVERS}" + params+=" --etcd-servers-overrides=${ETCD_SERVERS_OVERRIDES:-/events#${EVENT_STORE_URL}}" + elif [[ -n "${ETCD_SERVERS_OVERRIDES:-}" ]]; then + params+=" --etcd-servers-overrides=${ETCD_SERVERS_OVERRIDES:-}" fi params+=" --tls-cert-file=/etc/srv/kubernetes/server.cert" params+=" --tls-private-key-file=/etc/srv/kubernetes/server.key" @@ -704,9 +704,11 @@ readonly audit_policy_file="/etc/audit_policy.config" # Start kubelet as a supervisord process and master components as pods. start-kubelet -start-kubemaster-component "etcd" -if [ "${EVENT_STORE_IP:-}" == "127.0.0.1" ]; then - start-kubemaster-component "etcd-events" +if [[ -z "${ETCD_SERVERS:-}" ]]; then + start-kubemaster-component "etcd" + if [ "${EVENT_STORE_IP:-}" == "127.0.0.1" ]; then + start-kubemaster-component "etcd-events" + fi fi start-kubemaster-component "kube-apiserver" start-kubemaster-component "kube-controller-manager" diff --git a/test/kubemark/start-kubemark.sh b/test/kubemark/start-kubemark.sh index 94507ebce61..ddb17833f4c 100755 --- a/test/kubemark/start-kubemark.sh +++ b/test/kubemark/start-kubemark.sh @@ -64,7 +64,7 @@ SERVICE_CLUSTER_IP_RANGE="${SERVICE_CLUSTER_IP_RANGE:-}" EVENT_PD="${EVENT_PD:-}" # Etcd related variables. -ETCD_IMAGE="${ETCD_IMAGE:-3.2.24-1}" +ETCD_IMAGE="${ETCD_IMAGE:-3.3.10-0}" ETCD_VERSION="${ETCD_VERSION:-}" # Controller-manager related variables. @@ -80,6 +80,8 @@ SCHEDULER_TEST_ARGS="${SCHEDULER_TEST_ARGS:-}" APISERVER_TEST_ARGS="${APISERVER_TEST_ARGS:-}" STORAGE_MEDIA_TYPE="${STORAGE_MEDIA_TYPE:-}" STORAGE_BACKEND="${STORAGE_BACKEND:-etcd3}" +ETCD_SERVERS="${ETCD_SERVERS:-}" +ETCD_SERVERS_OVERRIDES="${ETCD_SERVERS_OVERRIDES:-}" ETCD_COMPACTION_INTERVAL_SEC="${ETCD_COMPACTION_INTERVAL_SEC:-}" RUNTIME_CONFIG="${RUNTIME_CONFIG:-}" NUM_NODES="${NUM_NODES:-}" diff --git a/test/test_owners.csv b/test/test_owners.csv index c8684e2ceca..16ba34c28db 100644 --- a/test/test_owners.csv +++ b/test/test_owners.csv @@ -763,7 +763,7 @@ k8s.io/kubernetes/pkg/scheduler/algorithm/priorities,fgrzadkowski,0, k8s.io/kubernetes/pkg/scheduler/algorithmprovider,fgrzadkowski,0, k8s.io/kubernetes/pkg/scheduler/algorithmprovider/defaults,fgrzadkowski,0, k8s.io/kubernetes/pkg/scheduler/api/validation,fgrzadkowski,0, -k8s.io/kubernetes/pkg/scheduler/cache,fgrzadkowski,0, +k8s.io/kubernetes/pkg/scheduler/nodeinfo,fgrzadkowski,0, k8s.io/kubernetes/pkg/scheduler/core,madhusudancs,1, k8s.io/kubernetes/pkg/scheduler/factory,fgrzadkowski,0, k8s.io/kubernetes/pkg/scheduler/util,wojtek-t,1, diff --git a/test/utils/BUILD b/test/utils/BUILD index 82a0722eeba..9bab197cba2 100644 --- a/test/utils/BUILD +++ b/test/utils/BUILD @@ -35,7 +35,6 @@ go_library( "//staging/src/k8s.io/api/apps/v1:go_default_library", "//staging/src/k8s.io/api/batch/v1:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library", - "//staging/src/k8s.io/api/extensions/v1beta1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/equality:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/resource:go_default_library", diff --git a/test/utils/audit.go b/test/utils/audit.go index e4cd1b07722..c78cb2719a2 100644 --- a/test/utils/audit.go +++ b/test/utils/audit.go @@ -20,6 +20,8 @@ import ( "bufio" "fmt" "io" + "sort" + "strings" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" @@ -28,17 +30,19 @@ import ( ) type AuditEvent struct { - Level auditinternal.Level - Stage auditinternal.Stage - RequestURI string - Verb string - Code int32 - User string - Resource string - Namespace string - RequestObject bool - ResponseObject bool - AuthorizeDecision string + Level auditinternal.Level + Stage auditinternal.Stage + RequestURI string + Verb string + Code int32 + User string + ImpersonatedUser string + ImpersonatedGroups string + Resource string + Namespace string + RequestObject bool + ResponseObject bool + AuthorizeDecision string } // Search the audit log for the expected audit lines. @@ -101,6 +105,11 @@ func parseAuditLine(line string, version schema.GroupVersion) (AuditEvent, error if e.RequestObject != nil { event.RequestObject = true } + if e.ImpersonatedUser != nil { + event.ImpersonatedUser = e.ImpersonatedUser.Username + sort.Strings(e.ImpersonatedUser.Groups) + event.ImpersonatedGroups = strings.Join(e.ImpersonatedUser.Groups, ",") + } event.AuthorizeDecision = e.Annotations["authorization.k8s.io/decision"] return event, nil } diff --git a/test/utils/create_resources.go b/test/utils/create_resources.go index f92649ac14d..173f296c676 100644 --- a/test/utils/create_resources.go +++ b/test/utils/create_resources.go @@ -22,9 +22,9 @@ import ( "fmt" "time" + apps "k8s.io/api/apps/v1" batch "k8s.io/api/batch/v1" "k8s.io/api/core/v1" - extensions "k8s.io/api/extensions/v1beta1" apierrs "k8s.io/apimachinery/pkg/api/errors" utilnet "k8s.io/apimachinery/pkg/util/net" "k8s.io/apimachinery/pkg/util/wait" @@ -97,12 +97,12 @@ func CreateRCWithRetries(c clientset.Interface, namespace string, obj *v1.Replic return RetryWithExponentialBackOff(createFunc) } -func CreateReplicaSetWithRetries(c clientset.Interface, namespace string, obj *extensions.ReplicaSet) error { +func CreateReplicaSetWithRetries(c clientset.Interface, namespace string, obj *apps.ReplicaSet) error { if obj == nil { return fmt.Errorf("Object provided to create is empty") } createFunc := func() (bool, error) { - _, err := c.ExtensionsV1beta1().ReplicaSets(namespace).Create(obj) + _, err := c.AppsV1().ReplicaSets(namespace).Create(obj) if err == nil || apierrs.IsAlreadyExists(err) { return true, nil } @@ -114,12 +114,12 @@ func CreateReplicaSetWithRetries(c clientset.Interface, namespace string, obj *e return RetryWithExponentialBackOff(createFunc) } -func CreateDeploymentWithRetries(c clientset.Interface, namespace string, obj *extensions.Deployment) error { +func CreateDeploymentWithRetries(c clientset.Interface, namespace string, obj *apps.Deployment) error { if obj == nil { return fmt.Errorf("Object provided to create is empty") } createFunc := func() (bool, error) { - _, err := c.ExtensionsV1beta1().Deployments(namespace).Create(obj) + _, err := c.AppsV1().Deployments(namespace).Create(obj) if err == nil || apierrs.IsAlreadyExists(err) { return true, nil } @@ -131,12 +131,12 @@ func CreateDeploymentWithRetries(c clientset.Interface, namespace string, obj *e return RetryWithExponentialBackOff(createFunc) } -func CreateDaemonSetWithRetries(c clientset.Interface, namespace string, obj *extensions.DaemonSet) error { +func CreateDaemonSetWithRetries(c clientset.Interface, namespace string, obj *apps.DaemonSet) error { if obj == nil { return fmt.Errorf("Object provided to create is empty") } createFunc := func() (bool, error) { - _, err := c.ExtensionsV1beta1().DaemonSets(namespace).Create(obj) + _, err := c.AppsV1().DaemonSets(namespace).Create(obj) if err == nil || apierrs.IsAlreadyExists(err) { return true, nil } diff --git a/test/utils/delete_resources.go b/test/utils/delete_resources.go index 5c67afda201..58221f56383 100644 --- a/test/utils/delete_resources.go +++ b/test/utils/delete_resources.go @@ -38,11 +38,11 @@ func deleteResource(c clientset.Interface, kind schema.GroupKind, namespace, nam case api.Kind("ReplicationController"): return c.CoreV1().ReplicationControllers(namespace).Delete(name, options) case extensionsinternal.Kind("ReplicaSet"), appsinternal.Kind("ReplicaSet"): - return c.ExtensionsV1beta1().ReplicaSets(namespace).Delete(name, options) + return c.AppsV1().ReplicaSets(namespace).Delete(name, options) case extensionsinternal.Kind("Deployment"), appsinternal.Kind("Deployment"): - return c.ExtensionsV1beta1().Deployments(namespace).Delete(name, options) + return c.AppsV1().Deployments(namespace).Delete(name, options) case extensionsinternal.Kind("DaemonSet"): - return c.ExtensionsV1beta1().DaemonSets(namespace).Delete(name, options) + return c.AppsV1().DaemonSets(namespace).Delete(name, options) case batchinternal.Kind("Job"): return c.BatchV1().Jobs(namespace).Delete(name, options) case api.Kind("Secret"): diff --git a/test/utils/image/manifest.go b/test/utils/image/manifest.go index 2e5015bd3a7..1fed673a04a 100644 --- a/test/utils/image/manifest.go +++ b/test/utils/image/manifest.go @@ -97,7 +97,7 @@ var ( APIServer = Config{e2eRegistry, "sample-apiserver", "1.10"} AppArmorLoader = Config{e2eRegistry, "apparmor-loader", "1.0"} BusyBox = Config{dockerLibraryRegistry, "busybox", "1.29"} - CheckMetadataConcealment = Config{e2eRegistry, "metadata-concealment", "1.1.1"} + CheckMetadataConcealment = Config{e2eRegistry, "metadata-concealment", "1.2"} CudaVectorAdd = Config{e2eRegistry, "cuda-vector-add", "1.0"} Dnsutils = Config{e2eRegistry, "dnsutils", "1.1"} EchoServer = Config{e2eRegistry, "echoserver", "2.2"} diff --git a/test/utils/runners.go b/test/utils/runners.go index 4ebfde80e13..5291e433c86 100644 --- a/test/utils/runners.go +++ b/test/utils/runners.go @@ -25,9 +25,9 @@ import ( "sync" "time" + apps "k8s.io/api/apps/v1" batch "k8s.io/api/batch/v1" "k8s.io/api/core/v1" - extensions "k8s.io/api/extensions/v1beta1" apiequality "k8s.io/apimachinery/pkg/api/equality" apierrs "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/resource" @@ -300,11 +300,11 @@ func (config *DeploymentConfig) GetGroupResource() schema.GroupResource { } func (config *DeploymentConfig) create() error { - deployment := &extensions.Deployment{ + deployment := &apps.Deployment{ ObjectMeta: metav1.ObjectMeta{ Name: config.Name, }, - Spec: extensions.DeploymentSpec{ + Spec: apps.DeploymentSpec{ Replicas: func(i int) *int32 { x := int32(i); return &x }(config.Replicas), Selector: &metav1.LabelSelector{ MatchLabels: map[string]string{ @@ -375,11 +375,11 @@ func (config *ReplicaSetConfig) GetGroupResource() schema.GroupResource { } func (config *ReplicaSetConfig) create() error { - rs := &extensions.ReplicaSet{ + rs := &apps.ReplicaSet{ ObjectMeta: metav1.ObjectMeta{ Name: config.Name, }, - Spec: extensions.ReplicaSetSpec{ + Spec: apps.ReplicaSetSpec{ Replicas: func(i int) *int32 { x := int32(i); return &x }(config.Replicas), Selector: &metav1.LabelSelector{ MatchLabels: map[string]string{ @@ -1327,11 +1327,11 @@ func (config *DaemonConfig) Run() error { nameLabel := map[string]string{ "name": config.Name + "-daemon", } - daemon := &extensions.DaemonSet{ + daemon := &apps.DaemonSet{ ObjectMeta: metav1.ObjectMeta{ Name: config.Name, }, - Spec: extensions.DaemonSetSpec{ + Spec: apps.DaemonSetSpec{ Template: v1.PodTemplateSpec{ ObjectMeta: metav1.ObjectMeta{ Labels: nameLabel, diff --git a/vendor/BUILD b/vendor/BUILD index d6912c3b4f7..dbff81b3618 100644 --- a/vendor/BUILD +++ b/vendor/BUILD @@ -26,6 +26,7 @@ filegroup( "//vendor/github.com/Azure/go-autorest/logger:all-srcs", "//vendor/github.com/Azure/go-autorest/version:all-srcs", "//vendor/github.com/GeertJohan/go.rice:all-srcs", + "//vendor/github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud:all-srcs", "//vendor/github.com/JeffAshton/win_pdh:all-srcs", "//vendor/github.com/MakeNowJust/heredoc:all-srcs", "//vendor/github.com/Microsoft/go-winio:all-srcs", @@ -298,6 +299,7 @@ filegroup( "//vendor/github.com/libopenstorage/openstorage/pkg/parser:all-srcs", "//vendor/github.com/libopenstorage/openstorage/pkg/units:all-srcs", "//vendor/github.com/libopenstorage/openstorage/volume:all-srcs", + "//vendor/github.com/liggitt/tabwriter:all-srcs", "//vendor/github.com/magiconair/properties:all-srcs", "//vendor/github.com/mailru/easyjson/buffer:all-srcs", "//vendor/github.com/mailru/easyjson/jlexer:all-srcs", @@ -389,6 +391,7 @@ filegroup( "//vendor/golang.org/x/crypto/poly1305:all-srcs", "//vendor/golang.org/x/crypto/salsa20/salsa:all-srcs", "//vendor/golang.org/x/crypto/ssh:all-srcs", + "//vendor/golang.org/x/lint:all-srcs", "//vendor/golang.org/x/net/context:all-srcs", "//vendor/golang.org/x/net/html:all-srcs", "//vendor/golang.org/x/net/http2:all-srcs", @@ -416,6 +419,8 @@ filegroup( "//vendor/golang.org/x/tools/benchmark/parse:all-srcs", "//vendor/golang.org/x/tools/container/intsets:all-srcs", "//vendor/golang.org/x/tools/go/ast/astutil:all-srcs", + "//vendor/golang.org/x/tools/go/gcexportdata:all-srcs", + "//vendor/golang.org/x/tools/go/gcimporter15:all-srcs", "//vendor/golang.org/x/tools/go/vcs:all-srcs", "//vendor/golang.org/x/tools/imports:all-srcs", "//vendor/gonum.org/v1/gonum/blas:all-srcs", @@ -468,11 +473,30 @@ filegroup( "//vendor/k8s.io/utils/clock:all-srcs", "//vendor/k8s.io/utils/exec:all-srcs", "//vendor/k8s.io/utils/pointer:all-srcs", +<<<<<<< HEAD "//vendor/sigs.k8s.io/structured-merge-diff/fieldpath:all-srcs", "//vendor/sigs.k8s.io/structured-merge-diff/merge:all-srcs", "//vendor/sigs.k8s.io/structured-merge-diff/schema:all-srcs", "//vendor/sigs.k8s.io/structured-merge-diff/typed:all-srcs", "//vendor/sigs.k8s.io/structured-merge-diff/value:all-srcs", +======= + "//vendor/sigs.k8s.io/kustomize/pkg/commands/build:all-srcs", + "//vendor/sigs.k8s.io/kustomize/pkg/constants:all-srcs", + "//vendor/sigs.k8s.io/kustomize/pkg/expansion:all-srcs", + "//vendor/sigs.k8s.io/kustomize/pkg/factory:all-srcs", + "//vendor/sigs.k8s.io/kustomize/pkg/fs:all-srcs", + "//vendor/sigs.k8s.io/kustomize/pkg/gvk:all-srcs", + "//vendor/sigs.k8s.io/kustomize/pkg/ifc:all-srcs", + "//vendor/sigs.k8s.io/kustomize/pkg/internal/error:all-srcs", + "//vendor/sigs.k8s.io/kustomize/pkg/loader:all-srcs", + "//vendor/sigs.k8s.io/kustomize/pkg/patch:all-srcs", + "//vendor/sigs.k8s.io/kustomize/pkg/resid:all-srcs", + "//vendor/sigs.k8s.io/kustomize/pkg/resmap:all-srcs", + "//vendor/sigs.k8s.io/kustomize/pkg/resource:all-srcs", + "//vendor/sigs.k8s.io/kustomize/pkg/target:all-srcs", + "//vendor/sigs.k8s.io/kustomize/pkg/transformers:all-srcs", + "//vendor/sigs.k8s.io/kustomize/pkg/types:all-srcs", +>>>>>>> upstream/master "//vendor/sigs.k8s.io/yaml:all-srcs", "//vendor/vbom.ml/util/sortorder:all-srcs", ], diff --git a/vendor/github.com/GoogleCloudPlatform/k8s-cloud-provider/LICENSE b/vendor/github.com/GoogleCloudPlatform/k8s-cloud-provider/LICENSE new file mode 100644 index 00000000000..d6456956733 --- /dev/null +++ b/vendor/github.com/GoogleCloudPlatform/k8s-cloud-provider/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/vendor/github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/BUILD b/vendor/github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/BUILD new file mode 100644 index 00000000000..202d1a3fdd7 --- /dev/null +++ b/vendor/github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/BUILD @@ -0,0 +1,48 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = [ + "constants.go", + "context.go", + "doc.go", + "gce_projects.go", + "gen.go", + "op.go", + "project.go", + "ratelimit.go", + "service.go", + "utils.go", + ], + importmap = "k8s.io/kubernetes/vendor/github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud", + importpath = "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud", + visibility = ["//visibility:public"], + deps = [ + "//vendor/github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/filter:go_default_library", + "//vendor/github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/meta:go_default_library", + "//vendor/google.golang.org/api/compute/v0.alpha:go_default_library", + "//vendor/google.golang.org/api/compute/v0.beta:go_default_library", + "//vendor/google.golang.org/api/compute/v1:go_default_library", + "//vendor/google.golang.org/api/googleapi:go_default_library", + "//vendor/k8s.io/klog:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [ + ":package-srcs", + "//vendor/github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/filter:all-srcs", + "//vendor/github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/meta:all-srcs", + "//vendor/github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/mock:all-srcs", + ], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/pkg/cloudprovider/providers/gce/cloud/constants.go b/vendor/github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/constants.go similarity index 94% rename from pkg/cloudprovider/providers/gce/cloud/constants.go rename to vendor/github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/constants.go index 8d09c8bead8..a1f433bb0af 100644 --- a/pkg/cloudprovider/providers/gce/cloud/constants.go +++ b/vendor/github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/constants.go @@ -1,11 +1,11 @@ /* -Copyright 2017 The Kubernetes Authors. +Copyright 2018 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 +https://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, diff --git a/pkg/cloudprovider/providers/gce/cloud/context.go b/vendor/github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/context.go similarity index 90% rename from pkg/cloudprovider/providers/gce/cloud/context.go rename to vendor/github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/context.go index 307a0a7a479..d0b6b0a9143 100644 --- a/pkg/cloudprovider/providers/gce/cloud/context.go +++ b/vendor/github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/context.go @@ -1,11 +1,11 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 2018 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 +https://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, diff --git a/pkg/cloudprovider/providers/gce/cloud/doc.go b/vendor/github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/doc.go similarity index 98% rename from pkg/cloudprovider/providers/gce/cloud/doc.go rename to vendor/github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/doc.go index 23b4ae838b8..1e52f6331ee 100644 --- a/pkg/cloudprovider/providers/gce/cloud/doc.go +++ b/vendor/github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/doc.go @@ -1,11 +1,11 @@ /* -Copyright 2017 The Kubernetes Authors. +Copyright 2018 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 +https://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, diff --git a/pkg/cloudprovider/providers/gce/cloud/filter/BUILD b/vendor/github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/filter/BUILD similarity index 63% rename from pkg/cloudprovider/providers/gce/cloud/filter/BUILD rename to vendor/github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/filter/BUILD index 0932666c50b..22f1f88777a 100644 --- a/pkg/cloudprovider/providers/gce/cloud/filter/BUILD +++ b/vendor/github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/filter/BUILD @@ -1,19 +1,14 @@ -load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") +load("@io_bazel_rules_go//go:def.bzl", "go_library") go_library( name = "go_default_library", srcs = ["filter.go"], - importpath = "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/filter", + importmap = "k8s.io/kubernetes/vendor/github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/filter", + importpath = "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/filter", visibility = ["//visibility:public"], deps = ["//vendor/k8s.io/klog:go_default_library"], ) -go_test( - name = "go_default_test", - srcs = ["filter_test.go"], - embed = [":go_default_library"], -) - filegroup( name = "package-srcs", srcs = glob(["**"]), diff --git a/pkg/cloudprovider/providers/gce/cloud/filter/filter.go b/vendor/github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/filter/filter.go similarity index 98% rename from pkg/cloudprovider/providers/gce/cloud/filter/filter.go rename to vendor/github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/filter/filter.go index b65ab6391a7..2a58b9c14be 100644 --- a/pkg/cloudprovider/providers/gce/cloud/filter/filter.go +++ b/vendor/github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/filter/filter.go @@ -1,11 +1,11 @@ /* -Copyright 2017 The Kubernetes Authors. +Copyright 2018 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 +https://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, diff --git a/pkg/cloudprovider/providers/gce/cloud/gce_projects.go b/vendor/github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/gce_projects.go similarity index 94% rename from pkg/cloudprovider/providers/gce/cloud/gce_projects.go rename to vendor/github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/gce_projects.go index c531881a94a..d7f73fdca6d 100644 --- a/pkg/cloudprovider/providers/gce/cloud/gce_projects.go +++ b/vendor/github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/gce_projects.go @@ -1,11 +1,11 @@ /* -Copyright 2017 The Kubernetes Authors. +Copyright 2018 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 +https://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, @@ -21,9 +21,9 @@ import ( "fmt" "net/http" + "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/meta" compute "google.golang.org/api/compute/v1" "google.golang.org/api/googleapi" - "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta" ) // ProjectsOps is the manually implemented methods for the Projects service. diff --git a/pkg/cloudprovider/providers/gce/cloud/gen.go b/vendor/github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/gen.go similarity index 99% rename from pkg/cloudprovider/providers/gce/cloud/gen.go rename to vendor/github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/gen.go index a3e7cd2c657..9c34936ffe9 100644 --- a/pkg/cloudprovider/providers/gce/cloud/gen.go +++ b/vendor/github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/gen.go @@ -1,11 +1,11 @@ /* -Copyright 2018 The Kubernetes Authors. +Copyright 2018 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 +https://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, @@ -28,8 +28,8 @@ import ( "google.golang.org/api/googleapi" "k8s.io/klog" - "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/filter" - "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta" + "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/filter" + "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/meta" alpha "google.golang.org/api/compute/v0.alpha" beta "google.golang.org/api/compute/v0.beta" @@ -54,8 +54,8 @@ type Cloud interface { AlphaForwardingRules() AlphaForwardingRules GlobalForwardingRules() GlobalForwardingRules HealthChecks() HealthChecks - BetaHealthChecks() BetaHealthChecks AlphaHealthChecks() AlphaHealthChecks + BetaHealthChecks() BetaHealthChecks HttpHealthChecks() HttpHealthChecks HttpsHealthChecks() HttpsHealthChecks InstanceGroups() InstanceGroups @@ -95,8 +95,8 @@ func NewGCE(s *Service) *GCE { gceAlphaForwardingRules: &GCEAlphaForwardingRules{s}, gceGlobalForwardingRules: &GCEGlobalForwardingRules{s}, gceHealthChecks: &GCEHealthChecks{s}, - gceBetaHealthChecks: &GCEBetaHealthChecks{s}, gceAlphaHealthChecks: &GCEAlphaHealthChecks{s}, + gceBetaHealthChecks: &GCEBetaHealthChecks{s}, gceHttpHealthChecks: &GCEHttpHealthChecks{s}, gceHttpsHealthChecks: &GCEHttpsHealthChecks{s}, gceInstanceGroups: &GCEInstanceGroups{s}, @@ -140,8 +140,8 @@ type GCE struct { gceAlphaForwardingRules *GCEAlphaForwardingRules gceGlobalForwardingRules *GCEGlobalForwardingRules gceHealthChecks *GCEHealthChecks - gceBetaHealthChecks *GCEBetaHealthChecks gceAlphaHealthChecks *GCEAlphaHealthChecks + gceBetaHealthChecks *GCEBetaHealthChecks gceHttpHealthChecks *GCEHttpHealthChecks gceHttpsHealthChecks *GCEHttpsHealthChecks gceInstanceGroups *GCEInstanceGroups @@ -242,16 +242,16 @@ func (gce *GCE) HealthChecks() HealthChecks { return gce.gceHealthChecks } -// BetaHealthChecks returns the interface for the beta HealthChecks. -func (gce *GCE) BetaHealthChecks() BetaHealthChecks { - return gce.gceBetaHealthChecks -} - // AlphaHealthChecks returns the interface for the alpha HealthChecks. func (gce *GCE) AlphaHealthChecks() AlphaHealthChecks { return gce.gceAlphaHealthChecks } +// BetaHealthChecks returns the interface for the beta HealthChecks. +func (gce *GCE) BetaHealthChecks() BetaHealthChecks { + return gce.gceBetaHealthChecks +} + // HttpHealthChecks returns the interface for the ga HttpHealthChecks. func (gce *GCE) HttpHealthChecks() HttpHealthChecks { return gce.gceHttpHealthChecks @@ -387,8 +387,8 @@ func NewMockGCE(projectRouter ProjectRouter) *MockGCE { MockAlphaForwardingRules: NewMockAlphaForwardingRules(projectRouter, mockForwardingRulesObjs), MockGlobalForwardingRules: NewMockGlobalForwardingRules(projectRouter, mockGlobalForwardingRulesObjs), MockHealthChecks: NewMockHealthChecks(projectRouter, mockHealthChecksObjs), - MockBetaHealthChecks: NewMockBetaHealthChecks(projectRouter, mockHealthChecksObjs), MockAlphaHealthChecks: NewMockAlphaHealthChecks(projectRouter, mockHealthChecksObjs), + MockBetaHealthChecks: NewMockBetaHealthChecks(projectRouter, mockHealthChecksObjs), MockHttpHealthChecks: NewMockHttpHealthChecks(projectRouter, mockHttpHealthChecksObjs), MockHttpsHealthChecks: NewMockHttpsHealthChecks(projectRouter, mockHttpsHealthChecksObjs), MockInstanceGroups: NewMockInstanceGroups(projectRouter, mockInstanceGroupsObjs), @@ -432,8 +432,8 @@ type MockGCE struct { MockAlphaForwardingRules *MockAlphaForwardingRules MockGlobalForwardingRules *MockGlobalForwardingRules MockHealthChecks *MockHealthChecks - MockBetaHealthChecks *MockBetaHealthChecks MockAlphaHealthChecks *MockAlphaHealthChecks + MockBetaHealthChecks *MockBetaHealthChecks MockHttpHealthChecks *MockHttpHealthChecks MockHttpsHealthChecks *MockHttpsHealthChecks MockInstanceGroups *MockInstanceGroups @@ -534,16 +534,16 @@ func (mock *MockGCE) HealthChecks() HealthChecks { return mock.MockHealthChecks } -// BetaHealthChecks returns the interface for the beta HealthChecks. -func (mock *MockGCE) BetaHealthChecks() BetaHealthChecks { - return mock.MockBetaHealthChecks -} - // AlphaHealthChecks returns the interface for the alpha HealthChecks. func (mock *MockGCE) AlphaHealthChecks() AlphaHealthChecks { return mock.MockAlphaHealthChecks } +// BetaHealthChecks returns the interface for the beta HealthChecks. +func (mock *MockGCE) BetaHealthChecks() BetaHealthChecks { + return mock.MockBetaHealthChecks +} + // HttpHealthChecks returns the interface for the ga HttpHealthChecks. func (mock *MockGCE) HttpHealthChecks() HttpHealthChecks { return mock.MockHttpHealthChecks @@ -7280,381 +7280,6 @@ func (g *GCEHealthChecks) Update(ctx context.Context, key *meta.Key, arg0 *ga.He return err } -// BetaHealthChecks is an interface that allows for mocking of HealthChecks. -type BetaHealthChecks interface { - Get(ctx context.Context, key *meta.Key) (*beta.HealthCheck, error) - List(ctx context.Context, fl *filter.F) ([]*beta.HealthCheck, error) - Insert(ctx context.Context, key *meta.Key, obj *beta.HealthCheck) error - Delete(ctx context.Context, key *meta.Key) error - Update(context.Context, *meta.Key, *beta.HealthCheck) error -} - -// NewMockBetaHealthChecks returns a new mock for HealthChecks. -func NewMockBetaHealthChecks(pr ProjectRouter, objs map[meta.Key]*MockHealthChecksObj) *MockBetaHealthChecks { - mock := &MockBetaHealthChecks{ - ProjectRouter: pr, - - Objects: objs, - GetError: map[meta.Key]error{}, - InsertError: map[meta.Key]error{}, - DeleteError: map[meta.Key]error{}, - } - return mock -} - -// MockBetaHealthChecks is the mock for HealthChecks. -type MockBetaHealthChecks struct { - Lock sync.Mutex - - ProjectRouter ProjectRouter - - // Objects maintained by the mock. - Objects map[meta.Key]*MockHealthChecksObj - - // If an entry exists for the given key and operation, then the error - // will be returned instead of the operation. - GetError map[meta.Key]error - ListError *error - InsertError map[meta.Key]error - DeleteError map[meta.Key]error - - // xxxHook allow you to intercept the standard processing of the mock in - // order to add your own logic. Return (true, _, _) to prevent the normal - // execution flow of the mock. Return (false, nil, nil) to continue with - // normal mock behavior/ after the hook function executes. - GetHook func(ctx context.Context, key *meta.Key, m *MockBetaHealthChecks) (bool, *beta.HealthCheck, error) - ListHook func(ctx context.Context, fl *filter.F, m *MockBetaHealthChecks) (bool, []*beta.HealthCheck, error) - InsertHook func(ctx context.Context, key *meta.Key, obj *beta.HealthCheck, m *MockBetaHealthChecks) (bool, error) - DeleteHook func(ctx context.Context, key *meta.Key, m *MockBetaHealthChecks) (bool, error) - UpdateHook func(context.Context, *meta.Key, *beta.HealthCheck, *MockBetaHealthChecks) error - - // X is extra state that can be used as part of the mock. Generated code - // will not use this field. - X interface{} -} - -// Get returns the object from the mock. -func (m *MockBetaHealthChecks) Get(ctx context.Context, key *meta.Key) (*beta.HealthCheck, error) { - if m.GetHook != nil { - if intercept, obj, err := m.GetHook(ctx, key, m); intercept { - klog.V(5).Infof("MockBetaHealthChecks.Get(%v, %s) = %+v, %v", ctx, key, obj, err) - return obj, err - } - } - if !key.Valid() { - return nil, fmt.Errorf("invalid GCE key (%+v)", key) - } - - m.Lock.Lock() - defer m.Lock.Unlock() - - if err, ok := m.GetError[*key]; ok { - klog.V(5).Infof("MockBetaHealthChecks.Get(%v, %s) = nil, %v", ctx, key, err) - return nil, err - } - if obj, ok := m.Objects[*key]; ok { - typedObj := obj.ToBeta() - klog.V(5).Infof("MockBetaHealthChecks.Get(%v, %s) = %+v, nil", ctx, key, typedObj) - return typedObj, nil - } - - err := &googleapi.Error{ - Code: http.StatusNotFound, - Message: fmt.Sprintf("MockBetaHealthChecks %v not found", key), - } - klog.V(5).Infof("MockBetaHealthChecks.Get(%v, %s) = nil, %v", ctx, key, err) - return nil, err -} - -// List all of the objects in the mock. -func (m *MockBetaHealthChecks) List(ctx context.Context, fl *filter.F) ([]*beta.HealthCheck, error) { - if m.ListHook != nil { - if intercept, objs, err := m.ListHook(ctx, fl, m); intercept { - klog.V(5).Infof("MockBetaHealthChecks.List(%v, %v) = [%v items], %v", ctx, fl, len(objs), err) - return objs, err - } - } - - m.Lock.Lock() - defer m.Lock.Unlock() - - if m.ListError != nil { - err := *m.ListError - klog.V(5).Infof("MockBetaHealthChecks.List(%v, %v) = nil, %v", ctx, fl, err) - - return nil, *m.ListError - } - - var objs []*beta.HealthCheck - for _, obj := range m.Objects { - if !fl.Match(obj.ToBeta()) { - continue - } - objs = append(objs, obj.ToBeta()) - } - - klog.V(5).Infof("MockBetaHealthChecks.List(%v, %v) = [%v items], nil", ctx, fl, len(objs)) - return objs, nil -} - -// Insert is a mock for inserting/creating a new object. -func (m *MockBetaHealthChecks) Insert(ctx context.Context, key *meta.Key, obj *beta.HealthCheck) error { - if m.InsertHook != nil { - if intercept, err := m.InsertHook(ctx, key, obj, m); intercept { - klog.V(5).Infof("MockBetaHealthChecks.Insert(%v, %v, %+v) = %v", ctx, key, obj, err) - return err - } - } - if !key.Valid() { - return fmt.Errorf("invalid GCE key (%+v)", key) - } - - m.Lock.Lock() - defer m.Lock.Unlock() - - if err, ok := m.InsertError[*key]; ok { - klog.V(5).Infof("MockBetaHealthChecks.Insert(%v, %v, %+v) = %v", ctx, key, obj, err) - return err - } - if _, ok := m.Objects[*key]; ok { - err := &googleapi.Error{ - Code: http.StatusConflict, - Message: fmt.Sprintf("MockBetaHealthChecks %v exists", key), - } - klog.V(5).Infof("MockBetaHealthChecks.Insert(%v, %v, %+v) = %v", ctx, key, obj, err) - return err - } - - obj.Name = key.Name - projectID := m.ProjectRouter.ProjectID(ctx, "beta", "healthChecks") - obj.SelfLink = SelfLink(meta.VersionBeta, projectID, "healthChecks", key) - - m.Objects[*key] = &MockHealthChecksObj{obj} - klog.V(5).Infof("MockBetaHealthChecks.Insert(%v, %v, %+v) = nil", ctx, key, obj) - return nil -} - -// Delete is a mock for deleting the object. -func (m *MockBetaHealthChecks) Delete(ctx context.Context, key *meta.Key) error { - if m.DeleteHook != nil { - if intercept, err := m.DeleteHook(ctx, key, m); intercept { - klog.V(5).Infof("MockBetaHealthChecks.Delete(%v, %v) = %v", ctx, key, err) - return err - } - } - if !key.Valid() { - return fmt.Errorf("invalid GCE key (%+v)", key) - } - - m.Lock.Lock() - defer m.Lock.Unlock() - - if err, ok := m.DeleteError[*key]; ok { - klog.V(5).Infof("MockBetaHealthChecks.Delete(%v, %v) = %v", ctx, key, err) - return err - } - if _, ok := m.Objects[*key]; !ok { - err := &googleapi.Error{ - Code: http.StatusNotFound, - Message: fmt.Sprintf("MockBetaHealthChecks %v not found", key), - } - klog.V(5).Infof("MockBetaHealthChecks.Delete(%v, %v) = %v", ctx, key, err) - return err - } - - delete(m.Objects, *key) - klog.V(5).Infof("MockBetaHealthChecks.Delete(%v, %v) = nil", ctx, key) - return nil -} - -// Obj wraps the object for use in the mock. -func (m *MockBetaHealthChecks) Obj(o *beta.HealthCheck) *MockHealthChecksObj { - return &MockHealthChecksObj{o} -} - -// Update is a mock for the corresponding method. -func (m *MockBetaHealthChecks) Update(ctx context.Context, key *meta.Key, arg0 *beta.HealthCheck) error { - if m.UpdateHook != nil { - return m.UpdateHook(ctx, key, arg0, m) - } - return nil -} - -// GCEBetaHealthChecks is a simplifying adapter for the GCE HealthChecks. -type GCEBetaHealthChecks struct { - s *Service -} - -// Get the HealthCheck named by key. -func (g *GCEBetaHealthChecks) Get(ctx context.Context, key *meta.Key) (*beta.HealthCheck, error) { - klog.V(5).Infof("GCEBetaHealthChecks.Get(%v, %v): called", ctx, key) - - if !key.Valid() { - klog.V(2).Infof("GCEBetaHealthChecks.Get(%v, %v): key is invalid (%#v)", ctx, key, key) - return nil, fmt.Errorf("invalid GCE key (%#v)", key) - } - projectID := g.s.ProjectRouter.ProjectID(ctx, "beta", "HealthChecks") - rk := &RateLimitKey{ - ProjectID: projectID, - Operation: "Get", - Version: meta.Version("beta"), - Service: "HealthChecks", - } - klog.V(5).Infof("GCEBetaHealthChecks.Get(%v, %v): projectID = %v, rk = %+v", ctx, key, projectID, rk) - if err := g.s.RateLimiter.Accept(ctx, rk); err != nil { - klog.V(4).Infof("GCEBetaHealthChecks.Get(%v, %v): RateLimiter error: %v", ctx, key, err) - return nil, err - } - call := g.s.Beta.HealthChecks.Get(projectID, key.Name) - call.Context(ctx) - v, err := call.Do() - klog.V(4).Infof("GCEBetaHealthChecks.Get(%v, %v) = %+v, %v", ctx, key, v, err) - return v, err -} - -// List all HealthCheck objects. -func (g *GCEBetaHealthChecks) List(ctx context.Context, fl *filter.F) ([]*beta.HealthCheck, error) { - klog.V(5).Infof("GCEBetaHealthChecks.List(%v, %v) called", ctx, fl) - projectID := g.s.ProjectRouter.ProjectID(ctx, "beta", "HealthChecks") - rk := &RateLimitKey{ - ProjectID: projectID, - Operation: "List", - Version: meta.Version("beta"), - Service: "HealthChecks", - } - if err := g.s.RateLimiter.Accept(ctx, rk); err != nil { - return nil, err - } - klog.V(5).Infof("GCEBetaHealthChecks.List(%v, %v): projectID = %v, rk = %+v", ctx, fl, projectID, rk) - call := g.s.Beta.HealthChecks.List(projectID) - if fl != filter.None { - call.Filter(fl.String()) - } - var all []*beta.HealthCheck - f := func(l *beta.HealthCheckList) error { - klog.V(5).Infof("GCEBetaHealthChecks.List(%v, ..., %v): page %+v", ctx, fl, l) - all = append(all, l.Items...) - return nil - } - if err := call.Pages(ctx, f); err != nil { - klog.V(4).Infof("GCEBetaHealthChecks.List(%v, ..., %v) = %v, %v", ctx, fl, nil, err) - return nil, err - } - - if klog.V(4) { - klog.V(4).Infof("GCEBetaHealthChecks.List(%v, ..., %v) = [%v items], %v", ctx, fl, len(all), nil) - } else if klog.V(5) { - var asStr []string - for _, o := range all { - asStr = append(asStr, fmt.Sprintf("%+v", o)) - } - klog.V(5).Infof("GCEBetaHealthChecks.List(%v, ..., %v) = %v, %v", ctx, fl, asStr, nil) - } - - return all, nil -} - -// Insert HealthCheck with key of value obj. -func (g *GCEBetaHealthChecks) Insert(ctx context.Context, key *meta.Key, obj *beta.HealthCheck) error { - klog.V(5).Infof("GCEBetaHealthChecks.Insert(%v, %v, %+v): called", ctx, key, obj) - if !key.Valid() { - klog.V(2).Infof("GCEBetaHealthChecks.Insert(%v, %v, ...): key is invalid (%#v)", ctx, key, key) - return fmt.Errorf("invalid GCE key (%+v)", key) - } - projectID := g.s.ProjectRouter.ProjectID(ctx, "beta", "HealthChecks") - rk := &RateLimitKey{ - ProjectID: projectID, - Operation: "Insert", - Version: meta.Version("beta"), - Service: "HealthChecks", - } - klog.V(5).Infof("GCEBetaHealthChecks.Insert(%v, %v, ...): projectID = %v, rk = %+v", ctx, key, projectID, rk) - if err := g.s.RateLimiter.Accept(ctx, rk); err != nil { - klog.V(4).Infof("GCEBetaHealthChecks.Insert(%v, %v, ...): RateLimiter error: %v", ctx, key, err) - return err - } - obj.Name = key.Name - call := g.s.Beta.HealthChecks.Insert(projectID, obj) - call.Context(ctx) - - op, err := call.Do() - if err != nil { - klog.V(4).Infof("GCEBetaHealthChecks.Insert(%v, %v, ...) = %+v", ctx, key, err) - return err - } - - err = g.s.WaitForCompletion(ctx, op) - klog.V(4).Infof("GCEBetaHealthChecks.Insert(%v, %v, %+v) = %+v", ctx, key, obj, err) - return err -} - -// Delete the HealthCheck referenced by key. -func (g *GCEBetaHealthChecks) Delete(ctx context.Context, key *meta.Key) error { - klog.V(5).Infof("GCEBetaHealthChecks.Delete(%v, %v): called", ctx, key) - if !key.Valid() { - klog.V(2).Infof("GCEBetaHealthChecks.Delete(%v, %v): key is invalid (%#v)", ctx, key, key) - return fmt.Errorf("invalid GCE key (%+v)", key) - } - projectID := g.s.ProjectRouter.ProjectID(ctx, "beta", "HealthChecks") - rk := &RateLimitKey{ - ProjectID: projectID, - Operation: "Delete", - Version: meta.Version("beta"), - Service: "HealthChecks", - } - klog.V(5).Infof("GCEBetaHealthChecks.Delete(%v, %v): projectID = %v, rk = %+v", ctx, key, projectID, rk) - if err := g.s.RateLimiter.Accept(ctx, rk); err != nil { - klog.V(4).Infof("GCEBetaHealthChecks.Delete(%v, %v): RateLimiter error: %v", ctx, key, err) - return err - } - call := g.s.Beta.HealthChecks.Delete(projectID, key.Name) - - call.Context(ctx) - - op, err := call.Do() - if err != nil { - klog.V(4).Infof("GCEBetaHealthChecks.Delete(%v, %v) = %v", ctx, key, err) - return err - } - - err = g.s.WaitForCompletion(ctx, op) - klog.V(4).Infof("GCEBetaHealthChecks.Delete(%v, %v) = %v", ctx, key, err) - return err -} - -// Update is a method on GCEBetaHealthChecks. -func (g *GCEBetaHealthChecks) Update(ctx context.Context, key *meta.Key, arg0 *beta.HealthCheck) error { - klog.V(5).Infof("GCEBetaHealthChecks.Update(%v, %v, ...): called", ctx, key) - - if !key.Valid() { - klog.V(2).Infof("GCEBetaHealthChecks.Update(%v, %v, ...): key is invalid (%#v)", ctx, key, key) - return fmt.Errorf("invalid GCE key (%+v)", key) - } - projectID := g.s.ProjectRouter.ProjectID(ctx, "beta", "HealthChecks") - rk := &RateLimitKey{ - ProjectID: projectID, - Operation: "Update", - Version: meta.Version("beta"), - Service: "HealthChecks", - } - klog.V(5).Infof("GCEBetaHealthChecks.Update(%v, %v, ...): projectID = %v, rk = %+v", ctx, key, projectID, rk) - - if err := g.s.RateLimiter.Accept(ctx, rk); err != nil { - klog.V(4).Infof("GCEBetaHealthChecks.Update(%v, %v, ...): RateLimiter error: %v", ctx, key, err) - return err - } - call := g.s.Beta.HealthChecks.Update(projectID, key.Name, arg0) - call.Context(ctx) - op, err := call.Do() - if err != nil { - klog.V(4).Infof("GCEBetaHealthChecks.Update(%v, %v, ...) = %+v", ctx, key, err) - return err - } - err = g.s.WaitForCompletion(ctx, op) - klog.V(4).Infof("GCEBetaHealthChecks.Update(%v, %v, ...) = %+v", ctx, key, err) - return err -} - // AlphaHealthChecks is an interface that allows for mocking of HealthChecks. type AlphaHealthChecks interface { Get(ctx context.Context, key *meta.Key) (*alpha.HealthCheck, error) @@ -8030,6 +7655,381 @@ func (g *GCEAlphaHealthChecks) Update(ctx context.Context, key *meta.Key, arg0 * return err } +// BetaHealthChecks is an interface that allows for mocking of HealthChecks. +type BetaHealthChecks interface { + Get(ctx context.Context, key *meta.Key) (*beta.HealthCheck, error) + List(ctx context.Context, fl *filter.F) ([]*beta.HealthCheck, error) + Insert(ctx context.Context, key *meta.Key, obj *beta.HealthCheck) error + Delete(ctx context.Context, key *meta.Key) error + Update(context.Context, *meta.Key, *beta.HealthCheck) error +} + +// NewMockBetaHealthChecks returns a new mock for HealthChecks. +func NewMockBetaHealthChecks(pr ProjectRouter, objs map[meta.Key]*MockHealthChecksObj) *MockBetaHealthChecks { + mock := &MockBetaHealthChecks{ + ProjectRouter: pr, + + Objects: objs, + GetError: map[meta.Key]error{}, + InsertError: map[meta.Key]error{}, + DeleteError: map[meta.Key]error{}, + } + return mock +} + +// MockBetaHealthChecks is the mock for HealthChecks. +type MockBetaHealthChecks struct { + Lock sync.Mutex + + ProjectRouter ProjectRouter + + // Objects maintained by the mock. + Objects map[meta.Key]*MockHealthChecksObj + + // If an entry exists for the given key and operation, then the error + // will be returned instead of the operation. + GetError map[meta.Key]error + ListError *error + InsertError map[meta.Key]error + DeleteError map[meta.Key]error + + // xxxHook allow you to intercept the standard processing of the mock in + // order to add your own logic. Return (true, _, _) to prevent the normal + // execution flow of the mock. Return (false, nil, nil) to continue with + // normal mock behavior/ after the hook function executes. + GetHook func(ctx context.Context, key *meta.Key, m *MockBetaHealthChecks) (bool, *beta.HealthCheck, error) + ListHook func(ctx context.Context, fl *filter.F, m *MockBetaHealthChecks) (bool, []*beta.HealthCheck, error) + InsertHook func(ctx context.Context, key *meta.Key, obj *beta.HealthCheck, m *MockBetaHealthChecks) (bool, error) + DeleteHook func(ctx context.Context, key *meta.Key, m *MockBetaHealthChecks) (bool, error) + UpdateHook func(context.Context, *meta.Key, *beta.HealthCheck, *MockBetaHealthChecks) error + + // X is extra state that can be used as part of the mock. Generated code + // will not use this field. + X interface{} +} + +// Get returns the object from the mock. +func (m *MockBetaHealthChecks) Get(ctx context.Context, key *meta.Key) (*beta.HealthCheck, error) { + if m.GetHook != nil { + if intercept, obj, err := m.GetHook(ctx, key, m); intercept { + klog.V(5).Infof("MockBetaHealthChecks.Get(%v, %s) = %+v, %v", ctx, key, obj, err) + return obj, err + } + } + if !key.Valid() { + return nil, fmt.Errorf("invalid GCE key (%+v)", key) + } + + m.Lock.Lock() + defer m.Lock.Unlock() + + if err, ok := m.GetError[*key]; ok { + klog.V(5).Infof("MockBetaHealthChecks.Get(%v, %s) = nil, %v", ctx, key, err) + return nil, err + } + if obj, ok := m.Objects[*key]; ok { + typedObj := obj.ToBeta() + klog.V(5).Infof("MockBetaHealthChecks.Get(%v, %s) = %+v, nil", ctx, key, typedObj) + return typedObj, nil + } + + err := &googleapi.Error{ + Code: http.StatusNotFound, + Message: fmt.Sprintf("MockBetaHealthChecks %v not found", key), + } + klog.V(5).Infof("MockBetaHealthChecks.Get(%v, %s) = nil, %v", ctx, key, err) + return nil, err +} + +// List all of the objects in the mock. +func (m *MockBetaHealthChecks) List(ctx context.Context, fl *filter.F) ([]*beta.HealthCheck, error) { + if m.ListHook != nil { + if intercept, objs, err := m.ListHook(ctx, fl, m); intercept { + klog.V(5).Infof("MockBetaHealthChecks.List(%v, %v) = [%v items], %v", ctx, fl, len(objs), err) + return objs, err + } + } + + m.Lock.Lock() + defer m.Lock.Unlock() + + if m.ListError != nil { + err := *m.ListError + klog.V(5).Infof("MockBetaHealthChecks.List(%v, %v) = nil, %v", ctx, fl, err) + + return nil, *m.ListError + } + + var objs []*beta.HealthCheck + for _, obj := range m.Objects { + if !fl.Match(obj.ToBeta()) { + continue + } + objs = append(objs, obj.ToBeta()) + } + + klog.V(5).Infof("MockBetaHealthChecks.List(%v, %v) = [%v items], nil", ctx, fl, len(objs)) + return objs, nil +} + +// Insert is a mock for inserting/creating a new object. +func (m *MockBetaHealthChecks) Insert(ctx context.Context, key *meta.Key, obj *beta.HealthCheck) error { + if m.InsertHook != nil { + if intercept, err := m.InsertHook(ctx, key, obj, m); intercept { + klog.V(5).Infof("MockBetaHealthChecks.Insert(%v, %v, %+v) = %v", ctx, key, obj, err) + return err + } + } + if !key.Valid() { + return fmt.Errorf("invalid GCE key (%+v)", key) + } + + m.Lock.Lock() + defer m.Lock.Unlock() + + if err, ok := m.InsertError[*key]; ok { + klog.V(5).Infof("MockBetaHealthChecks.Insert(%v, %v, %+v) = %v", ctx, key, obj, err) + return err + } + if _, ok := m.Objects[*key]; ok { + err := &googleapi.Error{ + Code: http.StatusConflict, + Message: fmt.Sprintf("MockBetaHealthChecks %v exists", key), + } + klog.V(5).Infof("MockBetaHealthChecks.Insert(%v, %v, %+v) = %v", ctx, key, obj, err) + return err + } + + obj.Name = key.Name + projectID := m.ProjectRouter.ProjectID(ctx, "beta", "healthChecks") + obj.SelfLink = SelfLink(meta.VersionBeta, projectID, "healthChecks", key) + + m.Objects[*key] = &MockHealthChecksObj{obj} + klog.V(5).Infof("MockBetaHealthChecks.Insert(%v, %v, %+v) = nil", ctx, key, obj) + return nil +} + +// Delete is a mock for deleting the object. +func (m *MockBetaHealthChecks) Delete(ctx context.Context, key *meta.Key) error { + if m.DeleteHook != nil { + if intercept, err := m.DeleteHook(ctx, key, m); intercept { + klog.V(5).Infof("MockBetaHealthChecks.Delete(%v, %v) = %v", ctx, key, err) + return err + } + } + if !key.Valid() { + return fmt.Errorf("invalid GCE key (%+v)", key) + } + + m.Lock.Lock() + defer m.Lock.Unlock() + + if err, ok := m.DeleteError[*key]; ok { + klog.V(5).Infof("MockBetaHealthChecks.Delete(%v, %v) = %v", ctx, key, err) + return err + } + if _, ok := m.Objects[*key]; !ok { + err := &googleapi.Error{ + Code: http.StatusNotFound, + Message: fmt.Sprintf("MockBetaHealthChecks %v not found", key), + } + klog.V(5).Infof("MockBetaHealthChecks.Delete(%v, %v) = %v", ctx, key, err) + return err + } + + delete(m.Objects, *key) + klog.V(5).Infof("MockBetaHealthChecks.Delete(%v, %v) = nil", ctx, key) + return nil +} + +// Obj wraps the object for use in the mock. +func (m *MockBetaHealthChecks) Obj(o *beta.HealthCheck) *MockHealthChecksObj { + return &MockHealthChecksObj{o} +} + +// Update is a mock for the corresponding method. +func (m *MockBetaHealthChecks) Update(ctx context.Context, key *meta.Key, arg0 *beta.HealthCheck) error { + if m.UpdateHook != nil { + return m.UpdateHook(ctx, key, arg0, m) + } + return nil +} + +// GCEBetaHealthChecks is a simplifying adapter for the GCE HealthChecks. +type GCEBetaHealthChecks struct { + s *Service +} + +// Get the HealthCheck named by key. +func (g *GCEBetaHealthChecks) Get(ctx context.Context, key *meta.Key) (*beta.HealthCheck, error) { + klog.V(5).Infof("GCEBetaHealthChecks.Get(%v, %v): called", ctx, key) + + if !key.Valid() { + klog.V(2).Infof("GCEBetaHealthChecks.Get(%v, %v): key is invalid (%#v)", ctx, key, key) + return nil, fmt.Errorf("invalid GCE key (%#v)", key) + } + projectID := g.s.ProjectRouter.ProjectID(ctx, "beta", "HealthChecks") + rk := &RateLimitKey{ + ProjectID: projectID, + Operation: "Get", + Version: meta.Version("beta"), + Service: "HealthChecks", + } + klog.V(5).Infof("GCEBetaHealthChecks.Get(%v, %v): projectID = %v, rk = %+v", ctx, key, projectID, rk) + if err := g.s.RateLimiter.Accept(ctx, rk); err != nil { + klog.V(4).Infof("GCEBetaHealthChecks.Get(%v, %v): RateLimiter error: %v", ctx, key, err) + return nil, err + } + call := g.s.Beta.HealthChecks.Get(projectID, key.Name) + call.Context(ctx) + v, err := call.Do() + klog.V(4).Infof("GCEBetaHealthChecks.Get(%v, %v) = %+v, %v", ctx, key, v, err) + return v, err +} + +// List all HealthCheck objects. +func (g *GCEBetaHealthChecks) List(ctx context.Context, fl *filter.F) ([]*beta.HealthCheck, error) { + klog.V(5).Infof("GCEBetaHealthChecks.List(%v, %v) called", ctx, fl) + projectID := g.s.ProjectRouter.ProjectID(ctx, "beta", "HealthChecks") + rk := &RateLimitKey{ + ProjectID: projectID, + Operation: "List", + Version: meta.Version("beta"), + Service: "HealthChecks", + } + if err := g.s.RateLimiter.Accept(ctx, rk); err != nil { + return nil, err + } + klog.V(5).Infof("GCEBetaHealthChecks.List(%v, %v): projectID = %v, rk = %+v", ctx, fl, projectID, rk) + call := g.s.Beta.HealthChecks.List(projectID) + if fl != filter.None { + call.Filter(fl.String()) + } + var all []*beta.HealthCheck + f := func(l *beta.HealthCheckList) error { + klog.V(5).Infof("GCEBetaHealthChecks.List(%v, ..., %v): page %+v", ctx, fl, l) + all = append(all, l.Items...) + return nil + } + if err := call.Pages(ctx, f); err != nil { + klog.V(4).Infof("GCEBetaHealthChecks.List(%v, ..., %v) = %v, %v", ctx, fl, nil, err) + return nil, err + } + + if klog.V(4) { + klog.V(4).Infof("GCEBetaHealthChecks.List(%v, ..., %v) = [%v items], %v", ctx, fl, len(all), nil) + } else if klog.V(5) { + var asStr []string + for _, o := range all { + asStr = append(asStr, fmt.Sprintf("%+v", o)) + } + klog.V(5).Infof("GCEBetaHealthChecks.List(%v, ..., %v) = %v, %v", ctx, fl, asStr, nil) + } + + return all, nil +} + +// Insert HealthCheck with key of value obj. +func (g *GCEBetaHealthChecks) Insert(ctx context.Context, key *meta.Key, obj *beta.HealthCheck) error { + klog.V(5).Infof("GCEBetaHealthChecks.Insert(%v, %v, %+v): called", ctx, key, obj) + if !key.Valid() { + klog.V(2).Infof("GCEBetaHealthChecks.Insert(%v, %v, ...): key is invalid (%#v)", ctx, key, key) + return fmt.Errorf("invalid GCE key (%+v)", key) + } + projectID := g.s.ProjectRouter.ProjectID(ctx, "beta", "HealthChecks") + rk := &RateLimitKey{ + ProjectID: projectID, + Operation: "Insert", + Version: meta.Version("beta"), + Service: "HealthChecks", + } + klog.V(5).Infof("GCEBetaHealthChecks.Insert(%v, %v, ...): projectID = %v, rk = %+v", ctx, key, projectID, rk) + if err := g.s.RateLimiter.Accept(ctx, rk); err != nil { + klog.V(4).Infof("GCEBetaHealthChecks.Insert(%v, %v, ...): RateLimiter error: %v", ctx, key, err) + return err + } + obj.Name = key.Name + call := g.s.Beta.HealthChecks.Insert(projectID, obj) + call.Context(ctx) + + op, err := call.Do() + if err != nil { + klog.V(4).Infof("GCEBetaHealthChecks.Insert(%v, %v, ...) = %+v", ctx, key, err) + return err + } + + err = g.s.WaitForCompletion(ctx, op) + klog.V(4).Infof("GCEBetaHealthChecks.Insert(%v, %v, %+v) = %+v", ctx, key, obj, err) + return err +} + +// Delete the HealthCheck referenced by key. +func (g *GCEBetaHealthChecks) Delete(ctx context.Context, key *meta.Key) error { + klog.V(5).Infof("GCEBetaHealthChecks.Delete(%v, %v): called", ctx, key) + if !key.Valid() { + klog.V(2).Infof("GCEBetaHealthChecks.Delete(%v, %v): key is invalid (%#v)", ctx, key, key) + return fmt.Errorf("invalid GCE key (%+v)", key) + } + projectID := g.s.ProjectRouter.ProjectID(ctx, "beta", "HealthChecks") + rk := &RateLimitKey{ + ProjectID: projectID, + Operation: "Delete", + Version: meta.Version("beta"), + Service: "HealthChecks", + } + klog.V(5).Infof("GCEBetaHealthChecks.Delete(%v, %v): projectID = %v, rk = %+v", ctx, key, projectID, rk) + if err := g.s.RateLimiter.Accept(ctx, rk); err != nil { + klog.V(4).Infof("GCEBetaHealthChecks.Delete(%v, %v): RateLimiter error: %v", ctx, key, err) + return err + } + call := g.s.Beta.HealthChecks.Delete(projectID, key.Name) + + call.Context(ctx) + + op, err := call.Do() + if err != nil { + klog.V(4).Infof("GCEBetaHealthChecks.Delete(%v, %v) = %v", ctx, key, err) + return err + } + + err = g.s.WaitForCompletion(ctx, op) + klog.V(4).Infof("GCEBetaHealthChecks.Delete(%v, %v) = %v", ctx, key, err) + return err +} + +// Update is a method on GCEBetaHealthChecks. +func (g *GCEBetaHealthChecks) Update(ctx context.Context, key *meta.Key, arg0 *beta.HealthCheck) error { + klog.V(5).Infof("GCEBetaHealthChecks.Update(%v, %v, ...): called", ctx, key) + + if !key.Valid() { + klog.V(2).Infof("GCEBetaHealthChecks.Update(%v, %v, ...): key is invalid (%#v)", ctx, key, key) + return fmt.Errorf("invalid GCE key (%+v)", key) + } + projectID := g.s.ProjectRouter.ProjectID(ctx, "beta", "HealthChecks") + rk := &RateLimitKey{ + ProjectID: projectID, + Operation: "Update", + Version: meta.Version("beta"), + Service: "HealthChecks", + } + klog.V(5).Infof("GCEBetaHealthChecks.Update(%v, %v, ...): projectID = %v, rk = %+v", ctx, key, projectID, rk) + + if err := g.s.RateLimiter.Accept(ctx, rk); err != nil { + klog.V(4).Infof("GCEBetaHealthChecks.Update(%v, %v, ...): RateLimiter error: %v", ctx, key, err) + return err + } + call := g.s.Beta.HealthChecks.Update(projectID, key.Name, arg0) + call.Context(ctx) + op, err := call.Do() + if err != nil { + klog.V(4).Infof("GCEBetaHealthChecks.Update(%v, %v, ...) = %+v", ctx, key, err) + return err + } + err = g.s.WaitForCompletion(ctx, op) + klog.V(4).Infof("GCEBetaHealthChecks.Update(%v, %v, ...) = %+v", ctx, key, err) + return err +} + // HttpHealthChecks is an interface that allows for mocking of HttpHealthChecks. type HttpHealthChecks interface { Get(ctx context.Context, key *meta.Key) (*ga.HttpHealthCheck, error) diff --git a/pkg/cloudprovider/providers/gce/cloud/meta/BUILD b/vendor/github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/meta/BUILD similarity index 74% rename from pkg/cloudprovider/providers/gce/cloud/meta/BUILD rename to vendor/github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/meta/BUILD index 591e6f22be5..6c722261912 100644 --- a/pkg/cloudprovider/providers/gce/cloud/meta/BUILD +++ b/vendor/github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/meta/BUILD @@ -1,4 +1,4 @@ -load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") +load("@io_bazel_rules_go//go:def.bzl", "go_library") go_library( name = "go_default_library", @@ -9,7 +9,8 @@ go_library( "method.go", "service.go", ], - importpath = "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta", + importmap = "k8s.io/kubernetes/vendor/github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/meta", + importpath = "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/meta", visibility = ["//visibility:public"], deps = [ "//vendor/google.golang.org/api/compute/v0.alpha:go_default_library", @@ -18,12 +19,6 @@ go_library( ], ) -go_test( - name = "go_default_test", - srcs = ["key_test.go"], - embed = [":go_default_library"], -) - filegroup( name = "package-srcs", srcs = glob(["**"]), diff --git a/pkg/cloudprovider/providers/gce/cloud/meta/doc.go b/vendor/github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/meta/doc.go similarity index 87% rename from pkg/cloudprovider/providers/gce/cloud/meta/doc.go rename to vendor/github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/meta/doc.go index 7aa24e06379..7633da38a05 100644 --- a/pkg/cloudprovider/providers/gce/cloud/meta/doc.go +++ b/vendor/github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/meta/doc.go @@ -1,11 +1,11 @@ /* -Copyright 2017 The Kubernetes Authors. +Copyright 2018 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 +https://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, diff --git a/pkg/cloudprovider/providers/gce/cloud/meta/key.go b/vendor/github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/meta/key.go similarity index 96% rename from pkg/cloudprovider/providers/gce/cloud/meta/key.go rename to vendor/github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/meta/key.go index 4b6241d2b90..b6a94ba062c 100644 --- a/pkg/cloudprovider/providers/gce/cloud/meta/key.go +++ b/vendor/github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/meta/key.go @@ -1,11 +1,11 @@ /* -Copyright 2017 The Kubernetes Authors. +Copyright 2018 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 +https://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, diff --git a/pkg/cloudprovider/providers/gce/cloud/meta/meta.go b/vendor/github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/meta/meta.go similarity index 99% rename from pkg/cloudprovider/providers/gce/cloud/meta/meta.go rename to vendor/github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/meta/meta.go index 04d13e0bfd2..1be6e1df57d 100644 --- a/pkg/cloudprovider/providers/gce/cloud/meta/meta.go +++ b/vendor/github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/meta/meta.go @@ -1,11 +1,11 @@ /* -Copyright 2017 The Kubernetes Authors. +Copyright 2018 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 +https://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, @@ -225,9 +225,9 @@ var AllServices = []*ServiceInfo{ Object: "HealthCheck", Service: "HealthChecks", Resource: "healthChecks", - version: VersionBeta, + version: VersionAlpha, keyType: Global, - serviceType: reflect.TypeOf(&beta.HealthChecksService{}), + serviceType: reflect.TypeOf(&alpha.HealthChecksService{}), additionalMethods: []string{ "Update", }, @@ -236,9 +236,9 @@ var AllServices = []*ServiceInfo{ Object: "HealthCheck", Service: "HealthChecks", Resource: "healthChecks", - version: VersionAlpha, + version: VersionBeta, keyType: Global, - serviceType: reflect.TypeOf(&alpha.HealthChecksService{}), + serviceType: reflect.TypeOf(&beta.HealthChecksService{}), additionalMethods: []string{ "Update", }, diff --git a/pkg/cloudprovider/providers/gce/cloud/meta/method.go b/vendor/github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/meta/method.go similarity index 99% rename from pkg/cloudprovider/providers/gce/cloud/meta/method.go rename to vendor/github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/meta/method.go index b37258705a2..f7e62dd3cd2 100644 --- a/pkg/cloudprovider/providers/gce/cloud/meta/method.go +++ b/vendor/github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/meta/method.go @@ -1,11 +1,11 @@ /* -Copyright 2017 The Kubernetes Authors. +Copyright 2018 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 +https://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, diff --git a/pkg/cloudprovider/providers/gce/cloud/meta/service.go b/vendor/github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/meta/service.go similarity index 98% rename from pkg/cloudprovider/providers/gce/cloud/meta/service.go rename to vendor/github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/meta/service.go index c18de2a5942..e7659e4916b 100644 --- a/pkg/cloudprovider/providers/gce/cloud/meta/service.go +++ b/vendor/github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/meta/service.go @@ -1,11 +1,11 @@ /* -Copyright 2017 The Kubernetes Authors. +Copyright 2018 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 +https://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, diff --git a/pkg/cloudprovider/providers/gce/cloud/mock/BUILD b/vendor/github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/mock/BUILD similarity index 60% rename from pkg/cloudprovider/providers/gce/cloud/mock/BUILD rename to vendor/github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/mock/BUILD index e6e359278c4..2da95097b2c 100644 --- a/pkg/cloudprovider/providers/gce/cloud/mock/BUILD +++ b/vendor/github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/mock/BUILD @@ -3,12 +3,13 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library") go_library( name = "go_default_library", srcs = ["mock.go"], - importpath = "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/mock", + importmap = "k8s.io/kubernetes/vendor/github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/mock", + importpath = "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/mock", visibility = ["//visibility:public"], deps = [ - "//pkg/cloudprovider/providers/gce/cloud:go_default_library", - "//pkg/cloudprovider/providers/gce/cloud/filter:go_default_library", - "//pkg/cloudprovider/providers/gce/cloud/meta:go_default_library", + "//vendor/github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud:go_default_library", + "//vendor/github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/filter:go_default_library", + "//vendor/github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/meta:go_default_library", "//vendor/google.golang.org/api/compute/v0.alpha:go_default_library", "//vendor/google.golang.org/api/compute/v0.beta:go_default_library", "//vendor/google.golang.org/api/compute/v1:go_default_library", diff --git a/pkg/cloudprovider/providers/gce/cloud/mock/mock.go b/vendor/github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/mock/mock.go similarity index 98% rename from pkg/cloudprovider/providers/gce/cloud/mock/mock.go rename to vendor/github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/mock/mock.go index 0489bf8d4a3..fb908dfaa32 100644 --- a/pkg/cloudprovider/providers/gce/cloud/mock/mock.go +++ b/vendor/github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/mock/mock.go @@ -1,11 +1,11 @@ /* -Copyright 2017 The Kubernetes Authors. +Copyright 2018 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 +https://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, @@ -30,13 +30,13 @@ import ( "net/http" "sync" + cloud "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud" + "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/filter" + "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/meta" alpha "google.golang.org/api/compute/v0.alpha" beta "google.golang.org/api/compute/v0.beta" ga "google.golang.org/api/compute/v1" "google.golang.org/api/googleapi" - cloud "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud" - "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/filter" - "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta" ) var ( diff --git a/pkg/cloudprovider/providers/gce/cloud/op.go b/vendor/github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/op.go similarity index 97% rename from pkg/cloudprovider/providers/gce/cloud/op.go rename to vendor/github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/op.go index eb45c769e46..e0caf5f315e 100644 --- a/pkg/cloudprovider/providers/gce/cloud/op.go +++ b/vendor/github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/op.go @@ -1,11 +1,11 @@ /* -Copyright 2017 The Kubernetes Authors. +Copyright 2018 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 +https://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, @@ -27,7 +27,7 @@ import ( ga "google.golang.org/api/compute/v1" "google.golang.org/api/googleapi" - "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta" + "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/meta" ) const ( diff --git a/pkg/cloudprovider/providers/gce/cloud/project.go b/vendor/github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/project.go similarity index 90% rename from pkg/cloudprovider/providers/gce/cloud/project.go rename to vendor/github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/project.go index 231e7cf916a..eb5d920c360 100644 --- a/pkg/cloudprovider/providers/gce/cloud/project.go +++ b/vendor/github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/project.go @@ -1,11 +1,11 @@ /* -Copyright 2017 The Kubernetes Authors. +Copyright 2018 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 +https://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, @@ -19,7 +19,7 @@ package cloud import ( "context" - "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta" + "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/meta" ) // ProjectRouter routes service calls to the appropriate GCE project. diff --git a/pkg/cloudprovider/providers/gce/cloud/ratelimit.go b/vendor/github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/ratelimit.go similarity index 95% rename from pkg/cloudprovider/providers/gce/cloud/ratelimit.go rename to vendor/github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/ratelimit.go index ca1278a008d..090db2abfa5 100644 --- a/pkg/cloudprovider/providers/gce/cloud/ratelimit.go +++ b/vendor/github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/ratelimit.go @@ -1,11 +1,11 @@ /* -Copyright 2017 The Kubernetes Authors. +Copyright 2018 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 +https://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, @@ -20,7 +20,7 @@ import ( "context" "time" - "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta" + "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/meta" ) // RateLimitKey is a key identifying the operation to be rate limited. The rate limit diff --git a/pkg/cloudprovider/providers/gce/cloud/service.go b/vendor/github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/service.go similarity index 97% rename from pkg/cloudprovider/providers/gce/cloud/service.go rename to vendor/github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/service.go index 4d7b4c557f2..839eb15f8d1 100644 --- a/pkg/cloudprovider/providers/gce/cloud/service.go +++ b/vendor/github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/service.go @@ -1,11 +1,11 @@ /* -Copyright 2017 The Kubernetes Authors. +Copyright 2018 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 +https://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, diff --git a/pkg/cloudprovider/providers/gce/cloud/utils.go b/vendor/github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/utils.go similarity index 97% rename from pkg/cloudprovider/providers/gce/cloud/utils.go rename to vendor/github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/utils.go index 0affadc96d2..71b60ab818a 100644 --- a/pkg/cloudprovider/providers/gce/cloud/utils.go +++ b/vendor/github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/utils.go @@ -1,11 +1,11 @@ /* -Copyright 2017 The Kubernetes Authors. +Copyright 2018 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 +https://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, @@ -21,7 +21,7 @@ import ( "fmt" "strings" - "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta" + "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/meta" ) const ( diff --git a/vendor/github.com/liggitt/tabwriter/.travis.yml b/vendor/github.com/liggitt/tabwriter/.travis.yml new file mode 100644 index 00000000000..2768dc0727e --- /dev/null +++ b/vendor/github.com/liggitt/tabwriter/.travis.yml @@ -0,0 +1,11 @@ +language: go + +go: + - "1.8" + - "1.9" + - "1.10" + - "1.11" + - "1.12" + - master + +script: go test -v ./... diff --git a/vendor/github.com/liggitt/tabwriter/BUILD b/vendor/github.com/liggitt/tabwriter/BUILD new file mode 100644 index 00000000000..73e6abf0420 --- /dev/null +++ b/vendor/github.com/liggitt/tabwriter/BUILD @@ -0,0 +1,23 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = ["tabwriter.go"], + importmap = "k8s.io/kubernetes/vendor/github.com/liggitt/tabwriter", + importpath = "github.com/liggitt/tabwriter", + visibility = ["//visibility:public"], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/vendor/github.com/liggitt/tabwriter/LICENSE b/vendor/github.com/liggitt/tabwriter/LICENSE new file mode 100644 index 00000000000..6a66aea5eaf --- /dev/null +++ b/vendor/github.com/liggitt/tabwriter/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2009 The Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/liggitt/tabwriter/README.md b/vendor/github.com/liggitt/tabwriter/README.md new file mode 100644 index 00000000000..e75d35672e9 --- /dev/null +++ b/vendor/github.com/liggitt/tabwriter/README.md @@ -0,0 +1,7 @@ +This repo is a drop-in replacement for the golang [text/tabwriter](https://golang.org/pkg/text/tabwriter/) package. + +It is based on that package at [cf2c2ea8](https://github.com/golang/go/tree/cf2c2ea89d09d486bb018b1817c5874388038c3a/src/text/tabwriter) and inherits its license. + +The following additional features are supported: +* `RememberWidths` flag allows remembering maximum widths seen per column even after Flush() is called. +* `RememberedWidths() []int` and `SetRememberedWidths([]int) *Writer` allows obtaining and transferring remembered column width between writers. diff --git a/vendor/github.com/liggitt/tabwriter/tabwriter.go b/vendor/github.com/liggitt/tabwriter/tabwriter.go new file mode 100644 index 00000000000..fd3431fb03d --- /dev/null +++ b/vendor/github.com/liggitt/tabwriter/tabwriter.go @@ -0,0 +1,637 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package tabwriter implements a write filter (tabwriter.Writer) that +// translates tabbed columns in input into properly aligned text. +// +// It is a drop-in replacement for the golang text/tabwriter package (https://golang.org/pkg/text/tabwriter), +// based on that package at https://github.com/golang/go/tree/cf2c2ea89d09d486bb018b1817c5874388038c3a +// with support for additional features. +// +// The package is using the Elastic Tabstops algorithm described at +// http://nickgravgaard.com/elastictabstops/index.html. +package tabwriter + +import ( + "io" + "unicode/utf8" +) + +// ---------------------------------------------------------------------------- +// Filter implementation + +// A cell represents a segment of text terminated by tabs or line breaks. +// The text itself is stored in a separate buffer; cell only describes the +// segment's size in bytes, its width in runes, and whether it's an htab +// ('\t') terminated cell. +// +type cell struct { + size int // cell size in bytes + width int // cell width in runes + htab bool // true if the cell is terminated by an htab ('\t') +} + +// A Writer is a filter that inserts padding around tab-delimited +// columns in its input to align them in the output. +// +// The Writer treats incoming bytes as UTF-8-encoded text consisting +// of cells terminated by horizontal ('\t') or vertical ('\v') tabs, +// and newline ('\n') or formfeed ('\f') characters; both newline and +// formfeed act as line breaks. +// +// Tab-terminated cells in contiguous lines constitute a column. The +// Writer inserts padding as needed to make all cells in a column have +// the same width, effectively aligning the columns. It assumes that +// all characters have the same width, except for tabs for which a +// tabwidth must be specified. Column cells must be tab-terminated, not +// tab-separated: non-tab terminated trailing text at the end of a line +// forms a cell but that cell is not part of an aligned column. +// For instance, in this example (where | stands for a horizontal tab): +// +// aaaa|bbb|d +// aa |b |dd +// a | +// aa |cccc|eee +// +// the b and c are in distinct columns (the b column is not contiguous +// all the way). The d and e are not in a column at all (there's no +// terminating tab, nor would the column be contiguous). +// +// The Writer assumes that all Unicode code points have the same width; +// this may not be true in some fonts or if the string contains combining +// characters. +// +// If DiscardEmptyColumns is set, empty columns that are terminated +// entirely by vertical (or "soft") tabs are discarded. Columns +// terminated by horizontal (or "hard") tabs are not affected by +// this flag. +// +// If a Writer is configured to filter HTML, HTML tags and entities +// are passed through. The widths of tags and entities are +// assumed to be zero (tags) and one (entities) for formatting purposes. +// +// A segment of text may be escaped by bracketing it with Escape +// characters. The tabwriter passes escaped text segments through +// unchanged. In particular, it does not interpret any tabs or line +// breaks within the segment. If the StripEscape flag is set, the +// Escape characters are stripped from the output; otherwise they +// are passed through as well. For the purpose of formatting, the +// width of the escaped text is always computed excluding the Escape +// characters. +// +// The formfeed character acts like a newline but it also terminates +// all columns in the current line (effectively calling Flush). Tab- +// terminated cells in the next line start new columns. Unless found +// inside an HTML tag or inside an escaped text segment, formfeed +// characters appear as newlines in the output. +// +// The Writer must buffer input internally, because proper spacing +// of one line may depend on the cells in future lines. Clients must +// call Flush when done calling Write. +// +type Writer struct { + // configuration + output io.Writer + minwidth int + tabwidth int + padding int + padbytes [8]byte + flags uint + + // current state + buf []byte // collected text excluding tabs or line breaks + pos int // buffer position up to which cell.width of incomplete cell has been computed + cell cell // current incomplete cell; cell.width is up to buf[pos] excluding ignored sections + endChar byte // terminating char of escaped sequence (Escape for escapes, '>', ';' for HTML tags/entities, or 0) + lines [][]cell // list of lines; each line is a list of cells + widths []int // list of column widths in runes - re-used during formatting + + maxwidths []int // list of max column widths in runes +} + +// addLine adds a new line. +// flushed is a hint indicating whether the underlying writer was just flushed. +// If so, the previous line is not likely to be a good indicator of the new line's cells. +func (b *Writer) addLine(flushed bool) { + // Grow slice instead of appending, + // as that gives us an opportunity + // to re-use an existing []cell. + if n := len(b.lines) + 1; n <= cap(b.lines) { + b.lines = b.lines[:n] + b.lines[n-1] = b.lines[n-1][:0] + } else { + b.lines = append(b.lines, nil) + } + + if !flushed { + // The previous line is probably a good indicator + // of how many cells the current line will have. + // If the current line's capacity is smaller than that, + // abandon it and make a new one. + if n := len(b.lines); n >= 2 { + if prev := len(b.lines[n-2]); prev > cap(b.lines[n-1]) { + b.lines[n-1] = make([]cell, 0, prev) + } + } + } +} + +// Reset the current state. +func (b *Writer) reset() { + b.buf = b.buf[:0] + b.pos = 0 + b.cell = cell{} + b.endChar = 0 + b.lines = b.lines[0:0] + b.widths = b.widths[0:0] + b.addLine(true) +} + +// Internal representation (current state): +// +// - all text written is appended to buf; tabs and line breaks are stripped away +// - at any given time there is a (possibly empty) incomplete cell at the end +// (the cell starts after a tab or line break) +// - cell.size is the number of bytes belonging to the cell so far +// - cell.width is text width in runes of that cell from the start of the cell to +// position pos; html tags and entities are excluded from this width if html +// filtering is enabled +// - the sizes and widths of processed text are kept in the lines list +// which contains a list of cells for each line +// - the widths list is a temporary list with current widths used during +// formatting; it is kept in Writer because it's re-used +// +// |<---------- size ---------->| +// | | +// |<- width ->|<- ignored ->| | +// | | | | +// [---processed---tab------------......] +// ^ ^ ^ +// | | | +// buf start of incomplete cell pos + +// Formatting can be controlled with these flags. +const ( + // Ignore html tags and treat entities (starting with '&' + // and ending in ';') as single characters (width = 1). + FilterHTML uint = 1 << iota + + // Strip Escape characters bracketing escaped text segments + // instead of passing them through unchanged with the text. + StripEscape + + // Force right-alignment of cell content. + // Default is left-alignment. + AlignRight + + // Handle empty columns as if they were not present in + // the input in the first place. + DiscardEmptyColumns + + // Always use tabs for indentation columns (i.e., padding of + // leading empty cells on the left) independent of padchar. + TabIndent + + // Print a vertical bar ('|') between columns (after formatting). + // Discarded columns appear as zero-width columns ("||"). + Debug + + // Remember maximum widths seen per column even after Flush() is called. + RememberWidths +) + +// A Writer must be initialized with a call to Init. The first parameter (output) +// specifies the filter output. The remaining parameters control the formatting: +// +// minwidth minimal cell width including any padding +// tabwidth width of tab characters (equivalent number of spaces) +// padding padding added to a cell before computing its width +// padchar ASCII char used for padding +// if padchar == '\t', the Writer will assume that the +// width of a '\t' in the formatted output is tabwidth, +// and cells are left-aligned independent of align_left +// (for correct-looking results, tabwidth must correspond +// to the tab width in the viewer displaying the result) +// flags formatting control +// +func (b *Writer) Init(output io.Writer, minwidth, tabwidth, padding int, padchar byte, flags uint) *Writer { + if minwidth < 0 || tabwidth < 0 || padding < 0 { + panic("negative minwidth, tabwidth, or padding") + } + b.output = output + b.minwidth = minwidth + b.tabwidth = tabwidth + b.padding = padding + for i := range b.padbytes { + b.padbytes[i] = padchar + } + if padchar == '\t' { + // tab padding enforces left-alignment + flags &^= AlignRight + } + b.flags = flags + + b.reset() + + return b +} + +// debugging support (keep code around) +func (b *Writer) dump() { + pos := 0 + for i, line := range b.lines { + print("(", i, ") ") + for _, c := range line { + print("[", string(b.buf[pos:pos+c.size]), "]") + pos += c.size + } + print("\n") + } + print("\n") +} + +// local error wrapper so we can distinguish errors we want to return +// as errors from genuine panics (which we don't want to return as errors) +type osError struct { + err error +} + +func (b *Writer) write0(buf []byte) { + n, err := b.output.Write(buf) + if n != len(buf) && err == nil { + err = io.ErrShortWrite + } + if err != nil { + panic(osError{err}) + } +} + +func (b *Writer) writeN(src []byte, n int) { + for n > len(src) { + b.write0(src) + n -= len(src) + } + b.write0(src[0:n]) +} + +var ( + newline = []byte{'\n'} + tabs = []byte("\t\t\t\t\t\t\t\t") +) + +func (b *Writer) writePadding(textw, cellw int, useTabs bool) { + if b.padbytes[0] == '\t' || useTabs { + // padding is done with tabs + if b.tabwidth == 0 { + return // tabs have no width - can't do any padding + } + // make cellw the smallest multiple of b.tabwidth + cellw = (cellw + b.tabwidth - 1) / b.tabwidth * b.tabwidth + n := cellw - textw // amount of padding + if n < 0 { + panic("internal error") + } + b.writeN(tabs, (n+b.tabwidth-1)/b.tabwidth) + return + } + + // padding is done with non-tab characters + b.writeN(b.padbytes[0:], cellw-textw) +} + +var vbar = []byte{'|'} + +func (b *Writer) writeLines(pos0 int, line0, line1 int) (pos int) { + pos = pos0 + for i := line0; i < line1; i++ { + line := b.lines[i] + + // if TabIndent is set, use tabs to pad leading empty cells + useTabs := b.flags&TabIndent != 0 + + for j, c := range line { + if j > 0 && b.flags&Debug != 0 { + // indicate column break + b.write0(vbar) + } + + if c.size == 0 { + // empty cell + if j < len(b.widths) { + b.writePadding(c.width, b.widths[j], useTabs) + } + } else { + // non-empty cell + useTabs = false + if b.flags&AlignRight == 0 { // align left + b.write0(b.buf[pos : pos+c.size]) + pos += c.size + if j < len(b.widths) { + b.writePadding(c.width, b.widths[j], false) + } + } else { // align right + if j < len(b.widths) { + b.writePadding(c.width, b.widths[j], false) + } + b.write0(b.buf[pos : pos+c.size]) + pos += c.size + } + } + } + + if i+1 == len(b.lines) { + // last buffered line - we don't have a newline, so just write + // any outstanding buffered data + b.write0(b.buf[pos : pos+b.cell.size]) + pos += b.cell.size + } else { + // not the last line - write newline + b.write0(newline) + } + } + return +} + +// Format the text between line0 and line1 (excluding line1); pos +// is the buffer position corresponding to the beginning of line0. +// Returns the buffer position corresponding to the beginning of +// line1 and an error, if any. +// +func (b *Writer) format(pos0 int, line0, line1 int) (pos int) { + pos = pos0 + column := len(b.widths) + for this := line0; this < line1; this++ { + line := b.lines[this] + + if column >= len(line)-1 { + continue + } + // cell exists in this column => this line + // has more cells than the previous line + // (the last cell per line is ignored because cells are + // tab-terminated; the last cell per line describes the + // text before the newline/formfeed and does not belong + // to a column) + + // print unprinted lines until beginning of block + pos = b.writeLines(pos, line0, this) + line0 = this + + // column block begin + width := b.minwidth // minimal column width + discardable := true // true if all cells in this column are empty and "soft" + for ; this < line1; this++ { + line = b.lines[this] + if column >= len(line)-1 { + break + } + // cell exists in this column + c := line[column] + // update width + if w := c.width + b.padding; w > width { + width = w + } + // update discardable + if c.width > 0 || c.htab { + discardable = false + } + } + // column block end + + // discard empty columns if necessary + if discardable && b.flags&DiscardEmptyColumns != 0 { + width = 0 + } + + if b.flags&RememberWidths != 0 { + if len(b.maxwidths) < len(b.widths) { + b.maxwidths = append(b.maxwidths, b.widths[len(b.maxwidths):]...) + } + + switch { + case len(b.maxwidths) == len(b.widths): + b.maxwidths = append(b.maxwidths, width) + case b.maxwidths[len(b.widths)] > width: + width = b.maxwidths[len(b.widths)] + case b.maxwidths[len(b.widths)] < width: + b.maxwidths[len(b.widths)] = width + } + } + + // format and print all columns to the right of this column + // (we know the widths of this column and all columns to the left) + b.widths = append(b.widths, width) // push width + pos = b.format(pos, line0, this) + b.widths = b.widths[0 : len(b.widths)-1] // pop width + line0 = this + } + + // print unprinted lines until end + return b.writeLines(pos, line0, line1) +} + +// Append text to current cell. +func (b *Writer) append(text []byte) { + b.buf = append(b.buf, text...) + b.cell.size += len(text) +} + +// Update the cell width. +func (b *Writer) updateWidth() { + b.cell.width += utf8.RuneCount(b.buf[b.pos:]) + b.pos = len(b.buf) +} + +// To escape a text segment, bracket it with Escape characters. +// For instance, the tab in this string "Ignore this tab: \xff\t\xff" +// does not terminate a cell and constitutes a single character of +// width one for formatting purposes. +// +// The value 0xff was chosen because it cannot appear in a valid UTF-8 sequence. +// +const Escape = '\xff' + +// Start escaped mode. +func (b *Writer) startEscape(ch byte) { + switch ch { + case Escape: + b.endChar = Escape + case '<': + b.endChar = '>' + case '&': + b.endChar = ';' + } +} + +// Terminate escaped mode. If the escaped text was an HTML tag, its width +// is assumed to be zero for formatting purposes; if it was an HTML entity, +// its width is assumed to be one. In all other cases, the width is the +// unicode width of the text. +// +func (b *Writer) endEscape() { + switch b.endChar { + case Escape: + b.updateWidth() + if b.flags&StripEscape == 0 { + b.cell.width -= 2 // don't count the Escape chars + } + case '>': // tag of zero width + case ';': + b.cell.width++ // entity, count as one rune + } + b.pos = len(b.buf) + b.endChar = 0 +} + +// Terminate the current cell by adding it to the list of cells of the +// current line. Returns the number of cells in that line. +// +func (b *Writer) terminateCell(htab bool) int { + b.cell.htab = htab + line := &b.lines[len(b.lines)-1] + *line = append(*line, b.cell) + b.cell = cell{} + return len(*line) +} + +func handlePanic(err *error, op string) { + if e := recover(); e != nil { + if nerr, ok := e.(osError); ok { + *err = nerr.err + return + } + panic("tabwriter: panic during " + op) + } +} + +// RememberedWidths returns a copy of the remembered per-column maximum widths. +// Requires use of the RememberWidths flag, and is not threadsafe. +func (b *Writer) RememberedWidths() []int { + retval := make([]int, len(b.maxwidths)) + copy(retval, b.maxwidths) + return retval +} + +// SetRememberedWidths sets the remembered per-column maximum widths. +// Requires use of the RememberWidths flag, and is not threadsafe. +func (b *Writer) SetRememberedWidths(widths []int) *Writer { + b.maxwidths = make([]int, len(widths)) + copy(b.maxwidths, widths) + return b +} + +// Flush should be called after the last call to Write to ensure +// that any data buffered in the Writer is written to output. Any +// incomplete escape sequence at the end is considered +// complete for formatting purposes. +func (b *Writer) Flush() error { + return b.flush() +} + +func (b *Writer) flush() (err error) { + defer b.reset() // even in the presence of errors + defer handlePanic(&err, "Flush") + + // add current cell if not empty + if b.cell.size > 0 { + if b.endChar != 0 { + // inside escape - terminate it even if incomplete + b.endEscape() + } + b.terminateCell(false) + } + + // format contents of buffer + b.format(0, 0, len(b.lines)) + return nil +} + +var hbar = []byte("---\n") + +// Write writes buf to the writer b. +// The only errors returned are ones encountered +// while writing to the underlying output stream. +// +func (b *Writer) Write(buf []byte) (n int, err error) { + defer handlePanic(&err, "Write") + + // split text into cells + n = 0 + for i, ch := range buf { + if b.endChar == 0 { + // outside escape + switch ch { + case '\t', '\v', '\n', '\f': + // end of cell + b.append(buf[n:i]) + b.updateWidth() + n = i + 1 // ch consumed + ncells := b.terminateCell(ch == '\t') + if ch == '\n' || ch == '\f' { + // terminate line + b.addLine(ch == '\f') + if ch == '\f' || ncells == 1 { + // A '\f' always forces a flush. Otherwise, if the previous + // line has only one cell which does not have an impact on + // the formatting of the following lines (the last cell per + // line is ignored by format()), thus we can flush the + // Writer contents. + if err = b.Flush(); err != nil { + return + } + if ch == '\f' && b.flags&Debug != 0 { + // indicate section break + b.write0(hbar) + } + } + } + + case Escape: + // start of escaped sequence + b.append(buf[n:i]) + b.updateWidth() + n = i + if b.flags&StripEscape != 0 { + n++ // strip Escape + } + b.startEscape(Escape) + + case '<', '&': + // possibly an html tag/entity + if b.flags&FilterHTML != 0 { + // begin of tag/entity + b.append(buf[n:i]) + b.updateWidth() + n = i + b.startEscape(ch) + } + } + + } else { + // inside escape + if ch == b.endChar { + // end of tag/entity + j := i + 1 + if ch == Escape && b.flags&StripEscape != 0 { + j = i // strip Escape + } + b.append(buf[n:j]) + n = i + 1 // ch consumed + b.endEscape() + } + } + } + + // append leftover text + b.append(buf[n:]) + n = len(buf) + return +} + +// NewWriter allocates and initializes a new tabwriter.Writer. +// The parameters are the same as for the Init function. +// +func NewWriter(output io.Writer, minwidth, tabwidth, padding int, padchar byte, flags uint) *Writer { + return new(Writer).Init(output, minwidth, tabwidth, padding, padchar, flags) +} diff --git a/vendor/github.com/opencontainers/runc/libcontainer/BUILD b/vendor/github.com/opencontainers/runc/libcontainer/BUILD index 32e0b736873..d76cbf280a9 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/BUILD +++ b/vendor/github.com/opencontainers/runc/libcontainer/BUILD @@ -53,6 +53,7 @@ go_library( "//vendor/github.com/opencontainers/runc/libcontainer/system:go_default_library", "//vendor/github.com/opencontainers/runc/libcontainer/user:go_default_library", "//vendor/github.com/opencontainers/selinux/go-selinux/label:go_default_library", + "//vendor/github.com/pkg/errors:go_default_library", "//vendor/github.com/sirupsen/logrus:go_default_library", "//vendor/github.com/syndtr/gocapability/capability:go_default_library", "//vendor/github.com/vishvananda/netlink:go_default_library", diff --git a/vendor/github.com/opencontainers/runc/libcontainer/README.md b/vendor/github.com/opencontainers/runc/libcontainer/README.md index 42f3efe5639..f2a2f0c6c4b 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/README.md +++ b/vendor/github.com/opencontainers/runc/libcontainer/README.md @@ -323,6 +323,7 @@ generated when building libcontainer with docker. ## Copyright and license -Code and documentation copyright 2014 Docker, inc. Code released under the Apache 2.0 license. -Docs released under Creative commons. - +Code and documentation copyright 2014 Docker, inc. +The code and documentation are released under the [Apache 2.0 license](../LICENSE). +The documentation is also released under Creative Commons Attribution 4.0 International License. +You may obtain a copy of the license, titled CC-BY-4.0, at http://creativecommons.org/licenses/by/4.0/. diff --git a/vendor/github.com/opencontainers/runc/libcontainer/SPEC.md b/vendor/github.com/opencontainers/runc/libcontainer/SPEC.md index 4363b6f9f4e..18bf64704b8 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/SPEC.md +++ b/vendor/github.com/opencontainers/runc/libcontainer/SPEC.md @@ -156,17 +156,21 @@ init process will block waiting for the parent to finish setup. ### IntelRdt -Intel platforms with new Xeon CPU support Intel Resource Director Technology -(RDT). Cache Allocation Technology (CAT) is a sub-feature of RDT, which -currently supports L3 cache resource allocation. +Intel platforms with new Xeon CPU support Resource Director Technology (RDT). +Cache Allocation Technology (CAT) and Memory Bandwidth Allocation (MBA) are +two sub-features of RDT. -This feature provides a way for the software to restrict cache allocation to a -defined 'subset' of L3 cache which may be overlapping with other 'subsets'. -The different subsets are identified by class of service (CLOS) and each CLOS -has a capacity bitmask (CBM). +Cache Allocation Technology (CAT) provides a way for the software to restrict +cache allocation to a defined 'subset' of L3 cache which may be overlapping +with other 'subsets'. The different subsets are identified by class of +service (CLOS) and each CLOS has a capacity bitmask (CBM). -It can be used to handle L3 cache resource allocation for containers if -hardware and kernel support Intel RDT/CAT. +Memory Bandwidth Allocation (MBA) provides indirect and approximate throttle +over memory bandwidth for the software. A user controls the resource by +indicating the percentage of maximum memory bandwidth. + +It can be used to handle L3 cache and memory bandwidth resources allocation +for containers if hardware and kernel support Intel RDT CAT and MBA features. In Linux 4.10 kernel or newer, the interface is defined and exposed via "resource control" filesystem, which is a "cgroup-like" interface. @@ -175,6 +179,9 @@ Comparing with cgroups, it has similar process management lifecycle and interfaces in a container. But unlike cgroups' hierarchy, it has single level filesystem layout. +CAT and MBA features are introduced in Linux 4.10 and 4.12 kernel via +"resource control" filesystem. + Intel RDT "resource control" filesystem hierarchy: ``` mount -t resctrl resctrl /sys/fs/resctrl @@ -182,59 +189,85 @@ tree /sys/fs/resctrl /sys/fs/resctrl/ |-- info | |-- L3 -| |-- cbm_mask -| |-- min_cbm_bits +| | |-- cbm_mask +| | |-- min_cbm_bits +| | |-- num_closids +| |-- MB +| |-- bandwidth_gran +| |-- delay_linear +| |-- min_bandwidth | |-- num_closids -|-- cpus +|-- ... |-- schemata |-- tasks |-- - |-- cpus + |-- ... |-- schemata |-- tasks - ``` -For runc, we can make use of `tasks` and `schemata` configuration for L3 cache -resource constraints. +For runc, we can make use of `tasks` and `schemata` configuration for L3 +cache and memory bandwidth resources constraints. The file `tasks` has a list of tasks that belongs to this group (e.g., " group). Tasks can be added to a group by writing the task ID -to the "tasks" file (which will automatically remove them from the previous +to the "tasks" file (which will automatically remove them from the previous group to which they belonged). New tasks created by fork(2) and clone(2) are -added to the same group as their parent. If a pid is not in any sub group, it -is in root group. +added to the same group as their parent. -The file `schemata` has allocation masks/values for L3 cache on each socket, -which contains L3 cache id and capacity bitmask (CBM). +The file `schemata` has a list of all the resources available to this group. +Each resource (L3 cache, memory bandwidth) has its own line and format. + +L3 cache schema: +It has allocation bitmasks/values for L3 cache on each socket, which +contains L3 cache id and capacity bitmask (CBM). ``` Format: "L3:=;=;..." ``` -For example, on a two-socket machine, L3's schema line could be `L3:0=ff;1=c0` -Which means L3 cache id 0's CBM is 0xff, and L3 cache id 1's CBM is 0xc0. +For example, on a two-socket machine, the schema line could be "L3:0=ff;1=c0" +which means L3 cache id 0's CBM is 0xff, and L3 cache id 1's CBM is 0xc0. The valid L3 cache CBM is a *contiguous bits set* and number of bits that can be set is less than the max bit. The max bits in the CBM is varied among -supported Intel Xeon platforms. In Intel RDT "resource control" filesystem -layout, the CBM in a group should be a subset of the CBM in root. Kernel will -check if it is valid when writing. e.g., 0xfffff in root indicates the max bits -of CBM is 20 bits, which mapping to entire L3 cache capacity. Some valid CBM -values to set in a group: 0xf, 0xf0, 0x3ff, 0x1f00 and etc. +supported Intel CPU models. Kernel will check if it is valid when writing. +e.g., default value 0xfffff in root indicates the max bits of CBM is 20 +bits, which mapping to entire L3 cache capacity. Some valid CBM values to +set in a group: 0xf, 0xf0, 0x3ff, 0x1f00 and etc. -For more information about Intel RDT/CAT kernel interface: +Memory bandwidth schema: +It has allocation values for memory bandwidth on each socket, which contains +L3 cache id and memory bandwidth percentage. +``` + Format: "MB:=bandwidth0;=bandwidth1;..." +``` +For example, on a two-socket machine, the schema line could be "MB:0=20;1=70" + +The minimum bandwidth percentage value for each CPU model is predefined and +can be looked up through "info/MB/min_bandwidth". The bandwidth granularity +that is allocated is also dependent on the CPU model and can be looked up at +"info/MB/bandwidth_gran". The available bandwidth control steps are: +min_bw + N * bw_gran. Intermediate values are rounded to the next control +step available on the hardware. + +For more information about Intel RDT kernel interface: https://www.kernel.org/doc/Documentation/x86/intel_rdt_ui.txt -An example for runc: ``` +An example for runc: Consider a two-socket machine with two L3 caches where the default CBM is -0xfffff and the max CBM length is 20 bits. With this configuration, tasks -inside the container only have access to the "upper" 80% of L3 cache id 0 and -the "lower" 50% L3 cache id 1: +0x7ff and the max CBM length is 11 bits, and minimum memory bandwidth of 10% +with a memory bandwidth granularity of 10%. + +Tasks inside the container only have access to the "upper" 7/11 of L3 cache +on socket 0 and the "lower" 5/11 L3 cache on socket 1, and may use a +maximum memory bandwidth of 20% on socket 0 and 70% on socket 1. "linux": { - "intelRdt": { - "l3CacheSchema": "L3:0=ffff0;1=3ff" - } + "intelRdt": { + "closID": "guaranteed_group", + "l3CacheSchema": "L3:0=7f0;1=1f", + "memBwSchema": "MB:0=20;1=70" + } } ``` diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/BUILD b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/BUILD index ff6c5c01009..8626e7a2360 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/BUILD +++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/BUILD @@ -12,6 +12,7 @@ go_library( "freezer.go", "fs_unsupported.go", "hugetlb.go", + "kmem.go", "memory.go", "name.go", "net_cls.go", @@ -29,6 +30,7 @@ go_library( "//vendor/github.com/opencontainers/runc/libcontainer/configs:go_default_library", "//vendor/github.com/opencontainers/runc/libcontainer/system:go_default_library", "//vendor/github.com/opencontainers/runc/libcontainer/utils:go_default_library", + "//vendor/github.com/pkg/errors:go_default_library", "//vendor/golang.org/x/sys/unix:go_default_library", ], "//conditions:default": [], diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/apply_raw.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/apply_raw.go index 6d9123dc26c..74bfcf94f0a 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/apply_raw.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/apply_raw.go @@ -3,7 +3,6 @@ package fs import ( - "errors" "fmt" "io" "io/ioutil" @@ -14,6 +13,8 @@ import ( "github.com/opencontainers/runc/libcontainer/cgroups" "github.com/opencontainers/runc/libcontainer/configs" libcontainerUtils "github.com/opencontainers/runc/libcontainer/utils" + "github.com/pkg/errors" + "golang.org/x/sys/unix" ) var ( @@ -35,7 +36,7 @@ var ( HugePageSizes, _ = cgroups.GetHugePageSize() ) -var errSubsystemDoesNotExist = errors.New("cgroup: subsystem does not exist") +var errSubsystemDoesNotExist = fmt.Errorf("cgroup: subsystem does not exist") type subsystemSet []subsystem @@ -62,9 +63,10 @@ type subsystem interface { } type Manager struct { - mu sync.Mutex - Cgroups *configs.Cgroup - Paths map[string]string + mu sync.Mutex + Cgroups *configs.Cgroup + Rootless bool // ignore permission-related errors + Paths map[string]string } // The absolute path to the root of the cgroup hierarchies. @@ -100,6 +102,33 @@ type cgroupData struct { pid int } +// isIgnorableError returns whether err is a permission error (in the loose +// sense of the word). This includes EROFS (which for an unprivileged user is +// basically a permission error) and EACCES (for similar reasons) as well as +// the normal EPERM. +func isIgnorableError(rootless bool, err error) bool { + // We do not ignore errors if we are root. + if !rootless { + return false + } + // Is it an ordinary EPERM? + if os.IsPermission(errors.Cause(err)) { + return true + } + + // Try to handle other errnos. + var errno error + switch err := errors.Cause(err).(type) { + case *os.PathError: + errno = err.Err + case *os.LinkError: + errno = err.Err + case *os.SyscallError: + errno = err.Err + } + return errno == unix.EROFS || errno == unix.EPERM || errno == unix.EACCES +} + func (m *Manager) Apply(pid int) (err error) { if m.Cgroups == nil { return nil @@ -145,11 +174,11 @@ func (m *Manager) Apply(pid int) (err error) { m.Paths[sys.Name()] = p if err := sys.Apply(d); err != nil { - if os.IsPermission(err) && m.Cgroups.Path == "" { - // If we didn't set a cgroup path, then let's defer the error here - // until we know whether we have set limits or not. - // If we hadn't set limits, then it's ok that we couldn't join this cgroup, because - // it will have the same limits as its parent. + // In the case of rootless (including euid=0 in userns), where an explicit cgroup path hasn't + // been set, we don't bail on error in case of permission problems. + // Cases where limits have been set (and we couldn't create our own + // cgroup) are handled by Set. + if isIgnorableError(m.Rootless, err) && m.Cgroups.Path == "" { delete(m.Paths, sys.Name()) continue } @@ -207,9 +236,16 @@ func (m *Manager) Set(container *configs.Config) error { for _, sys := range subsystems { path := paths[sys.Name()] if err := sys.Set(path, container.Cgroups); err != nil { + if m.Rootless && sys.Name() == "devices" { + continue + } + // When m.Rootless is true, errors from the device subsystem are ignored because it is really not expected to work. + // However, errors from other subsystems are not ignored. + // see @test "runc create (rootless + limits + no cgrouppath + no permission) fails with informative error" if path == "" { - // cgroup never applied - return fmt.Errorf("cannot set limits on the %s cgroup, as the container has not joined it", sys.Name()) + // We never created a path for this cgroup, so we cannot set + // limits for it (though we have already tried at this point). + return fmt.Errorf("cannot set %s limit: container could not join or create cgroup", sys.Name()) } return err } diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/cpu.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/cpu.go index b712bd0b1ed..e240a8313a2 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/cpu.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/cpu.go @@ -46,11 +46,7 @@ func (s *CpuGroup) ApplyDir(path string, cgroup *configs.Cgroup, pid int) error } // because we are not using d.join we need to place the pid into the procs file // unlike the other subsystems - if err := cgroups.WriteCgroupProc(path, pid); err != nil { - return err - } - - return nil + return cgroups.WriteCgroupProc(path, pid) } func (s *CpuGroup) SetRtSched(path string, cgroup *configs.Cgroup) error { @@ -83,11 +79,7 @@ func (s *CpuGroup) Set(path string, cgroup *configs.Cgroup) error { return err } } - if err := s.SetRtSched(path, cgroup); err != nil { - return err - } - - return nil + return s.SetRtSched(path, cgroup) } func (s *CpuGroup) Remove(d *cgroupData) error { diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/cpuset.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/cpuset.go index 20c9eafac24..5a1d152ea1d 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/cpuset.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/cpuset.go @@ -77,18 +77,14 @@ func (s *CpusetGroup) ApplyDir(dir string, cgroup *configs.Cgroup, pid int) erro // The logic is, if user specified cpuset configs, use these // specified configs, otherwise, inherit from parent. This makes // cpuset configs work correctly with 'cpuset.cpu_exclusive', and - // keep backward compatbility. + // keep backward compatibility. if err := s.ensureCpusAndMems(dir, cgroup); err != nil { return err } // because we are not using d.join we need to place the pid into the procs file // unlike the other subsystems - if err := cgroups.WriteCgroupProc(dir, pid); err != nil { - return err - } - - return nil + return cgroups.WriteCgroupProc(dir, pid) } func (s *CpusetGroup) getSubsystemSettings(parent string) (cpus []byte, mems []byte, err error) { diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/kmem.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/kmem.go new file mode 100644 index 00000000000..8df7377702a --- /dev/null +++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/kmem.go @@ -0,0 +1,55 @@ +// +build linux,!nokmem + +package fs + +import ( + "fmt" + "io/ioutil" + "os" + "path/filepath" + "strconv" + "syscall" // for Errno type only + + "github.com/opencontainers/runc/libcontainer/cgroups" + "golang.org/x/sys/unix" +) + +const cgroupKernelMemoryLimit = "memory.kmem.limit_in_bytes" + +func EnableKernelMemoryAccounting(path string) error { + // Check if kernel memory is enabled + // We have to limit the kernel memory here as it won't be accounted at all + // until a limit is set on the cgroup and limit cannot be set once the + // cgroup has children, or if there are already tasks in the cgroup. + for _, i := range []int64{1, -1} { + if err := setKernelMemory(path, i); err != nil { + return err + } + } + return nil +} + +func setKernelMemory(path string, kernelMemoryLimit int64) error { + if path == "" { + return fmt.Errorf("no such directory for %s", cgroupKernelMemoryLimit) + } + if !cgroups.PathExists(filepath.Join(path, cgroupKernelMemoryLimit)) { + // kernel memory is not enabled on the system so we should do nothing + return nil + } + if err := ioutil.WriteFile(filepath.Join(path, cgroupKernelMemoryLimit), []byte(strconv.FormatInt(kernelMemoryLimit, 10)), 0700); err != nil { + // Check if the error number returned by the syscall is "EBUSY" + // The EBUSY signal is returned on attempts to write to the + // memory.kmem.limit_in_bytes file if the cgroup has children or + // once tasks have been attached to the cgroup + if pathErr, ok := err.(*os.PathError); ok { + if errNo, ok := pathErr.Err.(syscall.Errno); ok { + if errNo == unix.EBUSY { + return fmt.Errorf("failed to set %s, because either tasks have already joined this cgroup or it has children", cgroupKernelMemoryLimit) + } + } + } + return fmt.Errorf("failed to write %v to %v: %v", kernelMemoryLimit, cgroupKernelMemoryLimit, err) + } + return nil +} diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/kmem_disabled.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/kmem_disabled.go new file mode 100644 index 00000000000..12253b6bbbf --- /dev/null +++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/kmem_disabled.go @@ -0,0 +1,11 @@ +// +build linux,nokmem + +package fs + +func EnableKernelMemoryAccounting(path string) error { + return nil +} + +func setKernelMemory(path string, kernelMemoryLimit int64) error { + return nil +} diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/memory.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/memory.go index ad395a5d621..d5310d569f2 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/memory.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/memory.go @@ -5,23 +5,18 @@ package fs import ( "bufio" "fmt" - "io/ioutil" "os" "path/filepath" "strconv" "strings" - "syscall" // only for Errno "github.com/opencontainers/runc/libcontainer/cgroups" "github.com/opencontainers/runc/libcontainer/configs" - - "golang.org/x/sys/unix" ) const ( - cgroupKernelMemoryLimit = "memory.kmem.limit_in_bytes" - cgroupMemorySwapLimit = "memory.memsw.limit_in_bytes" - cgroupMemoryLimit = "memory.limit_in_bytes" + cgroupMemorySwapLimit = "memory.memsw.limit_in_bytes" + cgroupMemoryLimit = "memory.limit_in_bytes" ) type MemoryGroup struct { @@ -67,44 +62,6 @@ func (s *MemoryGroup) Apply(d *cgroupData) (err error) { return nil } -func EnableKernelMemoryAccounting(path string) error { - // Check if kernel memory is enabled - // We have to limit the kernel memory here as it won't be accounted at all - // until a limit is set on the cgroup and limit cannot be set once the - // cgroup has children, or if there are already tasks in the cgroup. - for _, i := range []int64{1, -1} { - if err := setKernelMemory(path, i); err != nil { - return err - } - } - return nil -} - -func setKernelMemory(path string, kernelMemoryLimit int64) error { - if path == "" { - return fmt.Errorf("no such directory for %s", cgroupKernelMemoryLimit) - } - if !cgroups.PathExists(filepath.Join(path, cgroupKernelMemoryLimit)) { - // kernel memory is not enabled on the system so we should do nothing - return nil - } - if err := ioutil.WriteFile(filepath.Join(path, cgroupKernelMemoryLimit), []byte(strconv.FormatInt(kernelMemoryLimit, 10)), 0700); err != nil { - // Check if the error number returned by the syscall is "EBUSY" - // The EBUSY signal is returned on attempts to write to the - // memory.kmem.limit_in_bytes file if the cgroup has children or - // once tasks have been attached to the cgroup - if pathErr, ok := err.(*os.PathError); ok { - if errNo, ok := pathErr.Err.(syscall.Errno); ok { - if errNo == unix.EBUSY { - return fmt.Errorf("failed to set %s, because either tasks have already joined this cgroup or it has children", cgroupKernelMemoryLimit) - } - } - } - return fmt.Errorf("failed to write %v to %v: %v", kernelMemoryLimit, cgroupKernelMemoryLimit, err) - } - return nil -} - func setMemoryAndSwap(path string, cgroup *configs.Cgroup) error { // If the memory update is set to -1 we should also // set swap to -1, it means unlimited memory. diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/systemd/apply_systemd.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/systemd/apply_systemd.go index 66502263e0f..30bf5eaeaec 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/systemd/apply_systemd.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/systemd/apply_systemd.go @@ -5,6 +5,7 @@ package systemd import ( "errors" "fmt" + "math" "os" "path/filepath" "strings" @@ -295,13 +296,19 @@ func (m *Manager) Apply(pid int) error { // cpu.cfs_quota_us and cpu.cfs_period_us are controlled by systemd. if c.Resources.CpuQuota != 0 && c.Resources.CpuPeriod != 0 { - cpuQuotaPerSecUSec := uint64(c.Resources.CpuQuota*1000000) / c.Resources.CpuPeriod - // systemd converts CPUQuotaPerSecUSec (microseconds per CPU second) to CPUQuota - // (integer percentage of CPU) internally. This means that if a fractional percent of - // CPU is indicated by Resources.CpuQuota, we need to round up to the nearest - // 10ms (1% of a second) such that child cgroups can set the cpu.cfs_quota_us they expect. - if cpuQuotaPerSecUSec%10000 != 0 { - cpuQuotaPerSecUSec = ((cpuQuotaPerSecUSec / 10000) + 1) * 10000 + // corresponds to USEC_INFINITY in systemd + // if USEC_INFINITY is provided, CPUQuota is left unbound by systemd + // always setting a property value ensures we can apply a quota and remove it later + cpuQuotaPerSecUSec := uint64(math.MaxUint64) + if c.Resources.CpuQuota > 0 { + // systemd converts CPUQuotaPerSecUSec (microseconds per CPU second) to CPUQuota + // (integer percentage of CPU) internally. This means that if a fractional percent of + // CPU is indicated by Resources.CpuQuota, we need to round up to the nearest + // 10ms (1% of a second) such that child cgroups can set the cpu.cfs_quota_us they expect. + cpuQuotaPerSecUSec = uint64(c.Resources.CpuQuota*1000000) / c.Resources.CpuPeriod + if cpuQuotaPerSecUSec%10000 != 0 { + cpuQuotaPerSecUSec = ((cpuQuotaPerSecUSec / 10000) + 1) * 10000 + } } properties = append(properties, newProp("CPUQuotaPerSecUSec", cpuQuotaPerSecUSec)) @@ -312,6 +319,12 @@ func (m *Manager) Apply(pid int) error { newProp("BlockIOWeight", uint64(c.Resources.BlkioWeight))) } + if c.Resources.PidsLimit > 0 { + properties = append(properties, + newProp("TasksAccounting", true), + newProp("TasksMax", uint64(c.Resources.PidsLimit))) + } + // We have to set kernel memory here, as we can't change it once // processes have been attached to the cgroup. if c.Resources.KernelMemory != 0 { diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/utils.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/utils.go index 7c995efee51..7c61ff13fcc 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/utils.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/utils.go @@ -13,7 +13,7 @@ import ( "strings" "time" - "github.com/docker/go-units" + units "github.com/docker/go-units" ) const ( @@ -103,7 +103,7 @@ func FindCgroupMountpointDir() (string, error) { } if postSeparatorFields[0] == "cgroup" { - // Check that the mount is properly formated. + // Check that the mount is properly formatted. if numPostFields < 3 { return "", fmt.Errorf("Error found less than 3 fields post '-' in %q", text) } @@ -151,19 +151,20 @@ func getCgroupMountsHelper(ss map[string]bool, mi io.Reader, all bool) ([]Mount, Root: fields[3], } for _, opt := range strings.Split(fields[len(fields)-1], ",") { - if !ss[opt] { + seen, known := ss[opt] + if !known || (!all && seen) { continue } + ss[opt] = true if strings.HasPrefix(opt, cgroupNamePrefix) { - m.Subsystems = append(m.Subsystems, opt[len(cgroupNamePrefix):]) - } else { - m.Subsystems = append(m.Subsystems, opt) - } - if !all { - numFound++ + opt = opt[len(cgroupNamePrefix):] } + m.Subsystems = append(m.Subsystems, opt) + numFound++ + } + if len(m.Subsystems) > 0 || all { + res = append(res, m) } - res = append(res, m) } if err := scanner.Err(); err != nil { return nil, err @@ -187,7 +188,7 @@ func GetCgroupMounts(all bool) ([]Mount, error) { allMap := make(map[string]bool) for s := range allSubsystems { - allMap[s] = true + allMap[s] = false } return getCgroupMountsHelper(allMap, f, all) } @@ -262,7 +263,7 @@ func getCgroupPathHelper(subsystem, cgroup string) (string, error) { } // This is needed for nested containers, because in /proc/self/cgroup we - // see pathes from host, which don't exist in container. + // see paths from host, which don't exist in container. relCgroup, err := filepath.Rel(root, cgroup) if err != nil { return "", err diff --git a/vendor/github.com/opencontainers/runc/libcontainer/configs/config.go b/vendor/github.com/opencontainers/runc/libcontainer/configs/config.go index 3cae4fd8d96..b065f7f28ec 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/configs/config.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/configs/config.go @@ -141,9 +141,10 @@ type Config struct { // OomScoreAdj specifies the adjustment to be made by the kernel when calculating oom scores // for a process. Valid values are between the range [-1000, '1000'], where processes with - // higher scores are preferred for being killed. + // higher scores are preferred for being killed. If it is unset then we don't touch the current + // value. // More information about kernel oom score calculation here: https://lwn.net/Articles/317814/ - OomScoreAdj int `json:"oom_score_adj"` + OomScoreAdj *int `json:"oom_score_adj,omitempty"` // UidMappings is an array of User ID mappings for User Namespaces UidMappings []IDMap `json:"uid_mappings"` @@ -185,12 +186,19 @@ type Config struct { // callers keyring in this case. NoNewKeyring bool `json:"no_new_keyring"` - // Rootless specifies whether the container is a rootless container. - Rootless bool `json:"rootless"` - - // IntelRdt specifies settings for Intel RDT/CAT group that the container is placed into - // to limit the resources (e.g., L3 cache) the container has available + // IntelRdt specifies settings for Intel RDT group that the container is placed into + // to limit the resources (e.g., L3 cache, memory bandwidth) the container has available IntelRdt *IntelRdt `json:"intel_rdt,omitempty"` + + // RootlessEUID is set when the runc was launched with non-zero EUID. + // Note that RootlessEUID is set to false when launched with EUID=0 in userns. + // When RootlessEUID is set, runc creates a new userns for the container. + // (config.json needs to contain userns settings) + RootlessEUID bool `json:"rootless_euid,omitempty"` + + // RootlessCgroups is set when unlikely to have the full access to cgroups. + // When RootlessCgroups is set, cgroups errors are ignored. + RootlessCgroups bool `json:"rootless_cgroups,omitempty"` } type Hooks struct { diff --git a/vendor/github.com/opencontainers/runc/libcontainer/configs/intelrdt.go b/vendor/github.com/opencontainers/runc/libcontainer/configs/intelrdt.go index 36bd5f96a11..6f47aac077d 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/configs/intelrdt.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/configs/intelrdt.go @@ -4,4 +4,8 @@ type IntelRdt struct { // The schema for L3 cache id and capacity bitmask (CBM) // Format: "L3:=;=;..." L3CacheSchema string `json:"l3_cache_schema,omitempty"` + + // The schema of memory bandwidth percentage per L3 cache id + // Format: "MB:=bandwidth0;=bandwidth1;..." + MemBwSchema string `json:"memBwSchema,omitempty"` } diff --git a/vendor/github.com/opencontainers/runc/libcontainer/configs/validate/rootless.go b/vendor/github.com/opencontainers/runc/libcontainer/configs/validate/rootless.go index e532ac8fe28..393d9e81ee9 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/configs/validate/rootless.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/configs/validate/rootless.go @@ -2,23 +2,18 @@ package validate import ( "fmt" - "os" - "reflect" "strings" "github.com/opencontainers/runc/libcontainer/configs" ) -var ( - geteuid = os.Geteuid - getegid = os.Getegid -) - -func (v *ConfigValidator) rootless(config *configs.Config) error { - if err := rootlessMappings(config); err != nil { +// rootlessEUID makes sure that the config can be applied when runc +// is being executed as a non-root user (euid != 0) in the current user namespace. +func (v *ConfigValidator) rootlessEUID(config *configs.Config) error { + if err := rootlessEUIDMappings(config); err != nil { return err } - if err := rootlessMount(config); err != nil { + if err := rootlessEUIDMount(config); err != nil { return err } @@ -38,11 +33,9 @@ func hasIDMapping(id int, mappings []configs.IDMap) bool { return false } -func rootlessMappings(config *configs.Config) error { - if euid := geteuid(); euid != 0 { - if !config.Namespaces.Contains(configs.NEWUSER) { - return fmt.Errorf("rootless containers require user namespaces") - } +func rootlessEUIDMappings(config *configs.Config) error { + if !config.Namespaces.Contains(configs.NEWUSER) { + return fmt.Errorf("rootless container requires user namespaces") } if len(config.UidMappings) == 0 { @@ -51,34 +44,13 @@ func rootlessMappings(config *configs.Config) error { if len(config.GidMappings) == 0 { return fmt.Errorf("rootless containers requires at least one GID mapping") } - - return nil -} - -// cgroup verifies that the user isn't trying to set any cgroup limits or paths. -func rootlessCgroup(config *configs.Config) error { - // Nothing set at all. - if config.Cgroups == nil || config.Cgroups.Resources == nil { - return nil - } - - // Used for comparing to the zero value. - left := reflect.ValueOf(*config.Cgroups.Resources) - right := reflect.Zero(left.Type()) - - // This is all we need to do, since specconv won't add cgroup options in - // rootless mode. - if !reflect.DeepEqual(left.Interface(), right.Interface()) { - return fmt.Errorf("cannot specify resource limits in rootless container") - } - return nil } // mount verifies that the user isn't trying to set up any mounts they don't have // the rights to do. In addition, it makes sure that no mount has a `uid=` or // `gid=` option that doesn't resolve to root. -func rootlessMount(config *configs.Config) error { +func rootlessEUIDMount(config *configs.Config) error { // XXX: We could whitelist allowed devices at this point, but I'm not // convinced that's a good idea. The kernel is the best arbiter of // access control. diff --git a/vendor/github.com/opencontainers/runc/libcontainer/configs/validate/validator.go b/vendor/github.com/opencontainers/runc/libcontainer/configs/validate/validator.go index cbbba9a03a2..9c78141ebd3 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/configs/validate/validator.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/configs/validate/validator.go @@ -44,8 +44,8 @@ func (v *ConfigValidator) Validate(config *configs.Config) error { if err := v.intelrdt(config); err != nil { return err } - if config.Rootless { - if err := v.rootless(config); err != nil { + if config.RootlessEUID { + if err := v.rootlessEUID(config); err != nil { return err } } @@ -151,6 +151,16 @@ func (v *ConfigValidator) sysctl(config *configs.Config) error { return fmt.Errorf("sysctl %q is not allowed in the hosts network namespace", s) } } + if config.Namespaces.Contains(configs.NEWUTS) { + switch s { + case "kernel.domainname": + // This is namespaced and there's no explicit OCI field for it. + continue + case "kernel.hostname": + // This is namespaced but there's a conflicting (dedicated) OCI field for it. + return fmt.Errorf("sysctl %q is not allowed as it conflicts with the OCI %q field", s, "hostname") + } + } return fmt.Errorf("sysctl %q is not in a separate kernel namespace", s) } @@ -159,11 +169,22 @@ func (v *ConfigValidator) sysctl(config *configs.Config) error { func (v *ConfigValidator) intelrdt(config *configs.Config) error { if config.IntelRdt != nil { - if !intelrdt.IsEnabled() { - return fmt.Errorf("intelRdt is specified in config, but Intel RDT feature is not supported or enabled") + if !intelrdt.IsCatEnabled() && !intelrdt.IsMbaEnabled() { + return fmt.Errorf("intelRdt is specified in config, but Intel RDT is not supported or enabled") } - if config.IntelRdt.L3CacheSchema == "" { - return fmt.Errorf("intelRdt is specified in config, but intelRdt.l3CacheSchema is empty") + + if !intelrdt.IsCatEnabled() && config.IntelRdt.L3CacheSchema != "" { + return fmt.Errorf("intelRdt.l3CacheSchema is specified in config, but Intel RDT/CAT is not enabled") + } + if !intelrdt.IsMbaEnabled() && config.IntelRdt.MemBwSchema != "" { + return fmt.Errorf("intelRdt.memBwSchema is specified in config, but Intel RDT/MBA is not enabled") + } + + if intelrdt.IsCatEnabled() && config.IntelRdt.L3CacheSchema == "" { + return fmt.Errorf("Intel RDT/CAT is enabled and intelRdt is specified in config, but intelRdt.l3CacheSchema is empty") + } + if intelrdt.IsMbaEnabled() && config.IntelRdt.MemBwSchema == "" { + return fmt.Errorf("Intel RDT/MBA is enabled and intelRdt is specified in config, but intelRdt.memBwSchema is empty") } } diff --git a/vendor/github.com/opencontainers/runc/libcontainer/container_linux.go b/vendor/github.com/opencontainers/runc/libcontainer/container_linux.go index 246ec95f362..f8caa4b8991 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/container_linux.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/container_linux.go @@ -28,7 +28,6 @@ import ( "github.com/golang/protobuf/proto" "github.com/sirupsen/logrus" - "github.com/syndtr/gocapability/capability" "github.com/vishvananda/netlink/nl" "golang.org/x/sys/unix" ) @@ -60,7 +59,8 @@ type State struct { // Platform specific fields below here - // Specifies if the container was started under the rootless mode. + // Specified if the container was started under the rootless mode. + // Set to true if BaseState.Config.RootlessEUID && BaseState.Config.RootlessCgroups Rootless bool `json:"rootless"` // Path to all the cgroups setup for a container. Key is cgroup subsystem name @@ -225,17 +225,13 @@ func (c *linuxContainer) Set(config configs.Config) error { func (c *linuxContainer) Start(process *Process) error { c.m.Lock() defer c.m.Unlock() - status, err := c.currentStatus() - if err != nil { - return err - } - if status == Stopped { + if process.Init { if err := c.createExecFifo(); err != nil { return err } } - if err := c.start(process, status == Stopped); err != nil { - if status == Stopped { + if err := c.start(process); err != nil { + if process.Init { c.deleteExecFifo() } return err @@ -244,17 +240,10 @@ func (c *linuxContainer) Start(process *Process) error { } func (c *linuxContainer) Run(process *Process) error { - c.m.Lock() - status, err := c.currentStatus() - if err != nil { - c.m.Unlock() - return err - } - c.m.Unlock() if err := c.Start(process); err != nil { return err } - if status == Stopped { + if process.Init { return c.exec() } return nil @@ -335,8 +324,8 @@ type openResult struct { err error } -func (c *linuxContainer) start(process *Process, isInit bool) error { - parent, err := c.newParentProcess(process, isInit) +func (c *linuxContainer) start(process *Process) error { + parent, err := c.newParentProcess(process) if err != nil { return newSystemErrorWithCause(err, "creating new parent process") } @@ -349,7 +338,7 @@ func (c *linuxContainer) start(process *Process, isInit bool) error { } // generate a timestamp indicating when the container was started c.created = time.Now().UTC() - if isInit { + if process.Init { c.state = &createdState{ c: c, } @@ -411,10 +400,7 @@ func (c *linuxContainer) createExecFifo() error { return err } unix.Umask(oldMask) - if err := os.Chown(fifoName, rootuid, rootgid); err != nil { - return err - } - return nil + return os.Chown(fifoName, rootuid, rootgid) } func (c *linuxContainer) deleteExecFifo() { @@ -439,7 +425,7 @@ func (c *linuxContainer) includeExecFifo(cmd *exec.Cmd) error { return nil } -func (c *linuxContainer) newParentProcess(p *Process, doInit bool) (parentProcess, error) { +func (c *linuxContainer) newParentProcess(p *Process) (parentProcess, error) { parentPipe, childPipe, err := utils.NewSockPair("init") if err != nil { return nil, newSystemErrorWithCause(err, "creating new init pipe") @@ -448,7 +434,7 @@ func (c *linuxContainer) newParentProcess(p *Process, doInit bool) (parentProces if err != nil { return nil, newSystemErrorWithCause(err, "creating new command template") } - if !doInit { + if !p.Init { return c.newSetnsProcess(p, cmd, parentPipe, childPipe) } @@ -473,6 +459,7 @@ func (c *linuxContainer) commandTemplate(p *Process, childPipe *os.File) (*exec. if cmd.SysProcAttr == nil { cmd.SysProcAttr = &syscall.SysProcAttr{} } + cmd.Env = append(cmd.Env, fmt.Sprintf("GOMAXPROCS=%s", os.Getenv("GOMAXPROCS"))) cmd.ExtraFiles = append(cmd.ExtraFiles, p.ExtraFiles...) if p.ConsoleSocket != nil { cmd.ExtraFiles = append(cmd.ExtraFiles, p.ConsoleSocket) @@ -533,14 +520,15 @@ func (c *linuxContainer) newSetnsProcess(p *Process, cmd *exec.Cmd, parentPipe, return nil, err } return &setnsProcess{ - cmd: cmd, - cgroupPaths: c.cgroupManager.GetPaths(), - intelRdtPath: state.IntelRdtPath, - childPipe: childPipe, - parentPipe: parentPipe, - config: c.newInitConfig(p), - process: p, - bootstrapData: data, + cmd: cmd, + cgroupPaths: c.cgroupManager.GetPaths(), + rootlessCgroups: c.config.RootlessCgroups, + intelRdtPath: state.IntelRdtPath, + childPipe: childPipe, + parentPipe: parentPipe, + config: c.newInitConfig(p), + process: p, + bootstrapData: data, }, nil } @@ -556,7 +544,8 @@ func (c *linuxContainer) newInitConfig(process *Process) *initConfig { PassedFilesCount: len(process.ExtraFiles), ContainerId: c.ID(), NoNewPrivileges: c.config.NoNewPrivileges, - Rootless: c.config.Rootless, + RootlessEUID: c.config.RootlessEUID, + RootlessCgroups: c.config.RootlessCgroups, AppArmorProfile: c.config.AppArmorProfile, ProcessLabel: c.config.ProcessLabel, Rlimits: c.config.Rlimits, @@ -624,16 +613,16 @@ func (c *linuxContainer) Resume() error { func (c *linuxContainer) NotifyOOM() (<-chan struct{}, error) { // XXX(cyphar): This requires cgroups. - if c.config.Rootless { - return nil, fmt.Errorf("cannot get OOM notifications from rootless container") + if c.config.RootlessCgroups { + logrus.Warn("getting OOM notifications may fail if you don't have the full access to cgroups") } return notifyOnOOM(c.cgroupManager.GetPaths()) } func (c *linuxContainer) NotifyMemoryPressure(level PressureLevel) (<-chan struct{}, error) { // XXX(cyphar): This requires cgroups. - if c.config.Rootless { - return nil, fmt.Errorf("cannot get memory pressure notifications from rootless container") + if c.config.RootlessCgroups { + logrus.Warn("getting memory pressure notifications may fail if you don't have the full access to cgroups") } return notifyMemoryPressure(c.cgroupManager.GetPaths(), level) } @@ -668,7 +657,7 @@ func (c *linuxContainer) checkCriuFeatures(criuOpts *CriuOpts, rpcOpts *criurpc. Features: criuFeat, } - err := c.criuSwrk(nil, req, criuOpts, false) + err := c.criuSwrk(nil, req, criuOpts, false, nil) if err != nil { logrus.Debugf("%s", err) return fmt.Errorf("CRIU feature check failed") @@ -781,7 +770,7 @@ func (c *linuxContainer) checkCriuVersion(minVersion int) error { Type: &t, } - err := c.criuSwrk(nil, req, nil, false) + err := c.criuSwrk(nil, req, nil, false, nil) if err != nil { return fmt.Errorf("CRIU version check failed: %s", err) } @@ -877,12 +866,11 @@ func (c *linuxContainer) Checkpoint(criuOpts *CriuOpts) error { c.m.Lock() defer c.m.Unlock() + // Checkpoint is unlikely to work if os.Geteuid() != 0 || system.RunningInUserNS(). + // (CLI prints a warning) // TODO(avagin): Figure out how to make this work nicely. CRIU 2.0 has // support for doing unprivileged dumps, but the setup of // rootless containers might make this complicated. - if c.config.Rootless { - return fmt.Errorf("cannot checkpoint a rootless container") - } // criu 1.5.2 => 10502 if err := c.checkCriuVersion(10502); err != nil { @@ -939,6 +927,33 @@ func (c *linuxContainer) Checkpoint(criuOpts *CriuOpts) error { LazyPages: proto.Bool(criuOpts.LazyPages), } + // If the container is running in a network namespace and has + // a path to the network namespace configured, we will dump + // that network namespace as an external namespace and we + // will expect that the namespace exists during restore. + // This basically means that CRIU will ignore the namespace + // and expect to be setup correctly. + nsPath := c.config.Namespaces.PathOf(configs.NEWNET) + if nsPath != "" { + // For this to work we need at least criu 3.11.0 => 31100. + // As there was already a successful version check we will + // not error out if it fails. runc will just behave as it used + // to do and ignore external network namespaces. + err := c.checkCriuVersion(31100) + if err == nil { + // CRIU expects the information about an external namespace + // like this: --external net[]: + // This is always 'extRootNetNS'. + var netns syscall.Stat_t + err = syscall.Stat(nsPath, &netns) + if err != nil { + return err + } + criuExternal := fmt.Sprintf("net[%d]:extRootNetNS", netns.Ino) + rpcOpts.External = append(rpcOpts.External, criuExternal) + } + } + fcg := c.cgroupManager.GetPaths()["freezer"] if fcg != "" { rpcOpts.FreezeCgroup = proto.String(fcg) @@ -1043,7 +1058,7 @@ func (c *linuxContainer) Checkpoint(criuOpts *CriuOpts) error { } } - err = c.criuSwrk(nil, req, criuOpts, false) + err = c.criuSwrk(nil, req, criuOpts, false, nil) if err != nil { return err } @@ -1087,11 +1102,12 @@ func (c *linuxContainer) Restore(process *Process, criuOpts *CriuOpts) error { c.m.Lock() defer c.m.Unlock() + var extraFiles []*os.File + + // Restore is unlikely to work if os.Geteuid() != 0 || system.RunningInUserNS(). + // (CLI prints a warning) // TODO(avagin): Figure out how to make this work nicely. CRIU doesn't have // support for unprivileged restore at the moment. - if c.config.Rootless { - return fmt.Errorf("cannot restore a rootless container") - } // criu 1.5.2 => 10502 if err := c.checkCriuVersion(10502); err != nil { @@ -1161,6 +1177,38 @@ func (c *linuxContainer) Restore(process *Process, criuOpts *CriuOpts) error { }, } + // Same as during checkpointing. If the container has a specific network namespace + // assigned to it, this now expects that the checkpoint will be restored in a + // already created network namespace. + nsPath := c.config.Namespaces.PathOf(configs.NEWNET) + if nsPath != "" { + // For this to work we need at least criu 3.11.0 => 31100. + // As there was already a successful version check we will + // not error out if it fails. runc will just behave as it used + // to do and ignore external network namespaces. + err := c.checkCriuVersion(31100) + if err == nil { + // CRIU wants the information about an existing network namespace + // like this: --inherit-fd fd[]: + // The needs to be the same as during checkpointing. + // We are always using 'extRootNetNS' as the key in this. + netns, err := os.Open(nsPath) + defer netns.Close() + if err != nil { + logrus.Errorf("If a specific network namespace is defined it must exist: %s", err) + return fmt.Errorf("Requested network namespace %v does not exist", nsPath) + } + inheritFd := new(criurpc.InheritFd) + inheritFd.Key = proto.String("extRootNetNS") + // The offset of four is necessary because 0, 1, 2 and 3 is already + // used by stdin, stdout, stderr, 'criu swrk' socket. + inheritFd.Fd = proto.Int32(int32(4 + len(extraFiles))) + req.Opts.InheritFd = append(req.Opts.InheritFd, inheritFd) + // All open FDs need to be transferred to CRIU via extraFiles + extraFiles = append(extraFiles, netns) + } + } + for _, m := range c.config.Mounts { switch m.Device { case "bind": @@ -1219,7 +1267,7 @@ func (c *linuxContainer) Restore(process *Process, criuOpts *CriuOpts) error { req.Opts.InheritFd = append(req.Opts.InheritFd, inheritFd) } } - return c.criuSwrk(process, req, criuOpts, true) + return c.criuSwrk(process, req, criuOpts, true, extraFiles) } func (c *linuxContainer) criuApplyCgroups(pid int, req *criurpc.CriuReq) error { @@ -1249,7 +1297,7 @@ func (c *linuxContainer) criuApplyCgroups(pid int, req *criurpc.CriuReq) error { return nil } -func (c *linuxContainer) criuSwrk(process *Process, req *criurpc.CriuReq, opts *CriuOpts, applyCgroups bool) error { +func (c *linuxContainer) criuSwrk(process *Process, req *criurpc.CriuReq, opts *CriuOpts, applyCgroups bool, extraFiles []*os.File) error { fds, err := unix.Socketpair(unix.AF_LOCAL, unix.SOCK_SEQPACKET|unix.SOCK_CLOEXEC, 0) if err != nil { return err @@ -1290,6 +1338,9 @@ func (c *linuxContainer) criuSwrk(process *Process, req *criurpc.CriuReq, opts * cmd.Stderr = process.Stderr } cmd.ExtraFiles = append(cmd.ExtraFiles, criuServer) + if extraFiles != nil { + cmd.ExtraFiles = append(cmd.ExtraFiles, extraFiles...) + } if err := cmd.Start(); err != nil { return err @@ -1664,7 +1715,7 @@ func (c *linuxContainer) currentState() (*State, error) { InitProcessStartTime: startTime, Created: c.created, }, - Rootless: c.config.Rootless, + Rootless: c.config.RootlessEUID && c.config.RootlessCgroups, CgroupPaths: c.cgroupManager.GetPaths(), IntelRdtPath: intelRdtPath, NamespacePaths: make(map[configs.NamespaceType]string), @@ -1765,7 +1816,7 @@ func (c *linuxContainer) bootstrapData(cloneFlags uintptr, nsMaps map[configs.Na if !joinExistingUser { // write uid mappings if len(c.config.UidMappings) > 0 { - if c.config.Rootless && c.newuidmapPath != "" { + if c.config.RootlessEUID && c.newuidmapPath != "" { r.AddData(&Bytemsg{ Type: UidmapPathAttr, Value: []byte(c.newuidmapPath), @@ -1791,38 +1842,33 @@ func (c *linuxContainer) bootstrapData(cloneFlags uintptr, nsMaps map[configs.Na Type: GidmapAttr, Value: b, }) - if c.config.Rootless && c.newgidmapPath != "" { + if c.config.RootlessEUID && c.newgidmapPath != "" { r.AddData(&Bytemsg{ Type: GidmapPathAttr, Value: []byte(c.newgidmapPath), }) } if requiresRootOrMappingTool(c.config) { - // check if we have CAP_SETGID to setgroup properly - pid, err := capability.NewPid(0) - if err != nil { - return nil, err - } - if !pid.Get(capability.EFFECTIVE, capability.CAP_SETGID) { - r.AddData(&Boolmsg{ - Type: SetgroupAttr, - Value: true, - }) - } + r.AddData(&Boolmsg{ + Type: SetgroupAttr, + Value: true, + }) } } } - // write oom_score_adj - r.AddData(&Bytemsg{ - Type: OomScoreAdjAttr, - Value: []byte(fmt.Sprintf("%d", c.config.OomScoreAdj)), - }) + if c.config.OomScoreAdj != nil { + // write oom_score_adj + r.AddData(&Bytemsg{ + Type: OomScoreAdjAttr, + Value: []byte(fmt.Sprintf("%d", *c.config.OomScoreAdj)), + }) + } // write rootless r.AddData(&Boolmsg{ - Type: RootlessAttr, - Value: c.config.Rootless, + Type: RootlessEUIDAttr, + Value: c.config.RootlessEUID, }) return bytes.NewReader(r.Serialize()), nil diff --git a/vendor/github.com/opencontainers/runc/libcontainer/factory_linux.go b/vendor/github.com/opencontainers/runc/libcontainer/factory_linux.go index 7d53d5e04d8..e35957c3148 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/factory_linux.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/factory_linux.go @@ -11,6 +11,7 @@ import ( "runtime/debug" "strconv" + "github.com/cyphar/filepath-securejoin" "github.com/opencontainers/runc/libcontainer/cgroups" "github.com/opencontainers/runc/libcontainer/cgroups/fs" "github.com/opencontainers/runc/libcontainer/cgroups/systemd" @@ -59,9 +60,9 @@ func SystemdCgroups(l *LinuxFactory) error { return nil } -// Cgroupfs is an options func to configure a LinuxFactory to return -// containers that use the native cgroups filesystem implementation to -// create and manage cgroups. +// Cgroupfs is an options func to configure a LinuxFactory to return containers +// that use the native cgroups filesystem implementation to create and manage +// cgroups. func Cgroupfs(l *LinuxFactory) error { l.NewCgroupsManager = func(config *configs.Cgroup, paths map[string]string) cgroups.Manager { return &fs.Manager{ @@ -72,9 +73,26 @@ func Cgroupfs(l *LinuxFactory) error { return nil } +// RootlessCgroupfs is an options func to configure a LinuxFactory to return +// containers that use the native cgroups filesystem implementation to create +// and manage cgroups. The difference between RootlessCgroupfs and Cgroupfs is +// that RootlessCgroupfs can transparently handle permission errors that occur +// during rootless container (including euid=0 in userns) setup (while still allowing cgroup usage if +// they've been set up properly). +func RootlessCgroupfs(l *LinuxFactory) error { + l.NewCgroupsManager = func(config *configs.Cgroup, paths map[string]string) cgroups.Manager { + return &fs.Manager{ + Cgroups: config, + Rootless: true, + Paths: paths, + } + } + return nil +} + // IntelRdtfs is an options func to configure a LinuxFactory to return // containers that use the Intel RDT "resource control" filesystem to -// create and manage Intel Xeon platform shared resources (e.g., L3 cache). +// create and manage Intel RDT resources (e.g., L3 cache, memory bandwidth). func IntelRdtFs(l *LinuxFactory) error { l.NewIntelRdtManager = func(config *configs.Config, id string, path string) intelrdt.Manager { return &intelrdt.IntelRdtManager{ @@ -178,7 +196,10 @@ func (l *LinuxFactory) Create(id string, config *configs.Config) (Container, err if err := l.Validator.Validate(config); err != nil { return nil, newGenericError(err, ConfigInvalid) } - containerRoot := filepath.Join(l.Root, id) + containerRoot, err := securejoin.SecureJoin(l.Root, id) + if err != nil { + return nil, err + } if _, err := os.Stat(containerRoot); err == nil { return nil, newGenericError(fmt.Errorf("container with id exists: %v", id), IdInUse) } else if !os.IsNotExist(err) { @@ -201,7 +222,7 @@ func (l *LinuxFactory) Create(id string, config *configs.Config) (Container, err newgidmapPath: l.NewgidmapPath, cgroupManager: l.NewCgroupsManager(config.Cgroups, nil), } - if intelrdt.IsEnabled() { + if intelrdt.IsCatEnabled() || intelrdt.IsMbaEnabled() { c.intelRdtManager = l.NewIntelRdtManager(config, id, "") } c.state = &stoppedState{c: c} @@ -212,7 +233,14 @@ func (l *LinuxFactory) Load(id string) (Container, error) { if l.Root == "" { return nil, newGenericError(fmt.Errorf("invalid root"), ConfigInvalid) } - containerRoot := filepath.Join(l.Root, id) + //when load, we need to check id is valid or not. + if err := l.validateID(id); err != nil { + return nil, err + } + containerRoot, err := securejoin.SecureJoin(l.Root, id) + if err != nil { + return nil, err + } state, err := l.loadState(containerRoot, id) if err != nil { return nil, err @@ -240,7 +268,7 @@ func (l *LinuxFactory) Load(id string) (Container, error) { if err := c.refreshState(); err != nil { return nil, err } - if intelrdt.IsEnabled() { + if intelrdt.IsCatEnabled() || intelrdt.IsMbaEnabled() { c.intelRdtManager = l.NewIntelRdtManager(&state.Config, id, state.IntelRdtPath) } return c, nil @@ -322,7 +350,11 @@ func (l *LinuxFactory) StartInitialization() (err error) { } func (l *LinuxFactory) loadState(root, id string) (*State, error) { - f, err := os.Open(filepath.Join(root, stateFilename)) + stateFilePath, err := securejoin.SecureJoin(root, stateFilename) + if err != nil { + return nil, err + } + f, err := os.Open(stateFilePath) if err != nil { if os.IsNotExist(err) { return nil, newGenericError(fmt.Errorf("container %q does not exist", id), ContainerNotExists) @@ -338,7 +370,7 @@ func (l *LinuxFactory) loadState(root, id string) (*State, error) { } func (l *LinuxFactory) validateID(id string) error { - if !idRegex.MatchString(id) { + if !idRegex.MatchString(id) || string(os.PathSeparator)+id != utils.CleanPath(string(os.PathSeparator)+id) { return newGenericError(fmt.Errorf("invalid id format: %v", id), InvalidIdFormat) } diff --git a/vendor/github.com/opencontainers/runc/libcontainer/init_linux.go b/vendor/github.com/opencontainers/runc/libcontainer/init_linux.go index 2770be30718..cd7ff67a702 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/init_linux.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/init_linux.go @@ -6,6 +6,7 @@ import ( "encoding/json" "fmt" "io" + "io/ioutil" "net" "os" "strings" @@ -20,6 +21,7 @@ import ( "github.com/opencontainers/runc/libcontainer/system" "github.com/opencontainers/runc/libcontainer/user" "github.com/opencontainers/runc/libcontainer/utils" + "github.com/pkg/errors" "github.com/sirupsen/logrus" "github.com/vishvananda/netlink" ) @@ -64,7 +66,8 @@ type initConfig struct { CreateConsole bool `json:"create_console"` ConsoleWidth uint16 `json:"console_width"` ConsoleHeight uint16 `json:"console_height"` - Rootless bool `json:"rootless"` + RootlessEUID bool `json:"rootless_euid,omitempty"` + RootlessCgroups bool `json:"rootless_cgroups,omitempty"` } type initer interface { @@ -121,7 +124,7 @@ func finalizeNamespace(config *initConfig) error { // inherited are marked close-on-exec so they stay out of the // container if err := utils.CloseExecFrom(config.PassedFilesCount + 3); err != nil { - return err + return errors.Wrap(err, "close exec fds") } capabilities := &configs.Capabilities{} @@ -136,20 +139,20 @@ func finalizeNamespace(config *initConfig) error { } // drop capabilities in bounding set before changing user if err := w.ApplyBoundingSet(); err != nil { - return err + return errors.Wrap(err, "apply bounding set") } // preserve existing capabilities while we change users if err := system.SetKeepCaps(); err != nil { - return err + return errors.Wrap(err, "set keep caps") } if err := setupUser(config); err != nil { - return err + return errors.Wrap(err, "setup user") } if err := system.ClearKeepCaps(); err != nil { - return err + return errors.Wrap(err, "clear keep caps") } if err := w.ApplyCaps(); err != nil { - return err + return errors.Wrap(err, "apply caps") } if config.Cwd != "" { if err := unix.Chdir(config.Cwd); err != nil { @@ -217,11 +220,7 @@ func syncParentReady(pipe io.ReadWriter) error { } // Wait for parent to give the all-clear. - if err := readSync(pipe, procRun); err != nil { - return err - } - - return nil + return readSync(pipe, procRun) } // syncParentHooks sends to the given pipe a JSON payload which indicates that @@ -234,11 +233,7 @@ func syncParentHooks(pipe io.ReadWriter) error { } // Wait for parent to give the all-clear. - if err := readSync(pipe, procResume); err != nil { - return err - } - - return nil + return readSync(pipe, procResume) } // setupUser changes the groups, gid, and uid for the user inside the container @@ -282,7 +277,7 @@ func setupUser(config *initConfig) error { return fmt.Errorf("cannot set gid to unmapped user in user namespace") } - if config.Rootless { + if config.RootlessEUID { // We cannot set any additional groups in a rootless container and thus // we bail if the user asked us to do so. TODO: We currently can't do // this check earlier, but if libcontainer.Process.User was typesafe @@ -298,11 +293,18 @@ func setupUser(config *initConfig) error { return err } + setgroups, err := ioutil.ReadFile("/proc/self/setgroups") + if err != nil && !os.IsNotExist(err) { + return err + } + // This isn't allowed in an unprivileged user namespace since Linux 3.19. // There's nothing we can do about /etc/group entries, so we silently // ignore setting groups here (since the user didn't explicitly ask us to // set the group). - if !config.Rootless { + allowSupGroups := !config.RootlessEUID && strings.TrimSpace(string(setgroups)) != "deny" + + if allowSupGroups { suppGroups := append(execUser.Sgids, addGroups...) if err := unix.Setgroups(suppGroups); err != nil { return err diff --git a/vendor/github.com/opencontainers/runc/libcontainer/intelrdt/intelrdt.go b/vendor/github.com/opencontainers/runc/libcontainer/intelrdt/intelrdt.go index 487c630af61..4e081ae6fe8 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/intelrdt/intelrdt.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/intelrdt/intelrdt.go @@ -16,20 +16,25 @@ import ( ) /* - * About Intel RDT/CAT feature: + * About Intel RDT features: * Intel platforms with new Xeon CPU support Resource Director Technology (RDT). - * Intel Cache Allocation Technology (CAT) is a sub-feature of RDT. Currently L3 - * Cache is the only resource that is supported in RDT. + * Cache Allocation Technology (CAT) and Memory Bandwidth Allocation (MBA) are + * two sub-features of RDT. * - * This feature provides a way for the software to restrict cache allocation to a - * defined 'subset' of L3 cache which may be overlapping with other 'subsets'. - * The different subsets are identified by class of service (CLOS) and each CLOS - * has a capacity bitmask (CBM). + * Cache Allocation Technology (CAT) provides a way for the software to restrict + * cache allocation to a defined 'subset' of L3 cache which may be overlapping + * with other 'subsets'. The different subsets are identified by class of + * service (CLOS) and each CLOS has a capacity bitmask (CBM). * - * For more information about Intel RDT/CAT can be found in the section 17.17 - * of Intel Software Developer Manual. + * Memory Bandwidth Allocation (MBA) provides indirect and approximate throttle + * over memory bandwidth for the software. A user controls the resource by + * indicating the percentage of maximum memory bandwidth. * - * About Intel RDT/CAT kernel interface: + * More details about Intel RDT CAT and MBA can be found in the section 17.18 + * of Intel Software Developer Manual: + * https://software.intel.com/en-us/articles/intel-sdm + * + * About Intel RDT kernel interface: * In Linux 4.10 kernel or newer, the interface is defined and exposed via * "resource control" filesystem, which is a "cgroup-like" interface. * @@ -37,59 +42,86 @@ import ( * interfaces in a container. But unlike cgroups' hierarchy, it has single level * filesystem layout. * + * CAT and MBA features are introduced in Linux 4.10 and 4.12 kernel via + * "resource control" filesystem. + * * Intel RDT "resource control" filesystem hierarchy: * mount -t resctrl resctrl /sys/fs/resctrl * tree /sys/fs/resctrl * /sys/fs/resctrl/ * |-- info * | |-- L3 - * | |-- cbm_mask - * | |-- min_cbm_bits + * | | |-- cbm_mask + * | | |-- min_cbm_bits + * | | |-- num_closids + * | |-- MB + * | |-- bandwidth_gran + * | |-- delay_linear + * | |-- min_bandwidth * | |-- num_closids - * |-- cpus + * |-- ... * |-- schemata * |-- tasks * |-- - * |-- cpus + * |-- ... * |-- schemata * |-- tasks * - * For runc, we can make use of `tasks` and `schemata` configuration for L3 cache - * resource constraints. + * For runc, we can make use of `tasks` and `schemata` configuration for L3 + * cache and memory bandwidth resources constraints. * - * The file `tasks` has a list of tasks that belongs to this group (e.g., + * The file `tasks` has a list of tasks that belongs to this group (e.g., * " group). Tasks can be added to a group by writing the task ID - * to the "tasks" file (which will automatically remove them from the previous + * to the "tasks" file (which will automatically remove them from the previous * group to which they belonged). New tasks created by fork(2) and clone(2) are - * added to the same group as their parent. If a pid is not in any sub group, it is - * in root group. + * added to the same group as their parent. * - * The file `schemata` has allocation bitmasks/values for L3 cache on each socket, - * which contains L3 cache id and capacity bitmask (CBM). + * The file `schemata` has a list of all the resources available to this group. + * Each resource (L3 cache, memory bandwidth) has its own line and format. + * + * L3 cache schema: + * It has allocation bitmasks/values for L3 cache on each socket, which + * contains L3 cache id and capacity bitmask (CBM). * Format: "L3:=;=;..." - * For example, on a two-socket machine, L3's schema line could be `L3:0=ff;1=c0` + * For example, on a two-socket machine, the schema line could be "L3:0=ff;1=c0" * which means L3 cache id 0's CBM is 0xff, and L3 cache id 1's CBM is 0xc0. * * The valid L3 cache CBM is a *contiguous bits set* and number of bits that can * be set is less than the max bit. The max bits in the CBM is varied among - * supported Intel Xeon platforms. In Intel RDT "resource control" filesystem - * layout, the CBM in a group should be a subset of the CBM in root. Kernel will - * check if it is valid when writing. e.g., 0xfffff in root indicates the max bits - * of CBM is 20 bits, which mapping to entire L3 cache capacity. Some valid CBM - * values to set in a group: 0xf, 0xf0, 0x3ff, 0x1f00 and etc. + * supported Intel CPU models. Kernel will check if it is valid when writing. + * e.g., default value 0xfffff in root indicates the max bits of CBM is 20 + * bits, which mapping to entire L3 cache capacity. Some valid CBM values to + * set in a group: 0xf, 0xf0, 0x3ff, 0x1f00 and etc. * - * For more information about Intel RDT/CAT kernel interface: + * Memory bandwidth schema: + * It has allocation values for memory bandwidth on each socket, which contains + * L3 cache id and memory bandwidth percentage. + * Format: "MB:=bandwidth0;=bandwidth1;..." + * For example, on a two-socket machine, the schema line could be "MB:0=20;1=70" + * + * The minimum bandwidth percentage value for each CPU model is predefined and + * can be looked up through "info/MB/min_bandwidth". The bandwidth granularity + * that is allocated is also dependent on the CPU model and can be looked up at + * "info/MB/bandwidth_gran". The available bandwidth control steps are: + * min_bw + N * bw_gran. Intermediate values are rounded to the next control + * step available on the hardware. + * + * For more information about Intel RDT kernel interface: * https://www.kernel.org/doc/Documentation/x86/intel_rdt_ui.txt * * An example for runc: * Consider a two-socket machine with two L3 caches where the default CBM is - * 0xfffff and the max CBM length is 20 bits. With this configuration, tasks - * inside the container only have access to the "upper" 80% of L3 cache id 0 and - * the "lower" 50% L3 cache id 1: + * 0x7ff and the max CBM length is 11 bits, and minimum memory bandwidth of 10% + * with a memory bandwidth granularity of 10%. + * + * Tasks inside the container only have access to the "upper" 7/11 of L3 cache + * on socket 0 and the "lower" 5/11 L3 cache on socket 1, and may use a + * maximum memory bandwidth of 20% on socket 0 and 70% on socket 1. * * "linux": { - * "intelRdt": { - * "l3CacheSchema": "L3:0=ffff0;1=3ff" + * "intelRdt": { + * "l3CacheSchema": "L3:0=7f0;1=1f", + * "memBwSchema": "MB:0=20;1=70" * } * } */ @@ -129,8 +161,10 @@ var ( intelRdtRoot string intelRdtRootLock sync.Mutex - // The flag to indicate if Intel RDT is supported - isEnabled bool + // The flag to indicate if Intel RDT/CAT is enabled + isCatEnabled bool + // The flag to indicate if Intel RDT/MBA is enabled + isMbaEnabled bool ) type intelRdtData struct { @@ -139,19 +173,35 @@ type intelRdtData struct { pid int } -// Check if Intel RDT is enabled in init() +// Check if Intel RDT sub-features are enabled in init() func init() { - // 1. Check if hardware and kernel support Intel RDT/CAT feature - // "cat_l3" flag is set if supported - isFlagSet, err := parseCpuInfoFile("/proc/cpuinfo") - if !isFlagSet || err != nil { - isEnabled = false + // 1. Check if hardware and kernel support Intel RDT sub-features + // "cat_l3" flag for CAT and "mba" flag for MBA + isCatFlagSet, isMbaFlagSet, err := parseCpuInfoFile("/proc/cpuinfo") + if err != nil { return } // 2. Check if Intel RDT "resource control" filesystem is mounted // The user guarantees to mount the filesystem - isEnabled = isIntelRdtMounted() + if !isIntelRdtMounted() { + return + } + + // 3. Double check if Intel RDT sub-features are available in + // "resource control" filesystem. Intel RDT sub-features can be + // selectively disabled or enabled by kernel command line + // (e.g., rdt=!l3cat,mba) in 4.14 and newer kernel + if isCatFlagSet { + if _, err := os.Stat(filepath.Join(intelRdtRoot, "info", "L3")); err == nil { + isCatEnabled = true + } + } + if isMbaFlagSet { + if _, err := os.Stat(filepath.Join(intelRdtRoot, "info", "MB")); err == nil { + isMbaEnabled = true + } + } } // Return the mount point path of Intel RDT "resource control" filesysem @@ -177,7 +227,7 @@ func findIntelRdtMountpointDir() (string, error) { } if postSeparatorFields[0] == "resctrl" { - // Check that the mount is properly formated. + // Check that the mount is properly formatted. if numPostFields < 3 { return "", fmt.Errorf("Error found less than 3 fields post '-' in %q", text) } @@ -223,30 +273,40 @@ func isIntelRdtMounted() bool { return true } -func parseCpuInfoFile(path string) (bool, error) { +func parseCpuInfoFile(path string) (bool, bool, error) { + isCatFlagSet := false + isMbaFlagSet := false + f, err := os.Open(path) if err != nil { - return false, err + return false, false, err } defer f.Close() s := bufio.NewScanner(f) for s.Scan() { if err := s.Err(); err != nil { - return false, err + return false, false, err } - text := s.Text() - flags := strings.Split(text, " ") + line := s.Text() - // "cat_l3" flag is set if Intel RDT/CAT is supported - for _, flag := range flags { - if flag == "cat_l3" { - return true, nil + // Search "cat_l3" and "mba" flags in first "flags" line + if strings.Contains(line, "flags") { + flags := strings.Split(line, " ") + // "cat_l3" flag for CAT and "mba" flag for MBA + for _, flag := range flags { + switch flag { + case "cat_l3": + isCatFlagSet = true + case "mba": + isMbaFlagSet = true + } } + return isCatFlagSet, isMbaFlagSet, nil } } - return false, nil + return isCatFlagSet, isMbaFlagSet, nil } func parseUint(s string, base, bitSize int) (uint64, error) { @@ -292,30 +352,6 @@ func getIntelRdtParamString(path, file string) (string, error) { return strings.TrimSpace(string(contents)), nil } -func readTasksFile(dir string) ([]int, error) { - f, err := os.Open(filepath.Join(dir, IntelRdtTasks)) - if err != nil { - return nil, err - } - defer f.Close() - - var ( - s = bufio.NewScanner(f) - out = []int{} - ) - - for s.Scan() { - if t := s.Text(); t != "" { - pid, err := strconv.Atoi(t) - if err != nil { - return nil, err - } - out = append(out, pid) - } - } - return out, nil -} - func writeFile(dir, file, data string) error { if dir == "" { return fmt.Errorf("no such directory for %s", file) @@ -368,6 +404,57 @@ func getL3CacheInfo() (*L3CacheInfo, error) { return l3CacheInfo, nil } +// Get the read-only memory bandwidth information +func getMemBwInfo() (*MemBwInfo, error) { + memBwInfo := &MemBwInfo{} + + rootPath, err := getIntelRdtRoot() + if err != nil { + return memBwInfo, err + } + + path := filepath.Join(rootPath, "info", "MB") + bandwidthGran, err := getIntelRdtParamUint(path, "bandwidth_gran") + if err != nil { + return memBwInfo, err + } + delayLinear, err := getIntelRdtParamUint(path, "delay_linear") + if err != nil { + return memBwInfo, err + } + minBandwidth, err := getIntelRdtParamUint(path, "min_bandwidth") + if err != nil { + return memBwInfo, err + } + numClosids, err := getIntelRdtParamUint(path, "num_closids") + if err != nil { + return memBwInfo, err + } + + memBwInfo.BandwidthGran = bandwidthGran + memBwInfo.DelayLinear = delayLinear + memBwInfo.MinBandwidth = minBandwidth + memBwInfo.NumClosids = numClosids + + return memBwInfo, nil +} + +// Get diagnostics for last filesystem operation error from file info/last_cmd_status +func getLastCmdStatus() (string, error) { + rootPath, err := getIntelRdtRoot() + if err != nil { + return "", err + } + + path := filepath.Join(rootPath, "info") + lastCmdStatus, err := getIntelRdtParamString(path, "last_cmd_status") + if err != nil { + return "", err + } + + return lastCmdStatus, nil +} + // WriteIntelRdtTasks writes the specified pid into the "tasks" file func WriteIntelRdtTasks(dir string, pid int) error { if dir == "" { @@ -383,9 +470,14 @@ func WriteIntelRdtTasks(dir string, pid int) error { return nil } -// Check if Intel RDT is enabled -func IsEnabled() bool { - return isEnabled +// Check if Intel RDT/CAT is enabled +func IsCatEnabled() bool { + return isCatEnabled +} + +// Check if Intel RDT/MBA is enabled +func IsMbaEnabled() bool { + return isMbaEnabled } // Get the 'container_id' path in Intel RDT "resource control" filesystem @@ -452,65 +544,130 @@ func (m *IntelRdtManager) GetStats() (*Stats, error) { defer m.mu.Unlock() stats := NewStats() - // The read-only L3 cache information - l3CacheInfo, err := getL3CacheInfo() - if err != nil { - return nil, err - } - stats.L3CacheInfo = l3CacheInfo - - // The read-only L3 cache schema in root rootPath, err := getIntelRdtRoot() if err != nil { return nil, err } + // The read-only L3 cache and memory bandwidth schemata in root tmpRootStrings, err := getIntelRdtParamString(rootPath, "schemata") if err != nil { return nil, err } - // L3 cache schema is in the first line schemaRootStrings := strings.Split(tmpRootStrings, "\n") - stats.L3CacheSchemaRoot = schemaRootStrings[0] - // The L3 cache schema in 'container_id' group + // The L3 cache and memory bandwidth schemata in 'container_id' group tmpStrings, err := getIntelRdtParamString(m.GetPath(), "schemata") if err != nil { return nil, err } - // L3 cache schema is in the first line schemaStrings := strings.Split(tmpStrings, "\n") - stats.L3CacheSchema = schemaStrings[0] + + if IsCatEnabled() { + // The read-only L3 cache information + l3CacheInfo, err := getL3CacheInfo() + if err != nil { + return nil, err + } + stats.L3CacheInfo = l3CacheInfo + + // The read-only L3 cache schema in root + for _, schemaRoot := range schemaRootStrings { + if strings.Contains(schemaRoot, "L3") { + stats.L3CacheSchemaRoot = strings.TrimSpace(schemaRoot) + } + } + + // The L3 cache schema in 'container_id' group + for _, schema := range schemaStrings { + if strings.Contains(schema, "L3") { + stats.L3CacheSchema = strings.TrimSpace(schema) + } + } + } + + if IsMbaEnabled() { + // The read-only memory bandwidth information + memBwInfo, err := getMemBwInfo() + if err != nil { + return nil, err + } + stats.MemBwInfo = memBwInfo + + // The read-only memory bandwidth information + for _, schemaRoot := range schemaRootStrings { + if strings.Contains(schemaRoot, "MB") { + stats.MemBwSchemaRoot = strings.TrimSpace(schemaRoot) + } + } + + // The memory bandwidth schema in 'container_id' group + for _, schema := range schemaStrings { + if strings.Contains(schema, "MB") { + stats.MemBwSchema = strings.TrimSpace(schema) + } + } + } return stats, nil } // Set Intel RDT "resource control" filesystem as configured. func (m *IntelRdtManager) Set(container *configs.Config) error { - path := m.GetPath() - - // About L3 cache schema file: - // The schema has allocation masks/values for L3 cache on each socket, + // About L3 cache schema: + // It has allocation bitmasks/values for L3 cache on each socket, // which contains L3 cache id and capacity bitmask (CBM). - // Format: "L3:=;=;..." - // For example, on a two-socket machine, L3's schema line could be: - // L3:0=ff;1=c0 - // Which means L3 cache id 0's CBM is 0xff, and L3 cache id 1's CBM is 0xc0. + // Format: "L3:=;=;..." + // For example, on a two-socket machine, the schema line could be: + // L3:0=ff;1=c0 + // which means L3 cache id 0's CBM is 0xff, and L3 cache id 1's CBM + // is 0xc0. // - // About L3 cache CBM validity: // The valid L3 cache CBM is a *contiguous bits set* and number of // bits that can be set is less than the max bit. The max bits in the - // CBM is varied among supported Intel Xeon platforms. In Intel RDT - // "resource control" filesystem layout, the CBM in a group should - // be a subset of the CBM in root. Kernel will check if it is valid - // when writing. - // e.g., 0xfffff in root indicates the max bits of CBM is 20 bits, - // which mapping to entire L3 cache capacity. Some valid CBM values - // to set in a group: 0xf, 0xf0, 0x3ff, 0x1f00 and etc. + // CBM is varied among supported Intel CPU models. Kernel will check + // if it is valid when writing. e.g., default value 0xfffff in root + // indicates the max bits of CBM is 20 bits, which mapping to entire + // L3 cache capacity. Some valid CBM values to set in a group: + // 0xf, 0xf0, 0x3ff, 0x1f00 and etc. + // + // + // About memory bandwidth schema: + // It has allocation values for memory bandwidth on each socket, which + // contains L3 cache id and memory bandwidth percentage. + // Format: "MB:=bandwidth0;=bandwidth1;..." + // For example, on a two-socket machine, the schema line could be: + // "MB:0=20;1=70" + // + // The minimum bandwidth percentage value for each CPU model is + // predefined and can be looked up through "info/MB/min_bandwidth". + // The bandwidth granularity that is allocated is also dependent on + // the CPU model and can be looked up at "info/MB/bandwidth_gran". + // The available bandwidth control steps are: min_bw + N * bw_gran. + // Intermediate values are rounded to the next control step available + // on the hardware. if container.IntelRdt != nil { + path := m.GetPath() l3CacheSchema := container.IntelRdt.L3CacheSchema - if l3CacheSchema != "" { + memBwSchema := container.IntelRdt.MemBwSchema + + // Write a single joint schema string to schemata file + if l3CacheSchema != "" && memBwSchema != "" { + if err := writeFile(path, "schemata", l3CacheSchema+"\n"+memBwSchema); err != nil { + return NewLastCmdError(err) + } + } + + // Write only L3 cache schema string to schemata file + if l3CacheSchema != "" && memBwSchema == "" { if err := writeFile(path, "schemata", l3CacheSchema); err != nil { - return err + return NewLastCmdError(err) + } + } + + // Write only memory bandwidth schema string to schemata file + if l3CacheSchema == "" && memBwSchema != "" { + if err := writeFile(path, "schemata", memBwSchema); err != nil { + return NewLastCmdError(err) } } } @@ -521,11 +678,11 @@ func (m *IntelRdtManager) Set(container *configs.Config) error { func (raw *intelRdtData) join(id string) (string, error) { path := filepath.Join(raw.root, id) if err := os.MkdirAll(path, 0755); err != nil { - return "", err + return "", NewLastCmdError(err) } if err := WriteIntelRdtTasks(path, raw.pid); err != nil { - return "", err + return "", NewLastCmdError(err) } return path, nil } @@ -551,3 +708,23 @@ func IsNotFound(err error) bool { _, ok := err.(*NotFoundError) return ok } + +type LastCmdError struct { + LastCmdStatus string + Err error +} + +func (e *LastCmdError) Error() string { + return fmt.Sprintf(e.Err.Error() + ", last_cmd_status: " + e.LastCmdStatus) +} + +func NewLastCmdError(err error) error { + lastCmdStatus, err1 := getLastCmdStatus() + if err1 == nil { + return &LastCmdError{ + LastCmdStatus: lastCmdStatus, + Err: err, + } + } + return err +} diff --git a/vendor/github.com/opencontainers/runc/libcontainer/intelrdt/stats.go b/vendor/github.com/opencontainers/runc/libcontainer/intelrdt/stats.go index 095c0a380cd..df5686f3b80 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/intelrdt/stats.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/intelrdt/stats.go @@ -8,6 +8,13 @@ type L3CacheInfo struct { NumClosids uint64 `json:"num_closids,omitempty"` } +type MemBwInfo struct { + BandwidthGran uint64 `json:"bandwidth_gran,omitempty"` + DelayLinear uint64 `json:"delay_linear,omitempty"` + MinBandwidth uint64 `json:"min_bandwidth,omitempty"` + NumClosids uint64 `json:"num_closids,omitempty"` +} + type Stats struct { // The read-only L3 cache information L3CacheInfo *L3CacheInfo `json:"l3_cache_info,omitempty"` @@ -17,6 +24,15 @@ type Stats struct { // The L3 cache schema in 'container_id' group L3CacheSchema string `json:"l3_cache_schema,omitempty"` + + // The read-only memory bandwidth information + MemBwInfo *MemBwInfo `json:"mem_bw_info,omitempty"` + + // The read-only memory bandwidth schema in root + MemBwSchemaRoot string `json:"mem_bw_schema_root,omitempty"` + + // The memory bandwidth schema in 'container_id' group + MemBwSchema string `json:"mem_bw_schema,omitempty"` } func NewStats() *Stats { diff --git a/vendor/github.com/opencontainers/runc/libcontainer/keys/BUILD b/vendor/github.com/opencontainers/runc/libcontainer/keys/BUILD index b539ae2d45b..280323836c0 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/keys/BUILD +++ b/vendor/github.com/opencontainers/runc/libcontainer/keys/BUILD @@ -8,6 +8,7 @@ go_library( visibility = ["//visibility:public"], deps = select({ "@io_bazel_rules_go//go/platform:linux": [ + "//vendor/github.com/pkg/errors:go_default_library", "//vendor/golang.org/x/sys/unix:go_default_library", ], "//conditions:default": [], diff --git a/vendor/github.com/opencontainers/runc/libcontainer/keys/keyctl.go b/vendor/github.com/opencontainers/runc/libcontainer/keys/keyctl.go index ce8b4e6b040..74dedd56ca8 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/keys/keyctl.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/keys/keyctl.go @@ -7,6 +7,8 @@ import ( "strconv" "strings" + "github.com/pkg/errors" + "golang.org/x/sys/unix" ) @@ -15,7 +17,7 @@ type KeySerial uint32 func JoinSessionKeyring(name string) (KeySerial, error) { sessKeyId, err := unix.KeyctlJoinSessionKeyring(name) if err != nil { - return 0, fmt.Errorf("could not create session key: %v", err) + return 0, errors.Wrap(err, "create session key") } return KeySerial(sessKeyId), nil } @@ -42,9 +44,5 @@ func ModKeyringPerm(ringId KeySerial, mask, setbits uint32) error { perm := (uint32(perm64) & mask) | setbits - if err := unix.KeyctlSetperm(int(ringId), perm); err != nil { - return err - } - - return nil + return unix.KeyctlSetperm(int(ringId), perm) } diff --git a/vendor/github.com/opencontainers/runc/libcontainer/message_linux.go b/vendor/github.com/opencontainers/runc/libcontainer/message_linux.go index ed7f986df8d..1d4f5033aa2 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/message_linux.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/message_linux.go @@ -10,16 +10,16 @@ import ( // list of known message types we want to send to bootstrap program // The number is randomly chosen to not conflict with known netlink types const ( - InitMsg uint16 = 62000 - CloneFlagsAttr uint16 = 27281 - NsPathsAttr uint16 = 27282 - UidmapAttr uint16 = 27283 - GidmapAttr uint16 = 27284 - SetgroupAttr uint16 = 27285 - OomScoreAdjAttr uint16 = 27286 - RootlessAttr uint16 = 27287 - UidmapPathAttr uint16 = 27288 - GidmapPathAttr uint16 = 27289 + InitMsg uint16 = 62000 + CloneFlagsAttr uint16 = 27281 + NsPathsAttr uint16 = 27282 + UidmapAttr uint16 = 27283 + GidmapAttr uint16 = 27284 + SetgroupAttr uint16 = 27285 + OomScoreAdjAttr uint16 = 27286 + RootlessEUIDAttr uint16 = 27287 + UidmapPathAttr uint16 = 27288 + GidmapPathAttr uint16 = 27289 ) type Int32msg struct { diff --git a/vendor/github.com/opencontainers/runc/libcontainer/network_linux.go b/vendor/github.com/opencontainers/runc/libcontainer/network_linux.go index 5075bee4db5..569c53f6e8a 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/network_linux.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/network_linux.go @@ -5,18 +5,15 @@ package libcontainer import ( "fmt" "io/ioutil" - "net" "path/filepath" "strconv" "strings" "github.com/opencontainers/runc/libcontainer/configs" - "github.com/opencontainers/runc/libcontainer/utils" "github.com/vishvananda/netlink" ) var strategies = map[string]networkStrategy{ - "veth": &veth{}, "loopback": &loopback{}, } @@ -103,157 +100,3 @@ func (l *loopback) attach(n *configs.Network) (err error) { func (l *loopback) detach(n *configs.Network) (err error) { return nil } - -// veth is a network strategy that uses a bridge and creates -// a veth pair, one that is attached to the bridge on the host and the other -// is placed inside the container's namespace -type veth struct { -} - -func (v *veth) detach(n *configs.Network) (err error) { - return netlink.LinkSetMaster(&netlink.Device{LinkAttrs: netlink.LinkAttrs{Name: n.HostInterfaceName}}, nil) -} - -// attach a container network interface to an external network -func (v *veth) attach(n *configs.Network) (err error) { - brl, err := netlink.LinkByName(n.Bridge) - if err != nil { - return err - } - br, ok := brl.(*netlink.Bridge) - if !ok { - return fmt.Errorf("Wrong device type %T", brl) - } - host, err := netlink.LinkByName(n.HostInterfaceName) - if err != nil { - return err - } - - if err := netlink.LinkSetMaster(host, br); err != nil { - return err - } - if err := netlink.LinkSetMTU(host, n.Mtu); err != nil { - return err - } - if n.HairpinMode { - if err := netlink.LinkSetHairpin(host, true); err != nil { - return err - } - } - if err := netlink.LinkSetUp(host); err != nil { - return err - } - - return nil -} - -func (v *veth) create(n *network, nspid int) (err error) { - tmpName, err := v.generateTempPeerName() - if err != nil { - return err - } - n.TempVethPeerName = tmpName - if n.Bridge == "" { - return fmt.Errorf("bridge is not specified") - } - veth := &netlink.Veth{ - LinkAttrs: netlink.LinkAttrs{ - Name: n.HostInterfaceName, - TxQLen: n.TxQueueLen, - }, - PeerName: n.TempVethPeerName, - } - if err := netlink.LinkAdd(veth); err != nil { - return err - } - defer func() { - if err != nil { - netlink.LinkDel(veth) - } - }() - if err := v.attach(&n.Network); err != nil { - return err - } - child, err := netlink.LinkByName(n.TempVethPeerName) - if err != nil { - return err - } - return netlink.LinkSetNsPid(child, nspid) -} - -func (v *veth) generateTempPeerName() (string, error) { - return utils.GenerateRandomName("veth", 7) -} - -func (v *veth) initialize(config *network) error { - peer := config.TempVethPeerName - if peer == "" { - return fmt.Errorf("peer is not specified") - } - child, err := netlink.LinkByName(peer) - if err != nil { - return err - } - if err := netlink.LinkSetDown(child); err != nil { - return err - } - if err := netlink.LinkSetName(child, config.Name); err != nil { - return err - } - // get the interface again after we changed the name as the index also changes. - if child, err = netlink.LinkByName(config.Name); err != nil { - return err - } - if config.MacAddress != "" { - mac, err := net.ParseMAC(config.MacAddress) - if err != nil { - return err - } - if err := netlink.LinkSetHardwareAddr(child, mac); err != nil { - return err - } - } - ip, err := netlink.ParseAddr(config.Address) - if err != nil { - return err - } - if err := netlink.AddrAdd(child, ip); err != nil { - return err - } - if config.IPv6Address != "" { - ip6, err := netlink.ParseAddr(config.IPv6Address) - if err != nil { - return err - } - if err := netlink.AddrAdd(child, ip6); err != nil { - return err - } - } - if err := netlink.LinkSetMTU(child, config.Mtu); err != nil { - return err - } - if err := netlink.LinkSetUp(child); err != nil { - return err - } - if config.Gateway != "" { - gw := net.ParseIP(config.Gateway) - if err := netlink.RouteAdd(&netlink.Route{ - Scope: netlink.SCOPE_UNIVERSE, - LinkIndex: child.Attrs().Index, - Gw: gw, - }); err != nil { - return err - } - } - if config.IPv6Gateway != "" { - gw := net.ParseIP(config.IPv6Gateway) - if err := netlink.RouteAdd(&netlink.Route{ - Scope: netlink.SCOPE_UNIVERSE, - LinkIndex: child.Attrs().Index, - Gw: gw, - }); err != nil { - return err - } - } - return nil -} diff --git a/vendor/github.com/opencontainers/runc/libcontainer/process.go b/vendor/github.com/opencontainers/runc/libcontainer/process.go index 86bf7387f8c..9a7c6014121 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/process.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/process.go @@ -72,6 +72,9 @@ type Process struct { // ConsoleSocket provides the masterfd console. ConsoleSocket *os.File + // Init specifies whether the process is the first process in the container. + Init bool + ops processOperations } diff --git a/vendor/github.com/opencontainers/runc/libcontainer/process_linux.go b/vendor/github.com/opencontainers/runc/libcontainer/process_linux.go index 58980b0594e..217c213f8a3 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/process_linux.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/process_linux.go @@ -46,15 +46,16 @@ type parentProcess interface { } type setnsProcess struct { - cmd *exec.Cmd - parentPipe *os.File - childPipe *os.File - cgroupPaths map[string]string - intelRdtPath string - config *initConfig - fds []string - process *Process - bootstrapData io.Reader + cmd *exec.Cmd + parentPipe *os.File + childPipe *os.File + cgroupPaths map[string]string + rootlessCgroups bool + intelRdtPath string + config *initConfig + fds []string + process *Process + bootstrapData io.Reader } func (p *setnsProcess) startTime() (uint64, error) { @@ -86,7 +87,7 @@ func (p *setnsProcess) start() (err error) { return newSystemErrorWithCause(err, "executing setns process") } if len(p.cgroupPaths) > 0 { - if err := cgroups.EnterPid(p.cgroupPaths, p.pid()); err != nil { + if err := cgroups.EnterPid(p.cgroupPaths, p.pid()); err != nil && !p.rootlessCgroups { return newSystemErrorWithCausef(err, "adding pid %d to cgroups", p.pid()) } } @@ -537,7 +538,7 @@ func (p *Process) InitializeIO(rootuid, rootgid int) (i *IO, err error) { } fds = append(fds, r.Fd(), w.Fd()) p.Stderr, i.Stderr = w, r - // change ownership of the pipes incase we are in a user namespace + // change ownership of the pipes in case we are in a user namespace for _, fd := range fds { if err := unix.Fchown(int(fd), rootuid, rootgid); err != nil { return nil, err diff --git a/vendor/github.com/opencontainers/runc/libcontainer/rootfs_linux.go b/vendor/github.com/opencontainers/runc/libcontainer/rootfs_linux.go index 7f852efceb2..a278dad35db 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/rootfs_linux.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/rootfs_linux.go @@ -46,6 +46,7 @@ func prepareRootfs(pipe io.ReadWriter, iConfig *initConfig) (err error) { return newSystemErrorWithCause(err, "preparing rootfs") } + setupDev := needsSetupDev(config) for _, m := range config.Mounts { for _, precmd := range m.PremountCmds { if err := mountCmd(precmd); err != nil { @@ -64,8 +65,6 @@ func prepareRootfs(pipe io.ReadWriter, iConfig *initConfig) (err error) { } } - setupDev := needsSetupDev(config) - if setupDev { if err := createDevices(config); err != nil { return newSystemErrorWithCause(err, "creating device nodes") @@ -153,6 +152,26 @@ func finalizeRootfs(config *configs.Config) (err error) { return nil } +// /tmp has to be mounted as private to allow MS_MOVE to work in all situations +func prepareTmp(topTmpDir string) (string, error) { + tmpdir, err := ioutil.TempDir(topTmpDir, "runctop") + if err != nil { + return "", err + } + if err := unix.Mount(tmpdir, tmpdir, "bind", unix.MS_BIND, ""); err != nil { + return "", err + } + if err := unix.Mount("", tmpdir, "", uintptr(unix.MS_PRIVATE), ""); err != nil { + return "", err + } + return tmpdir, nil +} + +func cleanupTmp(tmpdir string) error { + unix.Unmount(tmpdir, 0) + return os.RemoveAll(tmpdir) +} + func mountCmd(cmd configs.Command) error { command := exec.Command(cmd.Path, cmd.Args[:]...) command.Env = cmd.Env @@ -200,7 +219,12 @@ func mountToRootfs(m *configs.Mount, rootfs, mountLabel string) error { } } if copyUp { - tmpDir, err = ioutil.TempDir("/tmp", "runctmpdir") + tmpdir, err := prepareTmp("/tmp") + if err != nil { + return newSystemErrorWithCause(err, "tmpcopyup: failed to setup tmpdir") + } + defer cleanupTmp(tmpdir) + tmpDir, err = ioutil.TempDir(tmpdir, "runctmpdir") if err != nil { return newSystemErrorWithCause(err, "tmpcopyup: failed to create tmpdir") } @@ -397,6 +421,7 @@ func checkMountDestination(rootfs, dest string) error { "/proc/stat", "/proc/swaps", "/proc/uptime", + "/proc/loadavg", "/proc/net/dev", } for _, valid := range validDestinations { @@ -413,7 +438,7 @@ func checkMountDestination(rootfs, dest string) error { if err != nil { return err } - if path == "." || !strings.HasPrefix(path, "..") { + if path != "." && !strings.HasPrefix(path, "..") { return fmt.Errorf("%q cannot be mounted because it is located inside %q", dest, invalid) } } @@ -803,10 +828,7 @@ func remount(m *configs.Mount, rootfs string) error { if !strings.HasPrefix(dest, rootfs) { dest = filepath.Join(rootfs, dest) } - if err := unix.Mount(m.Source, dest, m.Device, uintptr(m.Flags|unix.MS_REMOUNT), ""); err != nil { - return err - } - return nil + return unix.Mount(m.Source, dest, m.Device, uintptr(m.Flags|unix.MS_REMOUNT), "") } // Do the mount operation followed by additional mounts required to take care diff --git a/vendor/github.com/opencontainers/runc/libcontainer/setns_init_linux.go b/vendor/github.com/opencontainers/runc/libcontainer/setns_init_linux.go index 096c601e767..6613bb65cb5 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/setns_init_linux.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/setns_init_linux.go @@ -5,12 +5,14 @@ package libcontainer import ( "fmt" "os" + "runtime" "github.com/opencontainers/runc/libcontainer/apparmor" "github.com/opencontainers/runc/libcontainer/keys" "github.com/opencontainers/runc/libcontainer/seccomp" "github.com/opencontainers/runc/libcontainer/system" "github.com/opencontainers/selinux/go-selinux/label" + "github.com/pkg/errors" "golang.org/x/sys/unix" ) @@ -28,10 +30,19 @@ func (l *linuxSetnsInit) getSessionRingName() string { } func (l *linuxSetnsInit) Init() error { + runtime.LockOSThread() + defer runtime.UnlockOSThread() + if !l.config.Config.NoNewKeyring { - // do not inherit the parent's session keyring + // Do not inherit the parent's session keyring. if _, err := keys.JoinSessionKeyring(l.getSessionRingName()); err != nil { - return err + // Same justification as in standart_init_linux.go as to why we + // don't bail on ENOSYS. + // + // TODO(cyphar): And we should have logging here too. + if errors.Cause(err) != unix.ENOSYS { + return errors.Wrap(err, "join session keyring") + } } } if l.config.CreateConsole { @@ -47,6 +58,10 @@ func (l *linuxSetnsInit) Init() error { return err } } + if err := label.SetProcessLabel(l.config.ProcessLabel); err != nil { + return err + } + defer label.SetProcessLabel("") // Without NoNewPrivileges seccomp is a privileged operation, so we need to // do this before dropping capabilities; otherwise do it as late as possible // just before execve so as few syscalls take place after it as possible. @@ -61,9 +76,6 @@ func (l *linuxSetnsInit) Init() error { if err := apparmor.ApplyProfile(l.config.AppArmorProfile); err != nil { return err } - if err := label.SetProcessLabel(l.config.ProcessLabel); err != nil { - return err - } // Set seccomp as close to execve as possible, so as few syscalls take // place afterward (reducing the amount of syscalls that users need to // enable in their seccomp profiles). diff --git a/vendor/github.com/opencontainers/runc/libcontainer/standard_init_linux.go b/vendor/github.com/opencontainers/runc/libcontainer/standard_init_linux.go index e74d8002566..ad7ee8d8c8a 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/standard_init_linux.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/standard_init_linux.go @@ -6,6 +6,7 @@ import ( "fmt" "os" "os/exec" + "runtime" "syscall" //only for Exec "github.com/opencontainers/runc/libcontainer/apparmor" @@ -14,6 +15,7 @@ import ( "github.com/opencontainers/runc/libcontainer/seccomp" "github.com/opencontainers/runc/libcontainer/system" "github.com/opencontainers/selinux/go-selinux/label" + "github.com/pkg/errors" "golang.org/x/sys/unix" ) @@ -43,17 +45,31 @@ func (l *linuxStandardInit) getSessionRingParams() (string, uint32, uint32) { } func (l *linuxStandardInit) Init() error { + runtime.LockOSThread() + defer runtime.UnlockOSThread() if !l.config.Config.NoNewKeyring { ringname, keepperms, newperms := l.getSessionRingParams() // Do not inherit the parent's session keyring. - sessKeyId, err := keys.JoinSessionKeyring(ringname) - if err != nil { - return err - } - // Make session keyring searcheable. - if err := keys.ModKeyringPerm(sessKeyId, keepperms, newperms); err != nil { - return err + if sessKeyId, err := keys.JoinSessionKeyring(ringname); err != nil { + // If keyrings aren't supported then it is likely we are on an + // older kernel (or inside an LXC container). While we could bail, + // the security feature we are using here is best-effort (it only + // really provides marginal protection since VFS credentials are + // the only significant protection of keyrings). + // + // TODO(cyphar): Log this so people know what's going on, once we + // have proper logging in 'runc init'. + if errors.Cause(err) != unix.ENOSYS { + return errors.Wrap(err, "join session keyring") + } + } else { + // Make session keyring searcheable. If we've gotten this far we + // bail on any error -- we don't want to have a keyring with bad + // permissions. + if err := keys.ModKeyringPerm(sessKeyId, keepperms, newperms); err != nil { + return errors.Wrap(err, "mod keyring permissions") + } } } @@ -76,7 +92,7 @@ func (l *linuxStandardInit) Init() error { return err } if err := system.Setctty(); err != nil { - return err + return errors.Wrap(err, "setctty") } } @@ -89,46 +105,47 @@ func (l *linuxStandardInit) Init() error { if hostname := l.config.Config.Hostname; hostname != "" { if err := unix.Sethostname([]byte(hostname)); err != nil { - return err + return errors.Wrap(err, "sethostname") } } if err := apparmor.ApplyProfile(l.config.AppArmorProfile); err != nil { - return err - } - if err := label.SetProcessLabel(l.config.ProcessLabel); err != nil { - return err + return errors.Wrap(err, "apply apparmor profile") } for key, value := range l.config.Config.Sysctl { if err := writeSystemProperty(key, value); err != nil { - return err + return errors.Wrapf(err, "write sysctl key %s", key) } } for _, path := range l.config.Config.ReadonlyPaths { if err := readonlyPath(path); err != nil { - return err + return errors.Wrapf(err, "readonly path %s", path) } } for _, path := range l.config.Config.MaskPaths { if err := maskPath(path, l.config.Config.MountLabel); err != nil { - return err + return errors.Wrapf(err, "mask path %s", path) } } pdeath, err := system.GetParentDeathSignal() if err != nil { - return err + return errors.Wrap(err, "get pdeath signal") } if l.config.NoNewPrivileges { if err := unix.Prctl(unix.PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0); err != nil { - return err + return errors.Wrap(err, "set nonewprivileges") } } // Tell our parent that we're ready to Execv. This must be done before the // Seccomp rules have been applied, because we need to be able to read and // write to a socket. if err := syncParentReady(l.pipe); err != nil { - return err + return errors.Wrap(err, "sync ready") } + if err := label.SetProcessLabel(l.config.ProcessLabel); err != nil { + return errors.Wrap(err, "set process label") + } + defer label.SetProcessLabel("") // Without NoNewPrivileges seccomp is a privileged operation, so we need to // do this before dropping capabilities; otherwise do it as late as possible // just before execve so as few syscalls take place after it as possible. @@ -143,7 +160,7 @@ func (l *linuxStandardInit) Init() error { // finalizeNamespace can change user/group which clears the parent death // signal, so we restore it here. if err := pdeath.Restore(); err != nil { - return err + return errors.Wrap(err, "restore pdeath signal") } // Compare the parent from the initial start of the init process and make // sure that it did not change. if the parent changes that means it died diff --git a/vendor/github.com/opencontainers/runc/libcontainer/sync.go b/vendor/github.com/opencontainers/runc/libcontainer/sync.go index cf7b45bc329..a8704a2679d 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/sync.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/sync.go @@ -41,10 +41,7 @@ type syncT struct { // writeSync is used to write to a synchronisation pipe. An error is returned // if there was a problem writing the payload. func writeSync(pipe io.Writer, sync syncType) error { - if err := utils.WriteJSON(pipe, syncT{sync}); err != nil { - return err - } - return nil + return utils.WriteJSON(pipe, syncT{sync}) } // readSync is used to read from a synchronisation pipe. An error is returned diff --git a/vendor/github.com/opencontainers/runc/libcontainer/system/BUILD b/vendor/github.com/opencontainers/runc/libcontainer/system/BUILD index ad5438de66f..7efcde3b573 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/system/BUILD +++ b/vendor/github.com/opencontainers/runc/libcontainer/system/BUILD @@ -17,6 +17,41 @@ go_library( importpath = "github.com/opencontainers/runc/libcontainer/system", visibility = ["//visibility:public"], deps = select({ + "@io_bazel_rules_go//go/platform:android": [ + "//vendor/github.com/opencontainers/runc/libcontainer/user:go_default_library", + ], + "@io_bazel_rules_go//go/platform:darwin": [ + "//vendor/github.com/opencontainers/runc/libcontainer/user:go_default_library", + ], + "@io_bazel_rules_go//go/platform:dragonfly": [ + "//vendor/github.com/opencontainers/runc/libcontainer/user:go_default_library", + ], + "@io_bazel_rules_go//go/platform:freebsd": [ + "//vendor/github.com/opencontainers/runc/libcontainer/user:go_default_library", + ], + "@io_bazel_rules_go//go/platform:linux": [ + "//vendor/github.com/opencontainers/runc/libcontainer/user:go_default_library", + ], + "@io_bazel_rules_go//go/platform:nacl": [ + "//vendor/github.com/opencontainers/runc/libcontainer/user:go_default_library", + ], + "@io_bazel_rules_go//go/platform:netbsd": [ + "//vendor/github.com/opencontainers/runc/libcontainer/user:go_default_library", + ], + "@io_bazel_rules_go//go/platform:openbsd": [ + "//vendor/github.com/opencontainers/runc/libcontainer/user:go_default_library", + ], + "@io_bazel_rules_go//go/platform:plan9": [ + "//vendor/github.com/opencontainers/runc/libcontainer/user:go_default_library", + ], + "@io_bazel_rules_go//go/platform:solaris": [ + "//vendor/github.com/opencontainers/runc/libcontainer/user:go_default_library", + ], + "@io_bazel_rules_go//go/platform:windows": [ + "//vendor/github.com/opencontainers/runc/libcontainer/user:go_default_library", + ], + "//conditions:default": [], + }) + select({ "@io_bazel_rules_go//go/platform:linux_386": [ "//vendor/golang.org/x/sys/unix:go_default_library", ], diff --git a/vendor/github.com/opencontainers/runc/libcontainer/system/linux.go b/vendor/github.com/opencontainers/runc/libcontainer/system/linux.go index 5f124cd8bbc..a4ae8901acc 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/system/linux.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/system/linux.go @@ -3,13 +3,12 @@ package system import ( - "bufio" - "fmt" "os" "os/exec" "syscall" // only for exec "unsafe" + "github.com/opencontainers/runc/libcontainer/user" "golang.org/x/sys/unix" ) @@ -102,34 +101,43 @@ func Setctty() error { } // RunningInUserNS detects whether we are currently running in a user namespace. -// Copied from github.com/lxc/lxd/shared/util.go +// Originally copied from github.com/lxc/lxd/shared/util.go func RunningInUserNS() bool { - file, err := os.Open("/proc/self/uid_map") + uidmap, err := user.CurrentProcessUIDMap() if err != nil { // This kernel-provided file only exists if user namespaces are supported return false } - defer file.Close() + return UIDMapInUserNS(uidmap) +} - buf := bufio.NewReader(file) - l, _, err := buf.ReadLine() - if err != nil { - return false - } - - line := string(l) - var a, b, c int64 - fmt.Sscanf(line, "%d %d %d", &a, &b, &c) +func UIDMapInUserNS(uidmap []user.IDMap) bool { /* * We assume we are in the initial user namespace if we have a full * range - 4294967295 uids starting at uid 0. */ - if a == 0 && b == 0 && c == 4294967295 { + if len(uidmap) == 1 && uidmap[0].ID == 0 && uidmap[0].ParentID == 0 && uidmap[0].Count == 4294967295 { return false } return true } +// GetParentNSeuid returns the euid within the parent user namespace +func GetParentNSeuid() int64 { + euid := int64(os.Geteuid()) + uidmap, err := user.CurrentProcessUIDMap() + if err != nil { + // This kernel-provided file only exists if user namespaces are supported + return euid + } + for _, um := range uidmap { + if um.ID <= euid && euid <= um.ID+um.Count-1 { + return um.ParentID + euid - um.ID + } + } + return euid +} + // SetSubreaper sets the value i as the subreaper setting for the calling process func SetSubreaper(i int) error { return unix.Prctl(PR_SET_CHILD_SUBREAPER, uintptr(i), 0, 0, 0) diff --git a/vendor/github.com/opencontainers/runc/libcontainer/system/unsupported.go b/vendor/github.com/opencontainers/runc/libcontainer/system/unsupported.go index e7cfd62b293..b94be74a664 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/system/unsupported.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/system/unsupported.go @@ -2,8 +2,26 @@ package system +import ( + "os" + + "github.com/opencontainers/runc/libcontainer/user" +) + // RunningInUserNS is a stub for non-Linux systems // Always returns false func RunningInUserNS() bool { return false } + +// UIDMapInUserNS is a stub for non-Linux systems +// Always returns false +func UIDMapInUserNS(uidmap []user.IDMap) bool { + return false +} + +// GetParentNSeuid returns the euid within the parent user namespace +// Always returns os.Geteuid on non-linux +func GetParentNSeuid() int { + return os.Geteuid() +} diff --git a/vendor/github.com/opencontainers/runc/libcontainer/user/lookup_unix.go b/vendor/github.com/opencontainers/runc/libcontainer/user/lookup_unix.go index c45e3004118..92b5ae8de01 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/user/lookup_unix.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/user/lookup_unix.go @@ -5,6 +5,7 @@ package user import ( "io" "os" + "strconv" "golang.org/x/sys/unix" ) @@ -114,3 +115,30 @@ func CurrentUser() (User, error) { func CurrentGroup() (Group, error) { return LookupGid(unix.Getgid()) } + +func currentUserSubIDs(fileName string) ([]SubID, error) { + u, err := CurrentUser() + if err != nil { + return nil, err + } + filter := func(entry SubID) bool { + return entry.Name == u.Name || entry.Name == strconv.Itoa(u.Uid) + } + return ParseSubIDFileFilter(fileName, filter) +} + +func CurrentUserSubUIDs() ([]SubID, error) { + return currentUserSubIDs("/etc/subuid") +} + +func CurrentUserSubGIDs() ([]SubID, error) { + return currentUserSubIDs("/etc/subgid") +} + +func CurrentProcessUIDMap() ([]IDMap, error) { + return ParseIDMapFile("/proc/self/uid_map") +} + +func CurrentProcessGIDMap() ([]IDMap, error) { + return ParseIDMapFile("/proc/self/gid_map") +} diff --git a/vendor/github.com/opencontainers/runc/libcontainer/user/user.go b/vendor/github.com/opencontainers/runc/libcontainer/user/user.go index 93414516caa..7b912bbf8b4 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/user/user.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/user/user.go @@ -75,12 +75,29 @@ func groupFromOS(g *user.Group) (Group, error) { return newGroup, nil } +// SubID represents an entry in /etc/sub{u,g}id +type SubID struct { + Name string + SubID int64 + Count int64 +} + +// IDMap represents an entry in /proc/PID/{u,g}id_map +type IDMap struct { + ID int64 + ParentID int64 + Count int64 +} + func parseLine(line string, v ...interface{}) { - if line == "" { + parseParts(strings.Split(line, ":"), v...) +} + +func parseParts(parts []string, v ...interface{}) { + if len(parts) == 0 { return } - parts := strings.Split(line, ":") for i, p := range parts { // Ignore cases where we don't have enough fields to populate the arguments. // Some configuration files like to misbehave. @@ -96,6 +113,8 @@ func parseLine(line string, v ...interface{}) { case *int: // "numbers", with conversion errors ignored because of some misbehaving configuration files. *e, _ = strconv.Atoi(p) + case *int64: + *e, _ = strconv.ParseInt(p, 10, 64) case *[]string: // Comma-separated lists. if p != "" { @@ -105,7 +124,7 @@ func parseLine(line string, v ...interface{}) { } default: // Someone goof'd when writing code using this function. Scream so they can hear us. - panic(fmt.Sprintf("parseLine only accepts {*string, *int, *[]string} as arguments! %#v is not a pointer!", e)) + panic(fmt.Sprintf("parseLine only accepts {*string, *int, *int64, *[]string} as arguments! %#v is not a pointer!", e)) } } } @@ -479,3 +498,111 @@ func GetAdditionalGroupsPath(additionalGroups []string, groupPath string) ([]int } return GetAdditionalGroups(additionalGroups, group) } + +func ParseSubIDFile(path string) ([]SubID, error) { + subid, err := os.Open(path) + if err != nil { + return nil, err + } + defer subid.Close() + return ParseSubID(subid) +} + +func ParseSubID(subid io.Reader) ([]SubID, error) { + return ParseSubIDFilter(subid, nil) +} + +func ParseSubIDFileFilter(path string, filter func(SubID) bool) ([]SubID, error) { + subid, err := os.Open(path) + if err != nil { + return nil, err + } + defer subid.Close() + return ParseSubIDFilter(subid, filter) +} + +func ParseSubIDFilter(r io.Reader, filter func(SubID) bool) ([]SubID, error) { + if r == nil { + return nil, fmt.Errorf("nil source for subid-formatted data") + } + + var ( + s = bufio.NewScanner(r) + out = []SubID{} + ) + + for s.Scan() { + if err := s.Err(); err != nil { + return nil, err + } + + line := strings.TrimSpace(s.Text()) + if line == "" { + continue + } + + // see: man 5 subuid + p := SubID{} + parseLine(line, &p.Name, &p.SubID, &p.Count) + + if filter == nil || filter(p) { + out = append(out, p) + } + } + + return out, nil +} + +func ParseIDMapFile(path string) ([]IDMap, error) { + r, err := os.Open(path) + if err != nil { + return nil, err + } + defer r.Close() + return ParseIDMap(r) +} + +func ParseIDMap(r io.Reader) ([]IDMap, error) { + return ParseIDMapFilter(r, nil) +} + +func ParseIDMapFileFilter(path string, filter func(IDMap) bool) ([]IDMap, error) { + r, err := os.Open(path) + if err != nil { + return nil, err + } + defer r.Close() + return ParseIDMapFilter(r, filter) +} + +func ParseIDMapFilter(r io.Reader, filter func(IDMap) bool) ([]IDMap, error) { + if r == nil { + return nil, fmt.Errorf("nil source for idmap-formatted data") + } + + var ( + s = bufio.NewScanner(r) + out = []IDMap{} + ) + + for s.Scan() { + if err := s.Err(); err != nil { + return nil, err + } + + line := strings.TrimSpace(s.Text()) + if line == "" { + continue + } + + // see: man 7 user_namespaces + p := IDMap{} + parseParts(strings.Fields(line), &p.ID, &p.ParentID, &p.Count) + + if filter == nil || filter(p) { + out = append(out, p) + } + } + + return out, nil +} diff --git a/vendor/github.com/opencontainers/runc/libcontainer/utils/utils.go b/vendor/github.com/opencontainers/runc/libcontainer/utils/utils.go index baa54c9ba2c..40ccfaa1a01 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/utils/utils.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/utils/utils.go @@ -1,8 +1,6 @@ package utils import ( - "crypto/rand" - "encoding/hex" "encoding/json" "io" "os" @@ -17,19 +15,6 @@ const ( exitSignalOffset = 128 ) -// GenerateRandomName returns a new name joined with a prefix. This size -// specified is used to truncate the randomly generated value -func GenerateRandomName(prefix string, size int) (string, error) { - id := make([]byte, 32) - if _, err := io.ReadFull(rand.Reader, id); err != nil { - return "", err - } - if size > 64 { - size = 64 - } - return prefix + hex.EncodeToString(id)[:size], nil -} - // ResolveRootfs ensures that the current working directory is // not a symlink and returns the absolute path to the rootfs func ResolveRootfs(uncleanRootfs string) (string, error) { diff --git a/vendor/github.com/prometheus/client_golang/prometheus/BUILD b/vendor/github.com/prometheus/client_golang/prometheus/BUILD index 71227a5f45a..b8d4e34a394 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/BUILD +++ b/vendor/github.com/prometheus/client_golang/prometheus/BUILD @@ -13,6 +13,7 @@ go_library( "go_collector.go", "histogram.go", "http.go", + "labels.go", "metric.go", "observer.go", "process_collector.go", @@ -22,6 +23,7 @@ go_library( "untyped.go", "value.go", "vec.go", + "wrap.go", ], importmap = "k8s.io/kubernetes/vendor/github.com/prometheus/client_golang/prometheus", importpath = "github.com/prometheus/client_golang/prometheus", @@ -29,6 +31,7 @@ go_library( deps = [ "//vendor/github.com/beorn7/perks/quantile:go_default_library", "//vendor/github.com/golang/protobuf/proto:go_default_library", + "//vendor/github.com/prometheus/client_golang/prometheus/internal:go_default_library", "//vendor/github.com/prometheus/client_model/go:go_default_library", "//vendor/github.com/prometheus/common/expfmt:go_default_library", "//vendor/github.com/prometheus/common/model:go_default_library", @@ -47,7 +50,9 @@ filegroup( name = "all-srcs", srcs = [ ":package-srcs", + "//vendor/github.com/prometheus/client_golang/prometheus/internal:all-srcs", "//vendor/github.com/prometheus/client_golang/prometheus/promhttp:all-srcs", + "//vendor/github.com/prometheus/client_golang/prometheus/testutil:all-srcs", ], tags = ["automanaged"], visibility = ["//visibility:public"], diff --git a/vendor/github.com/prometheus/client_golang/prometheus/collector.go b/vendor/github.com/prometheus/client_golang/prometheus/collector.go index 623d3d83fef..c0d70b2faf1 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/collector.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/collector.go @@ -29,27 +29,72 @@ type Collector interface { // collected by this Collector to the provided channel and returns once // the last descriptor has been sent. The sent descriptors fulfill the // consistency and uniqueness requirements described in the Desc - // documentation. (It is valid if one and the same Collector sends - // duplicate descriptors. Those duplicates are simply ignored. However, - // two different Collectors must not send duplicate descriptors.) This - // method idempotently sends the same descriptors throughout the - // lifetime of the Collector. If a Collector encounters an error while - // executing this method, it must send an invalid descriptor (created - // with NewInvalidDesc) to signal the error to the registry. + // documentation. + // + // It is valid if one and the same Collector sends duplicate + // descriptors. Those duplicates are simply ignored. However, two + // different Collectors must not send duplicate descriptors. + // + // Sending no descriptor at all marks the Collector as “unchecked”, + // i.e. no checks will be performed at registration time, and the + // Collector may yield any Metric it sees fit in its Collect method. + // + // This method idempotently sends the same descriptors throughout the + // lifetime of the Collector. It may be called concurrently and + // therefore must be implemented in a concurrency safe way. + // + // If a Collector encounters an error while executing this method, it + // must send an invalid descriptor (created with NewInvalidDesc) to + // signal the error to the registry. Describe(chan<- *Desc) // Collect is called by the Prometheus registry when collecting // metrics. The implementation sends each collected metric via the // provided channel and returns once the last metric has been sent. The - // descriptor of each sent metric is one of those returned by - // Describe. Returned metrics that share the same descriptor must differ - // in their variable label values. This method may be called - // concurrently and must therefore be implemented in a concurrency safe - // way. Blocking occurs at the expense of total performance of rendering - // all registered metrics. Ideally, Collector implementations support - // concurrent readers. + // descriptor of each sent metric is one of those returned by Describe + // (unless the Collector is unchecked, see above). Returned metrics that + // share the same descriptor must differ in their variable label + // values. + // + // This method may be called concurrently and must therefore be + // implemented in a concurrency safe way. Blocking occurs at the expense + // of total performance of rendering all registered metrics. Ideally, + // Collector implementations support concurrent readers. Collect(chan<- Metric) } +// DescribeByCollect is a helper to implement the Describe method of a custom +// Collector. It collects the metrics from the provided Collector and sends +// their descriptors to the provided channel. +// +// If a Collector collects the same metrics throughout its lifetime, its +// Describe method can simply be implemented as: +// +// func (c customCollector) Describe(ch chan<- *Desc) { +// DescribeByCollect(c, ch) +// } +// +// However, this will not work if the metrics collected change dynamically over +// the lifetime of the Collector in a way that their combined set of descriptors +// changes as well. The shortcut implementation will then violate the contract +// of the Describe method. If a Collector sometimes collects no metrics at all +// (for example vectors like CounterVec, GaugeVec, etc., which only collect +// metrics after a metric with a fully specified label set has been accessed), +// it might even get registered as an unchecked Collecter (cf. the Register +// method of the Registerer interface). Hence, only use this shortcut +// implementation of Describe if you are certain to fulfill the contract. +// +// The Collector example demonstrates a use of DescribeByCollect. +func DescribeByCollect(c Collector, descs chan<- *Desc) { + metrics := make(chan Metric) + go func() { + c.Collect(metrics) + close(metrics) + }() + for m := range metrics { + descs <- m.Desc() + } +} + // selfCollector implements Collector for a single Metric so that the Metric // collects itself. Add it as an anonymous field to a struct that implements // Metric, and call init with the Metric itself as an argument. diff --git a/vendor/github.com/prometheus/client_golang/prometheus/counter.go b/vendor/github.com/prometheus/client_golang/prometheus/counter.go index 72d5256a508..d463e36d3e9 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/counter.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/counter.go @@ -15,6 +15,10 @@ package prometheus import ( "errors" + "math" + "sync/atomic" + + dto "github.com/prometheus/client_model/go" ) // Counter is a Metric that represents a single numerical value that only ever @@ -42,6 +46,14 @@ type Counter interface { type CounterOpts Opts // NewCounter creates a new Counter based on the provided CounterOpts. +// +// The returned implementation tracks the counter value in two separate +// variables, a float64 and a uint64. The latter is used to track calls of the +// Inc method and calls of the Add method with a value that can be represented +// as a uint64. This allows atomic increments of the counter with optimal +// performance. (It is common to have an Inc call in very hot execution paths.) +// Both internal tracking values are added up in the Write method. This has to +// be taken into account when it comes to precision and overflow behavior. func NewCounter(opts CounterOpts) Counter { desc := NewDesc( BuildFQName(opts.Namespace, opts.Subsystem, opts.Name), @@ -49,20 +61,58 @@ func NewCounter(opts CounterOpts) Counter { nil, opts.ConstLabels, ) - result := &counter{value: value{desc: desc, valType: CounterValue, labelPairs: desc.constLabelPairs}} + result := &counter{desc: desc, labelPairs: desc.constLabelPairs} result.init(result) // Init self-collection. return result } type counter struct { - value + // valBits contains the bits of the represented float64 value, while + // valInt stores values that are exact integers. Both have to go first + // in the struct to guarantee alignment for atomic operations. + // http://golang.org/pkg/sync/atomic/#pkg-note-BUG + valBits uint64 + valInt uint64 + + selfCollector + desc *Desc + + labelPairs []*dto.LabelPair +} + +func (c *counter) Desc() *Desc { + return c.desc } func (c *counter) Add(v float64) { if v < 0 { panic(errors.New("counter cannot decrease in value")) } - c.value.Add(v) + ival := uint64(v) + if float64(ival) == v { + atomic.AddUint64(&c.valInt, ival) + return + } + + for { + oldBits := atomic.LoadUint64(&c.valBits) + newBits := math.Float64bits(math.Float64frombits(oldBits) + v) + if atomic.CompareAndSwapUint64(&c.valBits, oldBits, newBits) { + return + } + } +} + +func (c *counter) Inc() { + atomic.AddUint64(&c.valInt, 1) +} + +func (c *counter) Write(out *dto.Metric) error { + fval := math.Float64frombits(atomic.LoadUint64(&c.valBits)) + ival := atomic.LoadUint64(&c.valInt) + val := fval + float64(ival) + + return populateMetric(CounterValue, val, c.labelPairs, out) } // CounterVec is a Collector that bundles a set of Counters that all share the @@ -70,16 +120,12 @@ func (c *counter) Add(v float64) { // if you want to count the same thing partitioned by various dimensions // (e.g. number of HTTP requests, partitioned by response code and // method). Create instances with NewCounterVec. -// -// CounterVec embeds MetricVec. See there for a full list of methods with -// detailed documentation. type CounterVec struct { - *MetricVec + *metricVec } // NewCounterVec creates a new CounterVec based on the provided CounterOpts and -// partitioned by the given label names. At least one label name must be -// provided. +// partitioned by the given label names. func NewCounterVec(opts CounterOpts, labelNames []string) *CounterVec { desc := NewDesc( BuildFQName(opts.Namespace, opts.Subsystem, opts.Name), @@ -88,34 +134,62 @@ func NewCounterVec(opts CounterOpts, labelNames []string) *CounterVec { opts.ConstLabels, ) return &CounterVec{ - MetricVec: newMetricVec(desc, func(lvs ...string) Metric { - result := &counter{value: value{ - desc: desc, - valType: CounterValue, - labelPairs: makeLabelPairs(desc, lvs), - }} + metricVec: newMetricVec(desc, func(lvs ...string) Metric { + if len(lvs) != len(desc.variableLabels) { + panic(makeInconsistentCardinalityError(desc.fqName, desc.variableLabels, lvs)) + } + result := &counter{desc: desc, labelPairs: makeLabelPairs(desc, lvs)} result.init(result) // Init self-collection. return result }), } } -// GetMetricWithLabelValues replaces the method of the same name in -// MetricVec. The difference is that this method returns a Counter and not a -// Metric so that no type conversion is required. -func (m *CounterVec) GetMetricWithLabelValues(lvs ...string) (Counter, error) { - metric, err := m.MetricVec.GetMetricWithLabelValues(lvs...) +// GetMetricWithLabelValues returns the Counter for the given slice of label +// values (same order as the VariableLabels in Desc). If that combination of +// label values is accessed for the first time, a new Counter is created. +// +// It is possible to call this method without using the returned Counter to only +// create the new Counter but leave it at its starting value 0. See also the +// SummaryVec example. +// +// Keeping the Counter for later use is possible (and should be considered if +// performance is critical), but keep in mind that Reset, DeleteLabelValues and +// Delete can be used to delete the Counter from the CounterVec. In that case, +// the Counter will still exist, but it will not be exported anymore, even if a +// Counter with the same label values is created later. +// +// An error is returned if the number of label values is not the same as the +// number of VariableLabels in Desc (minus any curried labels). +// +// Note that for more than one label value, this method is prone to mistakes +// caused by an incorrect order of arguments. Consider GetMetricWith(Labels) as +// an alternative to avoid that type of mistake. For higher label numbers, the +// latter has a much more readable (albeit more verbose) syntax, but it comes +// with a performance overhead (for creating and processing the Labels map). +// See also the GaugeVec example. +func (v *CounterVec) GetMetricWithLabelValues(lvs ...string) (Counter, error) { + metric, err := v.metricVec.getMetricWithLabelValues(lvs...) if metric != nil { return metric.(Counter), err } return nil, err } -// GetMetricWith replaces the method of the same name in MetricVec. The -// difference is that this method returns a Counter and not a Metric so that no -// type conversion is required. -func (m *CounterVec) GetMetricWith(labels Labels) (Counter, error) { - metric, err := m.MetricVec.GetMetricWith(labels) +// GetMetricWith returns the Counter for the given Labels map (the label names +// must match those of the VariableLabels in Desc). If that label map is +// accessed for the first time, a new Counter is created. Implications of +// creating a Counter without using it and keeping the Counter for later use are +// the same as for GetMetricWithLabelValues. +// +// An error is returned if the number and names of the Labels are inconsistent +// with those of the VariableLabels in Desc (minus any curried labels). +// +// This method is used for the same purpose as +// GetMetricWithLabelValues(...string). See there for pros and cons of the two +// methods. +func (v *CounterVec) GetMetricWith(labels Labels) (Counter, error) { + metric, err := v.metricVec.getMetricWith(labels) if metric != nil { return metric.(Counter), err } @@ -123,18 +197,57 @@ func (m *CounterVec) GetMetricWith(labels Labels) (Counter, error) { } // WithLabelValues works as GetMetricWithLabelValues, but panics where -// GetMetricWithLabelValues would have returned an error. By not returning an -// error, WithLabelValues allows shortcuts like +// GetMetricWithLabelValues would have returned an error. Not returning an +// error allows shortcuts like // myVec.WithLabelValues("404", "GET").Add(42) -func (m *CounterVec) WithLabelValues(lvs ...string) Counter { - return m.MetricVec.WithLabelValues(lvs...).(Counter) +func (v *CounterVec) WithLabelValues(lvs ...string) Counter { + c, err := v.GetMetricWithLabelValues(lvs...) + if err != nil { + panic(err) + } + return c } // With works as GetMetricWith, but panics where GetMetricWithLabels would have -// returned an error. By not returning an error, With allows shortcuts like -// myVec.With(Labels{"code": "404", "method": "GET"}).Add(42) -func (m *CounterVec) With(labels Labels) Counter { - return m.MetricVec.With(labels).(Counter) +// returned an error. Not returning an error allows shortcuts like +// myVec.With(prometheus.Labels{"code": "404", "method": "GET"}).Add(42) +func (v *CounterVec) With(labels Labels) Counter { + c, err := v.GetMetricWith(labels) + if err != nil { + panic(err) + } + return c +} + +// CurryWith returns a vector curried with the provided labels, i.e. the +// returned vector has those labels pre-set for all labeled operations performed +// on it. The cardinality of the curried vector is reduced accordingly. The +// order of the remaining labels stays the same (just with the curried labels +// taken out of the sequence – which is relevant for the +// (GetMetric)WithLabelValues methods). It is possible to curry a curried +// vector, but only with labels not yet used for currying before. +// +// The metrics contained in the CounterVec are shared between the curried and +// uncurried vectors. They are just accessed differently. Curried and uncurried +// vectors behave identically in terms of collection. Only one must be +// registered with a given registry (usually the uncurried version). The Reset +// method deletes all metrics, even if called on a curried vector. +func (v *CounterVec) CurryWith(labels Labels) (*CounterVec, error) { + vec, err := v.curryWith(labels) + if vec != nil { + return &CounterVec{vec}, err + } + return nil, err +} + +// MustCurryWith works as CurryWith but panics where CurryWith would have +// returned an error. +func (v *CounterVec) MustCurryWith(labels Labels) *CounterVec { + vec, err := v.CurryWith(labels) + if err != nil { + panic(err) + } + return vec } // CounterFunc is a Counter whose value is determined at collect time by calling a diff --git a/vendor/github.com/prometheus/client_golang/prometheus/desc.go b/vendor/github.com/prometheus/client_golang/prometheus/desc.go index 1835b16f65c..7b8827ffbca 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/desc.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/desc.go @@ -25,19 +25,6 @@ import ( dto "github.com/prometheus/client_model/go" ) -// reservedLabelPrefix is a prefix which is not legal in user-supplied -// label names. -const reservedLabelPrefix = "__" - -// Labels represents a collection of label name -> value mappings. This type is -// commonly used with the With(Labels) and GetMetricWith(Labels) methods of -// metric vector Collectors, e.g.: -// myVec.With(Labels{"code": "404", "method": "GET"}).Add(42) -// -// The other use-case is the specification of constant label pairs in Opts or to -// create a Desc. -type Labels map[string]string - // Desc is the descriptor used by every Prometheus Metric. It is essentially // the immutable meta-data of a Metric. The normal Metric implementations // included in this package manage their Desc under the hood. Users only have to @@ -80,24 +67,19 @@ type Desc struct { // NewDesc allocates and initializes a new Desc. Errors are recorded in the Desc // and will be reported on registration time. variableLabels and constLabels can -// be nil if no such labels should be set. fqName and help must not be empty. +// be nil if no such labels should be set. fqName must not be empty. // // variableLabels only contain the label names. Their label values are variable // and therefore not part of the Desc. (They are managed within the Metric.) // // For constLabels, the label values are constant. Therefore, they are fully -// specified in the Desc. See the Opts documentation for the implications of -// constant labels. +// specified in the Desc. See the Collector example for a usage pattern. func NewDesc(fqName, help string, variableLabels []string, constLabels Labels) *Desc { d := &Desc{ fqName: fqName, help: help, variableLabels: variableLabels, } - if help == "" { - d.err = errors.New("empty help string") - return d - } if !model.IsValidMetricName(model.LabelValue(fqName)) { d.err = fmt.Errorf("%q is not a valid metric name", fqName) return d @@ -122,6 +104,12 @@ func NewDesc(fqName, help string, variableLabels []string, constLabels Labels) * for _, labelName := range labelNames { labelValues = append(labelValues, constLabels[labelName]) } + // Validate the const label values. They can't have a wrong cardinality, so + // use in len(labelValues) as expectedNumberOfValues. + if err := validateLabelValues(labelValues, len(labelValues)); err != nil { + d.err = err + return d + } // Now add the variable label names, but prefix them with something that // cannot be in a regular label name. That prevents matching the label // dimension with a different mix between preset and variable labels. @@ -137,6 +125,7 @@ func NewDesc(fqName, help string, variableLabels []string, constLabels Labels) * d.err = errors.New("duplicate label names") return d } + vh := hashNew() for _, val := range labelValues { vh = hashAdd(vh, val) @@ -163,7 +152,7 @@ func NewDesc(fqName, help string, variableLabels []string, constLabels Labels) * Value: proto.String(v), }) } - sort.Sort(LabelPairSorter(d.constLabelPairs)) + sort.Sort(labelPairSorter(d.constLabelPairs)) return d } @@ -193,8 +182,3 @@ func (d *Desc) String() string { d.variableLabels, ) } - -func checkLabelName(l string) bool { - return model.LabelName(l).IsValid() && - !strings.HasPrefix(l, reservedLabelPrefix) -} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/doc.go b/vendor/github.com/prometheus/client_golang/prometheus/doc.go index 278969dc7cd..5d9525defc8 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/doc.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/doc.go @@ -11,10 +11,12 @@ // See the License for the specific language governing permissions and // limitations under the License. -// Package prometheus provides metrics primitives to instrument code for -// monitoring. It also offers a registry for metrics. Sub-packages allow to -// expose the registered metrics via HTTP (package promhttp) or push them to a -// Pushgateway (package push). +// Package prometheus is the core instrumentation package. It provides metrics +// primitives to instrument code for monitoring. It also offers a registry for +// metrics. Sub-packages allow to expose the registered metrics via HTTP +// (package promhttp) or push them to a Pushgateway (package push). There is +// also a sub-package promauto, which provides metrics constructors with +// automatic registration. // // All exported functions and methods are safe to be used concurrently unless // specified otherwise. @@ -60,7 +62,7 @@ // // The Handler function provides a default handler to expose metrics // // via an HTTP server. "/metrics" is the usual endpoint for that. // http.Handle("/metrics", promhttp.Handler()) -// log.Fatal(http.ListenAndServe(":8080", nil)) +// log.Fatal(http.ListenAndServe(":8080", nil)) // } // // @@ -72,7 +74,10 @@ // The number of exported identifiers in this package might appear a bit // overwhelming. However, in addition to the basic plumbing shown in the example // above, you only need to understand the different metric types and their -// vector versions for basic usage. +// vector versions for basic usage. Furthermore, if you are not concerned with +// fine-grained control of when and how to register metrics with the registry, +// have a look at the promauto package, which will effectively allow you to +// ignore registration altogether in simple cases. // // Above, you have already touched the Counter and the Gauge. There are two more // advanced metric types: the Summary and Histogram. A more thorough description @@ -116,7 +121,17 @@ // NewConstSummary (and their respective Must… versions). That will happen in // the Collect method. The Describe method has to return separate Desc // instances, representative of the “throw-away” metrics to be created later. -// NewDesc comes in handy to create those Desc instances. +// NewDesc comes in handy to create those Desc instances. Alternatively, you +// could return no Desc at all, which will marke the Collector “unchecked”. No +// checks are porformed at registration time, but metric consistency will still +// be ensured at scrape time, i.e. any inconsistencies will lead to scrape +// errors. Thus, with unchecked Collectors, the responsibility to not collect +// metrics that lead to inconsistencies in the total scrape result lies with the +// implementer of the Collector. While this is not a desirable state, it is +// sometimes necessary. The typical use case is a situatios where the exact +// metrics to be returned by a Collector cannot be predicted at registration +// time, but the implementer has sufficient knowledge of the whole system to +// guarantee metric consistency. // // The Collector example illustrates the use case. You can also look at the // source code of the processCollector (mirroring process metrics), the @@ -145,7 +160,7 @@ // registry. // // So far, everything we did operated on the so-called default registry, as it -// can be found in the global DefaultRegistry variable. With NewRegistry, you +// can be found in the global DefaultRegisterer variable. With NewRegistry, you // can create a custom registry, or you can even implement the Registerer or // Gatherer interfaces yourself. The methods Register and Unregister work in the // same way on a custom registry as the global functions Register and Unregister @@ -153,11 +168,11 @@ // // There are a number of uses for custom registries: You can use registries with // special properties, see NewPedanticRegistry. You can avoid global state, as -// it is imposed by the DefaultRegistry. You can use multiple registries at the -// same time to expose different metrics in different ways. You can use separate -// registries for testing purposes. +// it is imposed by the DefaultRegisterer. You can use multiple registries at +// the same time to expose different metrics in different ways. You can use +// separate registries for testing purposes. // -// Also note that the DefaultRegistry comes registered with a Collector for Go +// Also note that the DefaultRegisterer comes registered with a Collector for Go // runtime metrics (via NewGoCollector) and a Collector for process metrics (via // NewProcessCollector). With a custom registry, you are in control and decide // yourself about the Collectors to register. diff --git a/vendor/github.com/prometheus/client_golang/prometheus/fnv.go b/vendor/github.com/prometheus/client_golang/prometheus/fnv.go index e3b67df8ac0..3d383a735c3 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/fnv.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/fnv.go @@ -1,3 +1,16 @@ +// Copyright 2018 The Prometheus 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 prometheus // Inline and byte-free variant of hash/fnv's fnv64a. diff --git a/vendor/github.com/prometheus/client_golang/prometheus/gauge.go b/vendor/github.com/prometheus/client_golang/prometheus/gauge.go index 9ab5a3d6218..71d406bd92a 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/gauge.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/gauge.go @@ -13,6 +13,14 @@ package prometheus +import ( + "math" + "sync/atomic" + "time" + + dto "github.com/prometheus/client_model/go" +) + // Gauge is a Metric that represents a single numerical value that can // arbitrarily go up and down. // @@ -48,13 +56,74 @@ type Gauge interface { type GaugeOpts Opts // NewGauge creates a new Gauge based on the provided GaugeOpts. +// +// The returned implementation is optimized for a fast Set method. If you have a +// choice for managing the value of a Gauge via Set vs. Inc/Dec/Add/Sub, pick +// the former. For example, the Inc method of the returned Gauge is slower than +// the Inc method of a Counter returned by NewCounter. This matches the typical +// scenarios for Gauges and Counters, where the former tends to be Set-heavy and +// the latter Inc-heavy. func NewGauge(opts GaugeOpts) Gauge { - return newValue(NewDesc( + desc := NewDesc( BuildFQName(opts.Namespace, opts.Subsystem, opts.Name), opts.Help, nil, opts.ConstLabels, - ), GaugeValue, 0) + ) + result := &gauge{desc: desc, labelPairs: desc.constLabelPairs} + result.init(result) // Init self-collection. + return result +} + +type gauge struct { + // valBits contains the bits of the represented float64 value. It has + // to go first in the struct to guarantee alignment for atomic + // operations. http://golang.org/pkg/sync/atomic/#pkg-note-BUG + valBits uint64 + + selfCollector + + desc *Desc + labelPairs []*dto.LabelPair +} + +func (g *gauge) Desc() *Desc { + return g.desc +} + +func (g *gauge) Set(val float64) { + atomic.StoreUint64(&g.valBits, math.Float64bits(val)) +} + +func (g *gauge) SetToCurrentTime() { + g.Set(float64(time.Now().UnixNano()) / 1e9) +} + +func (g *gauge) Inc() { + g.Add(1) +} + +func (g *gauge) Dec() { + g.Add(-1) +} + +func (g *gauge) Add(val float64) { + for { + oldBits := atomic.LoadUint64(&g.valBits) + newBits := math.Float64bits(math.Float64frombits(oldBits) + val) + if atomic.CompareAndSwapUint64(&g.valBits, oldBits, newBits) { + return + } + } +} + +func (g *gauge) Sub(val float64) { + g.Add(val * -1) +} + +func (g *gauge) Write(out *dto.Metric) error { + val := math.Float64frombits(atomic.LoadUint64(&g.valBits)) + return populateMetric(GaugeValue, val, g.labelPairs, out) } // GaugeVec is a Collector that bundles a set of Gauges that all share the same @@ -63,12 +132,11 @@ func NewGauge(opts GaugeOpts) Gauge { // (e.g. number of operations queued, partitioned by user and operation // type). Create instances with NewGaugeVec. type GaugeVec struct { - *MetricVec + *metricVec } // NewGaugeVec creates a new GaugeVec based on the provided GaugeOpts and -// partitioned by the given label names. At least one label name must be -// provided. +// partitioned by the given label names. func NewGaugeVec(opts GaugeOpts, labelNames []string) *GaugeVec { desc := NewDesc( BuildFQName(opts.Namespace, opts.Subsystem, opts.Name), @@ -77,28 +145,62 @@ func NewGaugeVec(opts GaugeOpts, labelNames []string) *GaugeVec { opts.ConstLabels, ) return &GaugeVec{ - MetricVec: newMetricVec(desc, func(lvs ...string) Metric { - return newValue(desc, GaugeValue, 0, lvs...) + metricVec: newMetricVec(desc, func(lvs ...string) Metric { + if len(lvs) != len(desc.variableLabels) { + panic(makeInconsistentCardinalityError(desc.fqName, desc.variableLabels, lvs)) + } + result := &gauge{desc: desc, labelPairs: makeLabelPairs(desc, lvs)} + result.init(result) // Init self-collection. + return result }), } } -// GetMetricWithLabelValues replaces the method of the same name in -// MetricVec. The difference is that this method returns a Gauge and not a -// Metric so that no type conversion is required. -func (m *GaugeVec) GetMetricWithLabelValues(lvs ...string) (Gauge, error) { - metric, err := m.MetricVec.GetMetricWithLabelValues(lvs...) +// GetMetricWithLabelValues returns the Gauge for the given slice of label +// values (same order as the VariableLabels in Desc). If that combination of +// label values is accessed for the first time, a new Gauge is created. +// +// It is possible to call this method without using the returned Gauge to only +// create the new Gauge but leave it at its starting value 0. See also the +// SummaryVec example. +// +// Keeping the Gauge for later use is possible (and should be considered if +// performance is critical), but keep in mind that Reset, DeleteLabelValues and +// Delete can be used to delete the Gauge from the GaugeVec. In that case, the +// Gauge will still exist, but it will not be exported anymore, even if a +// Gauge with the same label values is created later. See also the CounterVec +// example. +// +// An error is returned if the number of label values is not the same as the +// number of VariableLabels in Desc (minus any curried labels). +// +// Note that for more than one label value, this method is prone to mistakes +// caused by an incorrect order of arguments. Consider GetMetricWith(Labels) as +// an alternative to avoid that type of mistake. For higher label numbers, the +// latter has a much more readable (albeit more verbose) syntax, but it comes +// with a performance overhead (for creating and processing the Labels map). +func (v *GaugeVec) GetMetricWithLabelValues(lvs ...string) (Gauge, error) { + metric, err := v.metricVec.getMetricWithLabelValues(lvs...) if metric != nil { return metric.(Gauge), err } return nil, err } -// GetMetricWith replaces the method of the same name in MetricVec. The -// difference is that this method returns a Gauge and not a Metric so that no -// type conversion is required. -func (m *GaugeVec) GetMetricWith(labels Labels) (Gauge, error) { - metric, err := m.MetricVec.GetMetricWith(labels) +// GetMetricWith returns the Gauge for the given Labels map (the label names +// must match those of the VariableLabels in Desc). If that label map is +// accessed for the first time, a new Gauge is created. Implications of +// creating a Gauge without using it and keeping the Gauge for later use are +// the same as for GetMetricWithLabelValues. +// +// An error is returned if the number and names of the Labels are inconsistent +// with those of the VariableLabels in Desc (minus any curried labels). +// +// This method is used for the same purpose as +// GetMetricWithLabelValues(...string). See there for pros and cons of the two +// methods. +func (v *GaugeVec) GetMetricWith(labels Labels) (Gauge, error) { + metric, err := v.metricVec.getMetricWith(labels) if metric != nil { return metric.(Gauge), err } @@ -106,18 +208,57 @@ func (m *GaugeVec) GetMetricWith(labels Labels) (Gauge, error) { } // WithLabelValues works as GetMetricWithLabelValues, but panics where -// GetMetricWithLabelValues would have returned an error. By not returning an -// error, WithLabelValues allows shortcuts like +// GetMetricWithLabelValues would have returned an error. Not returning an +// error allows shortcuts like // myVec.WithLabelValues("404", "GET").Add(42) -func (m *GaugeVec) WithLabelValues(lvs ...string) Gauge { - return m.MetricVec.WithLabelValues(lvs...).(Gauge) +func (v *GaugeVec) WithLabelValues(lvs ...string) Gauge { + g, err := v.GetMetricWithLabelValues(lvs...) + if err != nil { + panic(err) + } + return g } // With works as GetMetricWith, but panics where GetMetricWithLabels would have -// returned an error. By not returning an error, With allows shortcuts like -// myVec.With(Labels{"code": "404", "method": "GET"}).Add(42) -func (m *GaugeVec) With(labels Labels) Gauge { - return m.MetricVec.With(labels).(Gauge) +// returned an error. Not returning an error allows shortcuts like +// myVec.With(prometheus.Labels{"code": "404", "method": "GET"}).Add(42) +func (v *GaugeVec) With(labels Labels) Gauge { + g, err := v.GetMetricWith(labels) + if err != nil { + panic(err) + } + return g +} + +// CurryWith returns a vector curried with the provided labels, i.e. the +// returned vector has those labels pre-set for all labeled operations performed +// on it. The cardinality of the curried vector is reduced accordingly. The +// order of the remaining labels stays the same (just with the curried labels +// taken out of the sequence – which is relevant for the +// (GetMetric)WithLabelValues methods). It is possible to curry a curried +// vector, but only with labels not yet used for currying before. +// +// The metrics contained in the GaugeVec are shared between the curried and +// uncurried vectors. They are just accessed differently. Curried and uncurried +// vectors behave identically in terms of collection. Only one must be +// registered with a given registry (usually the uncurried version). The Reset +// method deletes all metrics, even if called on a curried vector. +func (v *GaugeVec) CurryWith(labels Labels) (*GaugeVec, error) { + vec, err := v.curryWith(labels) + if vec != nil { + return &GaugeVec{vec}, err + } + return nil, err +} + +// MustCurryWith works as CurryWith but panics where CurryWith would have +// returned an error. +func (v *GaugeVec) MustCurryWith(labels Labels) *GaugeVec { + vec, err := v.CurryWith(labels) + if err != nil { + panic(err) + } + return vec } // GaugeFunc is a Gauge whose value is determined at collect time by calling a diff --git a/vendor/github.com/prometheus/client_golang/prometheus/go_collector.go b/vendor/github.com/prometheus/client_golang/prometheus/go_collector.go index f96764559b5..ba3b9333edd 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/go_collector.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/go_collector.go @@ -1,3 +1,16 @@ +// Copyright 2018 The Prometheus 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 prometheus import ( @@ -11,13 +24,18 @@ type goCollector struct { goroutinesDesc *Desc threadsDesc *Desc gcDesc *Desc + goInfoDesc *Desc // metrics to describe and collect metrics memStatsMetrics } -// NewGoCollector returns a collector which exports metrics about the current -// go process. +// NewGoCollector returns a collector which exports metrics about the current Go +// process. This includes memory stats. To collect those, runtime.ReadMemStats +// is called. This causes a stop-the-world, which is very short with Go1.9+ +// (~25µs). However, with older Go versions, the stop-the-world duration depends +// on the heap size and can be quite significant (~1.7 ms/GiB as per +// https://go-review.googlesource.com/c/go/+/34937). func NewGoCollector() Collector { return &goCollector{ goroutinesDesc: NewDesc( @@ -26,12 +44,16 @@ func NewGoCollector() Collector { nil, nil), threadsDesc: NewDesc( "go_threads", - "Number of OS threads created", + "Number of OS threads created.", nil, nil), gcDesc: NewDesc( "go_gc_duration_seconds", "A summary of the GC invocation durations.", nil, nil), + goInfoDesc: NewDesc( + "go_info", + "Information about the Go environment.", + nil, Labels{"version": runtime.Version()}), metrics: memStatsMetrics{ { desc: NewDesc( @@ -239,6 +261,7 @@ func (c *goCollector) Describe(ch chan<- *Desc) { ch <- c.goroutinesDesc ch <- c.threadsDesc ch <- c.gcDesc + ch <- c.goInfoDesc for _, i := range c.metrics { ch <- i.desc } @@ -259,7 +282,9 @@ func (c *goCollector) Collect(ch chan<- Metric) { quantiles[float64(idx+1)/float64(len(stats.PauseQuantiles)-1)] = pq.Seconds() } quantiles[0.0] = stats.PauseQuantiles[0].Seconds() - ch <- MustNewConstSummary(c.gcDesc, uint64(stats.NumGC), float64(stats.PauseTotal.Seconds()), quantiles) + ch <- MustNewConstSummary(c.gcDesc, uint64(stats.NumGC), stats.PauseTotal.Seconds(), quantiles) + + ch <- MustNewConstMetric(c.goInfoDesc, GaugeValue, 1) ms := &runtime.MemStats{} runtime.ReadMemStats(ms) diff --git a/vendor/github.com/prometheus/client_golang/prometheus/histogram.go b/vendor/github.com/prometheus/client_golang/prometheus/histogram.go index f46eff6acfc..f88da707bc8 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/histogram.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/histogram.go @@ -16,7 +16,9 @@ package prometheus import ( "fmt" "math" + "runtime" "sort" + "sync" "sync/atomic" "github.com/golang/protobuf/proto" @@ -108,8 +110,9 @@ func ExponentialBuckets(start, factor float64, count int) []float64 { } // HistogramOpts bundles the options for creating a Histogram metric. It is -// mandatory to set Name and Help to a non-empty string. All other fields are -// optional and can safely be left at their zero value. +// mandatory to set Name to a non-empty string. All other fields are optional +// and can safely be left at their zero value, although it is strongly +// encouraged to set a Help string. type HistogramOpts struct { // Namespace, Subsystem, and Name are components of the fully-qualified // name of the Histogram (created by joining these components with @@ -120,29 +123,22 @@ type HistogramOpts struct { Subsystem string Name string - // Help provides information about this Histogram. Mandatory! + // Help provides information about this Histogram. // // Metrics with the same fully-qualified name must have the same Help // string. Help string - // ConstLabels are used to attach fixed labels to this - // Histogram. Histograms with the same fully-qualified name must have the - // same label names in their ConstLabels. + // ConstLabels are used to attach fixed labels to this metric. Metrics + // with the same fully-qualified name must have the same label names in + // their ConstLabels. // - // Note that in most cases, labels have a value that varies during the - // lifetime of a process. Those labels are usually managed with a - // HistogramVec. ConstLabels serve only special purposes. One is for the - // special case where the value of a label does not change during the - // lifetime of a process, e.g. if the revision of the running binary is - // put into a label. Another, more advanced purpose is if more than one - // Collector needs to collect Histograms with the same fully-qualified - // name. In that case, those Summaries must differ in the values of - // their ConstLabels. See the Collector examples. - // - // If the value of a label never changes (not even between binaries), - // that label most likely should not be a label at all (but part of the - // metric name). + // ConstLabels are only used rarely. In particular, do not use them to + // attach the same labels to all your metrics. Those use cases are + // better covered by target labels set by the scraping Prometheus + // server, or by one specific metric (e.g. a build_info or a + // machine_role metric). See also + // https://prometheus.io/docs/instrumenting/writing_exporters/#target-labels,-not-static-scraped-labels ConstLabels Labels // Buckets defines the buckets into which observations are counted. Each @@ -169,7 +165,7 @@ func NewHistogram(opts HistogramOpts) Histogram { func newHistogram(desc *Desc, opts HistogramOpts, labelValues ...string) Histogram { if len(desc.variableLabels) != len(labelValues) { - panic(errInconsistentCardinality) + panic(makeInconsistentCardinalityError(desc.fqName, desc.variableLabels, labelValues)) } for _, n := range desc.variableLabels { @@ -191,6 +187,7 @@ func newHistogram(desc *Desc, opts HistogramOpts, labelValues ...string) Histogr desc: desc, upperBounds: opts.Buckets, labelPairs: makeLabelPairs(desc, labelValues), + counts: [2]*histogramCounts{&histogramCounts{}, &histogramCounts{}}, } for i, upperBound := range h.upperBounds { if i < len(h.upperBounds)-1 { @@ -207,28 +204,53 @@ func newHistogram(desc *Desc, opts HistogramOpts, labelValues ...string) Histogr } } } - // Finally we know the final length of h.upperBounds and can make counts. - h.counts = make([]uint64, len(h.upperBounds)) + // Finally we know the final length of h.upperBounds and can make counts + // for both states: + h.counts[0].buckets = make([]uint64, len(h.upperBounds)) + h.counts[1].buckets = make([]uint64, len(h.upperBounds)) h.init(h) // Init self-collection. return h } -type histogram struct { +type histogramCounts struct { // sumBits contains the bits of the float64 representing the sum of all // observations. sumBits and count have to go first in the struct to // guarantee alignment for atomic operations. // http://golang.org/pkg/sync/atomic/#pkg-note-BUG sumBits uint64 count uint64 + buckets []uint64 +} + +type histogram struct { + // countAndHotIdx is a complicated one. For lock-free yet atomic + // observations, we need to save the total count of observations again, + // combined with the index of the currently-hot counts struct, so that + // we can perform the operation on both values atomically. The least + // significant bit defines the hot counts struct. The remaining 63 bits + // represent the total count of observations. This happens under the + // assumption that the 63bit count will never overflow. Rationale: An + // observations takes about 30ns. Let's assume it could happen in + // 10ns. Overflowing the counter will then take at least (2^63)*10ns, + // which is about 3000 years. + // + // This has to be first in the struct for 64bit alignment. See + // http://golang.org/pkg/sync/atomic/#pkg-note-BUG + countAndHotIdx uint64 selfCollector - // Note that there is no mutex required. - - desc *Desc + desc *Desc + writeMtx sync.Mutex // Only used in the Write method. upperBounds []float64 - counts []uint64 + + // Two counts, one is "hot" for lock-free observations, the other is + // "cold" for writing out a dto.Metric. It has to be an array of + // pointers to guarantee 64bit alignment of the histogramCounts, see + // http://golang.org/pkg/sync/atomic/#pkg-note-BUG. + counts [2]*histogramCounts + hotIdx int // Index of currently-hot counts. Only used within Write. labelPairs []*dto.LabelPair } @@ -248,36 +270,113 @@ func (h *histogram) Observe(v float64) { // 100 buckets: 78.1 ns/op linear - binary 54.9 ns/op // 300 buckets: 154 ns/op linear - binary 61.6 ns/op i := sort.SearchFloat64s(h.upperBounds, v) - if i < len(h.counts) { - atomic.AddUint64(&h.counts[i], 1) + + // We increment h.countAndHotIdx by 2 so that the counter in the upper + // 63 bits gets incremented by 1. At the same time, we get the new value + // back, which we can use to find the currently-hot counts. + n := atomic.AddUint64(&h.countAndHotIdx, 2) + hotCounts := h.counts[n%2] + + if i < len(h.upperBounds) { + atomic.AddUint64(&hotCounts.buckets[i], 1) } - atomic.AddUint64(&h.count, 1) for { - oldBits := atomic.LoadUint64(&h.sumBits) + oldBits := atomic.LoadUint64(&hotCounts.sumBits) newBits := math.Float64bits(math.Float64frombits(oldBits) + v) - if atomic.CompareAndSwapUint64(&h.sumBits, oldBits, newBits) { + if atomic.CompareAndSwapUint64(&hotCounts.sumBits, oldBits, newBits) { break } } + // Increment count last as we take it as a signal that the observation + // is complete. + atomic.AddUint64(&hotCounts.count, 1) } func (h *histogram) Write(out *dto.Metric) error { - his := &dto.Histogram{} - buckets := make([]*dto.Bucket, len(h.upperBounds)) + var ( + his = &dto.Histogram{} + buckets = make([]*dto.Bucket, len(h.upperBounds)) + hotCounts, coldCounts *histogramCounts + count uint64 + ) - his.SampleSum = proto.Float64(math.Float64frombits(atomic.LoadUint64(&h.sumBits))) - his.SampleCount = proto.Uint64(atomic.LoadUint64(&h.count)) - var count uint64 + // For simplicity, we mutex the rest of this method. It is not in the + // hot path, i.e. Observe is called much more often than Write. The + // complication of making Write lock-free isn't worth it. + h.writeMtx.Lock() + defer h.writeMtx.Unlock() + + // This is a bit arcane, which is why the following spells out this if + // clause in English: + // + // If the currently-hot counts struct is #0, we atomically increment + // h.countAndHotIdx by 1 so that from now on Observe will use the counts + // struct #1. Furthermore, the atomic increment gives us the new value, + // which, in its most significant 63 bits, tells us the count of + // observations done so far up to and including currently ongoing + // observations still using the counts struct just changed from hot to + // cold. To have a normal uint64 for the count, we bitshift by 1 and + // save the result in count. We also set h.hotIdx to 1 for the next + // Write call, and we will refer to counts #1 as hotCounts and to counts + // #0 as coldCounts. + // + // If the currently-hot counts struct is #1, we do the corresponding + // things the other way round. We have to _decrement_ h.countAndHotIdx + // (which is a bit arcane in itself, as we have to express -1 with an + // unsigned int...). + if h.hotIdx == 0 { + count = atomic.AddUint64(&h.countAndHotIdx, 1) >> 1 + h.hotIdx = 1 + hotCounts = h.counts[1] + coldCounts = h.counts[0] + } else { + count = atomic.AddUint64(&h.countAndHotIdx, ^uint64(0)) >> 1 // Decrement. + h.hotIdx = 0 + hotCounts = h.counts[0] + coldCounts = h.counts[1] + } + + // Now we have to wait for the now-declared-cold counts to actually cool + // down, i.e. wait for all observations still using it to finish. That's + // the case once the count in the cold counts struct is the same as the + // one atomically retrieved from the upper 63bits of h.countAndHotIdx. + for { + if count == atomic.LoadUint64(&coldCounts.count) { + break + } + runtime.Gosched() // Let observations get work done. + } + + his.SampleCount = proto.Uint64(count) + his.SampleSum = proto.Float64(math.Float64frombits(atomic.LoadUint64(&coldCounts.sumBits))) + var cumCount uint64 for i, upperBound := range h.upperBounds { - count += atomic.LoadUint64(&h.counts[i]) + cumCount += atomic.LoadUint64(&coldCounts.buckets[i]) buckets[i] = &dto.Bucket{ - CumulativeCount: proto.Uint64(count), + CumulativeCount: proto.Uint64(cumCount), UpperBound: proto.Float64(upperBound), } } + his.Bucket = buckets out.Histogram = his out.Label = h.labelPairs + + // Finally add all the cold counts to the new hot counts and reset the cold counts. + atomic.AddUint64(&hotCounts.count, count) + atomic.StoreUint64(&coldCounts.count, 0) + for { + oldBits := atomic.LoadUint64(&hotCounts.sumBits) + newBits := math.Float64bits(math.Float64frombits(oldBits) + his.GetSampleSum()) + if atomic.CompareAndSwapUint64(&hotCounts.sumBits, oldBits, newBits) { + atomic.StoreUint64(&coldCounts.sumBits, 0) + break + } + } + for i := range h.upperBounds { + atomic.AddUint64(&hotCounts.buckets[i], atomic.LoadUint64(&coldCounts.buckets[i])) + atomic.StoreUint64(&coldCounts.buckets[i], 0) + } return nil } @@ -287,12 +386,11 @@ func (h *histogram) Write(out *dto.Metric) error { // (e.g. HTTP request latencies, partitioned by status code and method). Create // instances with NewHistogramVec. type HistogramVec struct { - *MetricVec + *metricVec } // NewHistogramVec creates a new HistogramVec based on the provided HistogramOpts and -// partitioned by the given label names. At least one label name must be -// provided. +// partitioned by the given label names. func NewHistogramVec(opts HistogramOpts, labelNames []string) *HistogramVec { desc := NewDesc( BuildFQName(opts.Namespace, opts.Subsystem, opts.Name), @@ -301,28 +399,58 @@ func NewHistogramVec(opts HistogramOpts, labelNames []string) *HistogramVec { opts.ConstLabels, ) return &HistogramVec{ - MetricVec: newMetricVec(desc, func(lvs ...string) Metric { + metricVec: newMetricVec(desc, func(lvs ...string) Metric { return newHistogram(desc, opts, lvs...) }), } } -// GetMetricWithLabelValues replaces the method of the same name in -// MetricVec. The difference is that this method returns an Observer and not a -// Metric so that no type conversion to an Observer is required. -func (m *HistogramVec) GetMetricWithLabelValues(lvs ...string) (Observer, error) { - metric, err := m.MetricVec.GetMetricWithLabelValues(lvs...) +// GetMetricWithLabelValues returns the Histogram for the given slice of label +// values (same order as the VariableLabels in Desc). If that combination of +// label values is accessed for the first time, a new Histogram is created. +// +// It is possible to call this method without using the returned Histogram to only +// create the new Histogram but leave it at its starting value, a Histogram without +// any observations. +// +// Keeping the Histogram for later use is possible (and should be considered if +// performance is critical), but keep in mind that Reset, DeleteLabelValues and +// Delete can be used to delete the Histogram from the HistogramVec. In that case, the +// Histogram will still exist, but it will not be exported anymore, even if a +// Histogram with the same label values is created later. See also the CounterVec +// example. +// +// An error is returned if the number of label values is not the same as the +// number of VariableLabels in Desc (minus any curried labels). +// +// Note that for more than one label value, this method is prone to mistakes +// caused by an incorrect order of arguments. Consider GetMetricWith(Labels) as +// an alternative to avoid that type of mistake. For higher label numbers, the +// latter has a much more readable (albeit more verbose) syntax, but it comes +// with a performance overhead (for creating and processing the Labels map). +// See also the GaugeVec example. +func (v *HistogramVec) GetMetricWithLabelValues(lvs ...string) (Observer, error) { + metric, err := v.metricVec.getMetricWithLabelValues(lvs...) if metric != nil { return metric.(Observer), err } return nil, err } -// GetMetricWith replaces the method of the same name in MetricVec. The -// difference is that this method returns an Observer and not a Metric so that no -// type conversion to an Observer is required. -func (m *HistogramVec) GetMetricWith(labels Labels) (Observer, error) { - metric, err := m.MetricVec.GetMetricWith(labels) +// GetMetricWith returns the Histogram for the given Labels map (the label names +// must match those of the VariableLabels in Desc). If that label map is +// accessed for the first time, a new Histogram is created. Implications of +// creating a Histogram without using it and keeping the Histogram for later use +// are the same as for GetMetricWithLabelValues. +// +// An error is returned if the number and names of the Labels are inconsistent +// with those of the VariableLabels in Desc (minus any curried labels). +// +// This method is used for the same purpose as +// GetMetricWithLabelValues(...string). See there for pros and cons of the two +// methods. +func (v *HistogramVec) GetMetricWith(labels Labels) (Observer, error) { + metric, err := v.metricVec.getMetricWith(labels) if metric != nil { return metric.(Observer), err } @@ -330,18 +458,57 @@ func (m *HistogramVec) GetMetricWith(labels Labels) (Observer, error) { } // WithLabelValues works as GetMetricWithLabelValues, but panics where -// GetMetricWithLabelValues would have returned an error. By not returning an -// error, WithLabelValues allows shortcuts like +// GetMetricWithLabelValues would have returned an error. Not returning an +// error allows shortcuts like // myVec.WithLabelValues("404", "GET").Observe(42.21) -func (m *HistogramVec) WithLabelValues(lvs ...string) Observer { - return m.MetricVec.WithLabelValues(lvs...).(Observer) +func (v *HistogramVec) WithLabelValues(lvs ...string) Observer { + h, err := v.GetMetricWithLabelValues(lvs...) + if err != nil { + panic(err) + } + return h } -// With works as GetMetricWith, but panics where GetMetricWithLabels would have -// returned an error. By not returning an error, With allows shortcuts like -// myVec.With(Labels{"code": "404", "method": "GET"}).Observe(42.21) -func (m *HistogramVec) With(labels Labels) Observer { - return m.MetricVec.With(labels).(Observer) +// With works as GetMetricWith but panics where GetMetricWithLabels would have +// returned an error. Not returning an error allows shortcuts like +// myVec.With(prometheus.Labels{"code": "404", "method": "GET"}).Observe(42.21) +func (v *HistogramVec) With(labels Labels) Observer { + h, err := v.GetMetricWith(labels) + if err != nil { + panic(err) + } + return h +} + +// CurryWith returns a vector curried with the provided labels, i.e. the +// returned vector has those labels pre-set for all labeled operations performed +// on it. The cardinality of the curried vector is reduced accordingly. The +// order of the remaining labels stays the same (just with the curried labels +// taken out of the sequence – which is relevant for the +// (GetMetric)WithLabelValues methods). It is possible to curry a curried +// vector, but only with labels not yet used for currying before. +// +// The metrics contained in the HistogramVec are shared between the curried and +// uncurried vectors. They are just accessed differently. Curried and uncurried +// vectors behave identically in terms of collection. Only one must be +// registered with a given registry (usually the uncurried version). The Reset +// method deletes all metrics, even if called on a curried vector. +func (v *HistogramVec) CurryWith(labels Labels) (ObserverVec, error) { + vec, err := v.curryWith(labels) + if vec != nil { + return &HistogramVec{vec}, err + } + return nil, err +} + +// MustCurryWith works as CurryWith but panics where CurryWith would have +// returned an error. +func (v *HistogramVec) MustCurryWith(labels Labels) ObserverVec { + vec, err := v.CurryWith(labels) + if err != nil { + panic(err) + } + return vec } type constHistogram struct { @@ -393,7 +560,7 @@ func (h *constHistogram) Write(out *dto.Metric) error { // bucket. // // NewConstHistogram returns an error if the length of labelValues is not -// consistent with the variable labels in Desc. +// consistent with the variable labels in Desc or if Desc is invalid. func NewConstHistogram( desc *Desc, count uint64, @@ -401,8 +568,11 @@ func NewConstHistogram( buckets map[float64]uint64, labelValues ...string, ) (Metric, error) { - if len(desc.variableLabels) != len(labelValues) { - return nil, errInconsistentCardinality + if desc.err != nil { + return nil, desc.err + } + if err := validateLabelValues(labelValues, len(desc.variableLabels)); err != nil { + return nil, err } return &constHistogram{ desc: desc, diff --git a/vendor/github.com/prometheus/client_golang/prometheus/http.go b/vendor/github.com/prometheus/client_golang/prometheus/http.go index d485ce0b8e4..9f0875bfc81 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/http.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/http.go @@ -15,9 +15,7 @@ package prometheus import ( "bufio" - "bytes" "compress/gzip" - "fmt" "io" "net" "net/http" @@ -41,19 +39,10 @@ const ( acceptEncodingHeader = "Accept-Encoding" ) -var bufPool sync.Pool - -func getBuf() *bytes.Buffer { - buf := bufPool.Get() - if buf == nil { - return &bytes.Buffer{} - } - return buf.(*bytes.Buffer) -} - -func giveBuf(buf *bytes.Buffer) { - buf.Reset() - bufPool.Put(buf) +var gzipPool = sync.Pool{ + New: func() interface{} { + return gzip.NewWriter(nil) + }, } // Handler returns an HTTP handler for the DefaultGatherer. It is @@ -61,69 +50,50 @@ func giveBuf(buf *bytes.Buffer) { // name). // // Deprecated: Please note the issues described in the doc comment of -// InstrumentHandler. You might want to consider using promhttp.Handler instead -// (which is not instrumented, but can be instrumented with the tooling provided -// in package promhttp). +// InstrumentHandler. You might want to consider using promhttp.Handler instead. func Handler() http.Handler { return InstrumentHandler("prometheus", UninstrumentedHandler()) } // UninstrumentedHandler returns an HTTP handler for the DefaultGatherer. // -// Deprecated: Use promhttp.Handler instead. See there for further documentation. +// Deprecated: Use promhttp.HandlerFor(DefaultGatherer, promhttp.HandlerOpts{}) +// instead. See there for further documentation. func UninstrumentedHandler() http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { + return http.HandlerFunc(func(rsp http.ResponseWriter, req *http.Request) { mfs, err := DefaultGatherer.Gather() if err != nil { - http.Error(w, "An error has occurred during metrics collection:\n\n"+err.Error(), http.StatusInternalServerError) + httpError(rsp, err) return } contentType := expfmt.Negotiate(req.Header) - buf := getBuf() - defer giveBuf(buf) - writer, encoding := decorateWriter(req, buf) - enc := expfmt.NewEncoder(writer, contentType) - var lastErr error + header := rsp.Header() + header.Set(contentTypeHeader, string(contentType)) + + w := io.Writer(rsp) + if gzipAccepted(req.Header) { + header.Set(contentEncodingHeader, "gzip") + gz := gzipPool.Get().(*gzip.Writer) + defer gzipPool.Put(gz) + + gz.Reset(w) + defer gz.Close() + + w = gz + } + + enc := expfmt.NewEncoder(w, contentType) + for _, mf := range mfs { if err := enc.Encode(mf); err != nil { - lastErr = err - http.Error(w, "An error has occurred during metrics encoding:\n\n"+err.Error(), http.StatusInternalServerError) + httpError(rsp, err) return } } - if closer, ok := writer.(io.Closer); ok { - closer.Close() - } - if lastErr != nil && buf.Len() == 0 { - http.Error(w, "No metrics encoded, last error:\n\n"+err.Error(), http.StatusInternalServerError) - return - } - header := w.Header() - header.Set(contentTypeHeader, string(contentType)) - header.Set(contentLengthHeader, fmt.Sprint(buf.Len())) - if encoding != "" { - header.Set(contentEncodingHeader, encoding) - } - w.Write(buf.Bytes()) }) } -// decorateWriter wraps a writer to handle gzip compression if requested. It -// returns the decorated writer and the appropriate "Content-Encoding" header -// (which is empty if no compression is enabled). -func decorateWriter(request *http.Request, writer io.Writer) (io.Writer, string) { - header := request.Header.Get(acceptEncodingHeader) - parts := strings.Split(header, ",") - for _, part := range parts { - part := strings.TrimSpace(part) - if part == "gzip" || strings.HasPrefix(part, "gzip;") { - return gzip.NewWriter(writer), "gzip" - } - } - return writer, "" -} - var instLabels = []string{"method", "code"} type nower interface { @@ -140,16 +110,6 @@ var now nower = nowFunc(func() time.Time { return time.Now() }) -func nowSeries(t ...time.Time) nower { - return nowFunc(func() time.Time { - defer func() { - t = t[1:] - }() - - return t[0] - }) -} - // InstrumentHandler wraps the given HTTP handler for instrumentation. It // registers four metric collectors (if not already done) and reports HTTP // metrics to the (newly or already) registered collectors: http_requests_total @@ -160,21 +120,14 @@ func nowSeries(t ...time.Time) nower { // (label name "method") and HTTP status code (label name "code"). // // Deprecated: InstrumentHandler has several issues. Use the tooling provided in -// package promhttp instead. The issues are the following: -// -// - It uses Summaries rather than Histograms. Summaries are not useful if -// aggregation across multiple instances is required. -// -// - It uses microseconds as unit, which is deprecated and should be replaced by -// seconds. -// -// - The size of the request is calculated in a separate goroutine. Since this -// calculator requires access to the request header, it creates a race with -// any writes to the header performed during request handling. -// httputil.ReverseProxy is a prominent example for a handler -// performing such writes. -// -// - It has additional issues with HTTP/2, cf. +// package promhttp instead. The issues are the following: (1) It uses Summaries +// rather than Histograms. Summaries are not useful if aggregation across +// multiple instances is required. (2) It uses microseconds as unit, which is +// deprecated and should be replaced by seconds. (3) The size of the request is +// calculated in a separate goroutine. Since this calculator requires access to +// the request header, it creates a race with any writes to the header performed +// during request handling. httputil.ReverseProxy is a prominent example for a +// handler performing such writes. (4) It has additional issues with HTTP/2, cf. // https://github.com/prometheus/client_golang/issues/272. func InstrumentHandler(handlerName string, handler http.Handler) http.HandlerFunc { return InstrumentHandlerFunc(handlerName, handler.ServeHTTP) @@ -318,7 +271,7 @@ func InstrumentHandlerFuncWithOpts(opts SummaryOpts, handlerFunc func(http.Respo } func computeApproximateRequestSize(r *http.Request) <-chan int { - // Get URL length in current go routine for avoiding a race condition. + // Get URL length in current goroutine for avoiding a race condition. // HandlerFunc that runs in parallel may modify the URL. s := 0 if r.URL != nil { @@ -353,10 +306,9 @@ func computeApproximateRequestSize(r *http.Request) <-chan int { type responseWriterDelegator struct { http.ResponseWriter - handler, method string - status int - written int64 - wroteHeader bool + status int + written int64 + wroteHeader bool } func (r *responseWriterDelegator) WriteHeader(code int) { @@ -522,3 +474,31 @@ func sanitizeCode(s int) string { return strconv.Itoa(s) } } + +// gzipAccepted returns whether the client will accept gzip-encoded content. +func gzipAccepted(header http.Header) bool { + a := header.Get(acceptEncodingHeader) + parts := strings.Split(a, ",") + for _, part := range parts { + part = strings.TrimSpace(part) + if part == "gzip" || strings.HasPrefix(part, "gzip;") { + return true + } + } + return false +} + +// httpError removes any content-encoding header and then calls http.Error with +// the provided error and http.StatusInternalServerErrer. Error contents is +// supposed to be uncompressed plain text. However, same as with a plain +// http.Error, any header settings will be void if the header has already been +// sent. The error message will still be written to the writer, but it will +// probably be of limited use. +func httpError(rsp http.ResponseWriter, err error) { + rsp.Header().Del(contentEncodingHeader) + http.Error( + rsp, + "An error has occurred while serving metrics:\n\n"+err.Error(), + http.StatusInternalServerError, + ) +} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/internal/BUILD b/vendor/github.com/prometheus/client_golang/prometheus/internal/BUILD new file mode 100644 index 00000000000..94b96d1f1de --- /dev/null +++ b/vendor/github.com/prometheus/client_golang/prometheus/internal/BUILD @@ -0,0 +1,24 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = ["metric.go"], + importmap = "k8s.io/kubernetes/vendor/github.com/prometheus/client_golang/prometheus/internal", + importpath = "github.com/prometheus/client_golang/prometheus/internal", + visibility = ["//visibility:public"], + deps = ["//vendor/github.com/prometheus/client_model/go:go_default_library"], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/vendor/github.com/prometheus/client_golang/prometheus/internal/metric.go b/vendor/github.com/prometheus/client_golang/prometheus/internal/metric.go new file mode 100644 index 00000000000..351c26e1aed --- /dev/null +++ b/vendor/github.com/prometheus/client_golang/prometheus/internal/metric.go @@ -0,0 +1,85 @@ +// Copyright 2018 The Prometheus 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 internal + +import ( + "sort" + + dto "github.com/prometheus/client_model/go" +) + +// metricSorter is a sortable slice of *dto.Metric. +type metricSorter []*dto.Metric + +func (s metricSorter) Len() int { + return len(s) +} + +func (s metricSorter) Swap(i, j int) { + s[i], s[j] = s[j], s[i] +} + +func (s metricSorter) Less(i, j int) bool { + if len(s[i].Label) != len(s[j].Label) { + // This should not happen. The metrics are + // inconsistent. However, we have to deal with the fact, as + // people might use custom collectors or metric family injection + // to create inconsistent metrics. So let's simply compare the + // number of labels in this case. That will still yield + // reproducible sorting. + return len(s[i].Label) < len(s[j].Label) + } + for n, lp := range s[i].Label { + vi := lp.GetValue() + vj := s[j].Label[n].GetValue() + if vi != vj { + return vi < vj + } + } + + // We should never arrive here. Multiple metrics with the same + // label set in the same scrape will lead to undefined ingestion + // behavior. However, as above, we have to provide stable sorting + // here, even for inconsistent metrics. So sort equal metrics + // by their timestamp, with missing timestamps (implying "now") + // coming last. + if s[i].TimestampMs == nil { + return false + } + if s[j].TimestampMs == nil { + return true + } + return s[i].GetTimestampMs() < s[j].GetTimestampMs() +} + +// NormalizeMetricFamilies returns a MetricFamily slice with empty +// MetricFamilies pruned and the remaining MetricFamilies sorted by name within +// the slice, with the contained Metrics sorted within each MetricFamily. +func NormalizeMetricFamilies(metricFamiliesByName map[string]*dto.MetricFamily) []*dto.MetricFamily { + for _, mf := range metricFamiliesByName { + sort.Sort(metricSorter(mf.Metric)) + } + names := make([]string, 0, len(metricFamiliesByName)) + for name, mf := range metricFamiliesByName { + if len(mf.Metric) > 0 { + names = append(names, name) + } + } + sort.Strings(names) + result := make([]*dto.MetricFamily, 0, len(names)) + for _, name := range names { + result = append(result, metricFamiliesByName[name]) + } + return result +} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/labels.go b/vendor/github.com/prometheus/client_golang/prometheus/labels.go new file mode 100644 index 00000000000..2744443ac22 --- /dev/null +++ b/vendor/github.com/prometheus/client_golang/prometheus/labels.go @@ -0,0 +1,87 @@ +// Copyright 2018 The Prometheus 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 prometheus + +import ( + "errors" + "fmt" + "strings" + "unicode/utf8" + + "github.com/prometheus/common/model" +) + +// Labels represents a collection of label name -> value mappings. This type is +// commonly used with the With(Labels) and GetMetricWith(Labels) methods of +// metric vector Collectors, e.g.: +// myVec.With(Labels{"code": "404", "method": "GET"}).Add(42) +// +// The other use-case is the specification of constant label pairs in Opts or to +// create a Desc. +type Labels map[string]string + +// reservedLabelPrefix is a prefix which is not legal in user-supplied +// label names. +const reservedLabelPrefix = "__" + +var errInconsistentCardinality = errors.New("inconsistent label cardinality") + +func makeInconsistentCardinalityError(fqName string, labels, labelValues []string) error { + return fmt.Errorf( + "%s: %q has %d variable labels named %q but %d values %q were provided", + errInconsistentCardinality, fqName, + len(labels), labels, + len(labelValues), labelValues, + ) +} + +func validateValuesInLabels(labels Labels, expectedNumberOfValues int) error { + if len(labels) != expectedNumberOfValues { + return fmt.Errorf( + "%s: expected %d label values but got %d in %#v", + errInconsistentCardinality, expectedNumberOfValues, + len(labels), labels, + ) + } + + for name, val := range labels { + if !utf8.ValidString(val) { + return fmt.Errorf("label %s: value %q is not valid UTF-8", name, val) + } + } + + return nil +} + +func validateLabelValues(vals []string, expectedNumberOfValues int) error { + if len(vals) != expectedNumberOfValues { + return fmt.Errorf( + "%s: expected %d label values but got %d in %#v", + errInconsistentCardinality, expectedNumberOfValues, + len(vals), vals, + ) + } + + for _, val := range vals { + if !utf8.ValidString(val) { + return fmt.Errorf("label value %q is not valid UTF-8", val) + } + } + + return nil +} + +func checkLabelName(l string) bool { + return model.LabelName(l).IsValid() && !strings.HasPrefix(l, reservedLabelPrefix) +} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/metric.go b/vendor/github.com/prometheus/client_golang/prometheus/metric.go index d4063d98f41..55e6d86d596 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/metric.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/metric.go @@ -15,6 +15,9 @@ package prometheus import ( "strings" + "time" + + "github.com/golang/protobuf/proto" dto "github.com/prometheus/client_model/go" ) @@ -43,9 +46,8 @@ type Metric interface { // While populating dto.Metric, it is the responsibility of the // implementation to ensure validity of the Metric protobuf (like valid // UTF-8 strings or syntactically valid metric and label names). It is - // recommended to sort labels lexicographically. (Implementers may find - // LabelPairSorter useful for that.) Callers of Write should still make - // sure of sorting if they depend on it. + // recommended to sort labels lexicographically. Callers of Write should + // still make sure of sorting if they depend on it. Write(*dto.Metric) error // TODO(beorn7): The original rationale of passing in a pre-allocated // dto.Metric protobuf to save allocations has disappeared. The @@ -57,8 +59,9 @@ type Metric interface { // implementation XXX has its own XXXOpts type, but in most cases, it is just be // an alias of this type (which might change when the requirement arises.) // -// It is mandatory to set Name and Help to a non-empty string. All other fields -// are optional and can safely be left at their zero value. +// It is mandatory to set Name to a non-empty string. All other fields are +// optional and can safely be left at their zero value, although it is strongly +// encouraged to set a Help string. type Opts struct { // Namespace, Subsystem, and Name are components of the fully-qualified // name of the Metric (created by joining these components with @@ -69,7 +72,7 @@ type Opts struct { Subsystem string Name string - // Help provides information about this metric. Mandatory! + // Help provides information about this metric. // // Metrics with the same fully-qualified name must have the same Help // string. @@ -79,20 +82,12 @@ type Opts struct { // with the same fully-qualified name must have the same label names in // their ConstLabels. // - // Note that in most cases, labels have a value that varies during the - // lifetime of a process. Those labels are usually managed with a metric - // vector collector (like CounterVec, GaugeVec, UntypedVec). ConstLabels - // serve only special purposes. One is for the special case where the - // value of a label does not change during the lifetime of a process, - // e.g. if the revision of the running binary is put into a - // label. Another, more advanced purpose is if more than one Collector - // needs to collect Metrics with the same fully-qualified name. In that - // case, those Metrics must differ in the values of their - // ConstLabels. See the Collector examples. - // - // If the value of a label never changes (not even between binaries), - // that label most likely should not be a label at all (but part of the - // metric name). + // ConstLabels are only used rarely. In particular, do not use them to + // attach the same labels to all your metrics. Those use cases are + // better covered by target labels set by the scraping Prometheus + // server, or by one specific metric (e.g. a build_info or a + // machine_role metric). See also + // https://prometheus.io/docs/instrumenting/writing_exporters/#target-labels,-not-static-scraped-labels ConstLabels Labels } @@ -118,37 +113,22 @@ func BuildFQName(namespace, subsystem, name string) string { return name } -// LabelPairSorter implements sort.Interface. It is used to sort a slice of -// dto.LabelPair pointers. This is useful for implementing the Write method of -// custom metrics. -type LabelPairSorter []*dto.LabelPair +// labelPairSorter implements sort.Interface. It is used to sort a slice of +// dto.LabelPair pointers. +type labelPairSorter []*dto.LabelPair -func (s LabelPairSorter) Len() int { +func (s labelPairSorter) Len() int { return len(s) } -func (s LabelPairSorter) Swap(i, j int) { +func (s labelPairSorter) Swap(i, j int) { s[i], s[j] = s[j], s[i] } -func (s LabelPairSorter) Less(i, j int) bool { +func (s labelPairSorter) Less(i, j int) bool { return s[i].GetName() < s[j].GetName() } -type hashSorter []uint64 - -func (s hashSorter) Len() int { - return len(s) -} - -func (s hashSorter) Swap(i, j int) { - s[i], s[j] = s[j], s[i] -} - -func (s hashSorter) Less(i, j int) bool { - return s[i] < s[j] -} - type invalidMetric struct { desc *Desc err error @@ -164,3 +144,31 @@ func NewInvalidMetric(desc *Desc, err error) Metric { func (m *invalidMetric) Desc() *Desc { return m.desc } func (m *invalidMetric) Write(*dto.Metric) error { return m.err } + +type timestampedMetric struct { + Metric + t time.Time +} + +func (m timestampedMetric) Write(pb *dto.Metric) error { + e := m.Metric.Write(pb) + pb.TimestampMs = proto.Int64(m.t.Unix()*1000 + int64(m.t.Nanosecond()/1000000)) + return e +} + +// NewMetricWithTimestamp returns a new Metric wrapping the provided Metric in a +// way that it has an explicit timestamp set to the provided Time. This is only +// useful in rare cases as the timestamp of a Prometheus metric should usually +// be set by the Prometheus server during scraping. Exceptions include mirroring +// metrics with given timestamps from other metric +// sources. +// +// NewMetricWithTimestamp works best with MustNewConstMetric, +// MustNewConstHistogram, and MustNewConstSummary, see example. +// +// Currently, the exposition formats used by Prometheus are limited to +// millisecond resolution. Thus, the provided time will be rounded down to the +// next full millisecond value. +func NewMetricWithTimestamp(t time.Time, m Metric) Metric { + return timestampedMetric{Metric: m, t: t} +} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/observer.go b/vendor/github.com/prometheus/client_golang/prometheus/observer.go index b0520e85e8b..5806cd09e30 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/observer.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/observer.go @@ -45,6 +45,8 @@ type ObserverVec interface { GetMetricWithLabelValues(lvs ...string) (Observer, error) With(Labels) Observer WithLabelValues(...string) Observer + CurryWith(Labels) (ObserverVec, error) + MustCurryWith(Labels) ObserverVec Collector } diff --git a/vendor/github.com/prometheus/client_golang/prometheus/process_collector.go b/vendor/github.com/prometheus/client_golang/prometheus/process_collector.go index 94b2553e14a..55176d58ce6 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/process_collector.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/process_collector.go @@ -13,46 +13,74 @@ package prometheus -import "github.com/prometheus/procfs" +import ( + "errors" + "os" + + "github.com/prometheus/procfs" +) type processCollector struct { - pid int collectFn func(chan<- Metric) pidFn func() (int, error) + reportErrors bool cpuTotal *Desc openFDs, maxFDs *Desc - vsize, rss *Desc + vsize, maxVsize *Desc + rss *Desc startTime *Desc } -// NewProcessCollector returns a collector which exports the current state of -// process metrics including cpu, memory and file descriptor usage as well as -// the process start time for the given process id under the given namespace. -func NewProcessCollector(pid int, namespace string) Collector { - return NewProcessCollectorPIDFn( - func() (int, error) { return pid, nil }, - namespace, - ) +// ProcessCollectorOpts defines the behavior of a process metrics collector +// created with NewProcessCollector. +type ProcessCollectorOpts struct { + // PidFn returns the PID of the process the collector collects metrics + // for. It is called upon each collection. By default, the PID of the + // current process is used, as determined on construction time by + // calling os.Getpid(). + PidFn func() (int, error) + // If non-empty, each of the collected metrics is prefixed by the + // provided string and an underscore ("_"). + Namespace string + // If true, any error encountered during collection is reported as an + // invalid metric (see NewInvalidMetric). Otherwise, errors are ignored + // and the collected metrics will be incomplete. (Possibly, no metrics + // will be collected at all.) While that's usually not desired, it is + // appropriate for the common "mix-in" of process metrics, where process + // metrics are nice to have, but failing to collect them should not + // disrupt the collection of the remaining metrics. + ReportErrors bool } -// NewProcessCollectorPIDFn returns a collector which exports the current state -// of process metrics including cpu, memory and file descriptor usage as well -// as the process start time under the given namespace. The given pidFn is -// called on each collect and is used to determine the process to export -// metrics for. -func NewProcessCollectorPIDFn( - pidFn func() (int, error), - namespace string, -) Collector { +// NewProcessCollector returns a collector which exports the current state of +// process metrics including CPU, memory and file descriptor usage as well as +// the process start time. The detailed behavior is defined by the provided +// ProcessCollectorOpts. The zero value of ProcessCollectorOpts creates a +// collector for the current process with an empty namespace string and no error +// reporting. +// +// Currently, the collector depends on a Linux-style proc filesystem and +// therefore only exports metrics for Linux. +// +// Note: An older version of this function had the following signature: +// +// NewProcessCollector(pid int, namespace string) Collector +// +// Most commonly, it was called as +// +// NewProcessCollector(os.Getpid(), "") +// +// The following call of the current version is equivalent to the above: +// +// NewProcessCollector(ProcessCollectorOpts{}) +func NewProcessCollector(opts ProcessCollectorOpts) Collector { ns := "" - if len(namespace) > 0 { - ns = namespace + "_" + if len(opts.Namespace) > 0 { + ns = opts.Namespace + "_" } - c := processCollector{ - pidFn: pidFn, - collectFn: func(chan<- Metric) {}, - + c := &processCollector{ + reportErrors: opts.ReportErrors, cpuTotal: NewDesc( ns+"process_cpu_seconds_total", "Total user and system CPU time spent in seconds.", @@ -73,6 +101,11 @@ func NewProcessCollectorPIDFn( "Virtual memory size in bytes.", nil, nil, ), + maxVsize: NewDesc( + ns+"process_virtual_memory_max_bytes", + "Maximum amount of virtual memory available in bytes.", + nil, nil, + ), rss: NewDesc( ns+"process_resident_memory_bytes", "Resident memory size in bytes.", @@ -85,12 +118,23 @@ func NewProcessCollectorPIDFn( ), } + if opts.PidFn == nil { + pid := os.Getpid() + c.pidFn = func() (int, error) { return pid, nil } + } else { + c.pidFn = opts.PidFn + } + // Set up process metric collection if supported by the runtime. if _, err := procfs.NewStat(); err == nil { c.collectFn = c.processCollect + } else { + c.collectFn = func(ch chan<- Metric) { + c.reportError(ch, nil, errors.New("process metrics not supported on this platform")) + } } - return &c + return c } // Describe returns all descriptions of the collector. @@ -99,6 +143,7 @@ func (c *processCollector) Describe(ch chan<- *Desc) { ch <- c.openFDs ch <- c.maxFDs ch <- c.vsize + ch <- c.maxVsize ch <- c.rss ch <- c.startTime } @@ -108,16 +153,16 @@ func (c *processCollector) Collect(ch chan<- Metric) { c.collectFn(ch) } -// TODO(ts): Bring back error reporting by reverting 7faf9e7 as soon as the -// client allows users to configure the error behavior. func (c *processCollector) processCollect(ch chan<- Metric) { pid, err := c.pidFn() if err != nil { + c.reportError(ch, nil, err) return } p, err := procfs.NewProc(pid) if err != nil { + c.reportError(ch, nil, err) return } @@ -127,14 +172,33 @@ func (c *processCollector) processCollect(ch chan<- Metric) { ch <- MustNewConstMetric(c.rss, GaugeValue, float64(stat.ResidentMemory())) if startTime, err := stat.StartTime(); err == nil { ch <- MustNewConstMetric(c.startTime, GaugeValue, startTime) + } else { + c.reportError(ch, c.startTime, err) } + } else { + c.reportError(ch, nil, err) } if fds, err := p.FileDescriptorsLen(); err == nil { ch <- MustNewConstMetric(c.openFDs, GaugeValue, float64(fds)) + } else { + c.reportError(ch, c.openFDs, err) } if limits, err := p.NewLimits(); err == nil { ch <- MustNewConstMetric(c.maxFDs, GaugeValue, float64(limits.OpenFiles)) + ch <- MustNewConstMetric(c.maxVsize, GaugeValue, float64(limits.AddressSpace)) + } else { + c.reportError(ch, nil, err) } } + +func (c *processCollector) reportError(ch chan<- Metric, desc *Desc, err error) { + if !c.reportErrors { + return + } + if desc == nil { + desc = NewInvalidDesc(err) + } + ch <- NewInvalidMetric(desc, err) +} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/BUILD b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/BUILD index 710e19da8e5..83abcf19210 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/BUILD +++ b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/BUILD @@ -3,8 +3,9 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library") go_library( name = "go_default_library", srcs = [ - "delegator_1_7.go", + "delegator.go", "delegator_1_8.go", + "delegator_pre_1_8.go", "http.go", "instrument_client.go", "instrument_client_1_8.go", diff --git a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/delegator.go b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/delegator.go new file mode 100644 index 00000000000..67b56d37cfd --- /dev/null +++ b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/delegator.go @@ -0,0 +1,199 @@ +// Copyright 2017 The Prometheus 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 promhttp + +import ( + "bufio" + "io" + "net" + "net/http" +) + +const ( + closeNotifier = 1 << iota + flusher + hijacker + readerFrom + pusher +) + +type delegator interface { + http.ResponseWriter + + Status() int + Written() int64 +} + +type responseWriterDelegator struct { + http.ResponseWriter + + handler, method string + status int + written int64 + wroteHeader bool + observeWriteHeader func(int) +} + +func (r *responseWriterDelegator) Status() int { + return r.status +} + +func (r *responseWriterDelegator) Written() int64 { + return r.written +} + +func (r *responseWriterDelegator) WriteHeader(code int) { + r.status = code + r.wroteHeader = true + r.ResponseWriter.WriteHeader(code) + if r.observeWriteHeader != nil { + r.observeWriteHeader(code) + } +} + +func (r *responseWriterDelegator) Write(b []byte) (int, error) { + if !r.wroteHeader { + r.WriteHeader(http.StatusOK) + } + n, err := r.ResponseWriter.Write(b) + r.written += int64(n) + return n, err +} + +type closeNotifierDelegator struct{ *responseWriterDelegator } +type flusherDelegator struct{ *responseWriterDelegator } +type hijackerDelegator struct{ *responseWriterDelegator } +type readerFromDelegator struct{ *responseWriterDelegator } + +func (d closeNotifierDelegator) CloseNotify() <-chan bool { + return d.ResponseWriter.(http.CloseNotifier).CloseNotify() +} +func (d flusherDelegator) Flush() { + d.ResponseWriter.(http.Flusher).Flush() +} +func (d hijackerDelegator) Hijack() (net.Conn, *bufio.ReadWriter, error) { + return d.ResponseWriter.(http.Hijacker).Hijack() +} +func (d readerFromDelegator) ReadFrom(re io.Reader) (int64, error) { + if !d.wroteHeader { + d.WriteHeader(http.StatusOK) + } + n, err := d.ResponseWriter.(io.ReaderFrom).ReadFrom(re) + d.written += n + return n, err +} + +var pickDelegator = make([]func(*responseWriterDelegator) delegator, 32) + +func init() { + // TODO(beorn7): Code generation would help here. + pickDelegator[0] = func(d *responseWriterDelegator) delegator { // 0 + return d + } + pickDelegator[closeNotifier] = func(d *responseWriterDelegator) delegator { // 1 + return closeNotifierDelegator{d} + } + pickDelegator[flusher] = func(d *responseWriterDelegator) delegator { // 2 + return flusherDelegator{d} + } + pickDelegator[flusher+closeNotifier] = func(d *responseWriterDelegator) delegator { // 3 + return struct { + *responseWriterDelegator + http.Flusher + http.CloseNotifier + }{d, flusherDelegator{d}, closeNotifierDelegator{d}} + } + pickDelegator[hijacker] = func(d *responseWriterDelegator) delegator { // 4 + return hijackerDelegator{d} + } + pickDelegator[hijacker+closeNotifier] = func(d *responseWriterDelegator) delegator { // 5 + return struct { + *responseWriterDelegator + http.Hijacker + http.CloseNotifier + }{d, hijackerDelegator{d}, closeNotifierDelegator{d}} + } + pickDelegator[hijacker+flusher] = func(d *responseWriterDelegator) delegator { // 6 + return struct { + *responseWriterDelegator + http.Hijacker + http.Flusher + }{d, hijackerDelegator{d}, flusherDelegator{d}} + } + pickDelegator[hijacker+flusher+closeNotifier] = func(d *responseWriterDelegator) delegator { // 7 + return struct { + *responseWriterDelegator + http.Hijacker + http.Flusher + http.CloseNotifier + }{d, hijackerDelegator{d}, flusherDelegator{d}, closeNotifierDelegator{d}} + } + pickDelegator[readerFrom] = func(d *responseWriterDelegator) delegator { // 8 + return readerFromDelegator{d} + } + pickDelegator[readerFrom+closeNotifier] = func(d *responseWriterDelegator) delegator { // 9 + return struct { + *responseWriterDelegator + io.ReaderFrom + http.CloseNotifier + }{d, readerFromDelegator{d}, closeNotifierDelegator{d}} + } + pickDelegator[readerFrom+flusher] = func(d *responseWriterDelegator) delegator { // 10 + return struct { + *responseWriterDelegator + io.ReaderFrom + http.Flusher + }{d, readerFromDelegator{d}, flusherDelegator{d}} + } + pickDelegator[readerFrom+flusher+closeNotifier] = func(d *responseWriterDelegator) delegator { // 11 + return struct { + *responseWriterDelegator + io.ReaderFrom + http.Flusher + http.CloseNotifier + }{d, readerFromDelegator{d}, flusherDelegator{d}, closeNotifierDelegator{d}} + } + pickDelegator[readerFrom+hijacker] = func(d *responseWriterDelegator) delegator { // 12 + return struct { + *responseWriterDelegator + io.ReaderFrom + http.Hijacker + }{d, readerFromDelegator{d}, hijackerDelegator{d}} + } + pickDelegator[readerFrom+hijacker+closeNotifier] = func(d *responseWriterDelegator) delegator { // 13 + return struct { + *responseWriterDelegator + io.ReaderFrom + http.Hijacker + http.CloseNotifier + }{d, readerFromDelegator{d}, hijackerDelegator{d}, closeNotifierDelegator{d}} + } + pickDelegator[readerFrom+hijacker+flusher] = func(d *responseWriterDelegator) delegator { // 14 + return struct { + *responseWriterDelegator + io.ReaderFrom + http.Hijacker + http.Flusher + }{d, readerFromDelegator{d}, hijackerDelegator{d}, flusherDelegator{d}} + } + pickDelegator[readerFrom+hijacker+flusher+closeNotifier] = func(d *responseWriterDelegator) delegator { // 15 + return struct { + *responseWriterDelegator + io.ReaderFrom + http.Hijacker + http.Flusher + http.CloseNotifier + }{d, readerFromDelegator{d}, hijackerDelegator{d}, flusherDelegator{d}, closeNotifierDelegator{d}} + } +} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/delegator_1_8.go b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/delegator_1_8.go index b7743fb8713..31a70695695 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/delegator_1_8.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/delegator_1_8.go @@ -20,54 +20,162 @@ import ( "net/http" ) -// newDelegator handles the four different methods of upgrading a -// http.ResponseWriter to delegator. +type pusherDelegator struct{ *responseWriterDelegator } + +func (d pusherDelegator) Push(target string, opts *http.PushOptions) error { + return d.ResponseWriter.(http.Pusher).Push(target, opts) +} + +func init() { + pickDelegator[pusher] = func(d *responseWriterDelegator) delegator { // 16 + return pusherDelegator{d} + } + pickDelegator[pusher+closeNotifier] = func(d *responseWriterDelegator) delegator { // 17 + return struct { + *responseWriterDelegator + http.Pusher + http.CloseNotifier + }{d, pusherDelegator{d}, closeNotifierDelegator{d}} + } + pickDelegator[pusher+flusher] = func(d *responseWriterDelegator) delegator { // 18 + return struct { + *responseWriterDelegator + http.Pusher + http.Flusher + }{d, pusherDelegator{d}, flusherDelegator{d}} + } + pickDelegator[pusher+flusher+closeNotifier] = func(d *responseWriterDelegator) delegator { // 19 + return struct { + *responseWriterDelegator + http.Pusher + http.Flusher + http.CloseNotifier + }{d, pusherDelegator{d}, flusherDelegator{d}, closeNotifierDelegator{d}} + } + pickDelegator[pusher+hijacker] = func(d *responseWriterDelegator) delegator { // 20 + return struct { + *responseWriterDelegator + http.Pusher + http.Hijacker + }{d, pusherDelegator{d}, hijackerDelegator{d}} + } + pickDelegator[pusher+hijacker+closeNotifier] = func(d *responseWriterDelegator) delegator { // 21 + return struct { + *responseWriterDelegator + http.Pusher + http.Hijacker + http.CloseNotifier + }{d, pusherDelegator{d}, hijackerDelegator{d}, closeNotifierDelegator{d}} + } + pickDelegator[pusher+hijacker+flusher] = func(d *responseWriterDelegator) delegator { // 22 + return struct { + *responseWriterDelegator + http.Pusher + http.Hijacker + http.Flusher + }{d, pusherDelegator{d}, hijackerDelegator{d}, flusherDelegator{d}} + } + pickDelegator[pusher+hijacker+flusher+closeNotifier] = func(d *responseWriterDelegator) delegator { //23 + return struct { + *responseWriterDelegator + http.Pusher + http.Hijacker + http.Flusher + http.CloseNotifier + }{d, pusherDelegator{d}, hijackerDelegator{d}, flusherDelegator{d}, closeNotifierDelegator{d}} + } + pickDelegator[pusher+readerFrom] = func(d *responseWriterDelegator) delegator { // 24 + return struct { + *responseWriterDelegator + http.Pusher + io.ReaderFrom + }{d, pusherDelegator{d}, readerFromDelegator{d}} + } + pickDelegator[pusher+readerFrom+closeNotifier] = func(d *responseWriterDelegator) delegator { // 25 + return struct { + *responseWriterDelegator + http.Pusher + io.ReaderFrom + http.CloseNotifier + }{d, pusherDelegator{d}, readerFromDelegator{d}, closeNotifierDelegator{d}} + } + pickDelegator[pusher+readerFrom+flusher] = func(d *responseWriterDelegator) delegator { // 26 + return struct { + *responseWriterDelegator + http.Pusher + io.ReaderFrom + http.Flusher + }{d, pusherDelegator{d}, readerFromDelegator{d}, flusherDelegator{d}} + } + pickDelegator[pusher+readerFrom+flusher+closeNotifier] = func(d *responseWriterDelegator) delegator { // 27 + return struct { + *responseWriterDelegator + http.Pusher + io.ReaderFrom + http.Flusher + http.CloseNotifier + }{d, pusherDelegator{d}, readerFromDelegator{d}, flusherDelegator{d}, closeNotifierDelegator{d}} + } + pickDelegator[pusher+readerFrom+hijacker] = func(d *responseWriterDelegator) delegator { // 28 + return struct { + *responseWriterDelegator + http.Pusher + io.ReaderFrom + http.Hijacker + }{d, pusherDelegator{d}, readerFromDelegator{d}, hijackerDelegator{d}} + } + pickDelegator[pusher+readerFrom+hijacker+closeNotifier] = func(d *responseWriterDelegator) delegator { // 29 + return struct { + *responseWriterDelegator + http.Pusher + io.ReaderFrom + http.Hijacker + http.CloseNotifier + }{d, pusherDelegator{d}, readerFromDelegator{d}, hijackerDelegator{d}, closeNotifierDelegator{d}} + } + pickDelegator[pusher+readerFrom+hijacker+flusher] = func(d *responseWriterDelegator) delegator { // 30 + return struct { + *responseWriterDelegator + http.Pusher + io.ReaderFrom + http.Hijacker + http.Flusher + }{d, pusherDelegator{d}, readerFromDelegator{d}, hijackerDelegator{d}, flusherDelegator{d}} + } + pickDelegator[pusher+readerFrom+hijacker+flusher+closeNotifier] = func(d *responseWriterDelegator) delegator { // 31 + return struct { + *responseWriterDelegator + http.Pusher + io.ReaderFrom + http.Hijacker + http.Flusher + http.CloseNotifier + }{d, pusherDelegator{d}, readerFromDelegator{d}, hijackerDelegator{d}, flusherDelegator{d}, closeNotifierDelegator{d}} + } +} + func newDelegator(w http.ResponseWriter, observeWriteHeaderFunc func(int)) delegator { d := &responseWriterDelegator{ ResponseWriter: w, observeWriteHeader: observeWriteHeaderFunc, } - _, cn := w.(http.CloseNotifier) - _, fl := w.(http.Flusher) - _, hj := w.(http.Hijacker) - _, ps := w.(http.Pusher) - _, rf := w.(io.ReaderFrom) - - // Check for the four most common combination of interfaces a - // http.ResponseWriter might implement. - switch { - case cn && fl && hj && rf && ps: - // All interfaces. - return &fancyPushDelegator{ - fancyDelegator: &fancyDelegator{d}, - p: &pushDelegator{d}, - } - case cn && fl && hj && rf: - // All interfaces, except http.Pusher. - return &fancyDelegator{d} - case ps: - // Just http.Pusher. - return &pushDelegator{d} + id := 0 + if _, ok := w.(http.CloseNotifier); ok { + id += closeNotifier + } + if _, ok := w.(http.Flusher); ok { + id += flusher + } + if _, ok := w.(http.Hijacker); ok { + id += hijacker + } + if _, ok := w.(io.ReaderFrom); ok { + id += readerFrom + } + if _, ok := w.(http.Pusher); ok { + id += pusher } - return d -} - -type fancyPushDelegator struct { - p *pushDelegator - - *fancyDelegator -} - -func (f *fancyPushDelegator) Push(target string, opts *http.PushOptions) error { - return f.p.Push(target, opts) -} - -type pushDelegator struct { - *responseWriterDelegator -} - -func (f *pushDelegator) Push(target string, opts *http.PushOptions) error { - return f.ResponseWriter.(http.Pusher).Push(target, opts) + return pickDelegator[id](d) } diff --git a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/delegator_1_7.go b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/delegator_pre_1_8.go similarity index 75% rename from vendor/github.com/prometheus/client_golang/prometheus/promhttp/delegator_1_7.go rename to vendor/github.com/prometheus/client_golang/prometheus/promhttp/delegator_pre_1_8.go index 24b31503e9c..8bb9b8b68f8 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/delegator_1_7.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/delegator_pre_1_8.go @@ -26,13 +26,19 @@ func newDelegator(w http.ResponseWriter, observeWriteHeaderFunc func(int)) deleg observeWriteHeader: observeWriteHeaderFunc, } - _, cn := w.(http.CloseNotifier) - _, fl := w.(http.Flusher) - _, hj := w.(http.Hijacker) - _, rf := w.(io.ReaderFrom) - if cn && fl && hj && rf { - return &fancyDelegator{d} + id := 0 + if _, ok := w.(http.CloseNotifier); ok { + id += closeNotifier + } + if _, ok := w.(http.Flusher); ok { + id += flusher + } + if _, ok := w.(http.Hijacker); ok { + id += hijacker + } + if _, ok := w.(io.ReaderFrom); ok { + id += readerFrom } - return d + return pickDelegator[id](d) } diff --git a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/http.go b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/http.go index 4c70a7af63f..668eb6b3c93 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/http.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/http.go @@ -32,13 +32,13 @@ package promhttp import ( - "bytes" "compress/gzip" "fmt" "io" "net/http" "strings" "sync" + "time" "github.com/prometheus/common/expfmt" @@ -52,36 +52,56 @@ const ( acceptEncodingHeader = "Accept-Encoding" ) -var bufPool sync.Pool - -func getBuf() *bytes.Buffer { - buf := bufPool.Get() - if buf == nil { - return &bytes.Buffer{} - } - return buf.(*bytes.Buffer) +var gzipPool = sync.Pool{ + New: func() interface{} { + return gzip.NewWriter(nil) + }, } -func giveBuf(buf *bytes.Buffer) { - buf.Reset() - bufPool.Put(buf) -} - -// Handler returns an HTTP handler for the prometheus.DefaultGatherer. The -// Handler uses the default HandlerOpts, i.e. report the first error as an HTTP -// error, no error logging, and compression if requested by the client. +// Handler returns an http.Handler for the prometheus.DefaultGatherer, using +// default HandlerOpts, i.e. it reports the first error as an HTTP error, it has +// no error logging, and it applies compression if requested by the client. // -// If you want to create a Handler for the DefaultGatherer with different -// HandlerOpts, create it with HandlerFor with prometheus.DefaultGatherer and -// your desired HandlerOpts. +// The returned http.Handler is already instrumented using the +// InstrumentMetricHandler function and the prometheus.DefaultRegisterer. If you +// create multiple http.Handlers by separate calls of the Handler function, the +// metrics used for instrumentation will be shared between them, providing +// global scrape counts. +// +// This function is meant to cover the bulk of basic use cases. If you are doing +// anything that requires more customization (including using a non-default +// Gatherer, different instrumentation, and non-default HandlerOpts), use the +// HandlerFor function. See there for details. func Handler() http.Handler { - return HandlerFor(prometheus.DefaultGatherer, HandlerOpts{}) + return InstrumentMetricHandler( + prometheus.DefaultRegisterer, HandlerFor(prometheus.DefaultGatherer, HandlerOpts{}), + ) } -// HandlerFor returns an http.Handler for the provided Gatherer. The behavior -// of the Handler is defined by the provided HandlerOpts. +// HandlerFor returns an uninstrumented http.Handler for the provided +// Gatherer. The behavior of the Handler is defined by the provided +// HandlerOpts. Thus, HandlerFor is useful to create http.Handlers for custom +// Gatherers, with non-default HandlerOpts, and/or with custom (or no) +// instrumentation. Use the InstrumentMetricHandler function to apply the same +// kind of instrumentation as it is used by the Handler function. func HandlerFor(reg prometheus.Gatherer, opts HandlerOpts) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { + var inFlightSem chan struct{} + if opts.MaxRequestsInFlight > 0 { + inFlightSem = make(chan struct{}, opts.MaxRequestsInFlight) + } + + h := http.HandlerFunc(func(rsp http.ResponseWriter, req *http.Request) { + if inFlightSem != nil { + select { + case inFlightSem <- struct{}{}: // All good, carry on. + defer func() { <-inFlightSem }() + default: + http.Error(rsp, fmt.Sprintf( + "Limit of concurrent requests reached (%d), try again later.", opts.MaxRequestsInFlight, + ), http.StatusServiceUnavailable) + return + } + } mfs, err := reg.Gather() if err != nil { if opts.ErrorLog != nil { @@ -92,26 +112,40 @@ func HandlerFor(reg prometheus.Gatherer, opts HandlerOpts) http.Handler { panic(err) case ContinueOnError: if len(mfs) == 0 { - http.Error(w, "No metrics gathered, last error:\n\n"+err.Error(), http.StatusInternalServerError) + // Still report the error if no metrics have been gathered. + httpError(rsp, err) return } case HTTPErrorOnError: - http.Error(w, "An error has occurred during metrics gathering:\n\n"+err.Error(), http.StatusInternalServerError) + httpError(rsp, err) return } } contentType := expfmt.Negotiate(req.Header) - buf := getBuf() - defer giveBuf(buf) - writer, encoding := decorateWriter(req, buf, opts.DisableCompression) - enc := expfmt.NewEncoder(writer, contentType) + header := rsp.Header() + header.Set(contentTypeHeader, string(contentType)) + + w := io.Writer(rsp) + if !opts.DisableCompression && gzipAccepted(req.Header) { + header.Set(contentEncodingHeader, "gzip") + gz := gzipPool.Get().(*gzip.Writer) + defer gzipPool.Put(gz) + + gz.Reset(w) + defer gz.Close() + + w = gz + } + + enc := expfmt.NewEncoder(w, contentType) + var lastErr error for _, mf := range mfs { if err := enc.Encode(mf); err != nil { lastErr = err if opts.ErrorLog != nil { - opts.ErrorLog.Println("error encoding metric family:", err) + opts.ErrorLog.Println("error encoding and sending metric family:", err) } switch opts.ErrorHandling { case PanicOnError: @@ -119,27 +153,75 @@ func HandlerFor(reg prometheus.Gatherer, opts HandlerOpts) http.Handler { case ContinueOnError: // Handled later. case HTTPErrorOnError: - http.Error(w, "An error has occurred during metrics encoding:\n\n"+err.Error(), http.StatusInternalServerError) + httpError(rsp, err) return } } } - if closer, ok := writer.(io.Closer); ok { - closer.Close() + + if lastErr != nil { + httpError(rsp, lastErr) } - if lastErr != nil && buf.Len() == 0 { - http.Error(w, "No metrics encoded, last error:\n\n"+err.Error(), http.StatusInternalServerError) - return - } - header := w.Header() - header.Set(contentTypeHeader, string(contentType)) - header.Set(contentLengthHeader, fmt.Sprint(buf.Len())) - if encoding != "" { - header.Set(contentEncodingHeader, encoding) - } - w.Write(buf.Bytes()) - // TODO(beorn7): Consider streaming serving of metrics. }) + + if opts.Timeout <= 0 { + return h + } + return http.TimeoutHandler(h, opts.Timeout, fmt.Sprintf( + "Exceeded configured timeout of %v.\n", + opts.Timeout, + )) +} + +// InstrumentMetricHandler is usually used with an http.Handler returned by the +// HandlerFor function. It instruments the provided http.Handler with two +// metrics: A counter vector "promhttp_metric_handler_requests_total" to count +// scrapes partitioned by HTTP status code, and a gauge +// "promhttp_metric_handler_requests_in_flight" to track the number of +// simultaneous scrapes. This function idempotently registers collectors for +// both metrics with the provided Registerer. It panics if the registration +// fails. The provided metrics are useful to see how many scrapes hit the +// monitored target (which could be from different Prometheus servers or other +// scrapers), and how often they overlap (which would result in more than one +// scrape in flight at the same time). Note that the scrapes-in-flight gauge +// will contain the scrape by which it is exposed, while the scrape counter will +// only get incremented after the scrape is complete (as only then the status +// code is known). For tracking scrape durations, use the +// "scrape_duration_seconds" gauge created by the Prometheus server upon each +// scrape. +func InstrumentMetricHandler(reg prometheus.Registerer, handler http.Handler) http.Handler { + cnt := prometheus.NewCounterVec( + prometheus.CounterOpts{ + Name: "promhttp_metric_handler_requests_total", + Help: "Total number of scrapes by HTTP status code.", + }, + []string{"code"}, + ) + // Initialize the most likely HTTP status codes. + cnt.WithLabelValues("200") + cnt.WithLabelValues("500") + cnt.WithLabelValues("503") + if err := reg.Register(cnt); err != nil { + if are, ok := err.(prometheus.AlreadyRegisteredError); ok { + cnt = are.ExistingCollector.(*prometheus.CounterVec) + } else { + panic(err) + } + } + + gge := prometheus.NewGauge(prometheus.GaugeOpts{ + Name: "promhttp_metric_handler_requests_in_flight", + Help: "Current number of scrapes being served.", + }) + if err := reg.Register(gge); err != nil { + if are, ok := err.(prometheus.AlreadyRegisteredError); ok { + gge = are.ExistingCollector.(prometheus.Gauge) + } else { + panic(err) + } + } + + return InstrumentHandlerCounter(cnt, InstrumentHandlerInFlight(gge, handler)) } // HandlerErrorHandling defines how a Handler serving metrics will handle @@ -183,22 +265,47 @@ type HandlerOpts struct { // If DisableCompression is true, the handler will never compress the // response, even if requested by the client. DisableCompression bool + // The number of concurrent HTTP requests is limited to + // MaxRequestsInFlight. Additional requests are responded to with 503 + // Service Unavailable and a suitable message in the body. If + // MaxRequestsInFlight is 0 or negative, no limit is applied. + MaxRequestsInFlight int + // If handling a request takes longer than Timeout, it is responded to + // with 503 ServiceUnavailable and a suitable Message. No timeout is + // applied if Timeout is 0 or negative. Note that with the current + // implementation, reaching the timeout simply ends the HTTP requests as + // described above (and even that only if sending of the body hasn't + // started yet), while the bulk work of gathering all the metrics keeps + // running in the background (with the eventual result to be thrown + // away). Until the implementation is improved, it is recommended to + // implement a separate timeout in potentially slow Collectors. + Timeout time.Duration } -// decorateWriter wraps a writer to handle gzip compression if requested. It -// returns the decorated writer and the appropriate "Content-Encoding" header -// (which is empty if no compression is enabled). -func decorateWriter(request *http.Request, writer io.Writer, compressionDisabled bool) (io.Writer, string) { - if compressionDisabled { - return writer, "" - } - header := request.Header.Get(acceptEncodingHeader) - parts := strings.Split(header, ",") +// gzipAccepted returns whether the client will accept gzip-encoded content. +func gzipAccepted(header http.Header) bool { + a := header.Get(acceptEncodingHeader) + parts := strings.Split(a, ",") for _, part := range parts { - part := strings.TrimSpace(part) + part = strings.TrimSpace(part) if part == "gzip" || strings.HasPrefix(part, "gzip;") { - return gzip.NewWriter(writer), "gzip" + return true } } - return writer, "" + return false +} + +// httpError removes any content-encoding header and then calls http.Error with +// the provided error and http.StatusInternalServerErrer. Error contents is +// supposed to be uncompressed plain text. However, same as with a plain +// http.Error, any header settings will be void if the header has already been +// sent. The error message will still be written to the writer, but it will +// probably be of limited use. +func httpError(rsp http.ResponseWriter, err error) { + rsp.Header().Del(contentEncodingHeader) + http.Error( + rsp, + "An error has occurred while serving metrics:\n\n"+err.Error(), + http.StatusInternalServerError, + ) } diff --git a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_client.go b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_client.go index 1cf21f2174b..86fd564470f 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_client.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_client.go @@ -45,12 +45,11 @@ func InstrumentRoundTripperInFlight(gauge prometheus.Gauge, next http.RoundTripp // InstrumentRoundTripperCounter is a middleware that wraps the provided // http.RoundTripper to observe the request result with the provided CounterVec. -// The CounterVec must have zero, one, or two labels. The only allowed label -// names are "code" and "method". The function panics if any other instance -// labels are provided. Partitioning of the CounterVec happens by HTTP status -// code and/or HTTP method if the respective instance label names are present -// in the CounterVec. For unpartitioned counting, use a CounterVec with -// zero labels. +// The CounterVec must have zero, one, or two non-const non-curried labels. For +// those, the only allowed label names are "code" and "method". The function +// panics otherwise. Partitioning of the CounterVec happens by HTTP status code +// and/or HTTP method if the respective instance label names are present in the +// CounterVec. For unpartitioned counting, use a CounterVec with zero labels. // // If the wrapped RoundTripper panics or returns a non-nil error, the Counter // is not incremented. @@ -69,18 +68,21 @@ func InstrumentRoundTripperCounter(counter *prometheus.CounterVec, next http.Rou } // InstrumentRoundTripperDuration is a middleware that wraps the provided -// http.RoundTripper to observe the request duration with the provided ObserverVec. -// The ObserverVec must have zero, one, or two labels. The only allowed label -// names are "code" and "method". The function panics if any other instance -// labels are provided. The Observe method of the Observer in the ObserverVec -// is called with the request duration in seconds. Partitioning happens by HTTP -// status code and/or HTTP method if the respective instance label names are -// present in the ObserverVec. For unpartitioned observations, use an -// ObserverVec with zero labels. Note that partitioning of Histograms is -// expensive and should be used judiciously. +// http.RoundTripper to observe the request duration with the provided +// ObserverVec. The ObserverVec must have zero, one, or two non-const +// non-curried labels. For those, the only allowed label names are "code" and +// "method". The function panics otherwise. The Observe method of the Observer +// in the ObserverVec is called with the request duration in +// seconds. Partitioning happens by HTTP status code and/or HTTP method if the +// respective instance label names are present in the ObserverVec. For +// unpartitioned observations, use an ObserverVec with zero labels. Note that +// partitioning of Histograms is expensive and should be used judiciously. // // If the wrapped RoundTripper panics or returns a non-nil error, no values are // reported. +// +// Note that this method is only guaranteed to never observe negative durations +// if used with Go1.9+. func InstrumentRoundTripperDuration(obs prometheus.ObserverVec, next http.RoundTripper) RoundTripperFunc { code, method := checkLabels(obs) diff --git a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_client_1_8.go b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_client_1_8.go index b51d9105200..a034d1ec0f1 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_client_1_8.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_client_1_8.go @@ -48,8 +48,10 @@ type InstrumentTrace struct { // RoundTripper and reports times to hook functions provided in the // InstrumentTrace struct. Hook functions that are not present in the provided // InstrumentTrace struct are ignored. Times reported to the hook functions are -// time since the start of the request. Note that partitioning of Histograms -// is expensive and should be used judiciously. +// time since the start of the request. Only with Go1.9+, those times are +// guaranteed to never be negative. (Earlier Go versions are not using a +// monotonic clock.) Note that partitioning of Histograms is expensive and +// should be used judiciously. // // For hook functions that receive an error as an argument, no observations are // made in the event of a non-nil error value. @@ -79,8 +81,8 @@ func InstrumentRoundTripperTrace(it *InstrumentTrace, next http.RoundTripper) Ro } }, DNSDone: func(_ httptrace.DNSDoneInfo) { - if it.DNSStart != nil { - it.DNSStart(time.Since(start).Seconds()) + if it.DNSDone != nil { + it.DNSDone(time.Since(start).Seconds()) } }, ConnectStart: func(_, _ string) { diff --git a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_server.go b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_server.go index ac419e555fe..9db24380533 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_server.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_server.go @@ -14,9 +14,7 @@ package promhttp import ( - "bufio" - "io" - "net" + "errors" "net/http" "strconv" "strings" @@ -45,10 +43,10 @@ func InstrumentHandlerInFlight(g prometheus.Gauge, next http.Handler) http.Handl // InstrumentHandlerDuration is a middleware that wraps the provided // http.Handler to observe the request duration with the provided ObserverVec. -// The ObserverVec must have zero, one, or two labels. The only allowed label -// names are "code" and "method". The function panics if any other instance -// labels are provided. The Observe method of the Observer in the ObserverVec -// is called with the request duration in seconds. Partitioning happens by HTTP +// The ObserverVec must have zero, one, or two non-const non-curried labels. For +// those, the only allowed label names are "code" and "method". The function +// panics otherwise. The Observe method of the Observer in the ObserverVec is +// called with the request duration in seconds. Partitioning happens by HTTP // status code and/or HTTP method if the respective instance label names are // present in the ObserverVec. For unpartitioned observations, use an // ObserverVec with zero labels. Note that partitioning of Histograms is @@ -57,6 +55,9 @@ func InstrumentHandlerInFlight(g prometheus.Gauge, next http.Handler) http.Handl // If the wrapped Handler does not set a status code, a status code of 200 is assumed. // // If the wrapped Handler panics, no values are reported. +// +// Note that this method is only guaranteed to never observe negative durations +// if used with Go1.9+. func InstrumentHandlerDuration(obs prometheus.ObserverVec, next http.Handler) http.HandlerFunc { code, method := checkLabels(obs) @@ -77,14 +78,13 @@ func InstrumentHandlerDuration(obs prometheus.ObserverVec, next http.Handler) ht }) } -// InstrumentHandlerCounter is a middleware that wraps the provided -// http.Handler to observe the request result with the provided CounterVec. -// The CounterVec must have zero, one, or two labels. The only allowed label -// names are "code" and "method". The function panics if any other instance -// labels are provided. Partitioning of the CounterVec happens by HTTP status -// code and/or HTTP method if the respective instance label names are present -// in the CounterVec. For unpartitioned counting, use a CounterVec with -// zero labels. +// InstrumentHandlerCounter is a middleware that wraps the provided http.Handler +// to observe the request result with the provided CounterVec. The CounterVec +// must have zero, one, or two non-const non-curried labels. For those, the only +// allowed label names are "code" and "method". The function panics +// otherwise. Partitioning of the CounterVec happens by HTTP status code and/or +// HTTP method if the respective instance label names are present in the +// CounterVec. For unpartitioned counting, use a CounterVec with zero labels. // // If the wrapped Handler does not set a status code, a status code of 200 is assumed. // @@ -111,18 +111,20 @@ func InstrumentHandlerCounter(counter *prometheus.CounterVec, next http.Handler) // InstrumentHandlerTimeToWriteHeader is a middleware that wraps the provided // http.Handler to observe with the provided ObserverVec the request duration // until the response headers are written. The ObserverVec must have zero, one, -// or two labels. The only allowed label names are "code" and "method". The -// function panics if any other instance labels are provided. The Observe -// method of the Observer in the ObserverVec is called with the request -// duration in seconds. Partitioning happens by HTTP status code and/or HTTP -// method if the respective instance label names are present in the -// ObserverVec. For unpartitioned observations, use an ObserverVec with zero -// labels. Note that partitioning of Histograms is expensive and should be used -// judiciously. +// or two non-const non-curried labels. For those, the only allowed label names +// are "code" and "method". The function panics otherwise. The Observe method of +// the Observer in the ObserverVec is called with the request duration in +// seconds. Partitioning happens by HTTP status code and/or HTTP method if the +// respective instance label names are present in the ObserverVec. For +// unpartitioned observations, use an ObserverVec with zero labels. Note that +// partitioning of Histograms is expensive and should be used judiciously. // // If the wrapped Handler panics before calling WriteHeader, no value is // reported. // +// Note that this method is only guaranteed to never observe negative durations +// if used with Go1.9+. +// // See the example for InstrumentHandlerDuration for example usage. func InstrumentHandlerTimeToWriteHeader(obs prometheus.ObserverVec, next http.Handler) http.HandlerFunc { code, method := checkLabels(obs) @@ -137,15 +139,15 @@ func InstrumentHandlerTimeToWriteHeader(obs prometheus.ObserverVec, next http.Ha } // InstrumentHandlerRequestSize is a middleware that wraps the provided -// http.Handler to observe the request size with the provided ObserverVec. -// The ObserverVec must have zero, one, or two labels. The only allowed label -// names are "code" and "method". The function panics if any other instance -// labels are provided. The Observe method of the Observer in the ObserverVec -// is called with the request size in bytes. Partitioning happens by HTTP -// status code and/or HTTP method if the respective instance label names are -// present in the ObserverVec. For unpartitioned observations, use an -// ObserverVec with zero labels. Note that partitioning of Histograms is -// expensive and should be used judiciously. +// http.Handler to observe the request size with the provided ObserverVec. The +// ObserverVec must have zero, one, or two non-const non-curried labels. For +// those, the only allowed label names are "code" and "method". The function +// panics otherwise. The Observe method of the Observer in the ObserverVec is +// called with the request size in bytes. Partitioning happens by HTTP status +// code and/or HTTP method if the respective instance label names are present in +// the ObserverVec. For unpartitioned observations, use an ObserverVec with zero +// labels. Note that partitioning of Histograms is expensive and should be used +// judiciously. // // If the wrapped Handler does not set a status code, a status code of 200 is assumed. // @@ -172,15 +174,15 @@ func InstrumentHandlerRequestSize(obs prometheus.ObserverVec, next http.Handler) } // InstrumentHandlerResponseSize is a middleware that wraps the provided -// http.Handler to observe the response size with the provided ObserverVec. -// The ObserverVec must have zero, one, or two labels. The only allowed label -// names are "code" and "method". The function panics if any other instance -// labels are provided. The Observe method of the Observer in the ObserverVec -// is called with the response size in bytes. Partitioning happens by HTTP -// status code and/or HTTP method if the respective instance label names are -// present in the ObserverVec. For unpartitioned observations, use an -// ObserverVec with zero labels. Note that partitioning of Histograms is -// expensive and should be used judiciously. +// http.Handler to observe the response size with the provided ObserverVec. The +// ObserverVec must have zero, one, or two non-const non-curried labels. For +// those, the only allowed label names are "code" and "method". The function +// panics otherwise. The Observe method of the Observer in the ObserverVec is +// called with the response size in bytes. Partitioning happens by HTTP status +// code and/or HTTP method if the respective instance label names are present in +// the ObserverVec. For unpartitioned observations, use an ObserverVec with zero +// labels. Note that partitioning of Histograms is expensive and should be used +// judiciously. // // If the wrapped Handler does not set a status code, a status code of 200 is assumed. // @@ -201,9 +203,12 @@ func checkLabels(c prometheus.Collector) (code bool, method bool) { // once Descriptors can have their dimensionality queried. var ( desc *prometheus.Desc + m prometheus.Metric pm dto.Metric + lvs []string ) + // Get the Desc from the Collector. descc := make(chan *prometheus.Desc, 1) c.Describe(descc) @@ -220,49 +225,54 @@ func checkLabels(c prometheus.Collector) (code bool, method bool) { close(descc) - if _, err := prometheus.NewConstMetric(desc, prometheus.UntypedValue, 0); err == nil { - return + // Create a ConstMetric with the Desc. Since we don't know how many + // variable labels there are, try for as long as it needs. + for err := errors.New("dummy"); err != nil; lvs = append(lvs, magicString) { + m, err = prometheus.NewConstMetric(desc, prometheus.UntypedValue, 0, lvs...) } - if m, err := prometheus.NewConstMetric(desc, prometheus.UntypedValue, 0, magicString); err == nil { - if err := m.Write(&pm); err != nil { - panic("error checking metric for labels") - } - for _, label := range pm.Label { - name, value := label.GetName(), label.GetValue() - if value != magicString { - continue - } - switch name { - case "code": - code = true - case "method": - method = true - default: - panic("metric partitioned with non-supported labels") - } - return - } - panic("previously set label not found – this must never happen") + + // Write out the metric into a proto message and look at the labels. + // If the value is not the magicString, it is a constLabel, which doesn't interest us. + // If the label is curried, it doesn't interest us. + // In all other cases, only "code" or "method" is allowed. + if err := m.Write(&pm); err != nil { + panic("error checking metric for labels") } - if m, err := prometheus.NewConstMetric(desc, prometheus.UntypedValue, 0, magicString, magicString); err == nil { - if err := m.Write(&pm); err != nil { - panic("error checking metric for labels") + for _, label := range pm.Label { + name, value := label.GetName(), label.GetValue() + if value != magicString || isLabelCurried(c, name) { + continue } - for _, label := range pm.Label { - name, value := label.GetName(), label.GetValue() - if value != magicString { - continue - } - if name == "code" || name == "method" { - continue - } + switch name { + case "code": + code = true + case "method": + method = true + default: panic("metric partitioned with non-supported labels") } - code = true - method = true - return } - panic("metric partitioned with non-supported labels") + return +} + +func isLabelCurried(c prometheus.Collector, label string) bool { + // This is even hackier than the label test above. + // We essentially try to curry again and see if it works. + // But for that, we need to type-convert to the two + // types we use here, ObserverVec or *CounterVec. + switch v := c.(type) { + case *prometheus.CounterVec: + if _, err := v.CurryWith(prometheus.Labels{label: "dummy"}); err == nil { + return false + } + case prometheus.ObserverVec: + if _, err := v.CurryWith(prometheus.Labels{label: "dummy"}); err == nil { + return false + } + default: + panic("unsupported metric vec type") + } + return true } // emptyLabels is a one-time allocation for non-partitioned metrics to avoid @@ -435,71 +445,3 @@ func sanitizeCode(s int) string { return strconv.Itoa(s) } } - -type delegator interface { - Status() int - Written() int64 - - http.ResponseWriter -} - -type responseWriterDelegator struct { - http.ResponseWriter - - handler, method string - status int - written int64 - wroteHeader bool - observeWriteHeader func(int) -} - -func (r *responseWriterDelegator) Status() int { - return r.status -} - -func (r *responseWriterDelegator) Written() int64 { - return r.written -} - -func (r *responseWriterDelegator) WriteHeader(code int) { - r.status = code - r.wroteHeader = true - r.ResponseWriter.WriteHeader(code) - if r.observeWriteHeader != nil { - r.observeWriteHeader(code) - } -} - -func (r *responseWriterDelegator) Write(b []byte) (int, error) { - if !r.wroteHeader { - r.WriteHeader(http.StatusOK) - } - n, err := r.ResponseWriter.Write(b) - r.written += int64(n) - return n, err -} - -type fancyDelegator struct { - *responseWriterDelegator -} - -func (r *fancyDelegator) CloseNotify() <-chan bool { - return r.ResponseWriter.(http.CloseNotifier).CloseNotify() -} - -func (r *fancyDelegator) Hijack() (net.Conn, *bufio.ReadWriter, error) { - return r.ResponseWriter.(http.Hijacker).Hijack() -} - -func (r *fancyDelegator) Flush() { - r.ResponseWriter.(http.Flusher).Flush() -} - -func (r *fancyDelegator) ReadFrom(re io.Reader) (int64, error) { - if !r.wroteHeader { - r.WriteHeader(http.StatusOK) - } - n, err := r.ResponseWriter.(io.ReaderFrom).ReadFrom(re) - r.written += n - return n, err -} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/registry.go b/vendor/github.com/prometheus/client_golang/prometheus/registry.go index 8c6b5bd8ee1..f98c81a8691 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/registry.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/registry.go @@ -15,15 +15,22 @@ package prometheus import ( "bytes" - "errors" "fmt" + "io/ioutil" "os" + "path/filepath" + "runtime" "sort" + "strings" "sync" + "unicode/utf8" "github.com/golang/protobuf/proto" + "github.com/prometheus/common/expfmt" dto "github.com/prometheus/client_model/go" + + "github.com/prometheus/client_golang/prometheus/internal" ) const ( @@ -35,13 +42,14 @@ const ( // DefaultRegisterer and DefaultGatherer are the implementations of the // Registerer and Gatherer interface a number of convenience functions in this // package act on. Initially, both variables point to the same Registry, which -// has a process collector (see NewProcessCollector) and a Go collector (see -// NewGoCollector) already registered. This approach to keep default instances -// as global state mirrors the approach of other packages in the Go standard -// library. Note that there are caveats. Change the variables with caution and -// only if you understand the consequences. Users who want to avoid global state -// altogether should not use the convenience function and act on custom -// instances instead. +// has a process collector (currently on Linux only, see NewProcessCollector) +// and a Go collector (see NewGoCollector, in particular the note about +// stop-the-world implication with Go versions older than 1.9) already +// registered. This approach to keep default instances as global state mirrors +// the approach of other packages in the Go standard library. Note that there +// are caveats. Change the variables with caution and only if you understand the +// consequences. Users who want to avoid global state altogether should not use +// the convenience functions and act on custom instances instead. var ( defaultRegistry = NewRegistry() DefaultRegisterer Registerer = defaultRegistry @@ -49,7 +57,7 @@ var ( ) func init() { - MustRegister(NewProcessCollector(os.Getpid(), "")) + MustRegister(NewProcessCollector(ProcessCollectorOpts{})) MustRegister(NewGoCollector()) } @@ -65,7 +73,8 @@ func NewRegistry() *Registry { // NewPedanticRegistry returns a registry that checks during collection if each // collected Metric is consistent with its reported Desc, and if the Desc has -// actually been registered with the registry. +// actually been registered with the registry. Unchecked Collectors (those whose +// Describe methed does not yield any descriptors) are excluded from the check. // // Usually, a Registry will be happy as long as the union of all collected // Metrics is consistent and valid even if some metrics are not consistent with @@ -80,7 +89,7 @@ func NewPedanticRegistry() *Registry { // Registerer is the interface for the part of a registry in charge of // registering and unregistering. Users of custom registries should use -// Registerer as type for registration purposes (rather then the Registry type +// Registerer as type for registration purposes (rather than the Registry type // directly). In that way, they are free to use custom Registerer implementation // (e.g. for testing purposes). type Registerer interface { @@ -95,8 +104,13 @@ type Registerer interface { // returned error is an instance of AlreadyRegisteredError, which // contains the previously registered Collector. // - // It is in general not safe to register the same Collector multiple - // times concurrently. + // A Collector whose Describe method does not yield any Desc is treated + // as unchecked. Registration will always succeed. No check for + // re-registering (see previous paragraph) is performed. Thus, the + // caller is responsible for not double-registering the same unchecked + // Collector, and for providing a Collector that will not cause + // inconsistent metrics on collection. (This would lead to scrape + // errors.) Register(Collector) error // MustRegister works like Register but registers any number of // Collectors and panics upon the first registration that causes an @@ -105,7 +119,9 @@ type Registerer interface { // Unregister unregisters the Collector that equals the Collector passed // in as an argument. (Two Collectors are considered equal if their // Describe method yields the same set of descriptors.) The function - // returns whether a Collector was unregistered. + // returns whether a Collector was unregistered. Note that an unchecked + // Collector cannot be unregistered (as its Describe method does not + // yield any descriptor). // // Note that even after unregistering, it will not be possible to // register a new Collector that is inconsistent with the unregistered @@ -123,15 +139,23 @@ type Registerer interface { type Gatherer interface { // Gather calls the Collect method of the registered Collectors and then // gathers the collected metrics into a lexicographically sorted slice - // of MetricFamily protobufs. Even if an error occurs, Gather attempts - // to gather as many metrics as possible. Hence, if a non-nil error is - // returned, the returned MetricFamily slice could be nil (in case of a - // fatal error that prevented any meaningful metric collection) or - // contain a number of MetricFamily protobufs, some of which might be - // incomplete, and some might be missing altogether. The returned error - // (which might be a MultiError) explains the details. In scenarios - // where complete collection is critical, the returned MetricFamily - // protobufs should be disregarded if the returned error is non-nil. + // of uniquely named MetricFamily protobufs. Gather ensures that the + // returned slice is valid and self-consistent so that it can be used + // for valid exposition. As an exception to the strict consistency + // requirements described for metric.Desc, Gather will tolerate + // different sets of label names for metrics of the same metric family. + // + // Even if an error occurs, Gather attempts to gather as many metrics as + // possible. Hence, if a non-nil error is returned, the returned + // MetricFamily slice could be nil (in case of a fatal error that + // prevented any meaningful metric collection) or contain a number of + // MetricFamily protobufs, some of which might be incomplete, and some + // might be missing altogether. The returned error (which might be a + // MultiError) explains the details. Note that this is mostly useful for + // debugging purposes. If the gathered protobufs are to be used for + // exposition in actual monitoring, it is almost always better to not + // expose an incomplete result and instead disregard the returned + // MetricFamily protobufs in case the returned error is non-nil. Gather() ([]*dto.MetricFamily, error) } @@ -201,6 +225,13 @@ func (errs MultiError) Error() string { return buf.String() } +// Append appends the provided error if it is not nil. +func (errs *MultiError) Append(err error) { + if err != nil { + *errs = append(*errs, err) + } +} + // MaybeUnwrap returns nil if len(errs) is 0. It returns the first and only // contained error as error if len(errs is 1). In all other cases, it returns // the MultiError directly. This is helpful for returning a MultiError in a way @@ -225,6 +256,7 @@ type Registry struct { collectorsByID map[uint64]Collector // ID is a hash of the descIDs. descIDs map[uint64]struct{} dimHashesByName map[string]uint64 + uncheckedCollectors []Collector pedanticChecksEnabled bool } @@ -242,7 +274,12 @@ func (r *Registry) Register(c Collector) error { close(descChan) }() r.mtx.Lock() - defer r.mtx.Unlock() + defer func() { + // Drain channel in case of premature return to not leak a goroutine. + for range descChan { + } + r.mtx.Unlock() + }() // Conduct various tests... for desc := range descChan { @@ -282,9 +319,10 @@ func (r *Registry) Register(c Collector) error { } } } - // Did anything happen at all? + // A Collector yielding no Desc at all is considered unchecked. if len(newDescIDs) == 0 { - return errors.New("collector has no descriptors") + r.uncheckedCollectors = append(r.uncheckedCollectors, c) + return nil } if existing, exists := r.collectorsByID[collectorID]; exists { return AlreadyRegisteredError{ @@ -358,31 +396,25 @@ func (r *Registry) MustRegister(cs ...Collector) { // Gather implements Gatherer. func (r *Registry) Gather() ([]*dto.MetricFamily, error) { var ( - metricChan = make(chan Metric, capMetricChan) - metricHashes = map[uint64]struct{}{} - dimHashes = map[string]uint64{} - wg sync.WaitGroup - errs MultiError // The collected errors to return in the end. - registeredDescIDs map[uint64]struct{} // Only used for pedantic checks + checkedMetricChan = make(chan Metric, capMetricChan) + uncheckedMetricChan = make(chan Metric, capMetricChan) + metricHashes = map[uint64]struct{}{} + wg sync.WaitGroup + errs MultiError // The collected errors to return in the end. + registeredDescIDs map[uint64]struct{} // Only used for pedantic checks ) r.mtx.RLock() + goroutineBudget := len(r.collectorsByID) + len(r.uncheckedCollectors) metricFamiliesByName := make(map[string]*dto.MetricFamily, len(r.dimHashesByName)) - - // Scatter. - // (Collectors could be complex and slow, so we call them all at once.) - wg.Add(len(r.collectorsByID)) - go func() { - wg.Wait() - close(metricChan) - }() + checkedCollectors := make(chan Collector, len(r.collectorsByID)) + uncheckedCollectors := make(chan Collector, len(r.uncheckedCollectors)) for _, collector := range r.collectorsByID { - go func(collector Collector) { - defer wg.Done() - collector.Collect(metricChan) - }(collector) + checkedCollectors <- collector + } + for _, collector := range r.uncheckedCollectors { + uncheckedCollectors <- collector } - // In case pedantic checks are enabled, we have to copy the map before // giving up the RLock. if r.pedanticChecksEnabled { @@ -391,127 +423,258 @@ func (r *Registry) Gather() ([]*dto.MetricFamily, error) { registeredDescIDs[id] = struct{}{} } } - r.mtx.RUnlock() - // Drain metricChan in case of premature return. + wg.Add(goroutineBudget) + + collectWorker := func() { + for { + select { + case collector := <-checkedCollectors: + collector.Collect(checkedMetricChan) + case collector := <-uncheckedCollectors: + collector.Collect(uncheckedMetricChan) + default: + return + } + wg.Done() + } + } + + // Start the first worker now to make sure at least one is running. + go collectWorker() + goroutineBudget-- + + // Close checkedMetricChan and uncheckedMetricChan once all collectors + // are collected. + go func() { + wg.Wait() + close(checkedMetricChan) + close(uncheckedMetricChan) + }() + + // Drain checkedMetricChan and uncheckedMetricChan in case of premature return. defer func() { - for range metricChan { + if checkedMetricChan != nil { + for range checkedMetricChan { + } + } + if uncheckedMetricChan != nil { + for range uncheckedMetricChan { + } } }() - // Gather. - for metric := range metricChan { - // This could be done concurrently, too, but it required locking - // of metricFamiliesByName (and of metricHashes if checks are - // enabled). Most likely not worth it. - desc := metric.Desc() - dtoMetric := &dto.Metric{} - if err := metric.Write(dtoMetric); err != nil { - errs = append(errs, fmt.Errorf( - "error collecting metric %v: %s", desc, err, + // Copy the channel references so we can nil them out later to remove + // them from the select statements below. + cmc := checkedMetricChan + umc := uncheckedMetricChan + + for { + select { + case metric, ok := <-cmc: + if !ok { + cmc = nil + break + } + errs.Append(processMetric( + metric, metricFamiliesByName, + metricHashes, + registeredDescIDs, )) - continue + case metric, ok := <-umc: + if !ok { + umc = nil + break + } + errs.Append(processMetric( + metric, metricFamiliesByName, + metricHashes, + nil, + )) + default: + if goroutineBudget <= 0 || len(checkedCollectors)+len(uncheckedCollectors) == 0 { + // All collectors are already being worked on or + // we have already as many goroutines started as + // there are collectors. Do the same as above, + // just without the default. + select { + case metric, ok := <-cmc: + if !ok { + cmc = nil + break + } + errs.Append(processMetric( + metric, metricFamiliesByName, + metricHashes, + registeredDescIDs, + )) + case metric, ok := <-umc: + if !ok { + umc = nil + break + } + errs.Append(processMetric( + metric, metricFamiliesByName, + metricHashes, + nil, + )) + } + break + } + // Start more workers. + go collectWorker() + goroutineBudget-- + runtime.Gosched() } - metricFamily, ok := metricFamiliesByName[desc.fqName] - if ok { - if metricFamily.GetHelp() != desc.help { - errs = append(errs, fmt.Errorf( - "collected metric %s %s has help %q but should have %q", - desc.fqName, dtoMetric, desc.help, metricFamily.GetHelp(), - )) - continue - } - // TODO(beorn7): Simplify switch once Desc has type. - switch metricFamily.GetType() { - case dto.MetricType_COUNTER: - if dtoMetric.Counter == nil { - errs = append(errs, fmt.Errorf( - "collected metric %s %s should be a Counter", - desc.fqName, dtoMetric, - )) - continue - } - case dto.MetricType_GAUGE: - if dtoMetric.Gauge == nil { - errs = append(errs, fmt.Errorf( - "collected metric %s %s should be a Gauge", - desc.fqName, dtoMetric, - )) - continue - } - case dto.MetricType_SUMMARY: - if dtoMetric.Summary == nil { - errs = append(errs, fmt.Errorf( - "collected metric %s %s should be a Summary", - desc.fqName, dtoMetric, - )) - continue - } - case dto.MetricType_UNTYPED: - if dtoMetric.Untyped == nil { - errs = append(errs, fmt.Errorf( - "collected metric %s %s should be Untyped", - desc.fqName, dtoMetric, - )) - continue - } - case dto.MetricType_HISTOGRAM: - if dtoMetric.Histogram == nil { - errs = append(errs, fmt.Errorf( - "collected metric %s %s should be a Histogram", - desc.fqName, dtoMetric, - )) - continue - } - default: - panic("encountered MetricFamily with invalid type") - } - } else { - metricFamily = &dto.MetricFamily{} - metricFamily.Name = proto.String(desc.fqName) - metricFamily.Help = proto.String(desc.help) - // TODO(beorn7): Simplify switch once Desc has type. - switch { - case dtoMetric.Gauge != nil: - metricFamily.Type = dto.MetricType_GAUGE.Enum() - case dtoMetric.Counter != nil: - metricFamily.Type = dto.MetricType_COUNTER.Enum() - case dtoMetric.Summary != nil: - metricFamily.Type = dto.MetricType_SUMMARY.Enum() - case dtoMetric.Untyped != nil: - metricFamily.Type = dto.MetricType_UNTYPED.Enum() - case dtoMetric.Histogram != nil: - metricFamily.Type = dto.MetricType_HISTOGRAM.Enum() - default: - errs = append(errs, fmt.Errorf( - "empty metric collected: %s", dtoMetric, - )) - continue - } - metricFamiliesByName[desc.fqName] = metricFamily + // Once both checkedMetricChan and uncheckdMetricChan are closed + // and drained, the contraption above will nil out cmc and umc, + // and then we can leave the collect loop here. + if cmc == nil && umc == nil { + break } - if err := checkMetricConsistency(metricFamily, dtoMetric, metricHashes, dimHashes); err != nil { - errs = append(errs, err) - continue - } - if r.pedanticChecksEnabled { - // Is the desc registered at all? - if _, exist := registeredDescIDs[desc.id]; !exist { - errs = append(errs, fmt.Errorf( - "collected metric %s %s with unregistered descriptor %s", - metricFamily.GetName(), dtoMetric, desc, - )) - continue - } - if err := checkDescConsistency(metricFamily, dtoMetric, desc); err != nil { - errs = append(errs, err) - continue - } - } - metricFamily.Metric = append(metricFamily.Metric, dtoMetric) } - return normalizeMetricFamilies(metricFamiliesByName), errs.MaybeUnwrap() + return internal.NormalizeMetricFamilies(metricFamiliesByName), errs.MaybeUnwrap() +} + +// WriteToTextfile calls Gather on the provided Gatherer, encodes the result in the +// Prometheus text format, and writes it to a temporary file. Upon success, the +// temporary file is renamed to the provided filename. +// +// This is intended for use with the textfile collector of the node exporter. +// Note that the node exporter expects the filename to be suffixed with ".prom". +func WriteToTextfile(filename string, g Gatherer) error { + tmp, err := ioutil.TempFile(filepath.Dir(filename), filepath.Base(filename)) + if err != nil { + return err + } + defer os.Remove(tmp.Name()) + + mfs, err := g.Gather() + if err != nil { + return err + } + for _, mf := range mfs { + if _, err := expfmt.MetricFamilyToText(tmp, mf); err != nil { + return err + } + } + if err := tmp.Close(); err != nil { + return err + } + + if err := os.Chmod(tmp.Name(), 0644); err != nil { + return err + } + return os.Rename(tmp.Name(), filename) +} + +// processMetric is an internal helper method only used by the Gather method. +func processMetric( + metric Metric, + metricFamiliesByName map[string]*dto.MetricFamily, + metricHashes map[uint64]struct{}, + registeredDescIDs map[uint64]struct{}, +) error { + desc := metric.Desc() + // Wrapped metrics collected by an unchecked Collector can have an + // invalid Desc. + if desc.err != nil { + return desc.err + } + dtoMetric := &dto.Metric{} + if err := metric.Write(dtoMetric); err != nil { + return fmt.Errorf("error collecting metric %v: %s", desc, err) + } + metricFamily, ok := metricFamiliesByName[desc.fqName] + if ok { // Existing name. + if metricFamily.GetHelp() != desc.help { + return fmt.Errorf( + "collected metric %s %s has help %q but should have %q", + desc.fqName, dtoMetric, desc.help, metricFamily.GetHelp(), + ) + } + // TODO(beorn7): Simplify switch once Desc has type. + switch metricFamily.GetType() { + case dto.MetricType_COUNTER: + if dtoMetric.Counter == nil { + return fmt.Errorf( + "collected metric %s %s should be a Counter", + desc.fqName, dtoMetric, + ) + } + case dto.MetricType_GAUGE: + if dtoMetric.Gauge == nil { + return fmt.Errorf( + "collected metric %s %s should be a Gauge", + desc.fqName, dtoMetric, + ) + } + case dto.MetricType_SUMMARY: + if dtoMetric.Summary == nil { + return fmt.Errorf( + "collected metric %s %s should be a Summary", + desc.fqName, dtoMetric, + ) + } + case dto.MetricType_UNTYPED: + if dtoMetric.Untyped == nil { + return fmt.Errorf( + "collected metric %s %s should be Untyped", + desc.fqName, dtoMetric, + ) + } + case dto.MetricType_HISTOGRAM: + if dtoMetric.Histogram == nil { + return fmt.Errorf( + "collected metric %s %s should be a Histogram", + desc.fqName, dtoMetric, + ) + } + default: + panic("encountered MetricFamily with invalid type") + } + } else { // New name. + metricFamily = &dto.MetricFamily{} + metricFamily.Name = proto.String(desc.fqName) + metricFamily.Help = proto.String(desc.help) + // TODO(beorn7): Simplify switch once Desc has type. + switch { + case dtoMetric.Gauge != nil: + metricFamily.Type = dto.MetricType_GAUGE.Enum() + case dtoMetric.Counter != nil: + metricFamily.Type = dto.MetricType_COUNTER.Enum() + case dtoMetric.Summary != nil: + metricFamily.Type = dto.MetricType_SUMMARY.Enum() + case dtoMetric.Untyped != nil: + metricFamily.Type = dto.MetricType_UNTYPED.Enum() + case dtoMetric.Histogram != nil: + metricFamily.Type = dto.MetricType_HISTOGRAM.Enum() + default: + return fmt.Errorf("empty metric collected: %s", dtoMetric) + } + if err := checkSuffixCollisions(metricFamily, metricFamiliesByName); err != nil { + return err + } + metricFamiliesByName[desc.fqName] = metricFamily + } + if err := checkMetricConsistency(metricFamily, dtoMetric, metricHashes); err != nil { + return err + } + if registeredDescIDs != nil { + // Is the desc registered at all? + if _, exist := registeredDescIDs[desc.id]; !exist { + return fmt.Errorf( + "collected metric %s %s with unregistered descriptor %s", + metricFamily.GetName(), dtoMetric, desc, + ) + } + if err := checkDescConsistency(metricFamily, dtoMetric, desc); err != nil { + return err + } + } + metricFamily.Metric = append(metricFamily.Metric, dtoMetric) + return nil } // Gatherers is a slice of Gatherer instances that implements the Gatherer @@ -537,7 +700,6 @@ func (gs Gatherers) Gather() ([]*dto.MetricFamily, error) { var ( metricFamiliesByName = map[string]*dto.MetricFamily{} metricHashes = map[uint64]struct{}{} - dimHashes = map[string]uint64{} errs MultiError // The collected errors to return in the end. ) @@ -574,10 +736,14 @@ func (gs Gatherers) Gather() ([]*dto.MetricFamily, error) { existingMF.Name = mf.Name existingMF.Help = mf.Help existingMF.Type = mf.Type + if err := checkSuffixCollisions(existingMF, metricFamiliesByName); err != nil { + errs = append(errs, err) + continue + } metricFamiliesByName[mf.GetName()] = existingMF } for _, m := range mf.Metric { - if err := checkMetricConsistency(existingMF, m, metricHashes, dimHashes); err != nil { + if err := checkMetricConsistency(existingMF, m, metricHashes); err != nil { errs = append(errs, err) continue } @@ -585,88 +751,80 @@ func (gs Gatherers) Gather() ([]*dto.MetricFamily, error) { } } } - return normalizeMetricFamilies(metricFamiliesByName), errs.MaybeUnwrap() + return internal.NormalizeMetricFamilies(metricFamiliesByName), errs.MaybeUnwrap() } -// metricSorter is a sortable slice of *dto.Metric. -type metricSorter []*dto.Metric - -func (s metricSorter) Len() int { - return len(s) -} - -func (s metricSorter) Swap(i, j int) { - s[i], s[j] = s[j], s[i] -} - -func (s metricSorter) Less(i, j int) bool { - if len(s[i].Label) != len(s[j].Label) { - // This should not happen. The metrics are - // inconsistent. However, we have to deal with the fact, as - // people might use custom collectors or metric family injection - // to create inconsistent metrics. So let's simply compare the - // number of labels in this case. That will still yield - // reproducible sorting. - return len(s[i].Label) < len(s[j].Label) +// checkSuffixCollisions checks for collisions with the “magic” suffixes the +// Prometheus text format and the internal metric representation of the +// Prometheus server add while flattening Summaries and Histograms. +func checkSuffixCollisions(mf *dto.MetricFamily, mfs map[string]*dto.MetricFamily) error { + var ( + newName = mf.GetName() + newType = mf.GetType() + newNameWithoutSuffix = "" + ) + switch { + case strings.HasSuffix(newName, "_count"): + newNameWithoutSuffix = newName[:len(newName)-6] + case strings.HasSuffix(newName, "_sum"): + newNameWithoutSuffix = newName[:len(newName)-4] + case strings.HasSuffix(newName, "_bucket"): + newNameWithoutSuffix = newName[:len(newName)-7] } - for n, lp := range s[i].Label { - vi := lp.GetValue() - vj := s[j].Label[n].GetValue() - if vi != vj { - return vi < vj + if newNameWithoutSuffix != "" { + if existingMF, ok := mfs[newNameWithoutSuffix]; ok { + switch existingMF.GetType() { + case dto.MetricType_SUMMARY: + if !strings.HasSuffix(newName, "_bucket") { + return fmt.Errorf( + "collected metric named %q collides with previously collected summary named %q", + newName, newNameWithoutSuffix, + ) + } + case dto.MetricType_HISTOGRAM: + return fmt.Errorf( + "collected metric named %q collides with previously collected histogram named %q", + newName, newNameWithoutSuffix, + ) + } } } - - // We should never arrive here. Multiple metrics with the same - // label set in the same scrape will lead to undefined ingestion - // behavior. However, as above, we have to provide stable sorting - // here, even for inconsistent metrics. So sort equal metrics - // by their timestamp, with missing timestamps (implying "now") - // coming last. - if s[i].TimestampMs == nil { - return false - } - if s[j].TimestampMs == nil { - return true - } - return s[i].GetTimestampMs() < s[j].GetTimestampMs() -} - -// normalizeMetricFamilies returns a MetricFamily slice with empty -// MetricFamilies pruned and the remaining MetricFamilies sorted by name within -// the slice, with the contained Metrics sorted within each MetricFamily. -func normalizeMetricFamilies(metricFamiliesByName map[string]*dto.MetricFamily) []*dto.MetricFamily { - for _, mf := range metricFamiliesByName { - sort.Sort(metricSorter(mf.Metric)) - } - names := make([]string, 0, len(metricFamiliesByName)) - for name, mf := range metricFamiliesByName { - if len(mf.Metric) > 0 { - names = append(names, name) + if newType == dto.MetricType_SUMMARY || newType == dto.MetricType_HISTOGRAM { + if _, ok := mfs[newName+"_count"]; ok { + return fmt.Errorf( + "collected histogram or summary named %q collides with previously collected metric named %q", + newName, newName+"_count", + ) + } + if _, ok := mfs[newName+"_sum"]; ok { + return fmt.Errorf( + "collected histogram or summary named %q collides with previously collected metric named %q", + newName, newName+"_sum", + ) } } - sort.Strings(names) - result := make([]*dto.MetricFamily, 0, len(names)) - for _, name := range names { - result = append(result, metricFamiliesByName[name]) + if newType == dto.MetricType_HISTOGRAM { + if _, ok := mfs[newName+"_bucket"]; ok { + return fmt.Errorf( + "collected histogram named %q collides with previously collected metric named %q", + newName, newName+"_bucket", + ) + } } - return result + return nil } // checkMetricConsistency checks if the provided Metric is consistent with the -// provided MetricFamily. It also hashed the Metric labels and the MetricFamily -// name. If the resulting hash is alread in the provided metricHashes, an error -// is returned. If not, it is added to metricHashes. The provided dimHashes maps -// MetricFamily names to their dimHash (hashed sorted label names). If dimHashes -// doesn't yet contain a hash for the provided MetricFamily, it is -// added. Otherwise, an error is returned if the existing dimHashes in not equal -// the calculated dimHash. +// provided MetricFamily. It also hashes the Metric labels and the MetricFamily +// name. If the resulting hash is already in the provided metricHashes, an error +// is returned. If not, it is added to metricHashes. func checkMetricConsistency( metricFamily *dto.MetricFamily, dtoMetric *dto.Metric, metricHashes map[uint64]struct{}, - dimHashes map[string]uint64, ) error { + name := metricFamily.GetName() + // Type consistency with metric family. if metricFamily.GetType() == dto.MetricType_GAUGE && dtoMetric.Gauge == nil || metricFamily.GetType() == dto.MetricType_COUNTER && dtoMetric.Counter == nil || @@ -674,41 +832,59 @@ func checkMetricConsistency( metricFamily.GetType() == dto.MetricType_HISTOGRAM && dtoMetric.Histogram == nil || metricFamily.GetType() == dto.MetricType_UNTYPED && dtoMetric.Untyped == nil { return fmt.Errorf( - "collected metric %s %s is not a %s", - metricFamily.GetName(), dtoMetric, metricFamily.GetType(), + "collected metric %q { %s} is not a %s", + name, dtoMetric, metricFamily.GetType(), ) } - // Is the metric unique (i.e. no other metric with the same name and the same label values)? + previousLabelName := "" + for _, labelPair := range dtoMetric.GetLabel() { + labelName := labelPair.GetName() + if labelName == previousLabelName { + return fmt.Errorf( + "collected metric %q { %s} has two or more labels with the same name: %s", + name, dtoMetric, labelName, + ) + } + if !checkLabelName(labelName) { + return fmt.Errorf( + "collected metric %q { %s} has a label with an invalid name: %s", + name, dtoMetric, labelName, + ) + } + if dtoMetric.Summary != nil && labelName == quantileLabel { + return fmt.Errorf( + "collected metric %q { %s} must not have an explicit %q label", + name, dtoMetric, quantileLabel, + ) + } + if !utf8.ValidString(labelPair.GetValue()) { + return fmt.Errorf( + "collected metric %q { %s} has a label named %q whose value is not utf8: %#v", + name, dtoMetric, labelName, labelPair.GetValue()) + } + previousLabelName = labelName + } + + // Is the metric unique (i.e. no other metric with the same name and the same labels)? h := hashNew() - h = hashAdd(h, metricFamily.GetName()) + h = hashAdd(h, name) h = hashAddByte(h, separatorByte) - dh := hashNew() // Make sure label pairs are sorted. We depend on it for the consistency // check. - sort.Sort(LabelPairSorter(dtoMetric.Label)) + sort.Sort(labelPairSorter(dtoMetric.Label)) for _, lp := range dtoMetric.Label { + h = hashAdd(h, lp.GetName()) + h = hashAddByte(h, separatorByte) h = hashAdd(h, lp.GetValue()) h = hashAddByte(h, separatorByte) - dh = hashAdd(dh, lp.GetName()) - dh = hashAddByte(dh, separatorByte) } if _, exists := metricHashes[h]; exists { return fmt.Errorf( - "collected metric %s %s was collected before with the same name and label values", - metricFamily.GetName(), dtoMetric, + "collected metric %q { %s} was collected before with the same name and label values", + name, dtoMetric, ) } - if dimHash, ok := dimHashes[metricFamily.GetName()]; ok { - if dimHash != dh { - return fmt.Errorf( - "collected metric %s %s has label dimensions inconsistent with previously collected metrics in the same metric family", - metricFamily.GetName(), dtoMetric, - ) - } - } else { - dimHashes[metricFamily.GetName()] = dh - } metricHashes[h] = struct{}{} return nil } @@ -740,7 +916,7 @@ func checkDescConsistency( metricFamily.GetName(), dtoMetric, desc, ) } - sort.Sort(LabelPairSorter(lpsFromDesc)) + sort.Sort(labelPairSorter(lpsFromDesc)) for i, lpFromDesc := range lpsFromDesc { lpFromMetric := dtoMetric.Label[i] if lpFromDesc.GetName() != lpFromMetric.GetName() || diff --git a/vendor/github.com/prometheus/client_golang/prometheus/summary.go b/vendor/github.com/prometheus/client_golang/prometheus/summary.go index 1c65e25ece6..2980614dff4 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/summary.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/summary.go @@ -36,7 +36,10 @@ const quantileLabel = "quantile" // // A typical use-case is the observation of request latencies. By default, a // Summary provides the median, the 90th and the 99th percentile of the latency -// as rank estimations. +// as rank estimations. However, the default behavior will change in the +// upcoming v0.10 of the library. There will be no rank estimations at all by +// default. For a sane transition, it is recommended to set the desired rank +// estimations explicitly. // // Note that the rank estimations cannot be aggregated in a meaningful way with // the Prometheus query language (i.e. you cannot average or add them). If you @@ -78,8 +81,10 @@ const ( ) // SummaryOpts bundles the options for creating a Summary metric. It is -// mandatory to set Name and Help to a non-empty string. All other fields are -// optional and can safely be left at their zero value. +// mandatory to set Name to a non-empty string. While all other fields are +// optional and can safely be left at their zero value, it is recommended to set +// a help string and to explicitly set the Objectives field to the desired value +// as the default value will change in the upcoming v0.10 of the library. type SummaryOpts struct { // Namespace, Subsystem, and Name are components of the fully-qualified // name of the Summary (created by joining these components with @@ -90,29 +95,27 @@ type SummaryOpts struct { Subsystem string Name string - // Help provides information about this Summary. Mandatory! + // Help provides information about this Summary. // // Metrics with the same fully-qualified name must have the same Help // string. Help string - // ConstLabels are used to attach fixed labels to this - // Summary. Summaries with the same fully-qualified name must have the - // same label names in their ConstLabels. + // ConstLabels are used to attach fixed labels to this metric. Metrics + // with the same fully-qualified name must have the same label names in + // their ConstLabels. // - // Note that in most cases, labels have a value that varies during the - // lifetime of a process. Those labels are usually managed with a - // SummaryVec. ConstLabels serve only special purposes. One is for the - // special case where the value of a label does not change during the - // lifetime of a process, e.g. if the revision of the running binary is - // put into a label. Another, more advanced purpose is if more than one - // Collector needs to collect Summaries with the same fully-qualified - // name. In that case, those Summaries must differ in the values of - // their ConstLabels. See the Collector examples. + // Due to the way a Summary is represented in the Prometheus text format + // and how it is handled by the Prometheus server internally, “quantile” + // is an illegal label name. Construction of a Summary or SummaryVec + // will panic if this label name is used in ConstLabels. // - // If the value of a label never changes (not even between binaries), - // that label most likely should not be a label at all (but part of the - // metric name). + // ConstLabels are only used rarely. In particular, do not use them to + // attach the same labels to all your metrics. Those use cases are + // better covered by target labels set by the scraping Prometheus + // server, or by one specific metric (e.g. a build_info or a + // machine_role metric). See also + // https://prometheus.io/docs/instrumenting/writing_exporters/#target-labels,-not-static-scraped-labels ConstLabels Labels // Objectives defines the quantile rank estimates with their respective @@ -178,7 +181,7 @@ func NewSummary(opts SummaryOpts) Summary { func newSummary(desc *Desc, opts SummaryOpts, labelValues ...string) Summary { if len(desc.variableLabels) != len(labelValues) { - panic(errInconsistentCardinality) + panic(makeInconsistentCardinalityError(desc.fqName, desc.variableLabels, labelValues)) } for _, n := range desc.variableLabels { @@ -399,13 +402,21 @@ func (s quantSort) Less(i, j int) bool { // (e.g. HTTP request latencies, partitioned by status code and method). Create // instances with NewSummaryVec. type SummaryVec struct { - *MetricVec + *metricVec } // NewSummaryVec creates a new SummaryVec based on the provided SummaryOpts and -// partitioned by the given label names. At least one label name must be -// provided. +// partitioned by the given label names. +// +// Due to the way a Summary is represented in the Prometheus text format and how +// it is handled by the Prometheus server internally, “quantile” is an illegal +// label name. NewSummaryVec will panic if this label name is used. func NewSummaryVec(opts SummaryOpts, labelNames []string) *SummaryVec { + for _, ln := range labelNames { + if ln == quantileLabel { + panic(errQuantileLabelNotAllowed) + } + } desc := NewDesc( BuildFQName(opts.Namespace, opts.Subsystem, opts.Name), opts.Help, @@ -413,28 +424,58 @@ func NewSummaryVec(opts SummaryOpts, labelNames []string) *SummaryVec { opts.ConstLabels, ) return &SummaryVec{ - MetricVec: newMetricVec(desc, func(lvs ...string) Metric { + metricVec: newMetricVec(desc, func(lvs ...string) Metric { return newSummary(desc, opts, lvs...) }), } } -// GetMetricWithLabelValues replaces the method of the same name in MetricVec. -// The difference is that this method returns an Observer and not a Metric so -// that no type conversion to an Observer is required. -func (m *SummaryVec) GetMetricWithLabelValues(lvs ...string) (Observer, error) { - metric, err := m.MetricVec.GetMetricWithLabelValues(lvs...) +// GetMetricWithLabelValues returns the Summary for the given slice of label +// values (same order as the VariableLabels in Desc). If that combination of +// label values is accessed for the first time, a new Summary is created. +// +// It is possible to call this method without using the returned Summary to only +// create the new Summary but leave it at its starting value, a Summary without +// any observations. +// +// Keeping the Summary for later use is possible (and should be considered if +// performance is critical), but keep in mind that Reset, DeleteLabelValues and +// Delete can be used to delete the Summary from the SummaryVec. In that case, +// the Summary will still exist, but it will not be exported anymore, even if a +// Summary with the same label values is created later. See also the CounterVec +// example. +// +// An error is returned if the number of label values is not the same as the +// number of VariableLabels in Desc (minus any curried labels). +// +// Note that for more than one label value, this method is prone to mistakes +// caused by an incorrect order of arguments. Consider GetMetricWith(Labels) as +// an alternative to avoid that type of mistake. For higher label numbers, the +// latter has a much more readable (albeit more verbose) syntax, but it comes +// with a performance overhead (for creating and processing the Labels map). +// See also the GaugeVec example. +func (v *SummaryVec) GetMetricWithLabelValues(lvs ...string) (Observer, error) { + metric, err := v.metricVec.getMetricWithLabelValues(lvs...) if metric != nil { return metric.(Observer), err } return nil, err } -// GetMetricWith replaces the method of the same name in MetricVec. The -// difference is that this method returns an Observer and not a Metric so that -// no type conversion to an Observer is required. -func (m *SummaryVec) GetMetricWith(labels Labels) (Observer, error) { - metric, err := m.MetricVec.GetMetricWith(labels) +// GetMetricWith returns the Summary for the given Labels map (the label names +// must match those of the VariableLabels in Desc). If that label map is +// accessed for the first time, a new Summary is created. Implications of +// creating a Summary without using it and keeping the Summary for later use are +// the same as for GetMetricWithLabelValues. +// +// An error is returned if the number and names of the Labels are inconsistent +// with those of the VariableLabels in Desc (minus any curried labels). +// +// This method is used for the same purpose as +// GetMetricWithLabelValues(...string). See there for pros and cons of the two +// methods. +func (v *SummaryVec) GetMetricWith(labels Labels) (Observer, error) { + metric, err := v.metricVec.getMetricWith(labels) if metric != nil { return metric.(Observer), err } @@ -442,18 +483,57 @@ func (m *SummaryVec) GetMetricWith(labels Labels) (Observer, error) { } // WithLabelValues works as GetMetricWithLabelValues, but panics where -// GetMetricWithLabelValues would have returned an error. By not returning an -// error, WithLabelValues allows shortcuts like +// GetMetricWithLabelValues would have returned an error. Not returning an +// error allows shortcuts like // myVec.WithLabelValues("404", "GET").Observe(42.21) -func (m *SummaryVec) WithLabelValues(lvs ...string) Observer { - return m.MetricVec.WithLabelValues(lvs...).(Observer) +func (v *SummaryVec) WithLabelValues(lvs ...string) Observer { + s, err := v.GetMetricWithLabelValues(lvs...) + if err != nil { + panic(err) + } + return s } // With works as GetMetricWith, but panics where GetMetricWithLabels would have -// returned an error. By not returning an error, With allows shortcuts like -// myVec.With(Labels{"code": "404", "method": "GET"}).Observe(42.21) -func (m *SummaryVec) With(labels Labels) Observer { - return m.MetricVec.With(labels).(Observer) +// returned an error. Not returning an error allows shortcuts like +// myVec.With(prometheus.Labels{"code": "404", "method": "GET"}).Observe(42.21) +func (v *SummaryVec) With(labels Labels) Observer { + s, err := v.GetMetricWith(labels) + if err != nil { + panic(err) + } + return s +} + +// CurryWith returns a vector curried with the provided labels, i.e. the +// returned vector has those labels pre-set for all labeled operations performed +// on it. The cardinality of the curried vector is reduced accordingly. The +// order of the remaining labels stays the same (just with the curried labels +// taken out of the sequence – which is relevant for the +// (GetMetric)WithLabelValues methods). It is possible to curry a curried +// vector, but only with labels not yet used for currying before. +// +// The metrics contained in the SummaryVec are shared between the curried and +// uncurried vectors. They are just accessed differently. Curried and uncurried +// vectors behave identically in terms of collection. Only one must be +// registered with a given registry (usually the uncurried version). The Reset +// method deletes all metrics, even if called on a curried vector. +func (v *SummaryVec) CurryWith(labels Labels) (ObserverVec, error) { + vec, err := v.curryWith(labels) + if vec != nil { + return &SummaryVec{vec}, err + } + return nil, err +} + +// MustCurryWith works as CurryWith but panics where CurryWith would have +// returned an error. +func (v *SummaryVec) MustCurryWith(labels Labels) ObserverVec { + vec, err := v.CurryWith(labels) + if err != nil { + panic(err) + } + return vec } type constSummary struct { @@ -506,7 +586,7 @@ func (s *constSummary) Write(out *dto.Metric) error { // map[float64]float64{0.5: 0.23, 0.99: 0.56} // // NewConstSummary returns an error if the length of labelValues is not -// consistent with the variable labels in Desc. +// consistent with the variable labels in Desc or if Desc is invalid. func NewConstSummary( desc *Desc, count uint64, @@ -514,8 +594,11 @@ func NewConstSummary( quantiles map[float64]float64, labelValues ...string, ) (Metric, error) { - if len(desc.variableLabels) != len(labelValues) { - return nil, errInconsistentCardinality + if desc.err != nil { + return nil, desc.err + } + if err := validateLabelValues(labelValues, len(desc.variableLabels)); err != nil { + return nil, err } return &constSummary{ desc: desc, diff --git a/vendor/github.com/prometheus/client_golang/prometheus/testutil/BUILD b/vendor/github.com/prometheus/client_golang/prometheus/testutil/BUILD new file mode 100644 index 00000000000..3d4ee3dc145 --- /dev/null +++ b/vendor/github.com/prometheus/client_golang/prometheus/testutil/BUILD @@ -0,0 +1,29 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = ["testutil.go"], + importmap = "k8s.io/kubernetes/vendor/github.com/prometheus/client_golang/prometheus/testutil", + importpath = "github.com/prometheus/client_golang/prometheus/testutil", + visibility = ["//visibility:public"], + deps = [ + "//vendor/github.com/prometheus/client_golang/prometheus:go_default_library", + "//vendor/github.com/prometheus/client_golang/prometheus/internal:go_default_library", + "//vendor/github.com/prometheus/client_model/go:go_default_library", + "//vendor/github.com/prometheus/common/expfmt:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/vendor/github.com/prometheus/client_golang/prometheus/testutil/testutil.go b/vendor/github.com/prometheus/client_golang/prometheus/testutil/testutil.go new file mode 100644 index 00000000000..d148af9b855 --- /dev/null +++ b/vendor/github.com/prometheus/client_golang/prometheus/testutil/testutil.go @@ -0,0 +1,184 @@ +// Copyright 2018 The Prometheus 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 testutil provides helpers to test code using the prometheus package +// of client_golang. +// +// While writing unit tests to verify correct instrumentation of your code, it's +// a common mistake to mostly test the instrumentation library instead of your +// own code. Rather than verifying that a prometheus.Counter's value has changed +// as expected or that it shows up in the exposition after registration, it is +// in general more robust and more faithful to the concept of unit tests to use +// mock implementations of the prometheus.Counter and prometheus.Registerer +// interfaces that simply assert that the Add or Register methods have been +// called with the expected arguments. However, this might be overkill in simple +// scenarios. The ToFloat64 function is provided for simple inspection of a +// single-value metric, but it has to be used with caution. +// +// End-to-end tests to verify all or larger parts of the metrics exposition can +// be implemented with the CollectAndCompare or GatherAndCompare functions. The +// most appropriate use is not so much testing instrumentation of your code, but +// testing custom prometheus.Collector implementations and in particular whole +// exporters, i.e. programs that retrieve telemetry data from a 3rd party source +// and convert it into Prometheus metrics. +package testutil + +import ( + "bytes" + "fmt" + "io" + "reflect" + + "github.com/prometheus/common/expfmt" + + dto "github.com/prometheus/client_model/go" + + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/client_golang/prometheus/internal" +) + +// ToFloat64 collects all Metrics from the provided Collector. It expects that +// this results in exactly one Metric being collected, which must be a Gauge, +// Counter, or Untyped. In all other cases, ToFloat64 panics. ToFloat64 returns +// the value of the collected Metric. +// +// The Collector provided is typically a simple instance of Gauge or Counter, or +// – less commonly – a GaugeVec or CounterVec with exactly one element. But any +// Collector fulfilling the prerequisites described above will do. +// +// Use this function with caution. It is computationally very expensive and thus +// not suited at all to read values from Metrics in regular code. This is really +// only for testing purposes, and even for testing, other approaches are often +// more appropriate (see this package's documentation). +// +// A clear anti-pattern would be to use a metric type from the prometheus +// package to track values that are also needed for something else than the +// exposition of Prometheus metrics. For example, you would like to track the +// number of items in a queue because your code should reject queuing further +// items if a certain limit is reached. It is tempting to track the number of +// items in a prometheus.Gauge, as it is then easily available as a metric for +// exposition, too. However, then you would need to call ToFloat64 in your +// regular code, potentially quite often. The recommended way is to track the +// number of items conventionally (in the way you would have done it without +// considering Prometheus metrics) and then expose the number with a +// prometheus.GaugeFunc. +func ToFloat64(c prometheus.Collector) float64 { + var ( + m prometheus.Metric + mCount int + mChan = make(chan prometheus.Metric) + done = make(chan struct{}) + ) + + go func() { + for m = range mChan { + mCount++ + } + close(done) + }() + + c.Collect(mChan) + close(mChan) + <-done + + if mCount != 1 { + panic(fmt.Errorf("collected %d metrics instead of exactly 1", mCount)) + } + + pb := &dto.Metric{} + m.Write(pb) + if pb.Gauge != nil { + return pb.Gauge.GetValue() + } + if pb.Counter != nil { + return pb.Counter.GetValue() + } + if pb.Untyped != nil { + return pb.Untyped.GetValue() + } + panic(fmt.Errorf("collected a non-gauge/counter/untyped metric: %s", pb)) +} + +// CollectAndCompare registers the provided Collector with a newly created +// pedantic Registry. It then does the same as GatherAndCompare, gathering the +// metrics from the pedantic Registry. +func CollectAndCompare(c prometheus.Collector, expected io.Reader, metricNames ...string) error { + reg := prometheus.NewPedanticRegistry() + if err := reg.Register(c); err != nil { + return fmt.Errorf("registering collector failed: %s", err) + } + return GatherAndCompare(reg, expected, metricNames...) +} + +// GatherAndCompare gathers all metrics from the provided Gatherer and compares +// it to an expected output read from the provided Reader in the Prometheus text +// exposition format. If any metricNames are provided, only metrics with those +// names are compared. +func GatherAndCompare(g prometheus.Gatherer, expected io.Reader, metricNames ...string) error { + metrics, err := g.Gather() + if err != nil { + return fmt.Errorf("gathering metrics failed: %s", err) + } + if metricNames != nil { + metrics = filterMetrics(metrics, metricNames) + } + var tp expfmt.TextParser + expectedMetrics, err := tp.TextToMetricFamilies(expected) + if err != nil { + return fmt.Errorf("parsing expected metrics failed: %s", err) + } + + if !reflect.DeepEqual(metrics, internal.NormalizeMetricFamilies(expectedMetrics)) { + // Encode the gathered output to the readable text format for comparison. + var buf1 bytes.Buffer + enc := expfmt.NewEncoder(&buf1, expfmt.FmtText) + for _, mf := range metrics { + if err := enc.Encode(mf); err != nil { + return fmt.Errorf("encoding result failed: %s", err) + } + } + // Encode normalized expected metrics again to generate them in the same ordering + // the registry does to spot differences more easily. + var buf2 bytes.Buffer + enc = expfmt.NewEncoder(&buf2, expfmt.FmtText) + for _, mf := range internal.NormalizeMetricFamilies(expectedMetrics) { + if err := enc.Encode(mf); err != nil { + return fmt.Errorf("encoding result failed: %s", err) + } + } + + return fmt.Errorf(` +metric output does not match expectation; want: + +%s + +got: + +%s +`, buf2.String(), buf1.String()) + } + return nil +} + +func filterMetrics(metrics []*dto.MetricFamily, names []string) []*dto.MetricFamily { + var filtered []*dto.MetricFamily + for _, m := range metrics { + for _, name := range names { + if m.GetName() == name { + filtered = append(filtered, m) + break + } + } + } + return filtered +} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/timer.go b/vendor/github.com/prometheus/client_golang/prometheus/timer.go index 12b65699b99..b8fc5f18c85 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/timer.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/timer.go @@ -41,6 +41,9 @@ func NewTimer(o Observer) *Timer { // NewTimer. It calls the Observe method of the Observer provided during // construction with the duration in seconds as an argument. ObserveDuration is // usually called with a defer statement. +// +// Note that this method is only guaranteed to never observe negative durations +// if used with Go1.9+. func (t *Timer) ObserveDuration() { if t.observer != nil { t.observer.Observe(time.Since(t.begin).Seconds()) diff --git a/vendor/github.com/prometheus/client_golang/prometheus/untyped.go b/vendor/github.com/prometheus/client_golang/prometheus/untyped.go index 065501d38fb..0f9ce63f409 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/untyped.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/untyped.go @@ -13,113 +13,12 @@ package prometheus -// Untyped is a Metric that represents a single numerical value that can -// arbitrarily go up and down. -// -// An Untyped metric works the same as a Gauge. The only difference is that to -// no type information is implied. -// -// To create Untyped instances, use NewUntyped. -// -// Deprecated: The Untyped type is deprecated because it doesn't make sense in -// direct instrumentation. If you need to mirror an external metric of unknown -// type (usually while writing exporters), Use MustNewConstMetric to create an -// untyped metric instance on the fly. -type Untyped interface { - Metric - Collector - - // Set sets the Untyped metric to an arbitrary value. - Set(float64) - // Inc increments the Untyped metric by 1. - Inc() - // Dec decrements the Untyped metric by 1. - Dec() - // Add adds the given value to the Untyped metric. (The value can be - // negative, resulting in a decrease.) - Add(float64) - // Sub subtracts the given value from the Untyped metric. (The value can - // be negative, resulting in an increase.) - Sub(float64) -} - // UntypedOpts is an alias for Opts. See there for doc comments. type UntypedOpts Opts -// NewUntyped creates a new Untyped metric from the provided UntypedOpts. -func NewUntyped(opts UntypedOpts) Untyped { - return newValue(NewDesc( - BuildFQName(opts.Namespace, opts.Subsystem, opts.Name), - opts.Help, - nil, - opts.ConstLabels, - ), UntypedValue, 0) -} - -// UntypedVec is a Collector that bundles a set of Untyped metrics that all -// share the same Desc, but have different values for their variable -// labels. This is used if you want to count the same thing partitioned by -// various dimensions. Create instances with NewUntypedVec. -type UntypedVec struct { - *MetricVec -} - -// NewUntypedVec creates a new UntypedVec based on the provided UntypedOpts and -// partitioned by the given label names. At least one label name must be -// provided. -func NewUntypedVec(opts UntypedOpts, labelNames []string) *UntypedVec { - desc := NewDesc( - BuildFQName(opts.Namespace, opts.Subsystem, opts.Name), - opts.Help, - labelNames, - opts.ConstLabels, - ) - return &UntypedVec{ - MetricVec: newMetricVec(desc, func(lvs ...string) Metric { - return newValue(desc, UntypedValue, 0, lvs...) - }), - } -} - -// GetMetricWithLabelValues replaces the method of the same name in -// MetricVec. The difference is that this method returns an Untyped and not a -// Metric so that no type conversion is required. -func (m *UntypedVec) GetMetricWithLabelValues(lvs ...string) (Untyped, error) { - metric, err := m.MetricVec.GetMetricWithLabelValues(lvs...) - if metric != nil { - return metric.(Untyped), err - } - return nil, err -} - -// GetMetricWith replaces the method of the same name in MetricVec. The -// difference is that this method returns an Untyped and not a Metric so that no -// type conversion is required. -func (m *UntypedVec) GetMetricWith(labels Labels) (Untyped, error) { - metric, err := m.MetricVec.GetMetricWith(labels) - if metric != nil { - return metric.(Untyped), err - } - return nil, err -} - -// WithLabelValues works as GetMetricWithLabelValues, but panics where -// GetMetricWithLabelValues would have returned an error. By not returning an -// error, WithLabelValues allows shortcuts like -// myVec.WithLabelValues("404", "GET").Add(42) -func (m *UntypedVec) WithLabelValues(lvs ...string) Untyped { - return m.MetricVec.WithLabelValues(lvs...).(Untyped) -} - -// With works as GetMetricWith, but panics where GetMetricWithLabels would have -// returned an error. By not returning an error, With allows shortcuts like -// myVec.With(Labels{"code": "404", "method": "GET"}).Add(42) -func (m *UntypedVec) With(labels Labels) Untyped { - return m.MetricVec.With(labels).(Untyped) -} - -// UntypedFunc is an Untyped whose value is determined at collect time by -// calling a provided function. +// UntypedFunc works like GaugeFunc but the collected metric is of type +// "Untyped". UntypedFunc is useful to mirror an external metric of unknown +// type. // // To create UntypedFunc instances, use NewUntypedFunc. type UntypedFunc interface { diff --git a/vendor/github.com/prometheus/client_golang/prometheus/value.go b/vendor/github.com/prometheus/client_golang/prometheus/value.go index ff75ce58514..eb248f10874 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/value.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/value.go @@ -14,16 +14,12 @@ package prometheus import ( - "errors" "fmt" - "math" "sort" - "sync/atomic" - "time" - - dto "github.com/prometheus/client_model/go" "github.com/golang/protobuf/proto" + + dto "github.com/prometheus/client_model/go" ) // ValueType is an enumeration of metric types that represent a simple value. @@ -37,81 +33,6 @@ const ( UntypedValue ) -var errInconsistentCardinality = errors.New("inconsistent label cardinality") - -// value is a generic metric for simple values. It implements Metric, Collector, -// Counter, Gauge, and Untyped. Its effective type is determined by -// ValueType. This is a low-level building block used by the library to back the -// implementations of Counter, Gauge, and Untyped. -type value struct { - // valBits contains the bits of the represented float64 value. It has - // to go first in the struct to guarantee alignment for atomic - // operations. http://golang.org/pkg/sync/atomic/#pkg-note-BUG - valBits uint64 - - selfCollector - - desc *Desc - valType ValueType - labelPairs []*dto.LabelPair -} - -// newValue returns a newly allocated value with the given Desc, ValueType, -// sample value and label values. It panics if the number of label -// values is different from the number of variable labels in Desc. -func newValue(desc *Desc, valueType ValueType, val float64, labelValues ...string) *value { - if len(labelValues) != len(desc.variableLabels) { - panic(errInconsistentCardinality) - } - result := &value{ - desc: desc, - valType: valueType, - valBits: math.Float64bits(val), - labelPairs: makeLabelPairs(desc, labelValues), - } - result.init(result) - return result -} - -func (v *value) Desc() *Desc { - return v.desc -} - -func (v *value) Set(val float64) { - atomic.StoreUint64(&v.valBits, math.Float64bits(val)) -} - -func (v *value) SetToCurrentTime() { - v.Set(float64(time.Now().UnixNano()) / 1e9) -} - -func (v *value) Inc() { - v.Add(1) -} - -func (v *value) Dec() { - v.Add(-1) -} - -func (v *value) Add(val float64) { - for { - oldBits := atomic.LoadUint64(&v.valBits) - newBits := math.Float64bits(math.Float64frombits(oldBits) + val) - if atomic.CompareAndSwapUint64(&v.valBits, oldBits, newBits) { - return - } - } -} - -func (v *value) Sub(val float64) { - v.Add(val * -1) -} - -func (v *value) Write(out *dto.Metric) error { - val := math.Float64frombits(atomic.LoadUint64(&v.valBits)) - return populateMetric(v.valType, val, v.labelPairs, out) -} - // valueFunc is a generic metric for simple values retrieved on collect time // from a function. It implements Metric and Collector. Its effective type is // determined by ValueType. This is a low-level building block used by the @@ -156,10 +77,14 @@ func (v *valueFunc) Write(out *dto.Metric) error { // operations. However, when implementing custom Collectors, it is useful as a // throw-away metric that is generated on the fly to send it to Prometheus in // the Collect method. NewConstMetric returns an error if the length of -// labelValues is not consistent with the variable labels in Desc. +// labelValues is not consistent with the variable labels in Desc or if Desc is +// invalid. func NewConstMetric(desc *Desc, valueType ValueType, value float64, labelValues ...string) (Metric, error) { - if len(desc.variableLabels) != len(labelValues) { - return nil, errInconsistentCardinality + if desc.err != nil { + return nil, desc.err + } + if err := validateLabelValues(labelValues, len(desc.variableLabels)); err != nil { + return nil, err } return &constMetric{ desc: desc, @@ -231,9 +156,7 @@ func makeLabelPairs(desc *Desc, labelValues []string) []*dto.LabelPair { Value: proto.String(labelValues[i]), }) } - for _, lp := range desc.constLabelPairs { - labelPairs = append(labelPairs, lp) - } - sort.Sort(LabelPairSorter(labelPairs)) + labelPairs = append(labelPairs, desc.constLabelPairs...) + sort.Sort(labelPairSorter(labelPairs)) return labelPairs } diff --git a/vendor/github.com/prometheus/client_golang/prometheus/vec.go b/vendor/github.com/prometheus/client_golang/prometheus/vec.go index 7f3eef9a467..14ed9e856d1 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/vec.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/vec.go @@ -20,33 +20,180 @@ import ( "github.com/prometheus/common/model" ) -// MetricVec is a Collector to bundle metrics of the same name that -// differ in their label values. MetricVec is usually not used directly but as a -// building block for implementations of vectors of a given metric -// type. GaugeVec, CounterVec, SummaryVec, and UntypedVec are examples already -// provided in this package. -type MetricVec struct { - mtx sync.RWMutex // Protects the children. - children map[uint64][]metricWithLabelValues - desc *Desc +// metricVec is a Collector to bundle metrics of the same name that differ in +// their label values. metricVec is not used directly (and therefore +// unexported). It is used as a building block for implementations of vectors of +// a given metric type, like GaugeVec, CounterVec, SummaryVec, and HistogramVec. +// It also handles label currying. It uses basicMetricVec internally. +type metricVec struct { + *metricMap - newMetric func(labelValues ...string) Metric - hashAdd func(h uint64, s string) uint64 // replace hash function for testing collision handling + curry []curriedLabelValue + + // hashAdd and hashAddByte can be replaced for testing collision handling. + hashAdd func(h uint64, s string) uint64 hashAddByte func(h uint64, b byte) uint64 } -// newMetricVec returns an initialized MetricVec. The concrete value is -// returned for embedding into another struct. -func newMetricVec(desc *Desc, newMetric func(lvs ...string) Metric) *MetricVec { - return &MetricVec{ - children: map[uint64][]metricWithLabelValues{}, - desc: desc, - newMetric: newMetric, +// newMetricVec returns an initialized metricVec. +func newMetricVec(desc *Desc, newMetric func(lvs ...string) Metric) *metricVec { + return &metricVec{ + metricMap: &metricMap{ + metrics: map[uint64][]metricWithLabelValues{}, + desc: desc, + newMetric: newMetric, + }, hashAdd: hashAdd, hashAddByte: hashAddByte, } } +// DeleteLabelValues removes the metric where the variable labels are the same +// as those passed in as labels (same order as the VariableLabels in Desc). It +// returns true if a metric was deleted. +// +// It is not an error if the number of label values is not the same as the +// number of VariableLabels in Desc. However, such inconsistent label count can +// never match an actual metric, so the method will always return false in that +// case. +// +// Note that for more than one label value, this method is prone to mistakes +// caused by an incorrect order of arguments. Consider Delete(Labels) as an +// alternative to avoid that type of mistake. For higher label numbers, the +// latter has a much more readable (albeit more verbose) syntax, but it comes +// with a performance overhead (for creating and processing the Labels map). +// See also the CounterVec example. +func (m *metricVec) DeleteLabelValues(lvs ...string) bool { + h, err := m.hashLabelValues(lvs) + if err != nil { + return false + } + + return m.metricMap.deleteByHashWithLabelValues(h, lvs, m.curry) +} + +// Delete deletes the metric where the variable labels are the same as those +// passed in as labels. It returns true if a metric was deleted. +// +// It is not an error if the number and names of the Labels are inconsistent +// with those of the VariableLabels in Desc. However, such inconsistent Labels +// can never match an actual metric, so the method will always return false in +// that case. +// +// This method is used for the same purpose as DeleteLabelValues(...string). See +// there for pros and cons of the two methods. +func (m *metricVec) Delete(labels Labels) bool { + h, err := m.hashLabels(labels) + if err != nil { + return false + } + + return m.metricMap.deleteByHashWithLabels(h, labels, m.curry) +} + +func (m *metricVec) curryWith(labels Labels) (*metricVec, error) { + var ( + newCurry []curriedLabelValue + oldCurry = m.curry + iCurry int + ) + for i, label := range m.desc.variableLabels { + val, ok := labels[label] + if iCurry < len(oldCurry) && oldCurry[iCurry].index == i { + if ok { + return nil, fmt.Errorf("label name %q is already curried", label) + } + newCurry = append(newCurry, oldCurry[iCurry]) + iCurry++ + } else { + if !ok { + continue // Label stays uncurried. + } + newCurry = append(newCurry, curriedLabelValue{i, val}) + } + } + if l := len(oldCurry) + len(labels) - len(newCurry); l > 0 { + return nil, fmt.Errorf("%d unknown label(s) found during currying", l) + } + + return &metricVec{ + metricMap: m.metricMap, + curry: newCurry, + hashAdd: m.hashAdd, + hashAddByte: m.hashAddByte, + }, nil +} + +func (m *metricVec) getMetricWithLabelValues(lvs ...string) (Metric, error) { + h, err := m.hashLabelValues(lvs) + if err != nil { + return nil, err + } + + return m.metricMap.getOrCreateMetricWithLabelValues(h, lvs, m.curry), nil +} + +func (m *metricVec) getMetricWith(labels Labels) (Metric, error) { + h, err := m.hashLabels(labels) + if err != nil { + return nil, err + } + + return m.metricMap.getOrCreateMetricWithLabels(h, labels, m.curry), nil +} + +func (m *metricVec) hashLabelValues(vals []string) (uint64, error) { + if err := validateLabelValues(vals, len(m.desc.variableLabels)-len(m.curry)); err != nil { + return 0, err + } + + var ( + h = hashNew() + curry = m.curry + iVals, iCurry int + ) + for i := 0; i < len(m.desc.variableLabels); i++ { + if iCurry < len(curry) && curry[iCurry].index == i { + h = m.hashAdd(h, curry[iCurry].value) + iCurry++ + } else { + h = m.hashAdd(h, vals[iVals]) + iVals++ + } + h = m.hashAddByte(h, model.SeparatorByte) + } + return h, nil +} + +func (m *metricVec) hashLabels(labels Labels) (uint64, error) { + if err := validateValuesInLabels(labels, len(m.desc.variableLabels)-len(m.curry)); err != nil { + return 0, err + } + + var ( + h = hashNew() + curry = m.curry + iCurry int + ) + for i, label := range m.desc.variableLabels { + val, ok := labels[label] + if iCurry < len(curry) && curry[iCurry].index == i { + if ok { + return 0, fmt.Errorf("label name %q is already curried", label) + } + h = m.hashAdd(h, curry[iCurry].value) + iCurry++ + } else { + if !ok { + return 0, fmt.Errorf("label name %q missing in label map", label) + } + h = m.hashAdd(h, val) + } + h = m.hashAddByte(h, model.SeparatorByte) + } + return h, nil +} + // metricWithLabelValues provides the metric and its label values for // disambiguation on hash collision. type metricWithLabelValues struct { @@ -54,166 +201,72 @@ type metricWithLabelValues struct { metric Metric } -// Describe implements Collector. The length of the returned slice -// is always one. -func (m *MetricVec) Describe(ch chan<- *Desc) { +// curriedLabelValue sets the curried value for a label at the given index. +type curriedLabelValue struct { + index int + value string +} + +// metricMap is a helper for metricVec and shared between differently curried +// metricVecs. +type metricMap struct { + mtx sync.RWMutex // Protects metrics. + metrics map[uint64][]metricWithLabelValues + desc *Desc + newMetric func(labelValues ...string) Metric +} + +// Describe implements Collector. It will send exactly one Desc to the provided +// channel. +func (m *metricMap) Describe(ch chan<- *Desc) { ch <- m.desc } // Collect implements Collector. -func (m *MetricVec) Collect(ch chan<- Metric) { +func (m *metricMap) Collect(ch chan<- Metric) { m.mtx.RLock() defer m.mtx.RUnlock() - for _, metrics := range m.children { + for _, metrics := range m.metrics { for _, metric := range metrics { ch <- metric.metric } } } -// GetMetricWithLabelValues returns the Metric for the given slice of label -// values (same order as the VariableLabels in Desc). If that combination of -// label values is accessed for the first time, a new Metric is created. -// -// It is possible to call this method without using the returned Metric to only -// create the new Metric but leave it at its start value (e.g. a Summary or -// Histogram without any observations). See also the SummaryVec example. -// -// Keeping the Metric for later use is possible (and should be considered if -// performance is critical), but keep in mind that Reset, DeleteLabelValues and -// Delete can be used to delete the Metric from the MetricVec. In that case, the -// Metric will still exist, but it will not be exported anymore, even if a -// Metric with the same label values is created later. See also the CounterVec -// example. -// -// An error is returned if the number of label values is not the same as the -// number of VariableLabels in Desc. -// -// Note that for more than one label value, this method is prone to mistakes -// caused by an incorrect order of arguments. Consider GetMetricWith(Labels) as -// an alternative to avoid that type of mistake. For higher label numbers, the -// latter has a much more readable (albeit more verbose) syntax, but it comes -// with a performance overhead (for creating and processing the Labels map). -// See also the GaugeVec example. -func (m *MetricVec) GetMetricWithLabelValues(lvs ...string) (Metric, error) { - h, err := m.hashLabelValues(lvs) - if err != nil { - return nil, err - } - - return m.getOrCreateMetricWithLabelValues(h, lvs), nil -} - -// GetMetricWith returns the Metric for the given Labels map (the label names -// must match those of the VariableLabels in Desc). If that label map is -// accessed for the first time, a new Metric is created. Implications of -// creating a Metric without using it and keeping the Metric for later use are -// the same as for GetMetricWithLabelValues. -// -// An error is returned if the number and names of the Labels are inconsistent -// with those of the VariableLabels in Desc. -// -// This method is used for the same purpose as -// GetMetricWithLabelValues(...string). See there for pros and cons of the two -// methods. -func (m *MetricVec) GetMetricWith(labels Labels) (Metric, error) { - h, err := m.hashLabels(labels) - if err != nil { - return nil, err - } - - return m.getOrCreateMetricWithLabels(h, labels), nil -} - -// WithLabelValues works as GetMetricWithLabelValues, but panics if an error -// occurs. The method allows neat syntax like: -// httpReqs.WithLabelValues("404", "POST").Inc() -func (m *MetricVec) WithLabelValues(lvs ...string) Metric { - metric, err := m.GetMetricWithLabelValues(lvs...) - if err != nil { - panic(err) - } - return metric -} - -// With works as GetMetricWith, but panics if an error occurs. The method allows -// neat syntax like: -// httpReqs.With(Labels{"status":"404", "method":"POST"}).Inc() -func (m *MetricVec) With(labels Labels) Metric { - metric, err := m.GetMetricWith(labels) - if err != nil { - panic(err) - } - return metric -} - -// DeleteLabelValues removes the metric where the variable labels are the same -// as those passed in as labels (same order as the VariableLabels in Desc). It -// returns true if a metric was deleted. -// -// It is not an error if the number of label values is not the same as the -// number of VariableLabels in Desc. However, such inconsistent label count can -// never match an actual Metric, so the method will always return false in that -// case. -// -// Note that for more than one label value, this method is prone to mistakes -// caused by an incorrect order of arguments. Consider Delete(Labels) as an -// alternative to avoid that type of mistake. For higher label numbers, the -// latter has a much more readable (albeit more verbose) syntax, but it comes -// with a performance overhead (for creating and processing the Labels map). -// See also the CounterVec example. -func (m *MetricVec) DeleteLabelValues(lvs ...string) bool { +// Reset deletes all metrics in this vector. +func (m *metricMap) Reset() { m.mtx.Lock() defer m.mtx.Unlock() - h, err := m.hashLabelValues(lvs) - if err != nil { - return false + for h := range m.metrics { + delete(m.metrics, h) } - return m.deleteByHashWithLabelValues(h, lvs) -} - -// Delete deletes the metric where the variable labels are the same as those -// passed in as labels. It returns true if a metric was deleted. -// -// It is not an error if the number and names of the Labels are inconsistent -// with those of the VariableLabels in the Desc of the MetricVec. However, such -// inconsistent Labels can never match an actual Metric, so the method will -// always return false in that case. -// -// This method is used for the same purpose as DeleteLabelValues(...string). See -// there for pros and cons of the two methods. -func (m *MetricVec) Delete(labels Labels) bool { - m.mtx.Lock() - defer m.mtx.Unlock() - - h, err := m.hashLabels(labels) - if err != nil { - return false - } - - return m.deleteByHashWithLabels(h, labels) } // deleteByHashWithLabelValues removes the metric from the hash bucket h. If // there are multiple matches in the bucket, use lvs to select a metric and // remove only that metric. -func (m *MetricVec) deleteByHashWithLabelValues(h uint64, lvs []string) bool { - metrics, ok := m.children[h] +func (m *metricMap) deleteByHashWithLabelValues( + h uint64, lvs []string, curry []curriedLabelValue, +) bool { + m.mtx.Lock() + defer m.mtx.Unlock() + + metrics, ok := m.metrics[h] if !ok { return false } - i := m.findMetricWithLabelValues(metrics, lvs) + i := findMetricWithLabelValues(metrics, lvs, curry) if i >= len(metrics) { return false } if len(metrics) > 1 { - m.children[h] = append(metrics[:i], metrics[i+1:]...) + m.metrics[h] = append(metrics[:i], metrics[i+1:]...) } else { - delete(m.children, h) + delete(m.metrics, h) } return true } @@ -221,69 +274,38 @@ func (m *MetricVec) deleteByHashWithLabelValues(h uint64, lvs []string) bool { // deleteByHashWithLabels removes the metric from the hash bucket h. If there // are multiple matches in the bucket, use lvs to select a metric and remove // only that metric. -func (m *MetricVec) deleteByHashWithLabels(h uint64, labels Labels) bool { - metrics, ok := m.children[h] +func (m *metricMap) deleteByHashWithLabels( + h uint64, labels Labels, curry []curriedLabelValue, +) bool { + m.mtx.Lock() + defer m.mtx.Unlock() + + metrics, ok := m.metrics[h] if !ok { return false } - i := m.findMetricWithLabels(metrics, labels) + i := findMetricWithLabels(m.desc, metrics, labels, curry) if i >= len(metrics) { return false } if len(metrics) > 1 { - m.children[h] = append(metrics[:i], metrics[i+1:]...) + m.metrics[h] = append(metrics[:i], metrics[i+1:]...) } else { - delete(m.children, h) + delete(m.metrics, h) } return true } -// Reset deletes all metrics in this vector. -func (m *MetricVec) Reset() { - m.mtx.Lock() - defer m.mtx.Unlock() - - for h := range m.children { - delete(m.children, h) - } -} - -func (m *MetricVec) hashLabelValues(vals []string) (uint64, error) { - if len(vals) != len(m.desc.variableLabels) { - return 0, errInconsistentCardinality - } - h := hashNew() - for _, val := range vals { - h = m.hashAdd(h, val) - h = m.hashAddByte(h, model.SeparatorByte) - } - return h, nil -} - -func (m *MetricVec) hashLabels(labels Labels) (uint64, error) { - if len(labels) != len(m.desc.variableLabels) { - return 0, errInconsistentCardinality - } - h := hashNew() - for _, label := range m.desc.variableLabels { - val, ok := labels[label] - if !ok { - return 0, fmt.Errorf("label name %q missing in label map", label) - } - h = m.hashAdd(h, val) - h = m.hashAddByte(h, model.SeparatorByte) - } - return h, nil -} - // getOrCreateMetricWithLabelValues retrieves the metric by hash and label value // or creates it and returns the new one. // // This function holds the mutex. -func (m *MetricVec) getOrCreateMetricWithLabelValues(hash uint64, lvs []string) Metric { +func (m *metricMap) getOrCreateMetricWithLabelValues( + hash uint64, lvs []string, curry []curriedLabelValue, +) Metric { m.mtx.RLock() - metric, ok := m.getMetricWithLabelValues(hash, lvs) + metric, ok := m.getMetricWithHashAndLabelValues(hash, lvs, curry) m.mtx.RUnlock() if ok { return metric @@ -291,13 +313,11 @@ func (m *MetricVec) getOrCreateMetricWithLabelValues(hash uint64, lvs []string) m.mtx.Lock() defer m.mtx.Unlock() - metric, ok = m.getMetricWithLabelValues(hash, lvs) + metric, ok = m.getMetricWithHashAndLabelValues(hash, lvs, curry) if !ok { - // Copy to avoid allocation in case wo don't go down this code path. - copiedLVs := make([]string, len(lvs)) - copy(copiedLVs, lvs) - metric = m.newMetric(copiedLVs...) - m.children[hash] = append(m.children[hash], metricWithLabelValues{values: copiedLVs, metric: metric}) + inlinedLVs := inlineLabelValues(lvs, curry) + metric = m.newMetric(inlinedLVs...) + m.metrics[hash] = append(m.metrics[hash], metricWithLabelValues{values: inlinedLVs, metric: metric}) } return metric } @@ -306,9 +326,11 @@ func (m *MetricVec) getOrCreateMetricWithLabelValues(hash uint64, lvs []string) // or creates it and returns the new one. // // This function holds the mutex. -func (m *MetricVec) getOrCreateMetricWithLabels(hash uint64, labels Labels) Metric { +func (m *metricMap) getOrCreateMetricWithLabels( + hash uint64, labels Labels, curry []curriedLabelValue, +) Metric { m.mtx.RLock() - metric, ok := m.getMetricWithLabels(hash, labels) + metric, ok := m.getMetricWithHashAndLabels(hash, labels, curry) m.mtx.RUnlock() if ok { return metric @@ -316,33 +338,37 @@ func (m *MetricVec) getOrCreateMetricWithLabels(hash uint64, labels Labels) Metr m.mtx.Lock() defer m.mtx.Unlock() - metric, ok = m.getMetricWithLabels(hash, labels) + metric, ok = m.getMetricWithHashAndLabels(hash, labels, curry) if !ok { - lvs := m.extractLabelValues(labels) + lvs := extractLabelValues(m.desc, labels, curry) metric = m.newMetric(lvs...) - m.children[hash] = append(m.children[hash], metricWithLabelValues{values: lvs, metric: metric}) + m.metrics[hash] = append(m.metrics[hash], metricWithLabelValues{values: lvs, metric: metric}) } return metric } -// getMetricWithLabelValues gets a metric while handling possible collisions in -// the hash space. Must be called while holding read mutex. -func (m *MetricVec) getMetricWithLabelValues(h uint64, lvs []string) (Metric, bool) { - metrics, ok := m.children[h] +// getMetricWithHashAndLabelValues gets a metric while handling possible +// collisions in the hash space. Must be called while holding the read mutex. +func (m *metricMap) getMetricWithHashAndLabelValues( + h uint64, lvs []string, curry []curriedLabelValue, +) (Metric, bool) { + metrics, ok := m.metrics[h] if ok { - if i := m.findMetricWithLabelValues(metrics, lvs); i < len(metrics) { + if i := findMetricWithLabelValues(metrics, lvs, curry); i < len(metrics) { return metrics[i].metric, true } } return nil, false } -// getMetricWithLabels gets a metric while handling possible collisions in +// getMetricWithHashAndLabels gets a metric while handling possible collisions in // the hash space. Must be called while holding read mutex. -func (m *MetricVec) getMetricWithLabels(h uint64, labels Labels) (Metric, bool) { - metrics, ok := m.children[h] +func (m *metricMap) getMetricWithHashAndLabels( + h uint64, labels Labels, curry []curriedLabelValue, +) (Metric, bool) { + metrics, ok := m.metrics[h] if ok { - if i := m.findMetricWithLabels(metrics, labels); i < len(metrics) { + if i := findMetricWithLabels(m.desc, metrics, labels, curry); i < len(metrics) { return metrics[i].metric, true } } @@ -351,9 +377,11 @@ func (m *MetricVec) getMetricWithLabels(h uint64, labels Labels) (Metric, bool) // findMetricWithLabelValues returns the index of the matching metric or // len(metrics) if not found. -func (m *MetricVec) findMetricWithLabelValues(metrics []metricWithLabelValues, lvs []string) int { +func findMetricWithLabelValues( + metrics []metricWithLabelValues, lvs []string, curry []curriedLabelValue, +) int { for i, metric := range metrics { - if m.matchLabelValues(metric.values, lvs) { + if matchLabelValues(metric.values, lvs, curry) { return i } } @@ -362,32 +390,51 @@ func (m *MetricVec) findMetricWithLabelValues(metrics []metricWithLabelValues, l // findMetricWithLabels returns the index of the matching metric or len(metrics) // if not found. -func (m *MetricVec) findMetricWithLabels(metrics []metricWithLabelValues, labels Labels) int { +func findMetricWithLabels( + desc *Desc, metrics []metricWithLabelValues, labels Labels, curry []curriedLabelValue, +) int { for i, metric := range metrics { - if m.matchLabels(metric.values, labels) { + if matchLabels(desc, metric.values, labels, curry) { return i } } return len(metrics) } -func (m *MetricVec) matchLabelValues(values []string, lvs []string) bool { - if len(values) != len(lvs) { +func matchLabelValues(values []string, lvs []string, curry []curriedLabelValue) bool { + if len(values) != len(lvs)+len(curry) { return false } + var iLVs, iCurry int for i, v := range values { - if v != lvs[i] { + if iCurry < len(curry) && curry[iCurry].index == i { + if v != curry[iCurry].value { + return false + } + iCurry++ + continue + } + if v != lvs[iLVs] { return false } + iLVs++ } return true } -func (m *MetricVec) matchLabels(values []string, labels Labels) bool { - if len(labels) != len(values) { +func matchLabels(desc *Desc, values []string, labels Labels, curry []curriedLabelValue) bool { + if len(values) != len(labels)+len(curry) { return false } - for i, k := range m.desc.variableLabels { + iCurry := 0 + for i, k := range desc.variableLabels { + if iCurry < len(curry) && curry[iCurry].index == i { + if values[i] != curry[iCurry].value { + return false + } + iCurry++ + continue + } if values[i] != labels[k] { return false } @@ -395,10 +442,31 @@ func (m *MetricVec) matchLabels(values []string, labels Labels) bool { return true } -func (m *MetricVec) extractLabelValues(labels Labels) []string { - labelValues := make([]string, len(labels)) - for i, k := range m.desc.variableLabels { +func extractLabelValues(desc *Desc, labels Labels, curry []curriedLabelValue) []string { + labelValues := make([]string, len(labels)+len(curry)) + iCurry := 0 + for i, k := range desc.variableLabels { + if iCurry < len(curry) && curry[iCurry].index == i { + labelValues[i] = curry[iCurry].value + iCurry++ + continue + } labelValues[i] = labels[k] } return labelValues } + +func inlineLabelValues(lvs []string, curry []curriedLabelValue) []string { + labelValues := make([]string, len(lvs)+len(curry)) + var iCurry, iLVs int + for i := range labelValues { + if iCurry < len(curry) && curry[iCurry].index == i { + labelValues[i] = curry[iCurry].value + iCurry++ + continue + } + labelValues[i] = lvs[iLVs] + iLVs++ + } + return labelValues +} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/wrap.go b/vendor/github.com/prometheus/client_golang/prometheus/wrap.go new file mode 100644 index 00000000000..49159bf3eb0 --- /dev/null +++ b/vendor/github.com/prometheus/client_golang/prometheus/wrap.go @@ -0,0 +1,179 @@ +// Copyright 2018 The Prometheus 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 prometheus + +import ( + "fmt" + "sort" + + "github.com/golang/protobuf/proto" + + dto "github.com/prometheus/client_model/go" +) + +// WrapRegistererWith returns a Registerer wrapping the provided +// Registerer. Collectors registered with the returned Registerer will be +// registered with the wrapped Registerer in a modified way. The modified +// Collector adds the provided Labels to all Metrics it collects (as +// ConstLabels). The Metrics collected by the unmodified Collector must not +// duplicate any of those labels. +// +// WrapRegistererWith provides a way to add fixed labels to a subset of +// Collectors. It should not be used to add fixed labels to all metrics exposed. +// +// The Collector example demonstrates a use of WrapRegistererWith. +func WrapRegistererWith(labels Labels, reg Registerer) Registerer { + return &wrappingRegisterer{ + wrappedRegisterer: reg, + labels: labels, + } +} + +// WrapRegistererWithPrefix returns a Registerer wrapping the provided +// Registerer. Collectors registered with the returned Registerer will be +// registered with the wrapped Registerer in a modified way. The modified +// Collector adds the provided prefix to the name of all Metrics it collects. +// +// WrapRegistererWithPrefix is useful to have one place to prefix all metrics of +// a sub-system. To make this work, register metrics of the sub-system with the +// wrapping Registerer returned by WrapRegistererWithPrefix. It is rarely useful +// to use the same prefix for all metrics exposed. In particular, do not prefix +// metric names that are standardized across applications, as that would break +// horizontal monitoring, for example the metrics provided by the Go collector +// (see NewGoCollector) and the process collector (see NewProcessCollector). (In +// fact, those metrics are already prefixed with “go_” or “process_”, +// respectively.) +func WrapRegistererWithPrefix(prefix string, reg Registerer) Registerer { + return &wrappingRegisterer{ + wrappedRegisterer: reg, + prefix: prefix, + } +} + +type wrappingRegisterer struct { + wrappedRegisterer Registerer + prefix string + labels Labels +} + +func (r *wrappingRegisterer) Register(c Collector) error { + return r.wrappedRegisterer.Register(&wrappingCollector{ + wrappedCollector: c, + prefix: r.prefix, + labels: r.labels, + }) +} + +func (r *wrappingRegisterer) MustRegister(cs ...Collector) { + for _, c := range cs { + if err := r.Register(c); err != nil { + panic(err) + } + } +} + +func (r *wrappingRegisterer) Unregister(c Collector) bool { + return r.wrappedRegisterer.Unregister(&wrappingCollector{ + wrappedCollector: c, + prefix: r.prefix, + labels: r.labels, + }) +} + +type wrappingCollector struct { + wrappedCollector Collector + prefix string + labels Labels +} + +func (c *wrappingCollector) Collect(ch chan<- Metric) { + wrappedCh := make(chan Metric) + go func() { + c.wrappedCollector.Collect(wrappedCh) + close(wrappedCh) + }() + for m := range wrappedCh { + ch <- &wrappingMetric{ + wrappedMetric: m, + prefix: c.prefix, + labels: c.labels, + } + } +} + +func (c *wrappingCollector) Describe(ch chan<- *Desc) { + wrappedCh := make(chan *Desc) + go func() { + c.wrappedCollector.Describe(wrappedCh) + close(wrappedCh) + }() + for desc := range wrappedCh { + ch <- wrapDesc(desc, c.prefix, c.labels) + } +} + +type wrappingMetric struct { + wrappedMetric Metric + prefix string + labels Labels +} + +func (m *wrappingMetric) Desc() *Desc { + return wrapDesc(m.wrappedMetric.Desc(), m.prefix, m.labels) +} + +func (m *wrappingMetric) Write(out *dto.Metric) error { + if err := m.wrappedMetric.Write(out); err != nil { + return err + } + if len(m.labels) == 0 { + // No wrapping labels. + return nil + } + for ln, lv := range m.labels { + out.Label = append(out.Label, &dto.LabelPair{ + Name: proto.String(ln), + Value: proto.String(lv), + }) + } + sort.Sort(labelPairSorter(out.Label)) + return nil +} + +func wrapDesc(desc *Desc, prefix string, labels Labels) *Desc { + constLabels := Labels{} + for _, lp := range desc.constLabelPairs { + constLabels[*lp.Name] = *lp.Value + } + for ln, lv := range labels { + if _, alreadyUsed := constLabels[ln]; alreadyUsed { + return &Desc{ + fqName: desc.fqName, + help: desc.help, + variableLabels: desc.variableLabels, + constLabelPairs: desc.constLabelPairs, + err: fmt.Errorf("attempted wrapping with already existing label name %q", ln), + } + } + constLabels[ln] = lv + } + // NewDesc will do remaining validations. + newDesc := NewDesc(prefix+desc.fqName, desc.help, desc.variableLabels, constLabels) + // Propagate errors if there was any. This will override any errer + // created by NewDesc above, i.e. earlier errors get precedence. + if desc.err != nil { + newDesc.err = desc.err + } + return newDesc +} diff --git a/vendor/golang.org/x/lint/.travis.yml b/vendor/golang.org/x/lint/.travis.yml new file mode 100644 index 00000000000..50553ebd004 --- /dev/null +++ b/vendor/golang.org/x/lint/.travis.yml @@ -0,0 +1,19 @@ +sudo: false +language: go +go: + - 1.10.x + - 1.11.x + - master + +go_import_path: golang.org/x/lint + +install: + - go get -t -v ./... + +script: + - go test -v -race ./... + +matrix: + allow_failures: + - go: master + fast_finish: true diff --git a/vendor/golang.org/x/lint/BUILD b/vendor/golang.org/x/lint/BUILD new file mode 100644 index 00000000000..d81a1c029d5 --- /dev/null +++ b/vendor/golang.org/x/lint/BUILD @@ -0,0 +1,30 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = ["lint.go"], + importmap = "k8s.io/kubernetes/vendor/golang.org/x/lint", + importpath = "golang.org/x/lint", + visibility = ["//visibility:public"], + deps = [ + "//vendor/golang.org/x/tools/go/ast/astutil:go_default_library", + "//vendor/golang.org/x/tools/go/gcexportdata:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [ + ":package-srcs", + "//vendor/golang.org/x/lint/golint:all-srcs", + ], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/vendor/golang.org/x/lint/CONTRIBUTING.md b/vendor/golang.org/x/lint/CONTRIBUTING.md new file mode 100644 index 00000000000..1fadda62d2f --- /dev/null +++ b/vendor/golang.org/x/lint/CONTRIBUTING.md @@ -0,0 +1,15 @@ +# Contributing to Golint + +## Before filing an issue: + +### Are you having trouble building golint? + +Check you have the latest version of its dependencies. Run +``` +go get -u golang.org/x/lint/golint +``` +If you still have problems, consider searching for existing issues before filing a new issue. + +## Before sending a pull request: + +Have you understood the purpose of golint? Make sure to carefully read `README`. diff --git a/vendor/golang.org/x/lint/LICENSE b/vendor/golang.org/x/lint/LICENSE new file mode 100644 index 00000000000..65d761bc9f2 --- /dev/null +++ b/vendor/golang.org/x/lint/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2013 The Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/golang.org/x/lint/README.md b/vendor/golang.org/x/lint/README.md new file mode 100644 index 00000000000..b12ba6389e6 --- /dev/null +++ b/vendor/golang.org/x/lint/README.md @@ -0,0 +1,86 @@ +Golint is a linter for Go source code. + +[![Build Status](https://travis-ci.org/golang/lint.svg?branch=master)](https://travis-ci.org/golang/lint) + +## Installation + +Golint requires a +[supported release of Go](https://golang.org/doc/devel/release.html#policy). + + go get -u golang.org/x/lint/golint + +## Usage + +Invoke `golint` with one or more filenames, directories, or packages named +by its import path. Golint uses the same +[import path syntax](https://golang.org/cmd/go/#hdr-Import_path_syntax) as +the `go` command and therefore +also supports relative import paths like `./...`. Additionally the `...` +wildcard can be used as suffix on relative and absolute file paths to recurse +into them. + +The output of this tool is a list of suggestions in Vim quickfix format, +which is accepted by lots of different editors. + +## Purpose + +Golint differs from gofmt. Gofmt reformats Go source code, whereas +golint prints out style mistakes. + +Golint differs from govet. Govet is concerned with correctness, whereas +golint is concerned with coding style. Golint is in use at Google, and it +seeks to match the accepted style of the open source Go project. + +The suggestions made by golint are exactly that: suggestions. +Golint is not perfect, and has both false positives and false negatives. +Do not treat its output as a gold standard. We will not be adding pragmas +or other knobs to suppress specific warnings, so do not expect or require +code to be completely "lint-free". +In short, this tool is not, and will never be, trustworthy enough for its +suggestions to be enforced automatically, for example as part of a build process. +Golint makes suggestions for many of the mechanically checkable items listed in +[Effective Go](https://golang.org/doc/effective_go.html) and the +[CodeReviewComments wiki page](https://golang.org/wiki/CodeReviewComments). + +## Scope + +Golint is meant to carry out the stylistic conventions put forth in +[Effective Go](https://golang.org/doc/effective_go.html) and +[CodeReviewComments](https://golang.org/wiki/CodeReviewComments). +Changes that are not aligned with those documents will not be considered. + +## Contributions + +Contributions to this project are welcome provided they are [in scope](#scope), +though please send mail before starting work on anything major. +Contributors retain their copyright, so we need you to fill out +[a short form](https://developers.google.com/open-source/cla/individual) +before we can accept your contribution. + +## Vim + +Add this to your ~/.vimrc: + + set rtp+=$GOPATH/src/golang.org/x/lint/misc/vim + +If you have multiple entries in your GOPATH, replace `$GOPATH` with the right value. + +Running `:Lint` will run golint on the current file and populate the quickfix list. + +Optionally, add this to your `~/.vimrc` to automatically run `golint` on `:w` + + autocmd BufWritePost,FileWritePost *.go execute 'Lint' | cwindow + + +## Emacs + +Add this to your `.emacs` file: + + (add-to-list 'load-path (concat (getenv "GOPATH") "/src/github.com/golang/lint/misc/emacs")) + (require 'golint) + +If you have multiple entries in your GOPATH, replace `$GOPATH` with the right value. + +Running M-x golint will run golint on the current file. + +For more usage, see [Compilation-Mode](http://www.gnu.org/software/emacs/manual/html_node/emacs/Compilation-Mode.html). diff --git a/pkg/cloudprovider/providers/gce/cloud/gen/BUILD b/vendor/golang.org/x/lint/golint/BUILD similarity index 64% rename from pkg/cloudprovider/providers/gce/cloud/gen/BUILD rename to vendor/golang.org/x/lint/golint/BUILD index b51f9c80db1..28d1384cca3 100644 --- a/pkg/cloudprovider/providers/gce/cloud/gen/BUILD +++ b/vendor/golang.org/x/lint/golint/BUILD @@ -2,14 +2,19 @@ load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library") go_library( name = "go_default_library", - srcs = ["main.go"], - importpath = "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/gen", + srcs = [ + "golint.go", + "import.go", + "importcomment.go", + ], + importmap = "k8s.io/kubernetes/vendor/golang.org/x/lint/golint", + importpath = "golang.org/x/lint/golint", visibility = ["//visibility:private"], - deps = ["//pkg/cloudprovider/providers/gce/cloud/meta:go_default_library"], + deps = ["//vendor/golang.org/x/lint:go_default_library"], ) go_binary( - name = "gen", + name = "golint", embed = [":go_default_library"], visibility = ["//visibility:public"], ) diff --git a/vendor/golang.org/x/lint/golint/golint.go b/vendor/golang.org/x/lint/golint/golint.go new file mode 100644 index 00000000000..ac024b6d26f --- /dev/null +++ b/vendor/golang.org/x/lint/golint/golint.go @@ -0,0 +1,159 @@ +// Copyright (c) 2013 The Go Authors. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file or at +// https://developers.google.com/open-source/licenses/bsd. + +// golint lints the Go source files named on its command line. +package main + +import ( + "flag" + "fmt" + "go/build" + "io/ioutil" + "os" + "path/filepath" + "strings" + + "golang.org/x/lint" +) + +var ( + minConfidence = flag.Float64("min_confidence", 0.8, "minimum confidence of a problem to print it") + setExitStatus = flag.Bool("set_exit_status", false, "set exit status to 1 if any issues are found") + suggestions int +) + +func usage() { + fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0]) + fmt.Fprintf(os.Stderr, "\tgolint [flags] # runs on package in current directory\n") + fmt.Fprintf(os.Stderr, "\tgolint [flags] [packages]\n") + fmt.Fprintf(os.Stderr, "\tgolint [flags] [directories] # where a '/...' suffix includes all sub-directories\n") + fmt.Fprintf(os.Stderr, "\tgolint [flags] [files] # all must belong to a single package\n") + fmt.Fprintf(os.Stderr, "Flags:\n") + flag.PrintDefaults() +} + +func main() { + flag.Usage = usage + flag.Parse() + + if flag.NArg() == 0 { + lintDir(".") + } else { + // dirsRun, filesRun, and pkgsRun indicate whether golint is applied to + // directory, file or package targets. The distinction affects which + // checks are run. It is no valid to mix target types. + var dirsRun, filesRun, pkgsRun int + var args []string + for _, arg := range flag.Args() { + if strings.HasSuffix(arg, "/...") && isDir(arg[:len(arg)-len("/...")]) { + dirsRun = 1 + for _, dirname := range allPackagesInFS(arg) { + args = append(args, dirname) + } + } else if isDir(arg) { + dirsRun = 1 + args = append(args, arg) + } else if exists(arg) { + filesRun = 1 + args = append(args, arg) + } else { + pkgsRun = 1 + args = append(args, arg) + } + } + + if dirsRun+filesRun+pkgsRun != 1 { + usage() + os.Exit(2) + } + switch { + case dirsRun == 1: + for _, dir := range args { + lintDir(dir) + } + case filesRun == 1: + lintFiles(args...) + case pkgsRun == 1: + for _, pkg := range importPaths(args) { + lintPackage(pkg) + } + } + } + + if *setExitStatus && suggestions > 0 { + fmt.Fprintf(os.Stderr, "Found %d lint suggestions; failing.\n", suggestions) + os.Exit(1) + } +} + +func isDir(filename string) bool { + fi, err := os.Stat(filename) + return err == nil && fi.IsDir() +} + +func exists(filename string) bool { + _, err := os.Stat(filename) + return err == nil +} + +func lintFiles(filenames ...string) { + files := make(map[string][]byte) + for _, filename := range filenames { + src, err := ioutil.ReadFile(filename) + if err != nil { + fmt.Fprintln(os.Stderr, err) + continue + } + files[filename] = src + } + + l := new(lint.Linter) + ps, err := l.LintFiles(files) + if err != nil { + fmt.Fprintf(os.Stderr, "%v\n", err) + return + } + for _, p := range ps { + if p.Confidence >= *minConfidence { + fmt.Printf("%v: %s\n", p.Position, p.Text) + suggestions++ + } + } +} + +func lintDir(dirname string) { + pkg, err := build.ImportDir(dirname, 0) + lintImportedPackage(pkg, err) +} + +func lintPackage(pkgname string) { + pkg, err := build.Import(pkgname, ".", 0) + lintImportedPackage(pkg, err) +} + +func lintImportedPackage(pkg *build.Package, err error) { + if err != nil { + if _, nogo := err.(*build.NoGoError); nogo { + // Don't complain if the failure is due to no Go source files. + return + } + fmt.Fprintln(os.Stderr, err) + return + } + + var files []string + files = append(files, pkg.GoFiles...) + files = append(files, pkg.CgoFiles...) + files = append(files, pkg.TestGoFiles...) + if pkg.Dir != "." { + for i, f := range files { + files[i] = filepath.Join(pkg.Dir, f) + } + } + // TODO(dsymonds): Do foo_test too (pkg.XTestGoFiles) + + lintFiles(files...) +} diff --git a/vendor/golang.org/x/lint/golint/import.go b/vendor/golang.org/x/lint/golint/import.go new file mode 100644 index 00000000000..2ba9dea7792 --- /dev/null +++ b/vendor/golang.org/x/lint/golint/import.go @@ -0,0 +1,309 @@ +package main + +/* + +This file holds a direct copy of the import path matching code of +https://github.com/golang/go/blob/master/src/cmd/go/main.go. It can be +replaced when https://golang.org/issue/8768 is resolved. + +It has been updated to follow upstream changes in a few ways. + +*/ + +import ( + "fmt" + "go/build" + "log" + "os" + "path" + "path/filepath" + "regexp" + "runtime" + "strings" +) + +var ( + buildContext = build.Default + goroot = filepath.Clean(runtime.GOROOT()) + gorootSrc = filepath.Join(goroot, "src") +) + +// importPathsNoDotExpansion returns the import paths to use for the given +// command line, but it does no ... expansion. +func importPathsNoDotExpansion(args []string) []string { + if len(args) == 0 { + return []string{"."} + } + var out []string + for _, a := range args { + // Arguments are supposed to be import paths, but + // as a courtesy to Windows developers, rewrite \ to / + // in command-line arguments. Handles .\... and so on. + if filepath.Separator == '\\' { + a = strings.Replace(a, `\`, `/`, -1) + } + + // Put argument in canonical form, but preserve leading ./. + if strings.HasPrefix(a, "./") { + a = "./" + path.Clean(a) + if a == "./." { + a = "." + } + } else { + a = path.Clean(a) + } + if a == "all" || a == "std" { + out = append(out, allPackages(a)...) + continue + } + out = append(out, a) + } + return out +} + +// importPaths returns the import paths to use for the given command line. +func importPaths(args []string) []string { + args = importPathsNoDotExpansion(args) + var out []string + for _, a := range args { + if strings.Contains(a, "...") { + if build.IsLocalImport(a) { + out = append(out, allPackagesInFS(a)...) + } else { + out = append(out, allPackages(a)...) + } + continue + } + out = append(out, a) + } + return out +} + +// matchPattern(pattern)(name) reports whether +// name matches pattern. Pattern is a limited glob +// pattern in which '...' means 'any string' and there +// is no other special syntax. +func matchPattern(pattern string) func(name string) bool { + re := regexp.QuoteMeta(pattern) + re = strings.Replace(re, `\.\.\.`, `.*`, -1) + // Special case: foo/... matches foo too. + if strings.HasSuffix(re, `/.*`) { + re = re[:len(re)-len(`/.*`)] + `(/.*)?` + } + reg := regexp.MustCompile(`^` + re + `$`) + return func(name string) bool { + return reg.MatchString(name) + } +} + +// hasPathPrefix reports whether the path s begins with the +// elements in prefix. +func hasPathPrefix(s, prefix string) bool { + switch { + default: + return false + case len(s) == len(prefix): + return s == prefix + case len(s) > len(prefix): + if prefix != "" && prefix[len(prefix)-1] == '/' { + return strings.HasPrefix(s, prefix) + } + return s[len(prefix)] == '/' && s[:len(prefix)] == prefix + } +} + +// treeCanMatchPattern(pattern)(name) reports whether +// name or children of name can possibly match pattern. +// Pattern is the same limited glob accepted by matchPattern. +func treeCanMatchPattern(pattern string) func(name string) bool { + wildCard := false + if i := strings.Index(pattern, "..."); i >= 0 { + wildCard = true + pattern = pattern[:i] + } + return func(name string) bool { + return len(name) <= len(pattern) && hasPathPrefix(pattern, name) || + wildCard && strings.HasPrefix(name, pattern) + } +} + +// allPackages returns all the packages that can be found +// under the $GOPATH directories and $GOROOT matching pattern. +// The pattern is either "all" (all packages), "std" (standard packages) +// or a path including "...". +func allPackages(pattern string) []string { + pkgs := matchPackages(pattern) + if len(pkgs) == 0 { + fmt.Fprintf(os.Stderr, "warning: %q matched no packages\n", pattern) + } + return pkgs +} + +func matchPackages(pattern string) []string { + match := func(string) bool { return true } + treeCanMatch := func(string) bool { return true } + if pattern != "all" && pattern != "std" { + match = matchPattern(pattern) + treeCanMatch = treeCanMatchPattern(pattern) + } + + have := map[string]bool{ + "builtin": true, // ignore pseudo-package that exists only for documentation + } + if !buildContext.CgoEnabled { + have["runtime/cgo"] = true // ignore during walk + } + var pkgs []string + + // Commands + cmd := filepath.Join(goroot, "src/cmd") + string(filepath.Separator) + filepath.Walk(cmd, func(path string, fi os.FileInfo, err error) error { + if err != nil || !fi.IsDir() || path == cmd { + return nil + } + name := path[len(cmd):] + if !treeCanMatch(name) { + return filepath.SkipDir + } + // Commands are all in cmd/, not in subdirectories. + if strings.Contains(name, string(filepath.Separator)) { + return filepath.SkipDir + } + + // We use, e.g., cmd/gofmt as the pseudo import path for gofmt. + name = "cmd/" + name + if have[name] { + return nil + } + have[name] = true + if !match(name) { + return nil + } + _, err = buildContext.ImportDir(path, 0) + if err != nil { + if _, noGo := err.(*build.NoGoError); !noGo { + log.Print(err) + } + return nil + } + pkgs = append(pkgs, name) + return nil + }) + + for _, src := range buildContext.SrcDirs() { + if (pattern == "std" || pattern == "cmd") && src != gorootSrc { + continue + } + src = filepath.Clean(src) + string(filepath.Separator) + root := src + if pattern == "cmd" { + root += "cmd" + string(filepath.Separator) + } + filepath.Walk(root, func(path string, fi os.FileInfo, err error) error { + if err != nil || !fi.IsDir() || path == src { + return nil + } + + // Avoid .foo, _foo, and testdata directory trees. + _, elem := filepath.Split(path) + if strings.HasPrefix(elem, ".") || strings.HasPrefix(elem, "_") || elem == "testdata" { + return filepath.SkipDir + } + + name := filepath.ToSlash(path[len(src):]) + if pattern == "std" && (strings.Contains(name, ".") || name == "cmd") { + // The name "std" is only the standard library. + // If the name is cmd, it's the root of the command tree. + return filepath.SkipDir + } + if !treeCanMatch(name) { + return filepath.SkipDir + } + if have[name] { + return nil + } + have[name] = true + if !match(name) { + return nil + } + _, err = buildContext.ImportDir(path, 0) + if err != nil { + if _, noGo := err.(*build.NoGoError); noGo { + return nil + } + } + pkgs = append(pkgs, name) + return nil + }) + } + return pkgs +} + +// allPackagesInFS is like allPackages but is passed a pattern +// beginning ./ or ../, meaning it should scan the tree rooted +// at the given directory. There are ... in the pattern too. +func allPackagesInFS(pattern string) []string { + pkgs := matchPackagesInFS(pattern) + if len(pkgs) == 0 { + fmt.Fprintf(os.Stderr, "warning: %q matched no packages\n", pattern) + } + return pkgs +} + +func matchPackagesInFS(pattern string) []string { + // Find directory to begin the scan. + // Could be smarter but this one optimization + // is enough for now, since ... is usually at the + // end of a path. + i := strings.Index(pattern, "...") + dir, _ := path.Split(pattern[:i]) + + // pattern begins with ./ or ../. + // path.Clean will discard the ./ but not the ../. + // We need to preserve the ./ for pattern matching + // and in the returned import paths. + prefix := "" + if strings.HasPrefix(pattern, "./") { + prefix = "./" + } + match := matchPattern(pattern) + + var pkgs []string + filepath.Walk(dir, func(path string, fi os.FileInfo, err error) error { + if err != nil || !fi.IsDir() { + return nil + } + if path == dir { + // filepath.Walk starts at dir and recurses. For the recursive case, + // the path is the result of filepath.Join, which calls filepath.Clean. + // The initial case is not Cleaned, though, so we do this explicitly. + // + // This converts a path like "./io/" to "io". Without this step, running + // "cd $GOROOT/src/pkg; go list ./io/..." would incorrectly skip the io + // package, because prepending the prefix "./" to the unclean path would + // result in "././io", and match("././io") returns false. + path = filepath.Clean(path) + } + + // Avoid .foo, _foo, and testdata directory trees, but do not avoid "." or "..". + _, elem := filepath.Split(path) + dot := strings.HasPrefix(elem, ".") && elem != "." && elem != ".." + if dot || strings.HasPrefix(elem, "_") || elem == "testdata" { + return filepath.SkipDir + } + + name := prefix + filepath.ToSlash(path) + if !match(name) { + return nil + } + if _, err = build.ImportDir(path, 0); err != nil { + if _, noGo := err.(*build.NoGoError); !noGo { + log.Print(err) + } + return nil + } + pkgs = append(pkgs, name) + return nil + }) + return pkgs +} diff --git a/vendor/golang.org/x/lint/golint/importcomment.go b/vendor/golang.org/x/lint/golint/importcomment.go new file mode 100644 index 00000000000..f1dce770612 --- /dev/null +++ b/vendor/golang.org/x/lint/golint/importcomment.go @@ -0,0 +1,13 @@ +// Copyright (c) 2018 The Go Authors. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file or at +// https://developers.google.com/open-source/licenses/bsd. + +// +build go1.12 + +// Require use of the correct import path only for Go 1.12+ users, so +// any breakages coincide with people updating their CI configs or +// whatnot. + +package main diff --git a/vendor/golang.org/x/lint/lint.go b/vendor/golang.org/x/lint/lint.go new file mode 100644 index 00000000000..07036ed356f --- /dev/null +++ b/vendor/golang.org/x/lint/lint.go @@ -0,0 +1,1693 @@ +// Copyright (c) 2013 The Go Authors. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file or at +// https://developers.google.com/open-source/licenses/bsd. + +// Package lint contains a linter for Go source code. +package lint + +import ( + "bufio" + "bytes" + "fmt" + "go/ast" + "go/parser" + "go/printer" + "go/token" + "go/types" + "regexp" + "sort" + "strconv" + "strings" + "unicode" + "unicode/utf8" + + "golang.org/x/tools/go/ast/astutil" + "golang.org/x/tools/go/gcexportdata" +) + +const styleGuideBase = "https://golang.org/wiki/CodeReviewComments" + +// A Linter lints Go source code. +type Linter struct { +} + +// Problem represents a problem in some source code. +type Problem struct { + Position token.Position // position in source file + Text string // the prose that describes the problem + Link string // (optional) the link to the style guide for the problem + Confidence float64 // a value in (0,1] estimating the confidence in this problem's correctness + LineText string // the source line + Category string // a short name for the general category of the problem + + // If the problem has a suggested fix (the minority case), + // ReplacementLine is a full replacement for the relevant line of the source file. + ReplacementLine string +} + +func (p *Problem) String() string { + if p.Link != "" { + return p.Text + "\n\n" + p.Link + } + return p.Text +} + +type byPosition []Problem + +func (p byPosition) Len() int { return len(p) } +func (p byPosition) Swap(i, j int) { p[i], p[j] = p[j], p[i] } + +func (p byPosition) Less(i, j int) bool { + pi, pj := p[i].Position, p[j].Position + + if pi.Filename != pj.Filename { + return pi.Filename < pj.Filename + } + if pi.Line != pj.Line { + return pi.Line < pj.Line + } + if pi.Column != pj.Column { + return pi.Column < pj.Column + } + + return p[i].Text < p[j].Text +} + +// Lint lints src. +func (l *Linter) Lint(filename string, src []byte) ([]Problem, error) { + return l.LintFiles(map[string][]byte{filename: src}) +} + +// LintFiles lints a set of files of a single package. +// The argument is a map of filename to source. +func (l *Linter) LintFiles(files map[string][]byte) ([]Problem, error) { + pkg := &pkg{ + fset: token.NewFileSet(), + files: make(map[string]*file), + } + var pkgName string + for filename, src := range files { + if isGenerated(src) { + continue // See issue #239 + } + f, err := parser.ParseFile(pkg.fset, filename, src, parser.ParseComments) + if err != nil { + return nil, err + } + if pkgName == "" { + pkgName = f.Name.Name + } else if f.Name.Name != pkgName { + return nil, fmt.Errorf("%s is in package %s, not %s", filename, f.Name.Name, pkgName) + } + pkg.files[filename] = &file{ + pkg: pkg, + f: f, + fset: pkg.fset, + src: src, + filename: filename, + } + } + if len(pkg.files) == 0 { + return nil, nil + } + return pkg.lint(), nil +} + +var ( + genHdr = []byte("// Code generated ") + genFtr = []byte(" DO NOT EDIT.") +) + +// isGenerated reports whether the source file is generated code +// according the rules from https://golang.org/s/generatedcode. +func isGenerated(src []byte) bool { + sc := bufio.NewScanner(bytes.NewReader(src)) + for sc.Scan() { + b := sc.Bytes() + if bytes.HasPrefix(b, genHdr) && bytes.HasSuffix(b, genFtr) && len(b) >= len(genHdr)+len(genFtr) { + return true + } + } + return false +} + +// pkg represents a package being linted. +type pkg struct { + fset *token.FileSet + files map[string]*file + + typesPkg *types.Package + typesInfo *types.Info + + // sortable is the set of types in the package that implement sort.Interface. + sortable map[string]bool + // main is whether this is a "main" package. + main bool + + problems []Problem +} + +func (p *pkg) lint() []Problem { + if err := p.typeCheck(); err != nil { + /* TODO(dsymonds): Consider reporting these errors when golint operates on entire packages. + if e, ok := err.(types.Error); ok { + pos := p.fset.Position(e.Pos) + conf := 1.0 + if strings.Contains(e.Msg, "can't find import: ") { + // Golint is probably being run in a context that doesn't support + // typechecking (e.g. package files aren't found), so don't warn about it. + conf = 0 + } + if conf > 0 { + p.errorfAt(pos, conf, category("typechecking"), e.Msg) + } + + // TODO(dsymonds): Abort if !e.Soft? + } + */ + } + + p.scanSortable() + p.main = p.isMain() + + for _, f := range p.files { + f.lint() + } + + sort.Sort(byPosition(p.problems)) + + return p.problems +} + +// file represents a file being linted. +type file struct { + pkg *pkg + f *ast.File + fset *token.FileSet + src []byte + filename string +} + +func (f *file) isTest() bool { return strings.HasSuffix(f.filename, "_test.go") } + +func (f *file) lint() { + f.lintPackageComment() + f.lintImports() + f.lintBlankImports() + f.lintExported() + f.lintNames() + f.lintVarDecls() + f.lintElses() + f.lintRanges() + f.lintErrorf() + f.lintErrors() + f.lintErrorStrings() + f.lintReceiverNames() + f.lintIncDec() + f.lintErrorReturn() + f.lintUnexportedReturn() + f.lintTimeNames() + f.lintContextKeyTypes() + f.lintContextArgs() +} + +type link string +type category string + +// The variadic arguments may start with link and category types, +// and must end with a format string and any arguments. +// It returns the new Problem. +func (f *file) errorf(n ast.Node, confidence float64, args ...interface{}) *Problem { + pos := f.fset.Position(n.Pos()) + if pos.Filename == "" { + pos.Filename = f.filename + } + return f.pkg.errorfAt(pos, confidence, args...) +} + +func (p *pkg) errorfAt(pos token.Position, confidence float64, args ...interface{}) *Problem { + problem := Problem{ + Position: pos, + Confidence: confidence, + } + if pos.Filename != "" { + // The file might not exist in our mapping if a //line directive was encountered. + if f, ok := p.files[pos.Filename]; ok { + problem.LineText = srcLine(f.src, pos) + } + } + +argLoop: + for len(args) > 1 { // always leave at least the format string in args + switch v := args[0].(type) { + case link: + problem.Link = string(v) + case category: + problem.Category = string(v) + default: + break argLoop + } + args = args[1:] + } + + problem.Text = fmt.Sprintf(args[0].(string), args[1:]...) + + p.problems = append(p.problems, problem) + return &p.problems[len(p.problems)-1] +} + +var newImporter = func(fset *token.FileSet) types.ImporterFrom { + return gcexportdata.NewImporter(fset, make(map[string]*types.Package)) +} + +func (p *pkg) typeCheck() error { + config := &types.Config{ + // By setting a no-op error reporter, the type checker does as much work as possible. + Error: func(error) {}, + Importer: newImporter(p.fset), + } + info := &types.Info{ + Types: make(map[ast.Expr]types.TypeAndValue), + Defs: make(map[*ast.Ident]types.Object), + Uses: make(map[*ast.Ident]types.Object), + Scopes: make(map[ast.Node]*types.Scope), + } + var anyFile *file + var astFiles []*ast.File + for _, f := range p.files { + anyFile = f + astFiles = append(astFiles, f.f) + } + pkg, err := config.Check(anyFile.f.Name.Name, p.fset, astFiles, info) + // Remember the typechecking info, even if config.Check failed, + // since we will get partial information. + p.typesPkg = pkg + p.typesInfo = info + return err +} + +func (p *pkg) typeOf(expr ast.Expr) types.Type { + if p.typesInfo == nil { + return nil + } + return p.typesInfo.TypeOf(expr) +} + +func (p *pkg) isNamedType(typ types.Type, importPath, name string) bool { + n, ok := typ.(*types.Named) + if !ok { + return false + } + tn := n.Obj() + return tn != nil && tn.Pkg() != nil && tn.Pkg().Path() == importPath && tn.Name() == name +} + +// scopeOf returns the tightest scope encompassing id. +func (p *pkg) scopeOf(id *ast.Ident) *types.Scope { + var scope *types.Scope + if obj := p.typesInfo.ObjectOf(id); obj != nil { + scope = obj.Parent() + } + if scope == p.typesPkg.Scope() { + // We were given a top-level identifier. + // Use the file-level scope instead of the package-level scope. + pos := id.Pos() + for _, f := range p.files { + if f.f.Pos() <= pos && pos < f.f.End() { + scope = p.typesInfo.Scopes[f.f] + break + } + } + } + return scope +} + +func (p *pkg) scanSortable() { + p.sortable = make(map[string]bool) + + // bitfield for which methods exist on each type. + const ( + Len = 1 << iota + Less + Swap + ) + nmap := map[string]int{"Len": Len, "Less": Less, "Swap": Swap} + has := make(map[string]int) + for _, f := range p.files { + f.walk(func(n ast.Node) bool { + fn, ok := n.(*ast.FuncDecl) + if !ok || fn.Recv == nil || len(fn.Recv.List) == 0 { + return true + } + // TODO(dsymonds): We could check the signature to be more precise. + recv := receiverType(fn) + if i, ok := nmap[fn.Name.Name]; ok { + has[recv] |= i + } + return false + }) + } + for typ, ms := range has { + if ms == Len|Less|Swap { + p.sortable[typ] = true + } + } +} + +func (p *pkg) isMain() bool { + for _, f := range p.files { + if f.isMain() { + return true + } + } + return false +} + +func (f *file) isMain() bool { + if f.f.Name.Name == "main" { + return true + } + return false +} + +// lintPackageComment checks package comments. It complains if +// there is no package comment, or if it is not of the right form. +// This has a notable false positive in that a package comment +// could rightfully appear in a different file of the same package, +// but that's not easy to fix since this linter is file-oriented. +func (f *file) lintPackageComment() { + if f.isTest() { + return + } + + const ref = styleGuideBase + "#package-comments" + prefix := "Package " + f.f.Name.Name + " " + + // Look for a detached package comment. + // First, scan for the last comment that occurs before the "package" keyword. + var lastCG *ast.CommentGroup + for _, cg := range f.f.Comments { + if cg.Pos() > f.f.Package { + // Gone past "package" keyword. + break + } + lastCG = cg + } + if lastCG != nil && strings.HasPrefix(lastCG.Text(), prefix) { + endPos := f.fset.Position(lastCG.End()) + pkgPos := f.fset.Position(f.f.Package) + if endPos.Line+1 < pkgPos.Line { + // There isn't a great place to anchor this error; + // the start of the blank lines between the doc and the package statement + // is at least pointing at the location of the problem. + pos := token.Position{ + Filename: endPos.Filename, + // Offset not set; it is non-trivial, and doesn't appear to be needed. + Line: endPos.Line + 1, + Column: 1, + } + f.pkg.errorfAt(pos, 0.9, link(ref), category("comments"), "package comment is detached; there should be no blank lines between it and the package statement") + return + } + } + + if f.f.Doc == nil { + f.errorf(f.f, 0.2, link(ref), category("comments"), "should have a package comment, unless it's in another file for this package") + return + } + s := f.f.Doc.Text() + if ts := strings.TrimLeft(s, " \t"); ts != s { + f.errorf(f.f.Doc, 1, link(ref), category("comments"), "package comment should not have leading space") + s = ts + } + // Only non-main packages need to keep to this form. + if !f.pkg.main && !strings.HasPrefix(s, prefix) { + f.errorf(f.f.Doc, 1, link(ref), category("comments"), `package comment should be of the form "%s..."`, prefix) + } +} + +// lintBlankImports complains if a non-main package has blank imports that are +// not documented. +func (f *file) lintBlankImports() { + // In package main and in tests, we don't complain about blank imports. + if f.pkg.main || f.isTest() { + return + } + + // The first element of each contiguous group of blank imports should have + // an explanatory comment of some kind. + for i, imp := range f.f.Imports { + pos := f.fset.Position(imp.Pos()) + + if !isBlank(imp.Name) { + continue // Ignore non-blank imports. + } + if i > 0 { + prev := f.f.Imports[i-1] + prevPos := f.fset.Position(prev.Pos()) + if isBlank(prev.Name) && prevPos.Line+1 == pos.Line { + continue // A subsequent blank in a group. + } + } + + // This is the first blank import of a group. + if imp.Doc == nil && imp.Comment == nil { + ref := "" + f.errorf(imp, 1, link(ref), category("imports"), "a blank import should be only in a main or test package, or have a comment justifying it") + } + } +} + +// lintImports examines import blocks. +func (f *file) lintImports() { + for i, is := range f.f.Imports { + _ = i + if is.Name != nil && is.Name.Name == "." && !f.isTest() { + f.errorf(is, 1, link(styleGuideBase+"#import-dot"), category("imports"), "should not use dot imports") + } + + } +} + +const docCommentsLink = styleGuideBase + "#doc-comments" + +// lintExported examines the exported names. +// It complains if any required doc comments are missing, +// or if they are not of the right form. The exact rules are in +// lintFuncDoc, lintTypeDoc and lintValueSpecDoc; this function +// also tracks the GenDecl structure being traversed to permit +// doc comments for constants to be on top of the const block. +// It also complains if the names stutter when combined with +// the package name. +func (f *file) lintExported() { + if f.isTest() { + return + } + + var lastGen *ast.GenDecl // last GenDecl entered. + + // Set of GenDecls that have already had missing comments flagged. + genDeclMissingComments := make(map[*ast.GenDecl]bool) + + f.walk(func(node ast.Node) bool { + switch v := node.(type) { + case *ast.GenDecl: + if v.Tok == token.IMPORT { + return false + } + // token.CONST, token.TYPE or token.VAR + lastGen = v + return true + case *ast.FuncDecl: + f.lintFuncDoc(v) + if v.Recv == nil { + // Only check for stutter on functions, not methods. + // Method names are not used package-qualified. + f.checkStutter(v.Name, "func") + } + // Don't proceed inside funcs. + return false + case *ast.TypeSpec: + // inside a GenDecl, which usually has the doc + doc := v.Doc + if doc == nil { + doc = lastGen.Doc + } + f.lintTypeDoc(v, doc) + f.checkStutter(v.Name, "type") + // Don't proceed inside types. + return false + case *ast.ValueSpec: + f.lintValueSpecDoc(v, lastGen, genDeclMissingComments) + return false + } + return true + }) +} + +var ( + allCapsRE = regexp.MustCompile(`^[A-Z0-9_]+$`) + anyCapsRE = regexp.MustCompile(`[A-Z]`) +) + +// knownNameExceptions is a set of names that are known to be exempt from naming checks. +// This is usually because they are constrained by having to match names in the +// standard library. +var knownNameExceptions = map[string]bool{ + "LastInsertId": true, // must match database/sql + "kWh": true, +} + +func isInTopLevel(f *ast.File, ident *ast.Ident) bool { + path, _ := astutil.PathEnclosingInterval(f, ident.Pos(), ident.End()) + for _, f := range path { + switch f.(type) { + case *ast.File, *ast.GenDecl, *ast.ValueSpec, *ast.Ident: + continue + } + return false + } + return true +} + +// lintNames examines all names in the file. +// It complains if any use underscores or incorrect known initialisms. +func (f *file) lintNames() { + // Package names need slightly different handling than other names. + if strings.Contains(f.f.Name.Name, "_") && !strings.HasSuffix(f.f.Name.Name, "_test") { + f.errorf(f.f, 1, link("http://golang.org/doc/effective_go.html#package-names"), category("naming"), "don't use an underscore in package name") + } + if anyCapsRE.MatchString(f.f.Name.Name) { + f.errorf(f.f, 1, link("http://golang.org/doc/effective_go.html#package-names"), category("mixed-caps"), "don't use MixedCaps in package name; %s should be %s", f.f.Name.Name, strings.ToLower(f.f.Name.Name)) + } + + check := func(id *ast.Ident, thing string) { + if id.Name == "_" { + return + } + if knownNameExceptions[id.Name] { + return + } + + // Handle two common styles from other languages that don't belong in Go. + if len(id.Name) >= 5 && allCapsRE.MatchString(id.Name) && strings.Contains(id.Name, "_") { + capCount := 0 + for _, c := range id.Name { + if 'A' <= c && c <= 'Z' { + capCount++ + } + } + if capCount >= 2 { + f.errorf(id, 0.8, link(styleGuideBase+"#mixed-caps"), category("naming"), "don't use ALL_CAPS in Go names; use CamelCase") + return + } + } + if thing == "const" || (thing == "var" && isInTopLevel(f.f, id)) { + if len(id.Name) > 2 && id.Name[0] == 'k' && id.Name[1] >= 'A' && id.Name[1] <= 'Z' { + should := string(id.Name[1]+'a'-'A') + id.Name[2:] + f.errorf(id, 0.8, link(styleGuideBase+"#mixed-caps"), category("naming"), "don't use leading k in Go names; %s %s should be %s", thing, id.Name, should) + } + } + + should := lintName(id.Name) + if id.Name == should { + return + } + + if len(id.Name) > 2 && strings.Contains(id.Name[1:], "_") { + f.errorf(id, 0.9, link("http://golang.org/doc/effective_go.html#mixed-caps"), category("naming"), "don't use underscores in Go names; %s %s should be %s", thing, id.Name, should) + return + } + f.errorf(id, 0.8, link(styleGuideBase+"#initialisms"), category("naming"), "%s %s should be %s", thing, id.Name, should) + } + checkList := func(fl *ast.FieldList, thing string) { + if fl == nil { + return + } + for _, f := range fl.List { + for _, id := range f.Names { + check(id, thing) + } + } + } + f.walk(func(node ast.Node) bool { + switch v := node.(type) { + case *ast.AssignStmt: + if v.Tok == token.ASSIGN { + return true + } + for _, exp := range v.Lhs { + if id, ok := exp.(*ast.Ident); ok { + check(id, "var") + } + } + case *ast.FuncDecl: + if f.isTest() && (strings.HasPrefix(v.Name.Name, "Example") || strings.HasPrefix(v.Name.Name, "Test") || strings.HasPrefix(v.Name.Name, "Benchmark")) { + return true + } + + thing := "func" + if v.Recv != nil { + thing = "method" + } + + // Exclude naming warnings for functions that are exported to C but + // not exported in the Go API. + // See https://github.com/golang/lint/issues/144. + if ast.IsExported(v.Name.Name) || !isCgoExported(v) { + check(v.Name, thing) + } + + checkList(v.Type.Params, thing+" parameter") + checkList(v.Type.Results, thing+" result") + case *ast.GenDecl: + if v.Tok == token.IMPORT { + return true + } + var thing string + switch v.Tok { + case token.CONST: + thing = "const" + case token.TYPE: + thing = "type" + case token.VAR: + thing = "var" + } + for _, spec := range v.Specs { + switch s := spec.(type) { + case *ast.TypeSpec: + check(s.Name, thing) + case *ast.ValueSpec: + for _, id := range s.Names { + check(id, thing) + } + } + } + case *ast.InterfaceType: + // Do not check interface method names. + // They are often constrainted by the method names of concrete types. + for _, x := range v.Methods.List { + ft, ok := x.Type.(*ast.FuncType) + if !ok { // might be an embedded interface name + continue + } + checkList(ft.Params, "interface method parameter") + checkList(ft.Results, "interface method result") + } + case *ast.RangeStmt: + if v.Tok == token.ASSIGN { + return true + } + if id, ok := v.Key.(*ast.Ident); ok { + check(id, "range var") + } + if id, ok := v.Value.(*ast.Ident); ok { + check(id, "range var") + } + case *ast.StructType: + for _, f := range v.Fields.List { + for _, id := range f.Names { + check(id, "struct field") + } + } + } + return true + }) +} + +// lintName returns a different name if it should be different. +func lintName(name string) (should string) { + // Fast path for simple cases: "_" and all lowercase. + if name == "_" { + return name + } + allLower := true + for _, r := range name { + if !unicode.IsLower(r) { + allLower = false + break + } + } + if allLower { + return name + } + + // Split camelCase at any lower->upper transition, and split on underscores. + // Check each word for common initialisms. + runes := []rune(name) + w, i := 0, 0 // index of start of word, scan + for i+1 <= len(runes) { + eow := false // whether we hit the end of a word + if i+1 == len(runes) { + eow = true + } else if runes[i+1] == '_' { + // underscore; shift the remainder forward over any run of underscores + eow = true + n := 1 + for i+n+1 < len(runes) && runes[i+n+1] == '_' { + n++ + } + + // Leave at most one underscore if the underscore is between two digits + if i+n+1 < len(runes) && unicode.IsDigit(runes[i]) && unicode.IsDigit(runes[i+n+1]) { + n-- + } + + copy(runes[i+1:], runes[i+n+1:]) + runes = runes[:len(runes)-n] + } else if unicode.IsLower(runes[i]) && !unicode.IsLower(runes[i+1]) { + // lower->non-lower + eow = true + } + i++ + if !eow { + continue + } + + // [w,i) is a word. + word := string(runes[w:i]) + if u := strings.ToUpper(word); commonInitialisms[u] { + // Keep consistent case, which is lowercase only at the start. + if w == 0 && unicode.IsLower(runes[w]) { + u = strings.ToLower(u) + } + // All the common initialisms are ASCII, + // so we can replace the bytes exactly. + copy(runes[w:], []rune(u)) + } else if w > 0 && strings.ToLower(word) == word { + // already all lowercase, and not the first word, so uppercase the first character. + runes[w] = unicode.ToUpper(runes[w]) + } + w = i + } + return string(runes) +} + +// commonInitialisms is a set of common initialisms. +// Only add entries that are highly unlikely to be non-initialisms. +// For instance, "ID" is fine (Freudian code is rare), but "AND" is not. +var commonInitialisms = map[string]bool{ + "ACL": true, + "API": true, + "ASCII": true, + "CPU": true, + "CSS": true, + "DNS": true, + "EOF": true, + "GUID": true, + "HTML": true, + "HTTP": true, + "HTTPS": true, + "ID": true, + "IP": true, + "JSON": true, + "LHS": true, + "QPS": true, + "RAM": true, + "RHS": true, + "RPC": true, + "SLA": true, + "SMTP": true, + "SQL": true, + "SSH": true, + "TCP": true, + "TLS": true, + "TTL": true, + "UDP": true, + "UI": true, + "UID": true, + "UUID": true, + "URI": true, + "URL": true, + "UTF8": true, + "VM": true, + "XML": true, + "XMPP": true, + "XSRF": true, + "XSS": true, +} + +// lintTypeDoc examines the doc comment on a type. +// It complains if they are missing from an exported type, +// or if they are not of the standard form. +func (f *file) lintTypeDoc(t *ast.TypeSpec, doc *ast.CommentGroup) { + if !ast.IsExported(t.Name.Name) { + return + } + if doc == nil { + f.errorf(t, 1, link(docCommentsLink), category("comments"), "exported type %v should have comment or be unexported", t.Name) + return + } + + s := doc.Text() + articles := [...]string{"A", "An", "The"} + for _, a := range articles { + if strings.HasPrefix(s, a+" ") { + s = s[len(a)+1:] + break + } + } + if !strings.HasPrefix(s, t.Name.Name+" ") { + f.errorf(doc, 1, link(docCommentsLink), category("comments"), `comment on exported type %v should be of the form "%v ..." (with optional leading article)`, t.Name, t.Name) + } +} + +var commonMethods = map[string]bool{ + "Error": true, + "Read": true, + "ServeHTTP": true, + "String": true, + "Write": true, +} + +// lintFuncDoc examines doc comments on functions and methods. +// It complains if they are missing, or not of the right form. +// It has specific exclusions for well-known methods (see commonMethods above). +func (f *file) lintFuncDoc(fn *ast.FuncDecl) { + if !ast.IsExported(fn.Name.Name) { + // func is unexported + return + } + kind := "function" + name := fn.Name.Name + if fn.Recv != nil && len(fn.Recv.List) > 0 { + // method + kind = "method" + recv := receiverType(fn) + if !ast.IsExported(recv) { + // receiver is unexported + return + } + if commonMethods[name] { + return + } + switch name { + case "Len", "Less", "Swap": + if f.pkg.sortable[recv] { + return + } + } + name = recv + "." + name + } + if fn.Doc == nil { + f.errorf(fn, 1, link(docCommentsLink), category("comments"), "exported %s %s should have comment or be unexported", kind, name) + return + } + s := fn.Doc.Text() + prefix := fn.Name.Name + " " + if !strings.HasPrefix(s, prefix) { + f.errorf(fn.Doc, 1, link(docCommentsLink), category("comments"), `comment on exported %s %s should be of the form "%s..."`, kind, name, prefix) + } +} + +// lintValueSpecDoc examines package-global variables and constants. +// It complains if they are not individually declared, +// or if they are not suitably documented in the right form (unless they are in a block that is commented). +func (f *file) lintValueSpecDoc(vs *ast.ValueSpec, gd *ast.GenDecl, genDeclMissingComments map[*ast.GenDecl]bool) { + kind := "var" + if gd.Tok == token.CONST { + kind = "const" + } + + if len(vs.Names) > 1 { + // Check that none are exported except for the first. + for _, n := range vs.Names[1:] { + if ast.IsExported(n.Name) { + f.errorf(vs, 1, category("comments"), "exported %s %s should have its own declaration", kind, n.Name) + return + } + } + } + + // Only one name. + name := vs.Names[0].Name + if !ast.IsExported(name) { + return + } + + if vs.Doc == nil && gd.Doc == nil { + if genDeclMissingComments[gd] { + return + } + block := "" + if kind == "const" && gd.Lparen.IsValid() { + block = " (or a comment on this block)" + } + f.errorf(vs, 1, link(docCommentsLink), category("comments"), "exported %s %s should have comment%s or be unexported", kind, name, block) + genDeclMissingComments[gd] = true + return + } + // If this GenDecl has parens and a comment, we don't check its comment form. + if gd.Lparen.IsValid() && gd.Doc != nil { + return + } + // The relevant text to check will be on either vs.Doc or gd.Doc. + // Use vs.Doc preferentially. + doc := vs.Doc + if doc == nil { + doc = gd.Doc + } + prefix := name + " " + if !strings.HasPrefix(doc.Text(), prefix) { + f.errorf(doc, 1, link(docCommentsLink), category("comments"), `comment on exported %s %s should be of the form "%s..."`, kind, name, prefix) + } +} + +func (f *file) checkStutter(id *ast.Ident, thing string) { + pkg, name := f.f.Name.Name, id.Name + if !ast.IsExported(name) { + // unexported name + return + } + // A name stutters if the package name is a strict prefix + // and the next character of the name starts a new word. + if len(name) <= len(pkg) { + // name is too short to stutter. + // This permits the name to be the same as the package name. + return + } + if !strings.EqualFold(pkg, name[:len(pkg)]) { + return + } + // We can assume the name is well-formed UTF-8. + // If the next rune after the package name is uppercase or an underscore + // the it's starting a new word and thus this name stutters. + rem := name[len(pkg):] + if next, _ := utf8.DecodeRuneInString(rem); next == '_' || unicode.IsUpper(next) { + f.errorf(id, 0.8, link(styleGuideBase+"#package-names"), category("naming"), "%s name will be used as %s.%s by other packages, and that stutters; consider calling this %s", thing, pkg, name, rem) + } +} + +// zeroLiteral is a set of ast.BasicLit values that are zero values. +// It is not exhaustive. +var zeroLiteral = map[string]bool{ + "false": true, // bool + // runes + `'\x00'`: true, + `'\000'`: true, + // strings + `""`: true, + "``": true, + // numerics + "0": true, + "0.": true, + "0.0": true, + "0i": true, +} + +// lintVarDecls examines variable declarations. It complains about declarations with +// redundant LHS types that can be inferred from the RHS. +func (f *file) lintVarDecls() { + var lastGen *ast.GenDecl // last GenDecl entered. + + f.walk(func(node ast.Node) bool { + switch v := node.(type) { + case *ast.GenDecl: + if v.Tok != token.CONST && v.Tok != token.VAR { + return false + } + lastGen = v + return true + case *ast.ValueSpec: + if lastGen.Tok == token.CONST { + return false + } + if len(v.Names) > 1 || v.Type == nil || len(v.Values) == 0 { + return false + } + rhs := v.Values[0] + // An underscore var appears in a common idiom for compile-time interface satisfaction, + // as in "var _ Interface = (*Concrete)(nil)". + if isIdent(v.Names[0], "_") { + return false + } + // If the RHS is a zero value, suggest dropping it. + zero := false + if lit, ok := rhs.(*ast.BasicLit); ok { + zero = zeroLiteral[lit.Value] + } else if isIdent(rhs, "nil") { + zero = true + } + if zero { + f.errorf(rhs, 0.9, category("zero-value"), "should drop = %s from declaration of var %s; it is the zero value", f.render(rhs), v.Names[0]) + return false + } + lhsTyp := f.pkg.typeOf(v.Type) + rhsTyp := f.pkg.typeOf(rhs) + + if !validType(lhsTyp) || !validType(rhsTyp) { + // Type checking failed (often due to missing imports). + return false + } + + if !types.Identical(lhsTyp, rhsTyp) { + // Assignment to a different type is not redundant. + return false + } + + // The next three conditions are for suppressing the warning in situations + // where we were unable to typecheck. + + // If the LHS type is an interface, don't warn, since it is probably a + // concrete type on the RHS. Note that our feeble lexical check here + // will only pick up interface{} and other literal interface types; + // that covers most of the cases we care to exclude right now. + if _, ok := v.Type.(*ast.InterfaceType); ok { + return false + } + // If the RHS is an untyped const, only warn if the LHS type is its default type. + if defType, ok := f.isUntypedConst(rhs); ok && !isIdent(v.Type, defType) { + return false + } + + f.errorf(v.Type, 0.8, category("type-inference"), "should omit type %s from declaration of var %s; it will be inferred from the right-hand side", f.render(v.Type), v.Names[0]) + return false + } + return true + }) +} + +func validType(T types.Type) bool { + return T != nil && + T != types.Typ[types.Invalid] && + !strings.Contains(T.String(), "invalid type") // good but not foolproof +} + +// lintElses examines else blocks. It complains about any else block whose if block ends in a return. +func (f *file) lintElses() { + // We don't want to flag if { } else if { } else { } constructions. + // They will appear as an IfStmt whose Else field is also an IfStmt. + // Record such a node so we ignore it when we visit it. + ignore := make(map[*ast.IfStmt]bool) + + f.walk(func(node ast.Node) bool { + ifStmt, ok := node.(*ast.IfStmt) + if !ok || ifStmt.Else == nil { + return true + } + if elseif, ok := ifStmt.Else.(*ast.IfStmt); ok { + ignore[elseif] = true + return true + } + if ignore[ifStmt] { + return true + } + if _, ok := ifStmt.Else.(*ast.BlockStmt); !ok { + // only care about elses without conditions + return true + } + if len(ifStmt.Body.List) == 0 { + return true + } + shortDecl := false // does the if statement have a ":=" initialization statement? + if ifStmt.Init != nil { + if as, ok := ifStmt.Init.(*ast.AssignStmt); ok && as.Tok == token.DEFINE { + shortDecl = true + } + } + lastStmt := ifStmt.Body.List[len(ifStmt.Body.List)-1] + if _, ok := lastStmt.(*ast.ReturnStmt); ok { + extra := "" + if shortDecl { + extra = " (move short variable declaration to its own line if necessary)" + } + f.errorf(ifStmt.Else, 1, link(styleGuideBase+"#indent-error-flow"), category("indent"), "if block ends with a return statement, so drop this else and outdent its block"+extra) + } + return true + }) +} + +// lintRanges examines range clauses. It complains about redundant constructions. +func (f *file) lintRanges() { + f.walk(func(node ast.Node) bool { + rs, ok := node.(*ast.RangeStmt) + if !ok { + return true + } + + if isIdent(rs.Key, "_") && (rs.Value == nil || isIdent(rs.Value, "_")) { + p := f.errorf(rs.Key, 1, category("range-loop"), "should omit values from range; this loop is equivalent to `for range ...`") + + newRS := *rs // shallow copy + newRS.Value = nil + newRS.Key = nil + p.ReplacementLine = f.firstLineOf(&newRS, rs) + + return true + } + + if isIdent(rs.Value, "_") { + p := f.errorf(rs.Value, 1, category("range-loop"), "should omit 2nd value from range; this loop is equivalent to `for %s %s range ...`", f.render(rs.Key), rs.Tok) + + newRS := *rs // shallow copy + newRS.Value = nil + p.ReplacementLine = f.firstLineOf(&newRS, rs) + } + + return true + }) +} + +// lintErrorf examines errors.New and testing.Error calls. It complains if its only argument is an fmt.Sprintf invocation. +func (f *file) lintErrorf() { + f.walk(func(node ast.Node) bool { + ce, ok := node.(*ast.CallExpr) + if !ok || len(ce.Args) != 1 { + return true + } + isErrorsNew := isPkgDot(ce.Fun, "errors", "New") + var isTestingError bool + se, ok := ce.Fun.(*ast.SelectorExpr) + if ok && se.Sel.Name == "Error" { + if typ := f.pkg.typeOf(se.X); typ != nil { + isTestingError = typ.String() == "*testing.T" + } + } + if !isErrorsNew && !isTestingError { + return true + } + if !f.imports("errors") { + return true + } + arg := ce.Args[0] + ce, ok = arg.(*ast.CallExpr) + if !ok || !isPkgDot(ce.Fun, "fmt", "Sprintf") { + return true + } + errorfPrefix := "fmt" + if isTestingError { + errorfPrefix = f.render(se.X) + } + p := f.errorf(node, 1, category("errors"), "should replace %s(fmt.Sprintf(...)) with %s.Errorf(...)", f.render(se), errorfPrefix) + + m := f.srcLineWithMatch(ce, `^(.*)`+f.render(se)+`\(fmt\.Sprintf\((.*)\)\)(.*)$`) + if m != nil { + p.ReplacementLine = m[1] + errorfPrefix + ".Errorf(" + m[2] + ")" + m[3] + } + + return true + }) +} + +// lintErrors examines global error vars. It complains if they aren't named in the standard way. +func (f *file) lintErrors() { + for _, decl := range f.f.Decls { + gd, ok := decl.(*ast.GenDecl) + if !ok || gd.Tok != token.VAR { + continue + } + for _, spec := range gd.Specs { + spec := spec.(*ast.ValueSpec) + if len(spec.Names) != 1 || len(spec.Values) != 1 { + continue + } + ce, ok := spec.Values[0].(*ast.CallExpr) + if !ok { + continue + } + if !isPkgDot(ce.Fun, "errors", "New") && !isPkgDot(ce.Fun, "fmt", "Errorf") { + continue + } + + id := spec.Names[0] + prefix := "err" + if id.IsExported() { + prefix = "Err" + } + if !strings.HasPrefix(id.Name, prefix) { + f.errorf(id, 0.9, category("naming"), "error var %s should have name of the form %sFoo", id.Name, prefix) + } + } + } +} + +func lintErrorString(s string) (isClean bool, conf float64) { + const basicConfidence = 0.8 + const capConfidence = basicConfidence - 0.2 + first, firstN := utf8.DecodeRuneInString(s) + last, _ := utf8.DecodeLastRuneInString(s) + if last == '.' || last == ':' || last == '!' || last == '\n' { + return false, basicConfidence + } + if unicode.IsUpper(first) { + // People use proper nouns and exported Go identifiers in error strings, + // so decrease the confidence of warnings for capitalization. + if len(s) <= firstN { + return false, capConfidence + } + // Flag strings starting with something that doesn't look like an initialism. + if second, _ := utf8.DecodeRuneInString(s[firstN:]); !unicode.IsUpper(second) { + return false, capConfidence + } + } + return true, 0 +} + +// lintErrorStrings examines error strings. +// It complains if they are capitalized or end in punctuation or a newline. +func (f *file) lintErrorStrings() { + f.walk(func(node ast.Node) bool { + ce, ok := node.(*ast.CallExpr) + if !ok { + return true + } + if !isPkgDot(ce.Fun, "errors", "New") && !isPkgDot(ce.Fun, "fmt", "Errorf") { + return true + } + if len(ce.Args) < 1 { + return true + } + str, ok := ce.Args[0].(*ast.BasicLit) + if !ok || str.Kind != token.STRING { + return true + } + s, _ := strconv.Unquote(str.Value) // can assume well-formed Go + if s == "" { + return true + } + clean, conf := lintErrorString(s) + if clean { + return true + } + + f.errorf(str, conf, link(styleGuideBase+"#error-strings"), category("errors"), + "error strings should not be capitalized or end with punctuation or a newline") + return true + }) +} + +// lintReceiverNames examines receiver names. It complains about inconsistent +// names used for the same type and names such as "this". +func (f *file) lintReceiverNames() { + typeReceiver := map[string]string{} + f.walk(func(n ast.Node) bool { + fn, ok := n.(*ast.FuncDecl) + if !ok || fn.Recv == nil || len(fn.Recv.List) == 0 { + return true + } + names := fn.Recv.List[0].Names + if len(names) < 1 { + return true + } + name := names[0].Name + const ref = styleGuideBase + "#receiver-names" + if name == "_" { + f.errorf(n, 1, link(ref), category("naming"), `receiver name should not be an underscore, omit the name if it is unused`) + return true + } + if name == "this" || name == "self" { + f.errorf(n, 1, link(ref), category("naming"), `receiver name should be a reflection of its identity; don't use generic names such as "this" or "self"`) + return true + } + recv := receiverType(fn) + if prev, ok := typeReceiver[recv]; ok && prev != name { + f.errorf(n, 1, link(ref), category("naming"), "receiver name %s should be consistent with previous receiver name %s for %s", name, prev, recv) + return true + } + typeReceiver[recv] = name + return true + }) +} + +// lintIncDec examines statements that increment or decrement a variable. +// It complains if they don't use x++ or x--. +func (f *file) lintIncDec() { + f.walk(func(n ast.Node) bool { + as, ok := n.(*ast.AssignStmt) + if !ok { + return true + } + if len(as.Lhs) != 1 { + return true + } + if !isOne(as.Rhs[0]) { + return true + } + var suffix string + switch as.Tok { + case token.ADD_ASSIGN: + suffix = "++" + case token.SUB_ASSIGN: + suffix = "--" + default: + return true + } + f.errorf(as, 0.8, category("unary-op"), "should replace %s with %s%s", f.render(as), f.render(as.Lhs[0]), suffix) + return true + }) +} + +// lintErrorReturn examines function declarations that return an error. +// It complains if the error isn't the last parameter. +func (f *file) lintErrorReturn() { + f.walk(func(n ast.Node) bool { + fn, ok := n.(*ast.FuncDecl) + if !ok || fn.Type.Results == nil { + return true + } + ret := fn.Type.Results.List + if len(ret) <= 1 { + return true + } + if isIdent(ret[len(ret)-1].Type, "error") { + return true + } + // An error return parameter should be the last parameter. + // Flag any error parameters found before the last. + for _, r := range ret[:len(ret)-1] { + if isIdent(r.Type, "error") { + f.errorf(fn, 0.9, category("arg-order"), "error should be the last type when returning multiple items") + break // only flag one + } + } + return true + }) +} + +// lintUnexportedReturn examines exported function declarations. +// It complains if any return an unexported type. +func (f *file) lintUnexportedReturn() { + f.walk(func(n ast.Node) bool { + fn, ok := n.(*ast.FuncDecl) + if !ok { + return true + } + if fn.Type.Results == nil { + return false + } + if !fn.Name.IsExported() { + return false + } + thing := "func" + if fn.Recv != nil && len(fn.Recv.List) > 0 { + thing = "method" + if !ast.IsExported(receiverType(fn)) { + // Don't report exported methods of unexported types, + // such as private implementations of sort.Interface. + return false + } + } + for _, ret := range fn.Type.Results.List { + typ := f.pkg.typeOf(ret.Type) + if exportedType(typ) { + continue + } + f.errorf(ret.Type, 0.8, category("unexported-type-in-api"), + "exported %s %s returns unexported type %s, which can be annoying to use", + thing, fn.Name.Name, typ) + break // only flag one + } + return false + }) +} + +// exportedType reports whether typ is an exported type. +// It is imprecise, and will err on the side of returning true, +// such as for composite types. +func exportedType(typ types.Type) bool { + switch T := typ.(type) { + case *types.Named: + // Builtin types have no package. + return T.Obj().Pkg() == nil || T.Obj().Exported() + case *types.Map: + return exportedType(T.Key()) && exportedType(T.Elem()) + case interface { + Elem() types.Type + }: // array, slice, pointer, chan + return exportedType(T.Elem()) + } + // Be conservative about other types, such as struct, interface, etc. + return true +} + +// timeSuffixes is a list of name suffixes that imply a time unit. +// This is not an exhaustive list. +var timeSuffixes = []string{ + "Sec", "Secs", "Seconds", + "Msec", "Msecs", + "Milli", "Millis", "Milliseconds", + "Usec", "Usecs", "Microseconds", + "MS", "Ms", +} + +func (f *file) lintTimeNames() { + f.walk(func(node ast.Node) bool { + v, ok := node.(*ast.ValueSpec) + if !ok { + return true + } + for _, name := range v.Names { + origTyp := f.pkg.typeOf(name) + // Look for time.Duration or *time.Duration; + // the latter is common when using flag.Duration. + typ := origTyp + if pt, ok := typ.(*types.Pointer); ok { + typ = pt.Elem() + } + if !f.pkg.isNamedType(typ, "time", "Duration") { + continue + } + suffix := "" + for _, suf := range timeSuffixes { + if strings.HasSuffix(name.Name, suf) { + suffix = suf + break + } + } + if suffix == "" { + continue + } + f.errorf(v, 0.9, category("time"), "var %s is of type %v; don't use unit-specific suffix %q", name.Name, origTyp, suffix) + } + return true + }) +} + +// lintContextKeyTypes checks for call expressions to context.WithValue with +// basic types used for the key argument. +// See: https://golang.org/issue/17293 +func (f *file) lintContextKeyTypes() { + f.walk(func(node ast.Node) bool { + switch node := node.(type) { + case *ast.CallExpr: + f.checkContextKeyType(node) + } + + return true + }) +} + +// checkContextKeyType reports an error if the call expression calls +// context.WithValue with a key argument of basic type. +func (f *file) checkContextKeyType(x *ast.CallExpr) { + sel, ok := x.Fun.(*ast.SelectorExpr) + if !ok { + return + } + pkg, ok := sel.X.(*ast.Ident) + if !ok || pkg.Name != "context" { + return + } + if sel.Sel.Name != "WithValue" { + return + } + + // key is second argument to context.WithValue + if len(x.Args) != 3 { + return + } + key := f.pkg.typesInfo.Types[x.Args[1]] + + if ktyp, ok := key.Type.(*types.Basic); ok && ktyp.Kind() != types.Invalid { + f.errorf(x, 1.0, category("context"), fmt.Sprintf("should not use basic type %s as key in context.WithValue", key.Type)) + } +} + +// lintContextArgs examines function declarations that contain an +// argument with a type of context.Context +// It complains if that argument isn't the first parameter. +func (f *file) lintContextArgs() { + f.walk(func(n ast.Node) bool { + fn, ok := n.(*ast.FuncDecl) + if !ok || len(fn.Type.Params.List) <= 1 { + return true + } + // A context.Context should be the first parameter of a function. + // Flag any that show up after the first. + for _, arg := range fn.Type.Params.List[1:] { + if isPkgDot(arg.Type, "context", "Context") { + f.errorf(fn, 0.9, link("https://golang.org/pkg/context/"), category("arg-order"), "context.Context should be the first parameter of a function") + break // only flag one + } + } + return true + }) +} + +// containsComments returns whether the interval [start, end) contains any +// comments without "// MATCH " prefix. +func (f *file) containsComments(start, end token.Pos) bool { + for _, cgroup := range f.f.Comments { + comments := cgroup.List + if comments[0].Slash >= end { + // All comments starting with this group are after end pos. + return false + } + if comments[len(comments)-1].Slash < start { + // Comments group ends before start pos. + continue + } + for _, c := range comments { + if start <= c.Slash && c.Slash < end && !strings.HasPrefix(c.Text, "// MATCH ") { + return true + } + } + } + return false +} + +// receiverType returns the named type of the method receiver, sans "*", +// or "invalid-type" if fn.Recv is ill formed. +func receiverType(fn *ast.FuncDecl) string { + switch e := fn.Recv.List[0].Type.(type) { + case *ast.Ident: + return e.Name + case *ast.StarExpr: + if id, ok := e.X.(*ast.Ident); ok { + return id.Name + } + } + // The parser accepts much more than just the legal forms. + return "invalid-type" +} + +func (f *file) walk(fn func(ast.Node) bool) { + ast.Walk(walker(fn), f.f) +} + +func (f *file) render(x interface{}) string { + var buf bytes.Buffer + if err := printer.Fprint(&buf, f.fset, x); err != nil { + panic(err) + } + return buf.String() +} + +func (f *file) debugRender(x interface{}) string { + var buf bytes.Buffer + if err := ast.Fprint(&buf, f.fset, x, nil); err != nil { + panic(err) + } + return buf.String() +} + +// walker adapts a function to satisfy the ast.Visitor interface. +// The function return whether the walk should proceed into the node's children. +type walker func(ast.Node) bool + +func (w walker) Visit(node ast.Node) ast.Visitor { + if w(node) { + return w + } + return nil +} + +func isIdent(expr ast.Expr, ident string) bool { + id, ok := expr.(*ast.Ident) + return ok && id.Name == ident +} + +// isBlank returns whether id is the blank identifier "_". +// If id == nil, the answer is false. +func isBlank(id *ast.Ident) bool { return id != nil && id.Name == "_" } + +func isPkgDot(expr ast.Expr, pkg, name string) bool { + sel, ok := expr.(*ast.SelectorExpr) + return ok && isIdent(sel.X, pkg) && isIdent(sel.Sel, name) +} + +func isOne(expr ast.Expr) bool { + lit, ok := expr.(*ast.BasicLit) + return ok && lit.Kind == token.INT && lit.Value == "1" +} + +func isCgoExported(f *ast.FuncDecl) bool { + if f.Recv != nil || f.Doc == nil { + return false + } + + cgoExport := regexp.MustCompile(fmt.Sprintf("(?m)^//export %s$", regexp.QuoteMeta(f.Name.Name))) + for _, c := range f.Doc.List { + if cgoExport.MatchString(c.Text) { + return true + } + } + return false +} + +var basicTypeKinds = map[types.BasicKind]string{ + types.UntypedBool: "bool", + types.UntypedInt: "int", + types.UntypedRune: "rune", + types.UntypedFloat: "float64", + types.UntypedComplex: "complex128", + types.UntypedString: "string", +} + +// isUntypedConst reports whether expr is an untyped constant, +// and indicates what its default type is. +// scope may be nil. +func (f *file) isUntypedConst(expr ast.Expr) (defType string, ok bool) { + // Re-evaluate expr outside of its context to see if it's untyped. + // (An expr evaluated within, for example, an assignment context will get the type of the LHS.) + exprStr := f.render(expr) + tv, err := types.Eval(f.fset, f.pkg.typesPkg, expr.Pos(), exprStr) + if err != nil { + return "", false + } + if b, ok := tv.Type.(*types.Basic); ok { + if dt, ok := basicTypeKinds[b.Kind()]; ok { + return dt, true + } + } + + return "", false +} + +// firstLineOf renders the given node and returns its first line. +// It will also match the indentation of another node. +func (f *file) firstLineOf(node, match ast.Node) string { + line := f.render(node) + if i := strings.Index(line, "\n"); i >= 0 { + line = line[:i] + } + return f.indentOf(match) + line +} + +func (f *file) indentOf(node ast.Node) string { + line := srcLine(f.src, f.fset.Position(node.Pos())) + for i, r := range line { + switch r { + case ' ', '\t': + default: + return line[:i] + } + } + return line // unusual or empty line +} + +func (f *file) srcLineWithMatch(node ast.Node, pattern string) (m []string) { + line := srcLine(f.src, f.fset.Position(node.Pos())) + line = strings.TrimSuffix(line, "\n") + rx := regexp.MustCompile(pattern) + return rx.FindStringSubmatch(line) +} + +// imports returns true if the current file imports the specified package path. +func (f *file) imports(importPath string) bool { + all := astutil.Imports(f.fset, f.f) + for _, p := range all { + for _, i := range p { + uq, err := strconv.Unquote(i.Path.Value) + if err == nil && importPath == uq { + return true + } + } + } + return false +} + +// srcLine returns the complete line at p, including the terminating newline. +func srcLine(src []byte, p token.Position) string { + // Run to end of line in both directions if not at line start/end. + lo, hi := p.Offset, p.Offset+1 + for lo > 0 && src[lo-1] != '\n' { + lo-- + } + for hi < len(src) && src[hi-1] != '\n' { + hi++ + } + return string(src[lo:hi]) +} diff --git a/vendor/golang.org/x/tools/go/gcexportdata/BUILD b/vendor/golang.org/x/tools/go/gcexportdata/BUILD new file mode 100644 index 00000000000..ac13ca02938 --- /dev/null +++ b/vendor/golang.org/x/tools/go/gcexportdata/BUILD @@ -0,0 +1,27 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = [ + "gcexportdata.go", + "importer.go", + ], + importmap = "k8s.io/kubernetes/vendor/golang.org/x/tools/go/gcexportdata", + importpath = "golang.org/x/tools/go/gcexportdata", + visibility = ["//visibility:public"], + deps = ["//vendor/golang.org/x/tools/go/gcimporter15:go_default_library"], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/vendor/golang.org/x/tools/go/gcexportdata/gcexportdata.go b/vendor/golang.org/x/tools/go/gcexportdata/gcexportdata.go new file mode 100644 index 00000000000..23dc019289e --- /dev/null +++ b/vendor/golang.org/x/tools/go/gcexportdata/gcexportdata.go @@ -0,0 +1,100 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package gcexportdata provides functions for locating, reading, and +// writing export data files containing type information produced by the +// gc compiler. This package supports go1.7 export data format and all +// later versions. +// +// This package replaces the deprecated golang.org/x/tools/go/gcimporter15 +// package, which will be deleted in October 2017. +// +// Although it might seem convenient for this package to live alongside +// go/types in the standard library, this would cause version skew +// problems for developer tools that use it, since they must be able to +// consume the outputs of the gc compiler both before and after a Go +// update such as from Go 1.7 to Go 1.8. Because this package lives in +// golang.org/x/tools, sites can update their version of this repo some +// time before the Go 1.8 release and rebuild and redeploy their +// developer tools, which will then be able to consume both Go 1.7 and +// Go 1.8 export data files, so they will work before and after the +// Go update. (See discussion at https://github.com/golang/go/issues/15651.) +// +package gcexportdata + +import ( + "bufio" + "bytes" + "fmt" + "go/token" + "go/types" + "io" + "io/ioutil" + + gcimporter "golang.org/x/tools/go/gcimporter15" +) + +// Find returns the name of an object (.o) or archive (.a) file +// containing type information for the specified import path, +// using the workspace layout conventions of go/build. +// If no file was found, an empty filename is returned. +// +// A relative srcDir is interpreted relative to the current working directory. +// +// Find also returns the package's resolved (canonical) import path, +// reflecting the effects of srcDir and vendoring on importPath. +func Find(importPath string, srcDir string) (filename, path string) { + return gcimporter.FindPkg(importPath, srcDir) +} + +// NewReader returns a reader for the export data section of an object +// (.o) or archive (.a) file read from r. The new reader may provide +// additional trailing data beyond the end of the export data. +func NewReader(r io.Reader) (io.Reader, error) { + buf := bufio.NewReader(r) + _, err := gcimporter.FindExportData(buf) + // If we ever switch to a zip-like archive format with the ToC + // at the end, we can return the correct portion of export data, + // but for now we must return the entire rest of the file. + return buf, err +} + +// Read reads export data from in, decodes it, and returns type +// information for the package. +// The package name is specified by path. +// File position information is added to fset. +// +// Read may inspect and add to the imports map to ensure that references +// within the export data to other packages are consistent. The caller +// must ensure that imports[path] does not exist, or exists but is +// incomplete (see types.Package.Complete), and Read inserts the +// resulting package into this map entry. +// +// On return, the state of the reader is undefined. +func Read(in io.Reader, fset *token.FileSet, imports map[string]*types.Package, path string) (*types.Package, error) { + data, err := ioutil.ReadAll(in) + if err != nil { + return nil, fmt.Errorf("reading export data for %q: %v", path, err) + } + + if bytes.HasPrefix(data, []byte("!")) { + return nil, fmt.Errorf("can't read export data for %q directly from an archive file (call gcexportdata.NewReader first to extract export data)", path) + } + + // The App Engine Go runtime v1.6 uses the old export data format. + // TODO(adonovan): delete once v1.7 has been around for a while. + if bytes.HasPrefix(data, []byte("package ")) { + return gcimporter.ImportData(imports, path, path, bytes.NewReader(data)) + } + + _, pkg, err := gcimporter.BImportData(fset, imports, data, path) + return pkg, err +} + +// Write writes encoded type information for the specified package to out. +// The FileSet provides file position information for named objects. +func Write(out io.Writer, fset *token.FileSet, pkg *types.Package) error { + _, err := out.Write(gcimporter.BExportData(fset, pkg)) + return err +} diff --git a/vendor/golang.org/x/tools/go/gcexportdata/importer.go b/vendor/golang.org/x/tools/go/gcexportdata/importer.go new file mode 100644 index 00000000000..efe221e7e14 --- /dev/null +++ b/vendor/golang.org/x/tools/go/gcexportdata/importer.go @@ -0,0 +1,73 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package gcexportdata + +import ( + "fmt" + "go/token" + "go/types" + "os" +) + +// NewImporter returns a new instance of the types.Importer interface +// that reads type information from export data files written by gc. +// The Importer also satisfies types.ImporterFrom. +// +// Export data files are located using "go build" workspace conventions +// and the build.Default context. +// +// Use this importer instead of go/importer.For("gc", ...) to avoid the +// version-skew problems described in the documentation of this package, +// or to control the FileSet or access the imports map populated during +// package loading. +// +func NewImporter(fset *token.FileSet, imports map[string]*types.Package) types.ImporterFrom { + return importer{fset, imports} +} + +type importer struct { + fset *token.FileSet + imports map[string]*types.Package +} + +func (imp importer) Import(importPath string) (*types.Package, error) { + return imp.ImportFrom(importPath, "", 0) +} + +func (imp importer) ImportFrom(importPath, srcDir string, mode types.ImportMode) (_ *types.Package, err error) { + filename, path := Find(importPath, srcDir) + if filename == "" { + if importPath == "unsafe" { + // Even for unsafe, call Find first in case + // the package was vendored. + return types.Unsafe, nil + } + return nil, fmt.Errorf("can't find import: %s", importPath) + } + + if pkg, ok := imp.imports[path]; ok && pkg.Complete() { + return pkg, nil // cache hit + } + + // open file + f, err := os.Open(filename) + if err != nil { + return nil, err + } + defer func() { + f.Close() + if err != nil { + // add file name to error + err = fmt.Errorf("reading export data: %s: %v", filename, err) + } + }() + + r, err := NewReader(f) + if err != nil { + return nil, err + } + + return Read(r, imp.fset, imp.imports, path) +} diff --git a/vendor/golang.org/x/tools/go/gcimporter15/BUILD b/vendor/golang.org/x/tools/go/gcimporter15/BUILD new file mode 100644 index 00000000000..018ba602591 --- /dev/null +++ b/vendor/golang.org/x/tools/go/gcimporter15/BUILD @@ -0,0 +1,30 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = [ + "bexport.go", + "bimport.go", + "exportdata.go", + "gcimporter.go", + "isAlias18.go", + "isAlias19.go", + ], + importmap = "k8s.io/kubernetes/vendor/golang.org/x/tools/go/gcimporter15", + importpath = "golang.org/x/tools/go/gcimporter15", + visibility = ["//visibility:public"], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/vendor/golang.org/x/tools/go/gcimporter15/bexport.go b/vendor/golang.org/x/tools/go/gcimporter15/bexport.go new file mode 100644 index 00000000000..cbf8bc00d61 --- /dev/null +++ b/vendor/golang.org/x/tools/go/gcimporter15/bexport.go @@ -0,0 +1,828 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Binary package export. +// This file was derived from $GOROOT/src/cmd/compile/internal/gc/bexport.go; +// see that file for specification of the format. + +package gcimporter + +import ( + "bytes" + "encoding/binary" + "fmt" + "go/ast" + "go/constant" + "go/token" + "go/types" + "log" + "math" + "math/big" + "sort" + "strings" +) + +// If debugFormat is set, each integer and string value is preceded by a marker +// and position information in the encoding. This mechanism permits an importer +// to recognize immediately when it is out of sync. The importer recognizes this +// mode automatically (i.e., it can import export data produced with debugging +// support even if debugFormat is not set at the time of import). This mode will +// lead to massively larger export data (by a factor of 2 to 3) and should only +// be enabled during development and debugging. +// +// NOTE: This flag is the first flag to enable if importing dies because of +// (suspected) format errors, and whenever a change is made to the format. +const debugFormat = false // default: false + +// If trace is set, debugging output is printed to std out. +const trace = false // default: false + +// Current export format version. Increase with each format change. +// 4: type name objects support type aliases, uses aliasTag +// 3: Go1.8 encoding (same as version 2, aliasTag defined but never used) +// 2: removed unused bool in ODCL export (compiler only) +// 1: header format change (more regular), export package for _ struct fields +// 0: Go1.7 encoding +const exportVersion = 4 + +// trackAllTypes enables cycle tracking for all types, not just named +// types. The existing compiler invariants assume that unnamed types +// that are not completely set up are not used, or else there are spurious +// errors. +// If disabled, only named types are tracked, possibly leading to slightly +// less efficient encoding in rare cases. It also prevents the export of +// some corner-case type declarations (but those are not handled correctly +// with with the textual export format either). +// TODO(gri) enable and remove once issues caused by it are fixed +const trackAllTypes = false + +type exporter struct { + fset *token.FileSet + out bytes.Buffer + + // object -> index maps, indexed in order of serialization + strIndex map[string]int + pkgIndex map[*types.Package]int + typIndex map[types.Type]int + + // position encoding + posInfoFormat bool + prevFile string + prevLine int + + // debugging support + written int // bytes written + indent int // for trace +} + +// BExportData returns binary export data for pkg. +// If no file set is provided, position info will be missing. +func BExportData(fset *token.FileSet, pkg *types.Package) []byte { + p := exporter{ + fset: fset, + strIndex: map[string]int{"": 0}, // empty string is mapped to 0 + pkgIndex: make(map[*types.Package]int), + typIndex: make(map[types.Type]int), + posInfoFormat: true, // TODO(gri) might become a flag, eventually + } + + // write version info + // The version string must start with "version %d" where %d is the version + // number. Additional debugging information may follow after a blank; that + // text is ignored by the importer. + p.rawStringln(fmt.Sprintf("version %d", exportVersion)) + var debug string + if debugFormat { + debug = "debug" + } + p.rawStringln(debug) // cannot use p.bool since it's affected by debugFormat; also want to see this clearly + p.bool(trackAllTypes) + p.bool(p.posInfoFormat) + + // --- generic export data --- + + // populate type map with predeclared "known" types + for index, typ := range predeclared { + p.typIndex[typ] = index + } + if len(p.typIndex) != len(predeclared) { + log.Fatalf("gcimporter: duplicate entries in type map?") + } + + // write package data + p.pkg(pkg, true) + if trace { + p.tracef("\n") + } + + // write objects + objcount := 0 + scope := pkg.Scope() + for _, name := range scope.Names() { + if !ast.IsExported(name) { + continue + } + if trace { + p.tracef("\n") + } + p.obj(scope.Lookup(name)) + objcount++ + } + + // indicate end of list + if trace { + p.tracef("\n") + } + p.tag(endTag) + + // for self-verification only (redundant) + p.int(objcount) + + if trace { + p.tracef("\n") + } + + // --- end of export data --- + + return p.out.Bytes() +} + +func (p *exporter) pkg(pkg *types.Package, emptypath bool) { + if pkg == nil { + log.Fatalf("gcimporter: unexpected nil pkg") + } + + // if we saw the package before, write its index (>= 0) + if i, ok := p.pkgIndex[pkg]; ok { + p.index('P', i) + return + } + + // otherwise, remember the package, write the package tag (< 0) and package data + if trace { + p.tracef("P%d = { ", len(p.pkgIndex)) + defer p.tracef("} ") + } + p.pkgIndex[pkg] = len(p.pkgIndex) + + p.tag(packageTag) + p.string(pkg.Name()) + if emptypath { + p.string("") + } else { + p.string(pkg.Path()) + } +} + +func (p *exporter) obj(obj types.Object) { + switch obj := obj.(type) { + case *types.Const: + p.tag(constTag) + p.pos(obj) + p.qualifiedName(obj) + p.typ(obj.Type()) + p.value(obj.Val()) + + case *types.TypeName: + if isAlias(obj) { + p.tag(aliasTag) + p.pos(obj) + p.qualifiedName(obj) + } else { + p.tag(typeTag) + } + p.typ(obj.Type()) + + case *types.Var: + p.tag(varTag) + p.pos(obj) + p.qualifiedName(obj) + p.typ(obj.Type()) + + case *types.Func: + p.tag(funcTag) + p.pos(obj) + p.qualifiedName(obj) + sig := obj.Type().(*types.Signature) + p.paramList(sig.Params(), sig.Variadic()) + p.paramList(sig.Results(), false) + + default: + log.Fatalf("gcimporter: unexpected object %v (%T)", obj, obj) + } +} + +func (p *exporter) pos(obj types.Object) { + if !p.posInfoFormat { + return + } + + file, line := p.fileLine(obj) + if file == p.prevFile { + // common case: write line delta + // delta == 0 means different file or no line change + delta := line - p.prevLine + p.int(delta) + if delta == 0 { + p.int(-1) // -1 means no file change + } + } else { + // different file + p.int(0) + // Encode filename as length of common prefix with previous + // filename, followed by (possibly empty) suffix. Filenames + // frequently share path prefixes, so this can save a lot + // of space and make export data size less dependent on file + // path length. The suffix is unlikely to be empty because + // file names tend to end in ".go". + n := commonPrefixLen(p.prevFile, file) + p.int(n) // n >= 0 + p.string(file[n:]) // write suffix only + p.prevFile = file + p.int(line) + } + p.prevLine = line +} + +func (p *exporter) fileLine(obj types.Object) (file string, line int) { + if p.fset != nil { + pos := p.fset.Position(obj.Pos()) + file = pos.Filename + line = pos.Line + } + return +} + +func commonPrefixLen(a, b string) int { + if len(a) > len(b) { + a, b = b, a + } + // len(a) <= len(b) + i := 0 + for i < len(a) && a[i] == b[i] { + i++ + } + return i +} + +func (p *exporter) qualifiedName(obj types.Object) { + p.string(obj.Name()) + p.pkg(obj.Pkg(), false) +} + +func (p *exporter) typ(t types.Type) { + if t == nil { + log.Fatalf("gcimporter: nil type") + } + + // Possible optimization: Anonymous pointer types *T where + // T is a named type are common. We could canonicalize all + // such types *T to a single type PT = *T. This would lead + // to at most one *T entry in typIndex, and all future *T's + // would be encoded as the respective index directly. Would + // save 1 byte (pointerTag) per *T and reduce the typIndex + // size (at the cost of a canonicalization map). We can do + // this later, without encoding format change. + + // if we saw the type before, write its index (>= 0) + if i, ok := p.typIndex[t]; ok { + p.index('T', i) + return + } + + // otherwise, remember the type, write the type tag (< 0) and type data + if trackAllTypes { + if trace { + p.tracef("T%d = {>\n", len(p.typIndex)) + defer p.tracef("<\n} ") + } + p.typIndex[t] = len(p.typIndex) + } + + switch t := t.(type) { + case *types.Named: + if !trackAllTypes { + // if we don't track all types, track named types now + p.typIndex[t] = len(p.typIndex) + } + + p.tag(namedTag) + p.pos(t.Obj()) + p.qualifiedName(t.Obj()) + p.typ(t.Underlying()) + if !types.IsInterface(t) { + p.assocMethods(t) + } + + case *types.Array: + p.tag(arrayTag) + p.int64(t.Len()) + p.typ(t.Elem()) + + case *types.Slice: + p.tag(sliceTag) + p.typ(t.Elem()) + + case *dddSlice: + p.tag(dddTag) + p.typ(t.elem) + + case *types.Struct: + p.tag(structTag) + p.fieldList(t) + + case *types.Pointer: + p.tag(pointerTag) + p.typ(t.Elem()) + + case *types.Signature: + p.tag(signatureTag) + p.paramList(t.Params(), t.Variadic()) + p.paramList(t.Results(), false) + + case *types.Interface: + p.tag(interfaceTag) + p.iface(t) + + case *types.Map: + p.tag(mapTag) + p.typ(t.Key()) + p.typ(t.Elem()) + + case *types.Chan: + p.tag(chanTag) + p.int(int(3 - t.Dir())) // hack + p.typ(t.Elem()) + + default: + log.Fatalf("gcimporter: unexpected type %T: %s", t, t) + } +} + +func (p *exporter) assocMethods(named *types.Named) { + // Sort methods (for determinism). + var methods []*types.Func + for i := 0; i < named.NumMethods(); i++ { + methods = append(methods, named.Method(i)) + } + sort.Sort(methodsByName(methods)) + + p.int(len(methods)) + + if trace && methods != nil { + p.tracef("associated methods {>\n") + } + + for i, m := range methods { + if trace && i > 0 { + p.tracef("\n") + } + + p.pos(m) + name := m.Name() + p.string(name) + if !exported(name) { + p.pkg(m.Pkg(), false) + } + + sig := m.Type().(*types.Signature) + p.paramList(types.NewTuple(sig.Recv()), false) + p.paramList(sig.Params(), sig.Variadic()) + p.paramList(sig.Results(), false) + p.int(0) // dummy value for go:nointerface pragma - ignored by importer + } + + if trace && methods != nil { + p.tracef("<\n} ") + } +} + +type methodsByName []*types.Func + +func (x methodsByName) Len() int { return len(x) } +func (x methodsByName) Swap(i, j int) { x[i], x[j] = x[j], x[i] } +func (x methodsByName) Less(i, j int) bool { return x[i].Name() < x[j].Name() } + +func (p *exporter) fieldList(t *types.Struct) { + if trace && t.NumFields() > 0 { + p.tracef("fields {>\n") + defer p.tracef("<\n} ") + } + + p.int(t.NumFields()) + for i := 0; i < t.NumFields(); i++ { + if trace && i > 0 { + p.tracef("\n") + } + p.field(t.Field(i)) + p.string(t.Tag(i)) + } +} + +func (p *exporter) field(f *types.Var) { + if !f.IsField() { + log.Fatalf("gcimporter: field expected") + } + + p.pos(f) + p.fieldName(f) + p.typ(f.Type()) +} + +func (p *exporter) iface(t *types.Interface) { + // TODO(gri): enable importer to load embedded interfaces, + // then emit Embeddeds and ExplicitMethods separately here. + p.int(0) + + n := t.NumMethods() + if trace && n > 0 { + p.tracef("methods {>\n") + defer p.tracef("<\n} ") + } + p.int(n) + for i := 0; i < n; i++ { + if trace && i > 0 { + p.tracef("\n") + } + p.method(t.Method(i)) + } +} + +func (p *exporter) method(m *types.Func) { + sig := m.Type().(*types.Signature) + if sig.Recv() == nil { + log.Fatalf("gcimporter: method expected") + } + + p.pos(m) + p.string(m.Name()) + if m.Name() != "_" && !ast.IsExported(m.Name()) { + p.pkg(m.Pkg(), false) + } + + // interface method; no need to encode receiver. + p.paramList(sig.Params(), sig.Variadic()) + p.paramList(sig.Results(), false) +} + +func (p *exporter) fieldName(f *types.Var) { + name := f.Name() + + if f.Anonymous() { + // anonymous field - we distinguish between 3 cases: + // 1) field name matches base type name and is exported + // 2) field name matches base type name and is not exported + // 3) field name doesn't match base type name (alias name) + bname := basetypeName(f.Type()) + if name == bname { + if ast.IsExported(name) { + name = "" // 1) we don't need to know the field name or package + } else { + name = "?" // 2) use unexported name "?" to force package export + } + } else { + // 3) indicate alias and export name as is + // (this requires an extra "@" but this is a rare case) + p.string("@") + } + } + + p.string(name) + if name != "" && !ast.IsExported(name) { + p.pkg(f.Pkg(), false) + } +} + +func basetypeName(typ types.Type) string { + switch typ := deref(typ).(type) { + case *types.Basic: + return typ.Name() + case *types.Named: + return typ.Obj().Name() + default: + return "" // unnamed type + } +} + +func (p *exporter) paramList(params *types.Tuple, variadic bool) { + // use negative length to indicate unnamed parameters + // (look at the first parameter only since either all + // names are present or all are absent) + n := params.Len() + if n > 0 && params.At(0).Name() == "" { + n = -n + } + p.int(n) + for i := 0; i < params.Len(); i++ { + q := params.At(i) + t := q.Type() + if variadic && i == params.Len()-1 { + t = &dddSlice{t.(*types.Slice).Elem()} + } + p.typ(t) + if n > 0 { + name := q.Name() + p.string(name) + if name != "_" { + p.pkg(q.Pkg(), false) + } + } + p.string("") // no compiler-specific info + } +} + +func (p *exporter) value(x constant.Value) { + if trace { + p.tracef("= ") + } + + switch x.Kind() { + case constant.Bool: + tag := falseTag + if constant.BoolVal(x) { + tag = trueTag + } + p.tag(tag) + + case constant.Int: + if v, exact := constant.Int64Val(x); exact { + // common case: x fits into an int64 - use compact encoding + p.tag(int64Tag) + p.int64(v) + return + } + // uncommon case: large x - use float encoding + // (powers of 2 will be encoded efficiently with exponent) + p.tag(floatTag) + p.float(constant.ToFloat(x)) + + case constant.Float: + p.tag(floatTag) + p.float(x) + + case constant.Complex: + p.tag(complexTag) + p.float(constant.Real(x)) + p.float(constant.Imag(x)) + + case constant.String: + p.tag(stringTag) + p.string(constant.StringVal(x)) + + case constant.Unknown: + // package contains type errors + p.tag(unknownTag) + + default: + log.Fatalf("gcimporter: unexpected value %v (%T)", x, x) + } +} + +func (p *exporter) float(x constant.Value) { + if x.Kind() != constant.Float { + log.Fatalf("gcimporter: unexpected constant %v, want float", x) + } + // extract sign (there is no -0) + sign := constant.Sign(x) + if sign == 0 { + // x == 0 + p.int(0) + return + } + // x != 0 + + var f big.Float + if v, exact := constant.Float64Val(x); exact { + // float64 + f.SetFloat64(v) + } else if num, denom := constant.Num(x), constant.Denom(x); num.Kind() == constant.Int { + // TODO(gri): add big.Rat accessor to constant.Value. + r := valueToRat(num) + f.SetRat(r.Quo(r, valueToRat(denom))) + } else { + // Value too large to represent as a fraction => inaccessible. + // TODO(gri): add big.Float accessor to constant.Value. + f.SetFloat64(math.MaxFloat64) // FIXME + } + + // extract exponent such that 0.5 <= m < 1.0 + var m big.Float + exp := f.MantExp(&m) + + // extract mantissa as *big.Int + // - set exponent large enough so mant satisfies mant.IsInt() + // - get *big.Int from mant + m.SetMantExp(&m, int(m.MinPrec())) + mant, acc := m.Int(nil) + if acc != big.Exact { + log.Fatalf("gcimporter: internal error") + } + + p.int(sign) + p.int(exp) + p.string(string(mant.Bytes())) +} + +func valueToRat(x constant.Value) *big.Rat { + // Convert little-endian to big-endian. + // I can't believe this is necessary. + bytes := constant.Bytes(x) + for i := 0; i < len(bytes)/2; i++ { + bytes[i], bytes[len(bytes)-1-i] = bytes[len(bytes)-1-i], bytes[i] + } + return new(big.Rat).SetInt(new(big.Int).SetBytes(bytes)) +} + +func (p *exporter) bool(b bool) bool { + if trace { + p.tracef("[") + defer p.tracef("= %v] ", b) + } + + x := 0 + if b { + x = 1 + } + p.int(x) + return b +} + +// ---------------------------------------------------------------------------- +// Low-level encoders + +func (p *exporter) index(marker byte, index int) { + if index < 0 { + log.Fatalf("gcimporter: invalid index < 0") + } + if debugFormat { + p.marker('t') + } + if trace { + p.tracef("%c%d ", marker, index) + } + p.rawInt64(int64(index)) +} + +func (p *exporter) tag(tag int) { + if tag >= 0 { + log.Fatalf("gcimporter: invalid tag >= 0") + } + if debugFormat { + p.marker('t') + } + if trace { + p.tracef("%s ", tagString[-tag]) + } + p.rawInt64(int64(tag)) +} + +func (p *exporter) int(x int) { + p.int64(int64(x)) +} + +func (p *exporter) int64(x int64) { + if debugFormat { + p.marker('i') + } + if trace { + p.tracef("%d ", x) + } + p.rawInt64(x) +} + +func (p *exporter) string(s string) { + if debugFormat { + p.marker('s') + } + if trace { + p.tracef("%q ", s) + } + // if we saw the string before, write its index (>= 0) + // (the empty string is mapped to 0) + if i, ok := p.strIndex[s]; ok { + p.rawInt64(int64(i)) + return + } + // otherwise, remember string and write its negative length and bytes + p.strIndex[s] = len(p.strIndex) + p.rawInt64(-int64(len(s))) + for i := 0; i < len(s); i++ { + p.rawByte(s[i]) + } +} + +// marker emits a marker byte and position information which makes +// it easy for a reader to detect if it is "out of sync". Used for +// debugFormat format only. +func (p *exporter) marker(m byte) { + p.rawByte(m) + // Enable this for help tracking down the location + // of an incorrect marker when running in debugFormat. + if false && trace { + p.tracef("#%d ", p.written) + } + p.rawInt64(int64(p.written)) +} + +// rawInt64 should only be used by low-level encoders. +func (p *exporter) rawInt64(x int64) { + var tmp [binary.MaxVarintLen64]byte + n := binary.PutVarint(tmp[:], x) + for i := 0; i < n; i++ { + p.rawByte(tmp[i]) + } +} + +// rawStringln should only be used to emit the initial version string. +func (p *exporter) rawStringln(s string) { + for i := 0; i < len(s); i++ { + p.rawByte(s[i]) + } + p.rawByte('\n') +} + +// rawByte is the bottleneck interface to write to p.out. +// rawByte escapes b as follows (any encoding does that +// hides '$'): +// +// '$' => '|' 'S' +// '|' => '|' '|' +// +// Necessary so other tools can find the end of the +// export data by searching for "$$". +// rawByte should only be used by low-level encoders. +func (p *exporter) rawByte(b byte) { + switch b { + case '$': + // write '$' as '|' 'S' + b = 'S' + fallthrough + case '|': + // write '|' as '|' '|' + p.out.WriteByte('|') + p.written++ + } + p.out.WriteByte(b) + p.written++ +} + +// tracef is like fmt.Printf but it rewrites the format string +// to take care of indentation. +func (p *exporter) tracef(format string, args ...interface{}) { + if strings.ContainsAny(format, "<>\n") { + var buf bytes.Buffer + for i := 0; i < len(format); i++ { + // no need to deal with runes + ch := format[i] + switch ch { + case '>': + p.indent++ + continue + case '<': + p.indent-- + continue + } + buf.WriteByte(ch) + if ch == '\n' { + for j := p.indent; j > 0; j-- { + buf.WriteString(". ") + } + } + } + format = buf.String() + } + fmt.Printf(format, args...) +} + +// Debugging support. +// (tagString is only used when tracing is enabled) +var tagString = [...]string{ + // Packages + -packageTag: "package", + + // Types + -namedTag: "named type", + -arrayTag: "array", + -sliceTag: "slice", + -dddTag: "ddd", + -structTag: "struct", + -pointerTag: "pointer", + -signatureTag: "signature", + -interfaceTag: "interface", + -mapTag: "map", + -chanTag: "chan", + + // Values + -falseTag: "false", + -trueTag: "true", + -int64Tag: "int64", + -floatTag: "float", + -fractionTag: "fraction", + -complexTag: "complex", + -stringTag: "string", + -unknownTag: "unknown", + + // Type aliases + -aliasTag: "alias", +} diff --git a/vendor/golang.org/x/tools/go/gcimporter15/bimport.go b/vendor/golang.org/x/tools/go/gcimporter15/bimport.go new file mode 100644 index 00000000000..1936a7f6c97 --- /dev/null +++ b/vendor/golang.org/x/tools/go/gcimporter15/bimport.go @@ -0,0 +1,993 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// This file is a copy of $GOROOT/src/go/internal/gcimporter/bimport.go. + +package gcimporter + +import ( + "encoding/binary" + "fmt" + "go/constant" + "go/token" + "go/types" + "sort" + "strconv" + "strings" + "sync" + "unicode" + "unicode/utf8" +) + +type importer struct { + imports map[string]*types.Package + data []byte + importpath string + buf []byte // for reading strings + version int // export format version + + // object lists + strList []string // in order of appearance + pathList []string // in order of appearance + pkgList []*types.Package // in order of appearance + typList []types.Type // in order of appearance + interfaceList []*types.Interface // for delayed completion only + trackAllTypes bool + + // position encoding + posInfoFormat bool + prevFile string + prevLine int + fset *token.FileSet + files map[string]*token.File + + // debugging support + debugFormat bool + read int // bytes read +} + +// BImportData imports a package from the serialized package data +// and returns the number of bytes consumed and a reference to the package. +// If the export data version is not recognized or the format is otherwise +// compromised, an error is returned. +func BImportData(fset *token.FileSet, imports map[string]*types.Package, data []byte, path string) (_ int, pkg *types.Package, err error) { + // catch panics and return them as errors + defer func() { + if e := recover(); e != nil { + // The package (filename) causing the problem is added to this + // error by a wrapper in the caller (Import in gcimporter.go). + // Return a (possibly nil or incomplete) package unchanged (see #16088). + err = fmt.Errorf("cannot import, possibly version skew (%v) - reinstall package", e) + } + }() + + p := importer{ + imports: imports, + data: data, + importpath: path, + version: -1, // unknown version + strList: []string{""}, // empty string is mapped to 0 + pathList: []string{""}, // empty string is mapped to 0 + fset: fset, + files: make(map[string]*token.File), + } + + // read version info + var versionstr string + if b := p.rawByte(); b == 'c' || b == 'd' { + // Go1.7 encoding; first byte encodes low-level + // encoding format (compact vs debug). + // For backward-compatibility only (avoid problems with + // old installed packages). Newly compiled packages use + // the extensible format string. + // TODO(gri) Remove this support eventually; after Go1.8. + if b == 'd' { + p.debugFormat = true + } + p.trackAllTypes = p.rawByte() == 'a' + p.posInfoFormat = p.int() != 0 + versionstr = p.string() + if versionstr == "v1" { + p.version = 0 + } + } else { + // Go1.8 extensible encoding + // read version string and extract version number (ignore anything after the version number) + versionstr = p.rawStringln(b) + if s := strings.SplitN(versionstr, " ", 3); len(s) >= 2 && s[0] == "version" { + if v, err := strconv.Atoi(s[1]); err == nil && v > 0 { + p.version = v + } + } + } + + // read version specific flags - extend as necessary + switch p.version { + // case 6: + // ... + // fallthrough + case 5, 4, 3, 2, 1: + p.debugFormat = p.rawStringln(p.rawByte()) == "debug" + p.trackAllTypes = p.int() != 0 + p.posInfoFormat = p.int() != 0 + case 0: + // Go1.7 encoding format - nothing to do here + default: + errorf("unknown export format version %d (%q)", p.version, versionstr) + } + + // --- generic export data --- + + // populate typList with predeclared "known" types + p.typList = append(p.typList, predeclared...) + + // read package data + pkg = p.pkg() + + // read objects of phase 1 only (see cmd/compiler/internal/gc/bexport.go) + objcount := 0 + for { + tag := p.tagOrIndex() + if tag == endTag { + break + } + p.obj(tag) + objcount++ + } + + // self-verification + if count := p.int(); count != objcount { + errorf("got %d objects; want %d", objcount, count) + } + + // ignore compiler-specific import data + + // complete interfaces + // TODO(gri) re-investigate if we still need to do this in a delayed fashion + for _, typ := range p.interfaceList { + typ.Complete() + } + + // record all referenced packages as imports + list := append(([]*types.Package)(nil), p.pkgList[1:]...) + sort.Sort(byPath(list)) + pkg.SetImports(list) + + // package was imported completely and without errors + pkg.MarkComplete() + + return p.read, pkg, nil +} + +func errorf(format string, args ...interface{}) { + panic(fmt.Sprintf(format, args...)) +} + +func (p *importer) pkg() *types.Package { + // if the package was seen before, i is its index (>= 0) + i := p.tagOrIndex() + if i >= 0 { + return p.pkgList[i] + } + + // otherwise, i is the package tag (< 0) + if i != packageTag { + errorf("unexpected package tag %d version %d", i, p.version) + } + + // read package data + name := p.string() + var path string + if p.version >= 5 { + path = p.path() + } else { + path = p.string() + } + + // we should never see an empty package name + if name == "" { + errorf("empty package name in import") + } + + // an empty path denotes the package we are currently importing; + // it must be the first package we see + if (path == "") != (len(p.pkgList) == 0) { + errorf("package path %q for pkg index %d", path, len(p.pkgList)) + } + + // if the package was imported before, use that one; otherwise create a new one + if path == "" { + path = p.importpath + } + pkg := p.imports[path] + if pkg == nil { + pkg = types.NewPackage(path, name) + p.imports[path] = pkg + } else if pkg.Name() != name { + errorf("conflicting names %s and %s for package %q", pkg.Name(), name, path) + } + p.pkgList = append(p.pkgList, pkg) + + return pkg +} + +// objTag returns the tag value for each object kind. +func objTag(obj types.Object) int { + switch obj.(type) { + case *types.Const: + return constTag + case *types.TypeName: + return typeTag + case *types.Var: + return varTag + case *types.Func: + return funcTag + default: + errorf("unexpected object: %v (%T)", obj, obj) // panics + panic("unreachable") + } +} + +func sameObj(a, b types.Object) bool { + // Because unnamed types are not canonicalized, we cannot simply compare types for + // (pointer) identity. + // Ideally we'd check equality of constant values as well, but this is good enough. + return objTag(a) == objTag(b) && types.Identical(a.Type(), b.Type()) +} + +func (p *importer) declare(obj types.Object) { + pkg := obj.Pkg() + if alt := pkg.Scope().Insert(obj); alt != nil { + // This can only trigger if we import a (non-type) object a second time. + // Excluding type aliases, this cannot happen because 1) we only import a package + // once; and b) we ignore compiler-specific export data which may contain + // functions whose inlined function bodies refer to other functions that + // were already imported. + // However, type aliases require reexporting the original type, so we need + // to allow it (see also the comment in cmd/compile/internal/gc/bimport.go, + // method importer.obj, switch case importing functions). + // TODO(gri) review/update this comment once the gc compiler handles type aliases. + if !sameObj(obj, alt) { + errorf("inconsistent import:\n\t%v\npreviously imported as:\n\t%v\n", obj, alt) + } + } +} + +func (p *importer) obj(tag int) { + switch tag { + case constTag: + pos := p.pos() + pkg, name := p.qualifiedName() + typ := p.typ(nil) + val := p.value() + p.declare(types.NewConst(pos, pkg, name, typ, val)) + + case aliasTag: + // TODO(gri) verify type alias hookup is correct + pos := p.pos() + pkg, name := p.qualifiedName() + typ := p.typ(nil) + p.declare(types.NewTypeName(pos, pkg, name, typ)) + + case typeTag: + p.typ(nil) + + case varTag: + pos := p.pos() + pkg, name := p.qualifiedName() + typ := p.typ(nil) + p.declare(types.NewVar(pos, pkg, name, typ)) + + case funcTag: + pos := p.pos() + pkg, name := p.qualifiedName() + params, isddd := p.paramList() + result, _ := p.paramList() + sig := types.NewSignature(nil, params, result, isddd) + p.declare(types.NewFunc(pos, pkg, name, sig)) + + default: + errorf("unexpected object tag %d", tag) + } +} + +const deltaNewFile = -64 // see cmd/compile/internal/gc/bexport.go + +func (p *importer) pos() token.Pos { + if !p.posInfoFormat { + return token.NoPos + } + + file := p.prevFile + line := p.prevLine + delta := p.int() + line += delta + if p.version >= 5 { + if delta == deltaNewFile { + if n := p.int(); n >= 0 { + // file changed + file = p.path() + line = n + } + } + } else { + if delta == 0 { + if n := p.int(); n >= 0 { + // file changed + file = p.prevFile[:n] + p.string() + line = p.int() + } + } + } + p.prevFile = file + p.prevLine = line + + // Synthesize a token.Pos + + // Since we don't know the set of needed file positions, we + // reserve maxlines positions per file. + const maxlines = 64 * 1024 + f := p.files[file] + if f == nil { + f = p.fset.AddFile(file, -1, maxlines) + p.files[file] = f + // Allocate the fake linebreak indices on first use. + // TODO(adonovan): opt: save ~512KB using a more complex scheme? + fakeLinesOnce.Do(func() { + fakeLines = make([]int, maxlines) + for i := range fakeLines { + fakeLines[i] = i + } + }) + f.SetLines(fakeLines) + } + + if line > maxlines { + line = 1 + } + + // Treat the file as if it contained only newlines + // and column=1: use the line number as the offset. + return f.Pos(line - 1) +} + +var ( + fakeLines []int + fakeLinesOnce sync.Once +) + +func (p *importer) qualifiedName() (pkg *types.Package, name string) { + name = p.string() + pkg = p.pkg() + return +} + +func (p *importer) record(t types.Type) { + p.typList = append(p.typList, t) +} + +// A dddSlice is a types.Type representing ...T parameters. +// It only appears for parameter types and does not escape +// the importer. +type dddSlice struct { + elem types.Type +} + +func (t *dddSlice) Underlying() types.Type { return t } +func (t *dddSlice) String() string { return "..." + t.elem.String() } + +// parent is the package which declared the type; parent == nil means +// the package currently imported. The parent package is needed for +// exported struct fields and interface methods which don't contain +// explicit package information in the export data. +func (p *importer) typ(parent *types.Package) types.Type { + // if the type was seen before, i is its index (>= 0) + i := p.tagOrIndex() + if i >= 0 { + return p.typList[i] + } + + // otherwise, i is the type tag (< 0) + switch i { + case namedTag: + // read type object + pos := p.pos() + parent, name := p.qualifiedName() + scope := parent.Scope() + obj := scope.Lookup(name) + + // if the object doesn't exist yet, create and insert it + if obj == nil { + obj = types.NewTypeName(pos, parent, name, nil) + scope.Insert(obj) + } + + if _, ok := obj.(*types.TypeName); !ok { + errorf("pkg = %s, name = %s => %s", parent, name, obj) + } + + // associate new named type with obj if it doesn't exist yet + t0 := types.NewNamed(obj.(*types.TypeName), nil, nil) + + // but record the existing type, if any + t := obj.Type().(*types.Named) + p.record(t) + + // read underlying type + t0.SetUnderlying(p.typ(parent)) + + // interfaces don't have associated methods + if types.IsInterface(t0) { + return t + } + + // read associated methods + for i := p.int(); i > 0; i-- { + // TODO(gri) replace this with something closer to fieldName + pos := p.pos() + name := p.string() + if !exported(name) { + p.pkg() + } + + recv, _ := p.paramList() // TODO(gri) do we need a full param list for the receiver? + params, isddd := p.paramList() + result, _ := p.paramList() + p.int() // go:nointerface pragma - discarded + + sig := types.NewSignature(recv.At(0), params, result, isddd) + t0.AddMethod(types.NewFunc(pos, parent, name, sig)) + } + + return t + + case arrayTag: + t := new(types.Array) + if p.trackAllTypes { + p.record(t) + } + + n := p.int64() + *t = *types.NewArray(p.typ(parent), n) + return t + + case sliceTag: + t := new(types.Slice) + if p.trackAllTypes { + p.record(t) + } + + *t = *types.NewSlice(p.typ(parent)) + return t + + case dddTag: + t := new(dddSlice) + if p.trackAllTypes { + p.record(t) + } + + t.elem = p.typ(parent) + return t + + case structTag: + t := new(types.Struct) + if p.trackAllTypes { + p.record(t) + } + + *t = *types.NewStruct(p.fieldList(parent)) + return t + + case pointerTag: + t := new(types.Pointer) + if p.trackAllTypes { + p.record(t) + } + + *t = *types.NewPointer(p.typ(parent)) + return t + + case signatureTag: + t := new(types.Signature) + if p.trackAllTypes { + p.record(t) + } + + params, isddd := p.paramList() + result, _ := p.paramList() + *t = *types.NewSignature(nil, params, result, isddd) + return t + + case interfaceTag: + // Create a dummy entry in the type list. This is safe because we + // cannot expect the interface type to appear in a cycle, as any + // such cycle must contain a named type which would have been + // first defined earlier. + n := len(p.typList) + if p.trackAllTypes { + p.record(nil) + } + + var embeddeds []*types.Named + for n := p.int(); n > 0; n-- { + p.pos() + embeddeds = append(embeddeds, p.typ(parent).(*types.Named)) + } + + t := types.NewInterface(p.methodList(parent), embeddeds) + p.interfaceList = append(p.interfaceList, t) + if p.trackAllTypes { + p.typList[n] = t + } + return t + + case mapTag: + t := new(types.Map) + if p.trackAllTypes { + p.record(t) + } + + key := p.typ(parent) + val := p.typ(parent) + *t = *types.NewMap(key, val) + return t + + case chanTag: + t := new(types.Chan) + if p.trackAllTypes { + p.record(t) + } + + var dir types.ChanDir + // tag values must match the constants in cmd/compile/internal/gc/go.go + switch d := p.int(); d { + case 1 /* Crecv */ : + dir = types.RecvOnly + case 2 /* Csend */ : + dir = types.SendOnly + case 3 /* Cboth */ : + dir = types.SendRecv + default: + errorf("unexpected channel dir %d", d) + } + val := p.typ(parent) + *t = *types.NewChan(dir, val) + return t + + default: + errorf("unexpected type tag %d", i) // panics + panic("unreachable") + } +} + +func (p *importer) fieldList(parent *types.Package) (fields []*types.Var, tags []string) { + if n := p.int(); n > 0 { + fields = make([]*types.Var, n) + tags = make([]string, n) + for i := range fields { + fields[i], tags[i] = p.field(parent) + } + } + return +} + +func (p *importer) field(parent *types.Package) (*types.Var, string) { + pos := p.pos() + pkg, name, alias := p.fieldName(parent) + typ := p.typ(parent) + tag := p.string() + + anonymous := false + if name == "" { + // anonymous field - typ must be T or *T and T must be a type name + switch typ := deref(typ).(type) { + case *types.Basic: // basic types are named types + pkg = nil // // objects defined in Universe scope have no package + name = typ.Name() + case *types.Named: + name = typ.Obj().Name() + default: + errorf("named base type expected") + } + anonymous = true + } else if alias { + // anonymous field: we have an explicit name because it's an alias + anonymous = true + } + + return types.NewField(pos, pkg, name, typ, anonymous), tag +} + +func (p *importer) methodList(parent *types.Package) (methods []*types.Func) { + if n := p.int(); n > 0 { + methods = make([]*types.Func, n) + for i := range methods { + methods[i] = p.method(parent) + } + } + return +} + +func (p *importer) method(parent *types.Package) *types.Func { + pos := p.pos() + pkg, name, _ := p.fieldName(parent) + params, isddd := p.paramList() + result, _ := p.paramList() + sig := types.NewSignature(nil, params, result, isddd) + return types.NewFunc(pos, pkg, name, sig) +} + +func (p *importer) fieldName(parent *types.Package) (pkg *types.Package, name string, alias bool) { + name = p.string() + pkg = parent + if pkg == nil { + // use the imported package instead + pkg = p.pkgList[0] + } + if p.version == 0 && name == "_" { + // version 0 didn't export a package for _ fields + return + } + switch name { + case "": + // 1) field name matches base type name and is exported: nothing to do + case "?": + // 2) field name matches base type name and is not exported: need package + name = "" + pkg = p.pkg() + case "@": + // 3) field name doesn't match type name (alias) + name = p.string() + alias = true + fallthrough + default: + if !exported(name) { + pkg = p.pkg() + } + } + return +} + +func (p *importer) paramList() (*types.Tuple, bool) { + n := p.int() + if n == 0 { + return nil, false + } + // negative length indicates unnamed parameters + named := true + if n < 0 { + n = -n + named = false + } + // n > 0 + params := make([]*types.Var, n) + isddd := false + for i := range params { + params[i], isddd = p.param(named) + } + return types.NewTuple(params...), isddd +} + +func (p *importer) param(named bool) (*types.Var, bool) { + t := p.typ(nil) + td, isddd := t.(*dddSlice) + if isddd { + t = types.NewSlice(td.elem) + } + + var pkg *types.Package + var name string + if named { + name = p.string() + if name == "" { + errorf("expected named parameter") + } + if name != "_" { + pkg = p.pkg() + } + if i := strings.Index(name, "·"); i > 0 { + name = name[:i] // cut off gc-specific parameter numbering + } + } + + // read and discard compiler-specific info + p.string() + + return types.NewVar(token.NoPos, pkg, name, t), isddd +} + +func exported(name string) bool { + ch, _ := utf8.DecodeRuneInString(name) + return unicode.IsUpper(ch) +} + +func (p *importer) value() constant.Value { + switch tag := p.tagOrIndex(); tag { + case falseTag: + return constant.MakeBool(false) + case trueTag: + return constant.MakeBool(true) + case int64Tag: + return constant.MakeInt64(p.int64()) + case floatTag: + return p.float() + case complexTag: + re := p.float() + im := p.float() + return constant.BinaryOp(re, token.ADD, constant.MakeImag(im)) + case stringTag: + return constant.MakeString(p.string()) + case unknownTag: + return constant.MakeUnknown() + default: + errorf("unexpected value tag %d", tag) // panics + panic("unreachable") + } +} + +func (p *importer) float() constant.Value { + sign := p.int() + if sign == 0 { + return constant.MakeInt64(0) + } + + exp := p.int() + mant := []byte(p.string()) // big endian + + // remove leading 0's if any + for len(mant) > 0 && mant[0] == 0 { + mant = mant[1:] + } + + // convert to little endian + // TODO(gri) go/constant should have a more direct conversion function + // (e.g., once it supports a big.Float based implementation) + for i, j := 0, len(mant)-1; i < j; i, j = i+1, j-1 { + mant[i], mant[j] = mant[j], mant[i] + } + + // adjust exponent (constant.MakeFromBytes creates an integer value, + // but mant represents the mantissa bits such that 0.5 <= mant < 1.0) + exp -= len(mant) << 3 + if len(mant) > 0 { + for msd := mant[len(mant)-1]; msd&0x80 == 0; msd <<= 1 { + exp++ + } + } + + x := constant.MakeFromBytes(mant) + switch { + case exp < 0: + d := constant.Shift(constant.MakeInt64(1), token.SHL, uint(-exp)) + x = constant.BinaryOp(x, token.QUO, d) + case exp > 0: + x = constant.Shift(x, token.SHL, uint(exp)) + } + + if sign < 0 { + x = constant.UnaryOp(token.SUB, x, 0) + } + return x +} + +// ---------------------------------------------------------------------------- +// Low-level decoders + +func (p *importer) tagOrIndex() int { + if p.debugFormat { + p.marker('t') + } + + return int(p.rawInt64()) +} + +func (p *importer) int() int { + x := p.int64() + if int64(int(x)) != x { + errorf("exported integer too large") + } + return int(x) +} + +func (p *importer) int64() int64 { + if p.debugFormat { + p.marker('i') + } + + return p.rawInt64() +} + +func (p *importer) path() string { + if p.debugFormat { + p.marker('p') + } + // if the path was seen before, i is its index (>= 0) + // (the empty string is at index 0) + i := p.rawInt64() + if i >= 0 { + return p.pathList[i] + } + // otherwise, i is the negative path length (< 0) + a := make([]string, -i) + for n := range a { + a[n] = p.string() + } + s := strings.Join(a, "/") + p.pathList = append(p.pathList, s) + return s +} + +func (p *importer) string() string { + if p.debugFormat { + p.marker('s') + } + // if the string was seen before, i is its index (>= 0) + // (the empty string is at index 0) + i := p.rawInt64() + if i >= 0 { + return p.strList[i] + } + // otherwise, i is the negative string length (< 0) + if n := int(-i); n <= cap(p.buf) { + p.buf = p.buf[:n] + } else { + p.buf = make([]byte, n) + } + for i := range p.buf { + p.buf[i] = p.rawByte() + } + s := string(p.buf) + p.strList = append(p.strList, s) + return s +} + +func (p *importer) marker(want byte) { + if got := p.rawByte(); got != want { + errorf("incorrect marker: got %c; want %c (pos = %d)", got, want, p.read) + } + + pos := p.read + if n := int(p.rawInt64()); n != pos { + errorf("incorrect position: got %d; want %d", n, pos) + } +} + +// rawInt64 should only be used by low-level decoders. +func (p *importer) rawInt64() int64 { + i, err := binary.ReadVarint(p) + if err != nil { + errorf("read error: %v", err) + } + return i +} + +// rawStringln should only be used to read the initial version string. +func (p *importer) rawStringln(b byte) string { + p.buf = p.buf[:0] + for b != '\n' { + p.buf = append(p.buf, b) + b = p.rawByte() + } + return string(p.buf) +} + +// needed for binary.ReadVarint in rawInt64 +func (p *importer) ReadByte() (byte, error) { + return p.rawByte(), nil +} + +// byte is the bottleneck interface for reading p.data. +// It unescapes '|' 'S' to '$' and '|' '|' to '|'. +// rawByte should only be used by low-level decoders. +func (p *importer) rawByte() byte { + b := p.data[0] + r := 1 + if b == '|' { + b = p.data[1] + r = 2 + switch b { + case 'S': + b = '$' + case '|': + // nothing to do + default: + errorf("unexpected escape sequence in export data") + } + } + p.data = p.data[r:] + p.read += r + return b + +} + +// ---------------------------------------------------------------------------- +// Export format + +// Tags. Must be < 0. +const ( + // Objects + packageTag = -(iota + 1) + constTag + typeTag + varTag + funcTag + endTag + + // Types + namedTag + arrayTag + sliceTag + dddTag + structTag + pointerTag + signatureTag + interfaceTag + mapTag + chanTag + + // Values + falseTag + trueTag + int64Tag + floatTag + fractionTag // not used by gc + complexTag + stringTag + nilTag // only used by gc (appears in exported inlined function bodies) + unknownTag // not used by gc (only appears in packages with errors) + + // Type aliases + aliasTag +) + +var predeclared = []types.Type{ + // basic types + types.Typ[types.Bool], + types.Typ[types.Int], + types.Typ[types.Int8], + types.Typ[types.Int16], + types.Typ[types.Int32], + types.Typ[types.Int64], + types.Typ[types.Uint], + types.Typ[types.Uint8], + types.Typ[types.Uint16], + types.Typ[types.Uint32], + types.Typ[types.Uint64], + types.Typ[types.Uintptr], + types.Typ[types.Float32], + types.Typ[types.Float64], + types.Typ[types.Complex64], + types.Typ[types.Complex128], + types.Typ[types.String], + + // basic type aliases + types.Universe.Lookup("byte").Type(), + types.Universe.Lookup("rune").Type(), + + // error + types.Universe.Lookup("error").Type(), + + // untyped types + types.Typ[types.UntypedBool], + types.Typ[types.UntypedInt], + types.Typ[types.UntypedRune], + types.Typ[types.UntypedFloat], + types.Typ[types.UntypedComplex], + types.Typ[types.UntypedString], + types.Typ[types.UntypedNil], + + // package unsafe + types.Typ[types.UnsafePointer], + + // invalid type + types.Typ[types.Invalid], // only appears in packages with errors + + // used internally by gc; never used by this package or in .a files + anyType{}, +} + +type anyType struct{} + +func (t anyType) Underlying() types.Type { return t } +func (t anyType) String() string { return "any" } diff --git a/vendor/golang.org/x/tools/go/gcimporter15/exportdata.go b/vendor/golang.org/x/tools/go/gcimporter15/exportdata.go new file mode 100644 index 00000000000..f33dc5613e7 --- /dev/null +++ b/vendor/golang.org/x/tools/go/gcimporter15/exportdata.go @@ -0,0 +1,93 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// This file is a copy of $GOROOT/src/go/internal/gcimporter/exportdata.go. + +// This file implements FindExportData. + +package gcimporter + +import ( + "bufio" + "fmt" + "io" + "strconv" + "strings" +) + +func readGopackHeader(r *bufio.Reader) (name string, size int, err error) { + // See $GOROOT/include/ar.h. + hdr := make([]byte, 16+12+6+6+8+10+2) + _, err = io.ReadFull(r, hdr) + if err != nil { + return + } + // leave for debugging + if false { + fmt.Printf("header: %s", hdr) + } + s := strings.TrimSpace(string(hdr[16+12+6+6+8:][:10])) + size, err = strconv.Atoi(s) + if err != nil || hdr[len(hdr)-2] != '`' || hdr[len(hdr)-1] != '\n' { + err = fmt.Errorf("invalid archive header") + return + } + name = strings.TrimSpace(string(hdr[:16])) + return +} + +// FindExportData positions the reader r at the beginning of the +// export data section of an underlying GC-created object/archive +// file by reading from it. The reader must be positioned at the +// start of the file before calling this function. The hdr result +// is the string before the export data, either "$$" or "$$B". +// +func FindExportData(r *bufio.Reader) (hdr string, err error) { + // Read first line to make sure this is an object file. + line, err := r.ReadSlice('\n') + if err != nil { + err = fmt.Errorf("can't find export data (%v)", err) + return + } + + if string(line) == "!\n" { + // Archive file. Scan to __.PKGDEF. + var name string + if name, _, err = readGopackHeader(r); err != nil { + return + } + + // First entry should be __.PKGDEF. + if name != "__.PKGDEF" { + err = fmt.Errorf("go archive is missing __.PKGDEF") + return + } + + // Read first line of __.PKGDEF data, so that line + // is once again the first line of the input. + if line, err = r.ReadSlice('\n'); err != nil { + err = fmt.Errorf("can't find export data (%v)", err) + return + } + } + + // Now at __.PKGDEF in archive or still at beginning of file. + // Either way, line should begin with "go object ". + if !strings.HasPrefix(string(line), "go object ") { + err = fmt.Errorf("not a Go object file") + return + } + + // Skip over object header to export data. + // Begins after first line starting with $$. + for line[0] != '$' { + if line, err = r.ReadSlice('\n'); err != nil { + err = fmt.Errorf("can't find export data (%v)", err) + return + } + } + hdr = string(line) + + return +} diff --git a/vendor/golang.org/x/tools/go/gcimporter15/gcimporter.go b/vendor/golang.org/x/tools/go/gcimporter15/gcimporter.go new file mode 100644 index 00000000000..370203b9d92 --- /dev/null +++ b/vendor/golang.org/x/tools/go/gcimporter15/gcimporter.go @@ -0,0 +1,1041 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// This file is a copy of $GOROOT/src/go/internal/gcimporter/gcimporter.go, +// but it also contains the original source-based importer code for Go1.6. +// Once we stop supporting 1.6, we can remove that code. + +// Package gcimporter15 provides various functions for reading +// gc-generated object files that can be used to implement the +// Importer interface defined by the Go 1.5 standard library package. +// +// Deprecated: this package will be deleted in October 2017. +// New code should use golang.org/x/tools/go/gcexportdata. +// +package gcimporter + +import ( + "bufio" + "errors" + "fmt" + "go/build" + exact "go/constant" + "go/token" + "go/types" + "io" + "io/ioutil" + "os" + "path/filepath" + "sort" + "strconv" + "strings" + "text/scanner" +) + +// debugging/development support +const debug = false + +var pkgExts = [...]string{".a", ".o"} + +// FindPkg returns the filename and unique package id for an import +// path based on package information provided by build.Import (using +// the build.Default build.Context). A relative srcDir is interpreted +// relative to the current working directory. +// If no file was found, an empty filename is returned. +// +func FindPkg(path, srcDir string) (filename, id string) { + if path == "" { + return + } + + var noext string + switch { + default: + // "x" -> "$GOPATH/pkg/$GOOS_$GOARCH/x.ext", "x" + // Don't require the source files to be present. + if abs, err := filepath.Abs(srcDir); err == nil { // see issue 14282 + srcDir = abs + } + bp, _ := build.Import(path, srcDir, build.FindOnly|build.AllowBinary) + if bp.PkgObj == "" { + return + } + noext = strings.TrimSuffix(bp.PkgObj, ".a") + id = bp.ImportPath + + case build.IsLocalImport(path): + // "./x" -> "/this/directory/x.ext", "/this/directory/x" + noext = filepath.Join(srcDir, path) + id = noext + + case filepath.IsAbs(path): + // for completeness only - go/build.Import + // does not support absolute imports + // "/x" -> "/x.ext", "/x" + noext = path + id = path + } + + if false { // for debugging + if path != id { + fmt.Printf("%s -> %s\n", path, id) + } + } + + // try extensions + for _, ext := range pkgExts { + filename = noext + ext + if f, err := os.Stat(filename); err == nil && !f.IsDir() { + return + } + } + + filename = "" // not found + return +} + +// ImportData imports a package by reading the gc-generated export data, +// adds the corresponding package object to the packages map indexed by id, +// and returns the object. +// +// The packages map must contains all packages already imported. The data +// reader position must be the beginning of the export data section. The +// filename is only used in error messages. +// +// If packages[id] contains the completely imported package, that package +// can be used directly, and there is no need to call this function (but +// there is also no harm but for extra time used). +// +func ImportData(packages map[string]*types.Package, filename, id string, data io.Reader) (pkg *types.Package, err error) { + // support for parser error handling + defer func() { + switch r := recover().(type) { + case nil: + // nothing to do + case importError: + err = r + default: + panic(r) // internal error + } + }() + + var p parser + p.init(filename, id, data, packages) + pkg = p.parseExport() + + return +} + +// Import imports a gc-generated package given its import path and srcDir, adds +// the corresponding package object to the packages map, and returns the object. +// The packages map must contain all packages already imported. +// +func Import(packages map[string]*types.Package, path, srcDir string) (pkg *types.Package, err error) { + filename, id := FindPkg(path, srcDir) + if filename == "" { + if path == "unsafe" { + return types.Unsafe, nil + } + err = fmt.Errorf("can't find import: %s", id) + return + } + + // no need to re-import if the package was imported completely before + if pkg = packages[id]; pkg != nil && pkg.Complete() { + return + } + + // open file + f, err := os.Open(filename) + if err != nil { + return + } + defer func() { + f.Close() + if err != nil { + // add file name to error + err = fmt.Errorf("reading export data: %s: %v", filename, err) + } + }() + + var hdr string + buf := bufio.NewReader(f) + if hdr, err = FindExportData(buf); err != nil { + return + } + + switch hdr { + case "$$\n": + return ImportData(packages, filename, id, buf) + case "$$B\n": + var data []byte + data, err = ioutil.ReadAll(buf) + if err == nil { + fset := token.NewFileSet() + _, pkg, err = BImportData(fset, packages, data, id) + return + } + default: + err = fmt.Errorf("unknown export data header: %q", hdr) + } + + return +} + +// ---------------------------------------------------------------------------- +// Parser + +// TODO(gri) Imported objects don't have position information. +// Ideally use the debug table line info; alternatively +// create some fake position (or the position of the +// import). That way error messages referring to imported +// objects can print meaningful information. + +// parser parses the exports inside a gc compiler-produced +// object/archive file and populates its scope with the results. +type parser struct { + scanner scanner.Scanner + tok rune // current token + lit string // literal string; only valid for Ident, Int, String tokens + id string // package id of imported package + sharedPkgs map[string]*types.Package // package id -> package object (across importer) + localPkgs map[string]*types.Package // package id -> package object (just this package) +} + +func (p *parser) init(filename, id string, src io.Reader, packages map[string]*types.Package) { + p.scanner.Init(src) + p.scanner.Error = func(_ *scanner.Scanner, msg string) { p.error(msg) } + p.scanner.Mode = scanner.ScanIdents | scanner.ScanInts | scanner.ScanChars | scanner.ScanStrings | scanner.ScanComments | scanner.SkipComments + p.scanner.Whitespace = 1<<'\t' | 1<<' ' + p.scanner.Filename = filename // for good error messages + p.next() + p.id = id + p.sharedPkgs = packages + if debug { + // check consistency of packages map + for _, pkg := range packages { + if pkg.Name() == "" { + fmt.Printf("no package name for %s\n", pkg.Path()) + } + } + } +} + +func (p *parser) next() { + p.tok = p.scanner.Scan() + switch p.tok { + case scanner.Ident, scanner.Int, scanner.Char, scanner.String, '·': + p.lit = p.scanner.TokenText() + default: + p.lit = "" + } + if debug { + fmt.Printf("%s: %q -> %q\n", scanner.TokenString(p.tok), p.scanner.TokenText(), p.lit) + } +} + +func declTypeName(pkg *types.Package, name string) *types.TypeName { + scope := pkg.Scope() + if obj := scope.Lookup(name); obj != nil { + return obj.(*types.TypeName) + } + obj := types.NewTypeName(token.NoPos, pkg, name, nil) + // a named type may be referred to before the underlying type + // is known - set it up + types.NewNamed(obj, nil, nil) + scope.Insert(obj) + return obj +} + +// ---------------------------------------------------------------------------- +// Error handling + +// Internal errors are boxed as importErrors. +type importError struct { + pos scanner.Position + err error +} + +func (e importError) Error() string { + return fmt.Sprintf("import error %s (byte offset = %d): %s", e.pos, e.pos.Offset, e.err) +} + +func (p *parser) error(err interface{}) { + if s, ok := err.(string); ok { + err = errors.New(s) + } + // panic with a runtime.Error if err is not an error + panic(importError{p.scanner.Pos(), err.(error)}) +} + +func (p *parser) errorf(format string, args ...interface{}) { + p.error(fmt.Sprintf(format, args...)) +} + +func (p *parser) expect(tok rune) string { + lit := p.lit + if p.tok != tok { + p.errorf("expected %s, got %s (%s)", scanner.TokenString(tok), scanner.TokenString(p.tok), lit) + } + p.next() + return lit +} + +func (p *parser) expectSpecial(tok string) { + sep := 'x' // not white space + i := 0 + for i < len(tok) && p.tok == rune(tok[i]) && sep > ' ' { + sep = p.scanner.Peek() // if sep <= ' ', there is white space before the next token + p.next() + i++ + } + if i < len(tok) { + p.errorf("expected %q, got %q", tok, tok[0:i]) + } +} + +func (p *parser) expectKeyword(keyword string) { + lit := p.expect(scanner.Ident) + if lit != keyword { + p.errorf("expected keyword %s, got %q", keyword, lit) + } +} + +// ---------------------------------------------------------------------------- +// Qualified and unqualified names + +// PackageId = string_lit . +// +func (p *parser) parsePackageId() string { + id, err := strconv.Unquote(p.expect(scanner.String)) + if err != nil { + p.error(err) + } + // id == "" stands for the imported package id + // (only known at time of package installation) + if id == "" { + id = p.id + } + return id +} + +// PackageName = ident . +// +func (p *parser) parsePackageName() string { + return p.expect(scanner.Ident) +} + +// dotIdentifier = ( ident | '·' ) { ident | int | '·' } . +func (p *parser) parseDotIdent() string { + ident := "" + if p.tok != scanner.Int { + sep := 'x' // not white space + for (p.tok == scanner.Ident || p.tok == scanner.Int || p.tok == '·') && sep > ' ' { + ident += p.lit + sep = p.scanner.Peek() // if sep <= ' ', there is white space before the next token + p.next() + } + } + if ident == "" { + p.expect(scanner.Ident) // use expect() for error handling + } + return ident +} + +// QualifiedName = "@" PackageId "." ( "?" | dotIdentifier ) . +// +func (p *parser) parseQualifiedName() (id, name string) { + p.expect('@') + id = p.parsePackageId() + p.expect('.') + // Per rev f280b8a485fd (10/2/2013), qualified names may be used for anonymous fields. + if p.tok == '?' { + p.next() + } else { + name = p.parseDotIdent() + } + return +} + +// getPkg returns the package for a given id. If the package is +// not found, create the package and add it to the p.localPkgs +// and p.sharedPkgs maps. name is the (expected) name of the +// package. If name == "", the package name is expected to be +// set later via an import clause in the export data. +// +// id identifies a package, usually by a canonical package path like +// "encoding/json" but possibly by a non-canonical import path like +// "./json". +// +func (p *parser) getPkg(id, name string) *types.Package { + // package unsafe is not in the packages maps - handle explicitly + if id == "unsafe" { + return types.Unsafe + } + + pkg := p.localPkgs[id] + if pkg == nil { + // first import of id from this package + pkg = p.sharedPkgs[id] + if pkg == nil { + // first import of id by this importer; + // add (possibly unnamed) pkg to shared packages + pkg = types.NewPackage(id, name) + p.sharedPkgs[id] = pkg + } + // add (possibly unnamed) pkg to local packages + if p.localPkgs == nil { + p.localPkgs = make(map[string]*types.Package) + } + p.localPkgs[id] = pkg + } else if name != "" { + // package exists already and we have an expected package name; + // make sure names match or set package name if necessary + if pname := pkg.Name(); pname == "" { + pkg.SetName(name) + } else if pname != name { + p.errorf("%s package name mismatch: %s (given) vs %s (expected)", id, pname, name) + } + } + return pkg +} + +// parseExportedName is like parseQualifiedName, but +// the package id is resolved to an imported *types.Package. +// +func (p *parser) parseExportedName() (pkg *types.Package, name string) { + id, name := p.parseQualifiedName() + pkg = p.getPkg(id, "") + return +} + +// ---------------------------------------------------------------------------- +// Types + +// BasicType = identifier . +// +func (p *parser) parseBasicType() types.Type { + id := p.expect(scanner.Ident) + obj := types.Universe.Lookup(id) + if obj, ok := obj.(*types.TypeName); ok { + return obj.Type() + } + p.errorf("not a basic type: %s", id) + return nil +} + +// ArrayType = "[" int_lit "]" Type . +// +func (p *parser) parseArrayType(parent *types.Package) types.Type { + // "[" already consumed and lookahead known not to be "]" + lit := p.expect(scanner.Int) + p.expect(']') + elem := p.parseType(parent) + n, err := strconv.ParseInt(lit, 10, 64) + if err != nil { + p.error(err) + } + return types.NewArray(elem, n) +} + +// MapType = "map" "[" Type "]" Type . +// +func (p *parser) parseMapType(parent *types.Package) types.Type { + p.expectKeyword("map") + p.expect('[') + key := p.parseType(parent) + p.expect(']') + elem := p.parseType(parent) + return types.NewMap(key, elem) +} + +// Name = identifier | "?" | QualifiedName . +// +// For unqualified and anonymous names, the returned package is the parent +// package unless parent == nil, in which case the returned package is the +// package being imported. (The parent package is not nil if the the name +// is an unqualified struct field or interface method name belonging to a +// type declared in another package.) +// +// For qualified names, the returned package is nil (and not created if +// it doesn't exist yet) unless materializePkg is set (which creates an +// unnamed package with valid package path). In the latter case, a +// subsequent import clause is expected to provide a name for the package. +// +func (p *parser) parseName(parent *types.Package, materializePkg bool) (pkg *types.Package, name string) { + pkg = parent + if pkg == nil { + pkg = p.sharedPkgs[p.id] + } + switch p.tok { + case scanner.Ident: + name = p.lit + p.next() + case '?': + // anonymous + p.next() + case '@': + // exported name prefixed with package path + pkg = nil + var id string + id, name = p.parseQualifiedName() + if materializePkg { + pkg = p.getPkg(id, "") + } + default: + p.error("name expected") + } + return +} + +func deref(typ types.Type) types.Type { + if p, _ := typ.(*types.Pointer); p != nil { + return p.Elem() + } + return typ +} + +// Field = Name Type [ string_lit ] . +// +func (p *parser) parseField(parent *types.Package) (*types.Var, string) { + pkg, name := p.parseName(parent, true) + + if name == "_" { + // Blank fields should be package-qualified because they + // are unexported identifiers, but gc does not qualify them. + // Assuming that the ident belongs to the current package + // causes types to change during re-exporting, leading + // to spurious "can't assign A to B" errors from go/types. + // As a workaround, pretend all blank fields belong + // to the same unique dummy package. + const blankpkg = "<_>" + pkg = p.getPkg(blankpkg, blankpkg) + } + + typ := p.parseType(parent) + anonymous := false + if name == "" { + // anonymous field - typ must be T or *T and T must be a type name + switch typ := deref(typ).(type) { + case *types.Basic: // basic types are named types + pkg = nil // objects defined in Universe scope have no package + name = typ.Name() + case *types.Named: + name = typ.Obj().Name() + default: + p.errorf("anonymous field expected") + } + anonymous = true + } + tag := "" + if p.tok == scanner.String { + s := p.expect(scanner.String) + var err error + tag, err = strconv.Unquote(s) + if err != nil { + p.errorf("invalid struct tag %s: %s", s, err) + } + } + return types.NewField(token.NoPos, pkg, name, typ, anonymous), tag +} + +// StructType = "struct" "{" [ FieldList ] "}" . +// FieldList = Field { ";" Field } . +// +func (p *parser) parseStructType(parent *types.Package) types.Type { + var fields []*types.Var + var tags []string + + p.expectKeyword("struct") + p.expect('{') + for i := 0; p.tok != '}' && p.tok != scanner.EOF; i++ { + if i > 0 { + p.expect(';') + } + fld, tag := p.parseField(parent) + if tag != "" && tags == nil { + tags = make([]string, i) + } + if tags != nil { + tags = append(tags, tag) + } + fields = append(fields, fld) + } + p.expect('}') + + return types.NewStruct(fields, tags) +} + +// Parameter = ( identifier | "?" ) [ "..." ] Type [ string_lit ] . +// +func (p *parser) parseParameter() (par *types.Var, isVariadic bool) { + _, name := p.parseName(nil, false) + // remove gc-specific parameter numbering + if i := strings.Index(name, "·"); i >= 0 { + name = name[:i] + } + if p.tok == '.' { + p.expectSpecial("...") + isVariadic = true + } + typ := p.parseType(nil) + if isVariadic { + typ = types.NewSlice(typ) + } + // ignore argument tag (e.g. "noescape") + if p.tok == scanner.String { + p.next() + } + // TODO(gri) should we provide a package? + par = types.NewVar(token.NoPos, nil, name, typ) + return +} + +// Parameters = "(" [ ParameterList ] ")" . +// ParameterList = { Parameter "," } Parameter . +// +func (p *parser) parseParameters() (list []*types.Var, isVariadic bool) { + p.expect('(') + for p.tok != ')' && p.tok != scanner.EOF { + if len(list) > 0 { + p.expect(',') + } + par, variadic := p.parseParameter() + list = append(list, par) + if variadic { + if isVariadic { + p.error("... not on final argument") + } + isVariadic = true + } + } + p.expect(')') + + return +} + +// Signature = Parameters [ Result ] . +// Result = Type | Parameters . +// +func (p *parser) parseSignature(recv *types.Var) *types.Signature { + params, isVariadic := p.parseParameters() + + // optional result type + var results []*types.Var + if p.tok == '(' { + var variadic bool + results, variadic = p.parseParameters() + if variadic { + p.error("... not permitted on result type") + } + } + + return types.NewSignature(recv, types.NewTuple(params...), types.NewTuple(results...), isVariadic) +} + +// InterfaceType = "interface" "{" [ MethodList ] "}" . +// MethodList = Method { ";" Method } . +// Method = Name Signature . +// +// The methods of embedded interfaces are always "inlined" +// by the compiler and thus embedded interfaces are never +// visible in the export data. +// +func (p *parser) parseInterfaceType(parent *types.Package) types.Type { + var methods []*types.Func + + p.expectKeyword("interface") + p.expect('{') + for i := 0; p.tok != '}' && p.tok != scanner.EOF; i++ { + if i > 0 { + p.expect(';') + } + pkg, name := p.parseName(parent, true) + sig := p.parseSignature(nil) + methods = append(methods, types.NewFunc(token.NoPos, pkg, name, sig)) + } + p.expect('}') + + // Complete requires the type's embedded interfaces to be fully defined, + // but we do not define any + return types.NewInterface(methods, nil).Complete() +} + +// ChanType = ( "chan" [ "<-" ] | "<-" "chan" ) Type . +// +func (p *parser) parseChanType(parent *types.Package) types.Type { + dir := types.SendRecv + if p.tok == scanner.Ident { + p.expectKeyword("chan") + if p.tok == '<' { + p.expectSpecial("<-") + dir = types.SendOnly + } + } else { + p.expectSpecial("<-") + p.expectKeyword("chan") + dir = types.RecvOnly + } + elem := p.parseType(parent) + return types.NewChan(dir, elem) +} + +// Type = +// BasicType | TypeName | ArrayType | SliceType | StructType | +// PointerType | FuncType | InterfaceType | MapType | ChanType | +// "(" Type ")" . +// +// BasicType = ident . +// TypeName = ExportedName . +// SliceType = "[" "]" Type . +// PointerType = "*" Type . +// FuncType = "func" Signature . +// +func (p *parser) parseType(parent *types.Package) types.Type { + switch p.tok { + case scanner.Ident: + switch p.lit { + default: + return p.parseBasicType() + case "struct": + return p.parseStructType(parent) + case "func": + // FuncType + p.next() + return p.parseSignature(nil) + case "interface": + return p.parseInterfaceType(parent) + case "map": + return p.parseMapType(parent) + case "chan": + return p.parseChanType(parent) + } + case '@': + // TypeName + pkg, name := p.parseExportedName() + return declTypeName(pkg, name).Type() + case '[': + p.next() // look ahead + if p.tok == ']' { + // SliceType + p.next() + return types.NewSlice(p.parseType(parent)) + } + return p.parseArrayType(parent) + case '*': + // PointerType + p.next() + return types.NewPointer(p.parseType(parent)) + case '<': + return p.parseChanType(parent) + case '(': + // "(" Type ")" + p.next() + typ := p.parseType(parent) + p.expect(')') + return typ + } + p.errorf("expected type, got %s (%q)", scanner.TokenString(p.tok), p.lit) + return nil +} + +// ---------------------------------------------------------------------------- +// Declarations + +// ImportDecl = "import" PackageName PackageId . +// +func (p *parser) parseImportDecl() { + p.expectKeyword("import") + name := p.parsePackageName() + p.getPkg(p.parsePackageId(), name) +} + +// int_lit = [ "+" | "-" ] { "0" ... "9" } . +// +func (p *parser) parseInt() string { + s := "" + switch p.tok { + case '-': + s = "-" + p.next() + case '+': + p.next() + } + return s + p.expect(scanner.Int) +} + +// number = int_lit [ "p" int_lit ] . +// +func (p *parser) parseNumber() (typ *types.Basic, val exact.Value) { + // mantissa + mant := exact.MakeFromLiteral(p.parseInt(), token.INT, 0) + if mant == nil { + panic("invalid mantissa") + } + + if p.lit == "p" { + // exponent (base 2) + p.next() + exp, err := strconv.ParseInt(p.parseInt(), 10, 0) + if err != nil { + p.error(err) + } + if exp < 0 { + denom := exact.MakeInt64(1) + denom = exact.Shift(denom, token.SHL, uint(-exp)) + typ = types.Typ[types.UntypedFloat] + val = exact.BinaryOp(mant, token.QUO, denom) + return + } + if exp > 0 { + mant = exact.Shift(mant, token.SHL, uint(exp)) + } + typ = types.Typ[types.UntypedFloat] + val = mant + return + } + + typ = types.Typ[types.UntypedInt] + val = mant + return +} + +// ConstDecl = "const" ExportedName [ Type ] "=" Literal . +// Literal = bool_lit | int_lit | float_lit | complex_lit | rune_lit | string_lit . +// bool_lit = "true" | "false" . +// complex_lit = "(" float_lit "+" float_lit "i" ")" . +// rune_lit = "(" int_lit "+" int_lit ")" . +// string_lit = `"` { unicode_char } `"` . +// +func (p *parser) parseConstDecl() { + p.expectKeyword("const") + pkg, name := p.parseExportedName() + + var typ0 types.Type + if p.tok != '=' { + // constant types are never structured - no need for parent type + typ0 = p.parseType(nil) + } + + p.expect('=') + var typ types.Type + var val exact.Value + switch p.tok { + case scanner.Ident: + // bool_lit + if p.lit != "true" && p.lit != "false" { + p.error("expected true or false") + } + typ = types.Typ[types.UntypedBool] + val = exact.MakeBool(p.lit == "true") + p.next() + + case '-', scanner.Int: + // int_lit + typ, val = p.parseNumber() + + case '(': + // complex_lit or rune_lit + p.next() + if p.tok == scanner.Char { + p.next() + p.expect('+') + typ = types.Typ[types.UntypedRune] + _, val = p.parseNumber() + p.expect(')') + break + } + _, re := p.parseNumber() + p.expect('+') + _, im := p.parseNumber() + p.expectKeyword("i") + p.expect(')') + typ = types.Typ[types.UntypedComplex] + val = exact.BinaryOp(re, token.ADD, exact.MakeImag(im)) + + case scanner.Char: + // rune_lit + typ = types.Typ[types.UntypedRune] + val = exact.MakeFromLiteral(p.lit, token.CHAR, 0) + p.next() + + case scanner.String: + // string_lit + typ = types.Typ[types.UntypedString] + val = exact.MakeFromLiteral(p.lit, token.STRING, 0) + p.next() + + default: + p.errorf("expected literal got %s", scanner.TokenString(p.tok)) + } + + if typ0 == nil { + typ0 = typ + } + + pkg.Scope().Insert(types.NewConst(token.NoPos, pkg, name, typ0, val)) +} + +// TypeDecl = "type" ExportedName Type . +// +func (p *parser) parseTypeDecl() { + p.expectKeyword("type") + pkg, name := p.parseExportedName() + obj := declTypeName(pkg, name) + + // The type object may have been imported before and thus already + // have a type associated with it. We still need to parse the type + // structure, but throw it away if the object already has a type. + // This ensures that all imports refer to the same type object for + // a given type declaration. + typ := p.parseType(pkg) + + if name := obj.Type().(*types.Named); name.Underlying() == nil { + name.SetUnderlying(typ) + } +} + +// VarDecl = "var" ExportedName Type . +// +func (p *parser) parseVarDecl() { + p.expectKeyword("var") + pkg, name := p.parseExportedName() + typ := p.parseType(pkg) + pkg.Scope().Insert(types.NewVar(token.NoPos, pkg, name, typ)) +} + +// Func = Signature [ Body ] . +// Body = "{" ... "}" . +// +func (p *parser) parseFunc(recv *types.Var) *types.Signature { + sig := p.parseSignature(recv) + if p.tok == '{' { + p.next() + for i := 1; i > 0; p.next() { + switch p.tok { + case '{': + i++ + case '}': + i-- + } + } + } + return sig +} + +// MethodDecl = "func" Receiver Name Func . +// Receiver = "(" ( identifier | "?" ) [ "*" ] ExportedName ")" . +// +func (p *parser) parseMethodDecl() { + // "func" already consumed + p.expect('(') + recv, _ := p.parseParameter() // receiver + p.expect(')') + + // determine receiver base type object + base := deref(recv.Type()).(*types.Named) + + // parse method name, signature, and possibly inlined body + _, name := p.parseName(nil, false) + sig := p.parseFunc(recv) + + // methods always belong to the same package as the base type object + pkg := base.Obj().Pkg() + + // add method to type unless type was imported before + // and method exists already + // TODO(gri) This leads to a quadratic algorithm - ok for now because method counts are small. + base.AddMethod(types.NewFunc(token.NoPos, pkg, name, sig)) +} + +// FuncDecl = "func" ExportedName Func . +// +func (p *parser) parseFuncDecl() { + // "func" already consumed + pkg, name := p.parseExportedName() + typ := p.parseFunc(nil) + pkg.Scope().Insert(types.NewFunc(token.NoPos, pkg, name, typ)) +} + +// Decl = [ ImportDecl | ConstDecl | TypeDecl | VarDecl | FuncDecl | MethodDecl ] "\n" . +// +func (p *parser) parseDecl() { + if p.tok == scanner.Ident { + switch p.lit { + case "import": + p.parseImportDecl() + case "const": + p.parseConstDecl() + case "type": + p.parseTypeDecl() + case "var": + p.parseVarDecl() + case "func": + p.next() // look ahead + if p.tok == '(' { + p.parseMethodDecl() + } else { + p.parseFuncDecl() + } + } + } + p.expect('\n') +} + +// ---------------------------------------------------------------------------- +// Export + +// Export = "PackageClause { Decl } "$$" . +// PackageClause = "package" PackageName [ "safe" ] "\n" . +// +func (p *parser) parseExport() *types.Package { + p.expectKeyword("package") + name := p.parsePackageName() + if p.tok == scanner.Ident && p.lit == "safe" { + // package was compiled with -u option - ignore + p.next() + } + p.expect('\n') + + pkg := p.getPkg(p.id, name) + + for p.tok != '$' && p.tok != scanner.EOF { + p.parseDecl() + } + + if ch := p.scanner.Peek(); p.tok != '$' || ch != '$' { + // don't call next()/expect() since reading past the + // export data may cause scanner errors (e.g. NUL chars) + p.errorf("expected '$$', got %s %c", scanner.TokenString(p.tok), ch) + } + + if n := p.scanner.ErrorCount; n != 0 { + p.errorf("expected no scanner errors, got %d", n) + } + + // Record all locally referenced packages as imports. + var imports []*types.Package + for id, pkg2 := range p.localPkgs { + if pkg2.Name() == "" { + p.errorf("%s package has no name", id) + } + if id == p.id { + continue // avoid self-edge + } + imports = append(imports, pkg2) + } + sort.Sort(byPath(imports)) + pkg.SetImports(imports) + + // package was imported completely and without errors + pkg.MarkComplete() + + return pkg +} + +type byPath []*types.Package + +func (a byPath) Len() int { return len(a) } +func (a byPath) Swap(i, j int) { a[i], a[j] = a[j], a[i] } +func (a byPath) Less(i, j int) bool { return a[i].Path() < a[j].Path() } diff --git a/vendor/golang.org/x/tools/go/gcimporter15/isAlias18.go b/vendor/golang.org/x/tools/go/gcimporter15/isAlias18.go new file mode 100644 index 00000000000..225ffeedfa4 --- /dev/null +++ b/vendor/golang.org/x/tools/go/gcimporter15/isAlias18.go @@ -0,0 +1,13 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build !go1.9 + +package gcimporter + +import "go/types" + +func isAlias(obj *types.TypeName) bool { + return false // there are no type aliases before Go 1.9 +} diff --git a/vendor/golang.org/x/tools/go/gcimporter15/isAlias19.go b/vendor/golang.org/x/tools/go/gcimporter15/isAlias19.go new file mode 100644 index 00000000000..c2025d84a95 --- /dev/null +++ b/vendor/golang.org/x/tools/go/gcimporter15/isAlias19.go @@ -0,0 +1,13 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build go1.9 + +package gcimporter + +import "go/types" + +func isAlias(obj *types.TypeName) bool { + return obj.IsAlias() +} diff --git a/vendor/google.golang.org/api/compute/v0.alpha/BUILD b/vendor/google.golang.org/api/compute/v0.alpha/BUILD index 05eb0f7de45..f0c4411d382 100644 --- a/vendor/google.golang.org/api/compute/v0.alpha/BUILD +++ b/vendor/google.golang.org/api/compute/v0.alpha/BUILD @@ -7,8 +7,6 @@ go_library( importpath = "google.golang.org/api/compute/v0.alpha", visibility = ["//visibility:public"], deps = [ - "//vendor/golang.org/x/net/context:go_default_library", - "//vendor/golang.org/x/net/context/ctxhttp:go_default_library", "//vendor/google.golang.org/api/gensupport:go_default_library", "//vendor/google.golang.org/api/googleapi:go_default_library", ], diff --git a/vendor/google.golang.org/api/compute/v0.alpha/compute-api.json b/vendor/google.golang.org/api/compute/v0.alpha/compute-api.json index 481d09e2906..2b613a87c03 100644 --- a/vendor/google.golang.org/api/compute/v0.alpha/compute-api.json +++ b/vendor/google.golang.org/api/compute/v0.alpha/compute-api.json @@ -29,7 +29,7 @@ "description": "Creates and runs virtual machines on Google Cloud Platform.", "discoveryVersion": "v1", "documentationLink": "https://developers.google.com/compute/docs/reference/latest/", - "etag": "\"Zkyw9ACJZUvcYmlFaKGChzhmtnE/KNWJ1HZYolCRG_Vy_LaMdDtL5UU\"", + "etag": "\"J3WqvAcMk4eQjJXvfSI4Yr8VouA/Pblb0-q42Qtp25GnNdbN5oVoa5U\"", "icons": { "x16": "https://www.google.com/images/icons/product/compute_engine-16.png", "x32": "https://www.google.com/images/icons/product/compute_engine-32.png" @@ -505,9 +505,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -549,9 +549,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -571,6 +571,425 @@ } } }, + "allocations": { + "methods": { + "aggregatedList": { + "description": "Retrieves an aggregated list of allocations.", + "httpMethod": "GET", + "id": "compute.allocations.aggregatedList", + "parameterOrder": [ + "project" + ], + "parameters": { + "filter": { + "description": "A filter expression that filters resources listed in the response. The expression must specify the field name, a comparison operator, and the value that you want to use for filtering. The value must be a string, a number, or a boolean. The comparison operator must be either =, !=, \u003e, or \u003c.\n\nFor example, if you are filtering Compute Engine instances, you can exclude instances named example-instance by specifying name != example-instance.\n\nYou can also filter nested fields. For example, you could specify scheduling.automaticRestart = false to include instances only if they are not scheduled for automatic restarts. You can use filtering on nested fields to filter based on resource labels.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart = true) (cpuPlatform = \"Intel Skylake\"). By default, each expression is an AND expression. However, you can include AND and OR expressions explicitly. For example, (cpuPlatform = \"Intel Skylake\") OR (cpuPlatform = \"Intel Broadwell\") AND (scheduling.automaticRestart = true).", + "location": "query", + "type": "string" + }, + "maxResults": { + "default": "500", + "description": "The maximum number of results per page that should be returned. If the number of available results is larger than maxResults, Compute Engine returns a nextPageToken that can be used to get the next page of results in subsequent list requests. Acceptable values are 0 to 500, inclusive. (Default: 500)", + "format": "uint32", + "location": "query", + "minimum": "0", + "type": "integer" + }, + "orderBy": { + "description": "Sorts list results by a certain order. By default, results are returned in alphanumerical order based on the resource name.\n\nYou can also sort results in descending order based on the creation timestamp using orderBy=\"creationTimestamp desc\". This sorts results based on the creationTimestamp field in reverse chronological order (newest result first). Use this to sort resources like operations so that the newest operation is returned first.\n\nCurrently, only sorting by name or creationTimestamp desc is supported.", + "location": "query", + "type": "string" + }, + "pageToken": { + "description": "Specifies a page token to use. Set pageToken to the nextPageToken returned by a previous list request to get the next page of results.", + "location": "query", + "type": "string" + }, + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + } + }, + "path": "{project}/aggregated/allocations", + "response": { + "$ref": "AllocationAggregatedList" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute", + "https://www.googleapis.com/auth/compute.readonly" + ] + }, + "delete": { + "description": "Deletes the specified allocation.", + "httpMethod": "DELETE", + "id": "compute.allocations.delete", + "parameterOrder": [ + "project", + "zone", + "allocation" + ], + "parameters": { + "allocation": { + "description": "Name of the allocation to delete.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + }, + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "requestId": { + "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", + "location": "query", + "type": "string" + }, + "zone": { + "description": "Name of the zone for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + } + }, + "path": "{project}/zones/{zone}/allocations/{allocation}", + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute" + ] + }, + "get": { + "description": "Retrieves all information of the specified allocation.", + "httpMethod": "GET", + "id": "compute.allocations.get", + "parameterOrder": [ + "project", + "zone", + "allocation" + ], + "parameters": { + "allocation": { + "description": "Name of the allocation to retrieve.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + }, + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "zone": { + "description": "Name of the zone for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + } + }, + "path": "{project}/zones/{zone}/allocations/{allocation}", + "response": { + "$ref": "Allocation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute", + "https://www.googleapis.com/auth/compute.readonly" + ] + }, + "getIamPolicy": { + "description": "Gets the access control policy for a resource. May be empty if no such policy or resource exists.", + "httpMethod": "GET", + "id": "compute.allocations.getIamPolicy", + "parameterOrder": [ + "project", + "zone", + "resource" + ], + "parameters": { + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "resource": { + "description": "Name or id of the resource for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + "required": true, + "type": "string" + }, + "zone": { + "description": "The name of the zone for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + } + }, + "path": "{project}/zones/{zone}/allocations/{resource}/getIamPolicy", + "response": { + "$ref": "Policy" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute", + "https://www.googleapis.com/auth/compute.readonly" + ] + }, + "insert": { + "description": "Creates a new allocation.", + "httpMethod": "POST", + "id": "compute.allocations.insert", + "parameterOrder": [ + "project", + "zone" + ], + "parameters": { + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "requestId": { + "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", + "location": "query", + "type": "string" + }, + "zone": { + "description": "Name of the zone for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + } + }, + "path": "{project}/zones/{zone}/allocations", + "request": { + "$ref": "Allocation" + }, + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute" + ] + }, + "list": { + "description": "A list all the allocations that have been configured for the specified project in specified zone.", + "httpMethod": "GET", + "id": "compute.allocations.list", + "parameterOrder": [ + "project", + "zone" + ], + "parameters": { + "filter": { + "description": "A filter expression that filters resources listed in the response. The expression must specify the field name, a comparison operator, and the value that you want to use for filtering. The value must be a string, a number, or a boolean. The comparison operator must be either =, !=, \u003e, or \u003c.\n\nFor example, if you are filtering Compute Engine instances, you can exclude instances named example-instance by specifying name != example-instance.\n\nYou can also filter nested fields. For example, you could specify scheduling.automaticRestart = false to include instances only if they are not scheduled for automatic restarts. You can use filtering on nested fields to filter based on resource labels.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart = true) (cpuPlatform = \"Intel Skylake\"). By default, each expression is an AND expression. However, you can include AND and OR expressions explicitly. For example, (cpuPlatform = \"Intel Skylake\") OR (cpuPlatform = \"Intel Broadwell\") AND (scheduling.automaticRestart = true).", + "location": "query", + "type": "string" + }, + "maxResults": { + "default": "500", + "description": "The maximum number of results per page that should be returned. If the number of available results is larger than maxResults, Compute Engine returns a nextPageToken that can be used to get the next page of results in subsequent list requests. Acceptable values are 0 to 500, inclusive. (Default: 500)", + "format": "uint32", + "location": "query", + "minimum": "0", + "type": "integer" + }, + "orderBy": { + "description": "Sorts list results by a certain order. By default, results are returned in alphanumerical order based on the resource name.\n\nYou can also sort results in descending order based on the creation timestamp using orderBy=\"creationTimestamp desc\". This sorts results based on the creationTimestamp field in reverse chronological order (newest result first). Use this to sort resources like operations so that the newest operation is returned first.\n\nCurrently, only sorting by name or creationTimestamp desc is supported.", + "location": "query", + "type": "string" + }, + "pageToken": { + "description": "Specifies a page token to use. Set pageToken to the nextPageToken returned by a previous list request to get the next page of results.", + "location": "query", + "type": "string" + }, + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "zone": { + "description": "Name of the zone for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + } + }, + "path": "{project}/zones/{zone}/allocations", + "response": { + "$ref": "AllocationList" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute", + "https://www.googleapis.com/auth/compute.readonly" + ] + }, + "setIamPolicy": { + "description": "Sets the access control policy on the specified resource. Replaces any existing policy.", + "httpMethod": "POST", + "id": "compute.allocations.setIamPolicy", + "parameterOrder": [ + "project", + "zone", + "resource" + ], + "parameters": { + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "resource": { + "description": "Name or id of the resource for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + "required": true, + "type": "string" + }, + "zone": { + "description": "The name of the zone for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + } + }, + "path": "{project}/zones/{zone}/allocations/{resource}/setIamPolicy", + "request": { + "$ref": "ZoneSetPolicyRequest" + }, + "response": { + "$ref": "Policy" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute" + ] + }, + "testIamPermissions": { + "description": "Returns permissions that a caller has on the specified resource.", + "httpMethod": "POST", + "id": "compute.allocations.testIamPermissions", + "parameterOrder": [ + "project", + "zone", + "resource" + ], + "parameters": { + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "resource": { + "description": "Name or id of the resource for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + "required": true, + "type": "string" + }, + "zone": { + "description": "The name of the zone for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + } + }, + "path": "{project}/zones/{zone}/allocations/{resource}/testIamPermissions", + "request": { + "$ref": "TestPermissionsRequest" + }, + "response": { + "$ref": "TestPermissionsResponse" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute", + "https://www.googleapis.com/auth/compute.readonly" + ] + }, + "updateResourceShape": { + "description": "Updates the shape of an allocation.", + "httpMethod": "POST", + "id": "compute.allocations.updateResourceShape", + "parameterOrder": [ + "project", + "zone", + "allocation" + ], + "parameters": { + "allocation": { + "description": "Name of the allocation to update.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + }, + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "requestId": { + "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", + "location": "query", + "type": "string" + }, + "zone": { + "description": "Name of the zone for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + } + }, + "path": "{project}/zones/{zone}/allocations/{allocation}/updateResourceShape", + "request": { + "$ref": "AllocationsUpdateResourceShapeRequest" + }, + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute" + ] + } + } + }, "autoscalers": { "methods": { "aggregatedList": { @@ -873,9 +1292,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -952,7 +1371,7 @@ "backendBuckets": { "methods": { "addSignedUrlKey": { - "description": "Adds the given Signed URL Key to the backend bucket.", + "description": "Adds a key for validating requests with signed URLs for this backend bucket.", "httpMethod": "POST", "id": "compute.backendBuckets.addSignedUrlKey", "parameterOrder": [ @@ -1030,7 +1449,7 @@ ] }, "deleteSignedUrlKey": { - "description": "Deletes the given Signed URL Key from the backend bucket.", + "description": "Deletes a key for validating requests with signed URLs for this backend bucket.", "httpMethod": "POST", "id": "compute.backendBuckets.deleteSignedUrlKey", "parameterOrder": [ @@ -1124,9 +1543,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z0-9](?:[-a-z0-9_]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -1281,9 +1700,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z0-9](?:[-a-z0-9_]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -1317,9 +1736,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "(?:[-a-z0-9_]{0,62}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -1383,7 +1802,7 @@ "backendServices": { "methods": { "addSignedUrlKey": { - "description": "Adds the given Signed URL Key to the specified backend service.", + "description": "Adds a key for validating requests with signed URLs for this backend service.", "httpMethod": "POST", "id": "compute.backendServices.addSignedUrlKey", "parameterOrder": [ @@ -1510,7 +1929,7 @@ ] }, "deleteSignedUrlKey": { - "description": "Deletes the given Signed URL Key from the specified backend service.", + "description": "Deletes a key for validating requests with signed URLs for this backend service.", "httpMethod": "POST", "id": "compute.backendServices.deleteSignedUrlKey", "parameterOrder": [ @@ -1554,7 +1973,7 @@ ] }, "get": { - "description": "Returns the specified BackendService resource. Gets a list of available backend services by making a list() request.", + "description": "Returns the specified BackendService resource. Gets a list of available backend services.", "httpMethod": "GET", "id": "compute.backendServices.get", "parameterOrder": [ @@ -1717,7 +2136,7 @@ "backendService": { "description": "Name of the BackendService resource to patch.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -1803,9 +2222,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "(?:[-a-z0-9_]{0,62}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -2033,7 +2452,7 @@ "disk": { "description": "The disk name for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -2131,7 +2550,7 @@ "disk": { "description": "Name of the persistent disk to snapshot.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -2229,7 +2648,7 @@ "disk": { "description": "Name of the persistent disk to return.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -2276,9 +2695,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -2416,7 +2835,7 @@ "disk": { "description": "The disk name for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -2465,7 +2884,7 @@ "disk": { "description": "The name of the persistent disk.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -2519,9 +2938,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -2568,9 +2987,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -2612,9 +3031,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -2655,7 +3074,7 @@ "firewall": { "description": "Name of the firewall rule to delete.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -2693,7 +3112,7 @@ "firewall": { "description": "Name of the firewall rule to return.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -2809,7 +3228,7 @@ "firewall": { "description": "Name of the firewall rule to patch.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -2855,9 +3274,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "(?:[-a-z0-9_]{0,62}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -2887,7 +3306,7 @@ "firewall": { "description": "Name of the firewall rule to update.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -3234,9 +3653,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -3327,9 +3746,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -3522,9 +3941,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -3558,9 +3977,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "(?:[-a-z0-9_]{0,62}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -3794,9 +4213,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -3871,9 +4290,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "(?:[-a-z0-9_]{0,62}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -4093,6 +4512,143 @@ } } }, + "globalOrganizationOperations": { + "methods": { + "delete": { + "description": "Deletes the specified Operations resource.", + "httpMethod": "DELETE", + "id": "compute.globalOrganizationOperations.delete", + "parameterOrder": [ + "operation" + ], + "parameters": { + "operation": { + "description": "Name of the Operations resource to delete.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + }, + "parentId": { + "description": "Parent ID for this request.", + "location": "query", + "type": "string" + } + }, + "path": "locations/global/operations/{operation}", + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute" + ] + }, + "get": { + "description": "Retrieves the specified Operations resource. Gets a list of operations by making a list() request.", + "httpMethod": "GET", + "id": "compute.globalOrganizationOperations.get", + "parameterOrder": [ + "operation" + ], + "parameters": { + "operation": { + "description": "Name of the Operations resource to return.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + }, + "parentId": { + "description": "Parent ID for this request.", + "location": "query", + "type": "string" + } + }, + "path": "locations/global/operations/{operation}", + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute", + "https://www.googleapis.com/auth/compute.readonly" + ] + }, + "list": { + "description": "Retrieves a list of Operation resources contained within the specified organization.", + "httpMethod": "GET", + "id": "compute.globalOrganizationOperations.list", + "parameters": { + "filter": { + "description": "A filter expression that filters resources listed in the response. The expression must specify the field name, a comparison operator, and the value that you want to use for filtering. The value must be a string, a number, or a boolean. The comparison operator must be either =, !=, \u003e, or \u003c.\n\nFor example, if you are filtering Compute Engine instances, you can exclude instances named example-instance by specifying name != example-instance.\n\nYou can also filter nested fields. For example, you could specify scheduling.automaticRestart = false to include instances only if they are not scheduled for automatic restarts. You can use filtering on nested fields to filter based on resource labels.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart = true) (cpuPlatform = \"Intel Skylake\"). By default, each expression is an AND expression. However, you can include AND and OR expressions explicitly. For example, (cpuPlatform = \"Intel Skylake\") OR (cpuPlatform = \"Intel Broadwell\") AND (scheduling.automaticRestart = true).", + "location": "query", + "type": "string" + }, + "maxResults": { + "default": "500", + "description": "The maximum number of results per page that should be returned. If the number of available results is larger than maxResults, Compute Engine returns a nextPageToken that can be used to get the next page of results in subsequent list requests. Acceptable values are 0 to 500, inclusive. (Default: 500)", + "format": "uint32", + "location": "query", + "minimum": "0", + "type": "integer" + }, + "orderBy": { + "description": "Sorts list results by a certain order. By default, results are returned in alphanumerical order based on the resource name.\n\nYou can also sort results in descending order based on the creation timestamp using orderBy=\"creationTimestamp desc\". This sorts results based on the creationTimestamp field in reverse chronological order (newest result first). Use this to sort resources like operations so that the newest operation is returned first.\n\nCurrently, only sorting by name or creationTimestamp desc is supported.", + "location": "query", + "type": "string" + }, + "pageToken": { + "description": "Specifies a page token to use. Set pageToken to the nextPageToken returned by a previous list request to get the next page of results.", + "location": "query", + "type": "string" + }, + "parentId": { + "description": "Parent ID for this request.", + "location": "query", + "type": "string" + } + }, + "path": "locations/global/operations", + "response": { + "$ref": "OperationList" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute", + "https://www.googleapis.com/auth/compute.readonly" + ] + }, + "wait": { + "description": "Waits for the specified Operations resource until it is done or timeout, and retrieves the specified Operations resource. 1. Immediately returns when the operation is already done. 2. Waits for no more than the default deadline (2 minutes, subject to change) and then returns the current state of the operation, which may be DONE or still in progress. 3. Is best-effort: a. The server can wait less than the default deadline or zero seconds, in overload situations. b. There is no guarantee that the operation is actually done when returns. 4. User should be prepared to retry if the operation is not DONE.", + "httpMethod": "POST", + "id": "compute.globalOrganizationOperations.wait", + "parameterOrder": [ + "operation" + ], + "parameters": { + "operation": { + "description": "Name of the Operations resource to return.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + }, + "parentId": { + "description": "Parent ID for this request.", + "location": "query", + "type": "string" + } + }, + "path": "locations/global/operations/{operation}/wait", + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute", + "https://www.googleapis.com/auth/compute.readonly" + ] + } + } + }, "healthChecks": { "methods": { "aggregatedList": { @@ -4356,9 +4912,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "(?:[-a-z0-9_]{0,62}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -4419,528 +4975,6 @@ } } }, - "hostTypes": { - "methods": { - "aggregatedList": { - "description": "Retrieves an aggregated list of host types.", - "httpMethod": "GET", - "id": "compute.hostTypes.aggregatedList", - "parameterOrder": [ - "project" - ], - "parameters": { - "filter": { - "description": "A filter expression that filters resources listed in the response. The expression must specify the field name, a comparison operator, and the value that you want to use for filtering. The value must be a string, a number, or a boolean. The comparison operator must be either =, !=, \u003e, or \u003c.\n\nFor example, if you are filtering Compute Engine instances, you can exclude instances named example-instance by specifying name != example-instance.\n\nYou can also filter nested fields. For example, you could specify scheduling.automaticRestart = false to include instances only if they are not scheduled for automatic restarts. You can use filtering on nested fields to filter based on resource labels.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart = true) (cpuPlatform = \"Intel Skylake\"). By default, each expression is an AND expression. However, you can include AND and OR expressions explicitly. For example, (cpuPlatform = \"Intel Skylake\") OR (cpuPlatform = \"Intel Broadwell\") AND (scheduling.automaticRestart = true).", - "location": "query", - "type": "string" - }, - "maxResults": { - "default": "500", - "description": "The maximum number of results per page that should be returned. If the number of available results is larger than maxResults, Compute Engine returns a nextPageToken that can be used to get the next page of results in subsequent list requests. Acceptable values are 0 to 500, inclusive. (Default: 500)", - "format": "uint32", - "location": "query", - "minimum": "0", - "type": "integer" - }, - "orderBy": { - "description": "Sorts list results by a certain order. By default, results are returned in alphanumerical order based on the resource name.\n\nYou can also sort results in descending order based on the creation timestamp using orderBy=\"creationTimestamp desc\". This sorts results based on the creationTimestamp field in reverse chronological order (newest result first). Use this to sort resources like operations so that the newest operation is returned first.\n\nCurrently, only sorting by name or creationTimestamp desc is supported.", - "location": "query", - "type": "string" - }, - "pageToken": { - "description": "Specifies a page token to use. Set pageToken to the nextPageToken returned by a previous list request to get the next page of results.", - "location": "query", - "type": "string" - }, - "project": { - "description": "Project ID for this request.", - "location": "path", - "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", - "required": true, - "type": "string" - } - }, - "path": "{project}/aggregated/hostTypes", - "response": { - "$ref": "HostTypeAggregatedList" - }, - "scopes": [ - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/compute", - "https://www.googleapis.com/auth/compute.readonly" - ] - }, - "get": { - "description": "Returns the specified host type. Gets a list of available host types by making a list() request.", - "httpMethod": "GET", - "id": "compute.hostTypes.get", - "parameterOrder": [ - "project", - "zone", - "hostType" - ], - "parameters": { - "hostType": { - "description": "Name of the host type to return.", - "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", - "required": true, - "type": "string" - }, - "project": { - "description": "Project ID for this request.", - "location": "path", - "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", - "required": true, - "type": "string" - }, - "zone": { - "description": "The name of the zone for this request.", - "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", - "required": true, - "type": "string" - } - }, - "path": "{project}/zones/{zone}/hostTypes/{hostType}", - "response": { - "$ref": "HostType" - }, - "scopes": [ - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/compute", - "https://www.googleapis.com/auth/compute.readonly" - ] - }, - "list": { - "description": "Retrieves a list of host types available to the specified project.", - "httpMethod": "GET", - "id": "compute.hostTypes.list", - "parameterOrder": [ - "project", - "zone" - ], - "parameters": { - "filter": { - "description": "A filter expression that filters resources listed in the response. The expression must specify the field name, a comparison operator, and the value that you want to use for filtering. The value must be a string, a number, or a boolean. The comparison operator must be either =, !=, \u003e, or \u003c.\n\nFor example, if you are filtering Compute Engine instances, you can exclude instances named example-instance by specifying name != example-instance.\n\nYou can also filter nested fields. For example, you could specify scheduling.automaticRestart = false to include instances only if they are not scheduled for automatic restarts. You can use filtering on nested fields to filter based on resource labels.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart = true) (cpuPlatform = \"Intel Skylake\"). By default, each expression is an AND expression. However, you can include AND and OR expressions explicitly. For example, (cpuPlatform = \"Intel Skylake\") OR (cpuPlatform = \"Intel Broadwell\") AND (scheduling.automaticRestart = true).", - "location": "query", - "type": "string" - }, - "maxResults": { - "default": "500", - "description": "The maximum number of results per page that should be returned. If the number of available results is larger than maxResults, Compute Engine returns a nextPageToken that can be used to get the next page of results in subsequent list requests. Acceptable values are 0 to 500, inclusive. (Default: 500)", - "format": "uint32", - "location": "query", - "minimum": "0", - "type": "integer" - }, - "orderBy": { - "description": "Sorts list results by a certain order. By default, results are returned in alphanumerical order based on the resource name.\n\nYou can also sort results in descending order based on the creation timestamp using orderBy=\"creationTimestamp desc\". This sorts results based on the creationTimestamp field in reverse chronological order (newest result first). Use this to sort resources like operations so that the newest operation is returned first.\n\nCurrently, only sorting by name or creationTimestamp desc is supported.", - "location": "query", - "type": "string" - }, - "pageToken": { - "description": "Specifies a page token to use. Set pageToken to the nextPageToken returned by a previous list request to get the next page of results.", - "location": "query", - "type": "string" - }, - "project": { - "description": "Project ID for this request.", - "location": "path", - "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", - "required": true, - "type": "string" - }, - "zone": { - "description": "The name of the zone for this request.", - "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", - "required": true, - "type": "string" - } - }, - "path": "{project}/zones/{zone}/hostTypes", - "response": { - "$ref": "HostTypeList" - }, - "scopes": [ - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/compute", - "https://www.googleapis.com/auth/compute.readonly" - ] - } - } - }, - "hosts": { - "methods": { - "aggregatedList": { - "description": "Retrieves an aggregated list of hosts.", - "httpMethod": "GET", - "id": "compute.hosts.aggregatedList", - "parameterOrder": [ - "project" - ], - "parameters": { - "filter": { - "description": "A filter expression that filters resources listed in the response. The expression must specify the field name, a comparison operator, and the value that you want to use for filtering. The value must be a string, a number, or a boolean. The comparison operator must be either =, !=, \u003e, or \u003c.\n\nFor example, if you are filtering Compute Engine instances, you can exclude instances named example-instance by specifying name != example-instance.\n\nYou can also filter nested fields. For example, you could specify scheduling.automaticRestart = false to include instances only if they are not scheduled for automatic restarts. You can use filtering on nested fields to filter based on resource labels.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart = true) (cpuPlatform = \"Intel Skylake\"). By default, each expression is an AND expression. However, you can include AND and OR expressions explicitly. For example, (cpuPlatform = \"Intel Skylake\") OR (cpuPlatform = \"Intel Broadwell\") AND (scheduling.automaticRestart = true).", - "location": "query", - "type": "string" - }, - "maxResults": { - "default": "500", - "description": "The maximum number of results per page that should be returned. If the number of available results is larger than maxResults, Compute Engine returns a nextPageToken that can be used to get the next page of results in subsequent list requests. Acceptable values are 0 to 500, inclusive. (Default: 500)", - "format": "uint32", - "location": "query", - "minimum": "0", - "type": "integer" - }, - "orderBy": { - "description": "Sorts list results by a certain order. By default, results are returned in alphanumerical order based on the resource name.\n\nYou can also sort results in descending order based on the creation timestamp using orderBy=\"creationTimestamp desc\". This sorts results based on the creationTimestamp field in reverse chronological order (newest result first). Use this to sort resources like operations so that the newest operation is returned first.\n\nCurrently, only sorting by name or creationTimestamp desc is supported.", - "location": "query", - "type": "string" - }, - "pageToken": { - "description": "Specifies a page token to use. Set pageToken to the nextPageToken returned by a previous list request to get the next page of results.", - "location": "query", - "type": "string" - }, - "project": { - "description": "Project ID for this request.", - "location": "path", - "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", - "required": true, - "type": "string" - } - }, - "path": "{project}/aggregated/hosts", - "response": { - "$ref": "HostAggregatedList" - }, - "scopes": [ - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/compute", - "https://www.googleapis.com/auth/compute.readonly" - ] - }, - "delete": { - "description": "Deletes the specified Host resource.", - "httpMethod": "DELETE", - "id": "compute.hosts.delete", - "parameterOrder": [ - "project", - "zone", - "host" - ], - "parameters": { - "host": { - "description": "Name of the Host resource to delete.", - "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", - "required": true, - "type": "string" - }, - "project": { - "description": "Project ID for this request.", - "location": "path", - "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", - "required": true, - "type": "string" - }, - "requestId": { - "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", - "location": "query", - "type": "string" - }, - "zone": { - "description": "The name of the zone for this request.", - "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", - "required": true, - "type": "string" - } - }, - "path": "{project}/zones/{zone}/hosts/{host}", - "response": { - "$ref": "Operation" - }, - "scopes": [ - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/compute" - ] - }, - "get": { - "description": "Returns the specified host. Gets a list of available hosts by making a list() request.", - "httpMethod": "GET", - "id": "compute.hosts.get", - "parameterOrder": [ - "project", - "zone", - "host" - ], - "parameters": { - "host": { - "description": "Name of the host to return.", - "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", - "required": true, - "type": "string" - }, - "project": { - "description": "Project ID for this request.", - "location": "path", - "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", - "required": true, - "type": "string" - }, - "zone": { - "description": "The name of the zone for this request.", - "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", - "required": true, - "type": "string" - } - }, - "path": "{project}/zones/{zone}/hosts/{host}", - "response": { - "$ref": "Host" - }, - "scopes": [ - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/compute", - "https://www.googleapis.com/auth/compute.readonly" - ] - }, - "getIamPolicy": { - "description": "Gets the access control policy for a resource. May be empty if no such policy or resource exists.", - "httpMethod": "GET", - "id": "compute.hosts.getIamPolicy", - "parameterOrder": [ - "project", - "zone", - "resource" - ], - "parameters": { - "project": { - "description": "Project ID for this request.", - "location": "path", - "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", - "required": true, - "type": "string" - }, - "resource": { - "description": "Name of the resource for this request.", - "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", - "required": true, - "type": "string" - }, - "zone": { - "description": "The name of the zone for this request.", - "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", - "required": true, - "type": "string" - } - }, - "path": "{project}/zones/{zone}/hosts/{resource}/getIamPolicy", - "response": { - "$ref": "Policy" - }, - "scopes": [ - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/compute", - "https://www.googleapis.com/auth/compute.readonly" - ] - }, - "insert": { - "description": "Creates a host resource in the specified project using the data included in the request.", - "httpMethod": "POST", - "id": "compute.hosts.insert", - "parameterOrder": [ - "project", - "zone" - ], - "parameters": { - "project": { - "description": "Project ID for this request.", - "location": "path", - "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", - "required": true, - "type": "string" - }, - "requestId": { - "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", - "location": "query", - "type": "string" - }, - "zone": { - "description": "The name of the zone for this request.", - "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", - "required": true, - "type": "string" - } - }, - "path": "{project}/zones/{zone}/hosts", - "request": { - "$ref": "Host" - }, - "response": { - "$ref": "Operation" - }, - "scopes": [ - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/compute" - ] - }, - "list": { - "description": "Retrieves a list of hosts available to the specified project.", - "httpMethod": "GET", - "id": "compute.hosts.list", - "parameterOrder": [ - "project", - "zone" - ], - "parameters": { - "filter": { - "description": "A filter expression that filters resources listed in the response. The expression must specify the field name, a comparison operator, and the value that you want to use for filtering. The value must be a string, a number, or a boolean. The comparison operator must be either =, !=, \u003e, or \u003c.\n\nFor example, if you are filtering Compute Engine instances, you can exclude instances named example-instance by specifying name != example-instance.\n\nYou can also filter nested fields. For example, you could specify scheduling.automaticRestart = false to include instances only if they are not scheduled for automatic restarts. You can use filtering on nested fields to filter based on resource labels.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart = true) (cpuPlatform = \"Intel Skylake\"). By default, each expression is an AND expression. However, you can include AND and OR expressions explicitly. For example, (cpuPlatform = \"Intel Skylake\") OR (cpuPlatform = \"Intel Broadwell\") AND (scheduling.automaticRestart = true).", - "location": "query", - "type": "string" - }, - "maxResults": { - "default": "500", - "description": "The maximum number of results per page that should be returned. If the number of available results is larger than maxResults, Compute Engine returns a nextPageToken that can be used to get the next page of results in subsequent list requests. Acceptable values are 0 to 500, inclusive. (Default: 500)", - "format": "uint32", - "location": "query", - "minimum": "0", - "type": "integer" - }, - "orderBy": { - "description": "Sorts list results by a certain order. By default, results are returned in alphanumerical order based on the resource name.\n\nYou can also sort results in descending order based on the creation timestamp using orderBy=\"creationTimestamp desc\". This sorts results based on the creationTimestamp field in reverse chronological order (newest result first). Use this to sort resources like operations so that the newest operation is returned first.\n\nCurrently, only sorting by name or creationTimestamp desc is supported.", - "location": "query", - "type": "string" - }, - "pageToken": { - "description": "Specifies a page token to use. Set pageToken to the nextPageToken returned by a previous list request to get the next page of results.", - "location": "query", - "type": "string" - }, - "project": { - "description": "Project ID for this request.", - "location": "path", - "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", - "required": true, - "type": "string" - }, - "zone": { - "description": "The name of the zone for this request.", - "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", - "required": true, - "type": "string" - } - }, - "path": "{project}/zones/{zone}/hosts", - "response": { - "$ref": "HostList" - }, - "scopes": [ - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/compute", - "https://www.googleapis.com/auth/compute.readonly" - ] - }, - "setIamPolicy": { - "description": "Sets the access control policy on the specified resource. Replaces any existing policy.", - "httpMethod": "POST", - "id": "compute.hosts.setIamPolicy", - "parameterOrder": [ - "project", - "zone", - "resource" - ], - "parameters": { - "project": { - "description": "Project ID for this request.", - "location": "path", - "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", - "required": true, - "type": "string" - }, - "resource": { - "description": "Name of the resource for this request.", - "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", - "required": true, - "type": "string" - }, - "zone": { - "description": "The name of the zone for this request.", - "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", - "required": true, - "type": "string" - } - }, - "path": "{project}/zones/{zone}/hosts/{resource}/setIamPolicy", - "request": { - "$ref": "ZoneSetPolicyRequest" - }, - "response": { - "$ref": "Policy" - }, - "scopes": [ - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/compute" - ] - }, - "testIamPermissions": { - "description": "Returns permissions that a caller has on the specified resource.", - "httpMethod": "POST", - "id": "compute.hosts.testIamPermissions", - "parameterOrder": [ - "project", - "zone", - "resource" - ], - "parameters": { - "project": { - "description": "Project ID for this request.", - "location": "path", - "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", - "required": true, - "type": "string" - }, - "resource": { - "description": "Name of the resource for this request.", - "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", - "required": true, - "type": "string" - }, - "zone": { - "description": "The name of the zone for this request.", - "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", - "required": true, - "type": "string" - } - }, - "path": "{project}/zones/{zone}/hosts/{resource}/testIamPermissions", - "request": { - "$ref": "TestPermissionsRequest" - }, - "response": { - "$ref": "TestPermissionsResponse" - }, - "scopes": [ - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/compute", - "https://www.googleapis.com/auth/compute.readonly" - ] - } - } - }, "httpHealthChecks": { "methods": { "delete": { @@ -5155,9 +5189,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "(?:[-a-z0-9_]{0,62}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -5432,9 +5466,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "(?:[-a-z0-9_]{0,62}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -5509,7 +5543,7 @@ "image": { "description": "Name of the image resource to delete.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -5547,7 +5581,7 @@ "image": { "description": "Image name.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -5588,7 +5622,7 @@ "image": { "description": "Name of the image resource to return.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -5622,7 +5656,7 @@ "family": { "description": "Name of the image family to search for.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -5661,9 +5695,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z0-9](?:[-a-z0-9_]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -5785,9 +5819,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z0-9](?:[-a-z0-9_]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -5821,9 +5855,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -5857,9 +5891,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "(?:[-a-z0-9_]{0,62}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -5882,7 +5916,7 @@ "instanceGroupManagers": { "methods": { "abandonInstances": { - "description": "Schedules a group action to remove the specified instances from the managed instance group. Abandoning an instance does not delete the instance, but it does remove the instance from any target pools that are applied by the managed instance group. This method reduces the targetSize of the managed instance group by the number of instances that you abandon. This operation is marked as DONE when the action is scheduled even if the instances have not yet been removed from the group. You must separately verify the status of the abandoning action with the listmanagedinstances method.\n\nIf the group is part of a backend service that has enabled connection draining, it can take up to 60 seconds after the connection draining duration has elapsed before the VM instance is removed or deleted.\n\nYou can specify a maximum of 1000 instances with this method per request.", + "description": "Flags the specified instances to be removed from the managed instance group. Abandoning an instance does not delete the instance, but it does remove the instance from any target pools that are applied by the managed instance group. This method reduces the targetSize of the managed instance group by the number of instances that you abandon. This operation is marked as DONE when the action is scheduled even if the instances have not yet been removed from the group. You must separately verify the status of the abandoning action with the listmanagedinstances method.\n\nIf the group is part of a backend service that has enabled connection draining, it can take up to 60 seconds after the connection draining duration has elapsed before the VM instance is removed or deleted.\n\nYou can specify a maximum of 1000 instances with this method per request.", "httpMethod": "POST", "id": "compute.instanceGroupManagers.abandonInstances", "parameterOrder": [ @@ -6019,6 +6053,53 @@ "https://www.googleapis.com/auth/compute" ] }, + "createInstances": { + "description": "Creates instances with per-instance configs in this managed instance group. Instances are created using the current instance template. The create instances operation is marked DONE if the createInstances request is successful. The underlying actions take additional time. You must separately verify the status of the creating or actions with the listmanagedinstances method.", + "httpMethod": "POST", + "id": "compute.instanceGroupManagers.createInstances", + "parameterOrder": [ + "project", + "zone", + "instanceGroupManager" + ], + "parameters": { + "instanceGroupManager": { + "description": "The name of the managed instance group. It should conform to RFC1035.", + "location": "path", + "required": true, + "type": "string" + }, + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "requestId": { + "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", + "location": "query", + "type": "string" + }, + "zone": { + "description": "The name of the zone where the managed instance group is located. It should conform to RFC1035.", + "location": "path", + "required": true, + "type": "string" + } + }, + "path": "{project}/zones/{zone}/instanceGroupManagers/{instanceGroupManager}/createInstances", + "request": { + "$ref": "InstanceGroupManagersCreateInstancesRequest" + }, + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute" + ] + }, "delete": { "description": "Deletes the specified managed instance group and all of the instances in that group. Note that the instance group must not belong to a backend service. Read Deleting an instance group for more information.", "httpMethod": "DELETE", @@ -6064,7 +6145,7 @@ ] }, "deleteInstances": { - "description": "Schedules a group action to delete the specified instances in the managed instance group. The instances are also removed from any target pools of which they were a member. This method reduces the targetSize of the managed instance group by the number of instances that you delete. This operation is marked as DONE when the action is scheduled even if the instances are still being deleted. You must separately verify the status of the deleting action with the listmanagedinstances method.\n\nIf the group is part of a backend service that has enabled connection draining, it can take up to 60 seconds after the connection draining duration has elapsed before the VM instance is removed or deleted.\n\nYou can specify a maximum of 1000 instances with this method per request.", + "description": "Flags the specified instances in the managed instance group for immediate deletion. The instances are also removed from any target pools of which they were a member. This method reduces the targetSize of the managed instance group by the number of instances that you delete. This operation is marked as DONE when the action is scheduled even if the instances are still being deleted. You must separately verify the status of the deleting action with the listmanagedinstances method.\n\nIf the group is part of a backend service that has enabled connection draining, it can take up to 60 seconds after the connection draining duration has elapsed before the VM instance is removed or deleted.\n\nYou can specify a maximum of 1000 instances with this method per request.", "httpMethod": "POST", "id": "compute.instanceGroupManagers.deleteInstances", "parameterOrder": [ @@ -6193,7 +6274,7 @@ ] }, "insert": { - "description": "Creates a managed instance group using the information that you specify in the request. After the group is created, it schedules an action to create instances in the group using the specified instance template. This operation is marked as DONE when the group is created even if the instances in the group have not yet been created. You must separately verify the status of the individual instances with the listmanagedinstances method.\n\nA managed instance group can have up to 1000 VM instances per group. Please contact Cloud Support if you need an increase in this limit.", + "description": "Creates a managed instance group using the information that you specify in the request. After the group is created, instances in the group are created using the specified instance template. This operation is marked as DONE when the group is created even if the instances in the group have not yet been created. You must separately verify the status of the individual instances with the listmanagedinstances method.\n\nA managed instance group can have up to 1000 VM instances per group. Please contact Cloud Support if you need an increase in this limit.", "httpMethod": "POST", "id": "compute.instanceGroupManagers.insert", "parameterOrder": [ @@ -6299,6 +6380,7 @@ ], "parameters": { "filter": { + "description": "A filter expression that filters resources listed in the response. The expression must specify the field name, a comparison operator, and the value that you want to use for filtering. The value must be a string, a number, or a boolean. The comparison operator must be either =, !=, \u003e, or \u003c.\n\nFor example, if you are filtering Compute Engine instances, you can exclude instances named example-instance by specifying name != example-instance.\n\nYou can also filter nested fields. For example, you could specify scheduling.automaticRestart = false to include instances only if they are not scheduled for automatic restarts. You can use filtering on nested fields to filter based on resource labels.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart = true) (cpuPlatform = \"Intel Skylake\"). By default, each expression is an AND expression. However, you can include AND and OR expressions explicitly. For example, (cpuPlatform = \"Intel Skylake\") OR (cpuPlatform = \"Intel Broadwell\") AND (scheduling.automaticRestart = true).", "location": "query", "type": "string" }, @@ -6310,16 +6392,19 @@ }, "maxResults": { "default": "500", + "description": "The maximum number of results per page that should be returned. If the number of available results is larger than maxResults, Compute Engine returns a nextPageToken that can be used to get the next page of results in subsequent list requests. Acceptable values are 0 to 500, inclusive. (Default: 500)", "format": "uint32", "location": "query", "minimum": "0", "type": "integer" }, "order_by": { + "description": "Sorts list results by a certain order. By default, results are returned in alphanumerical order based on the resource name.\n\nYou can also sort results in descending order based on the creation timestamp using orderBy=\"creationTimestamp desc\". This sorts results based on the creationTimestamp field in reverse chronological order (newest result first). Use this to sort resources like operations so that the newest operation is returned first.\n\nCurrently, only sorting by name or creationTimestamp desc is supported.", "location": "query", "type": "string" }, "pageToken": { + "description": "Specifies a page token to use. Set pageToken to the nextPageToken returned by a previous list request to get the next page of results.", "location": "query", "type": "string" }, @@ -6458,7 +6543,7 @@ ] }, "recreateInstances": { - "description": "Schedules a group action to recreate the specified instances in the managed instance group. The instances are deleted and recreated using the current instance template for the managed instance group. This operation is marked as DONE when the action is scheduled even if the instances have not yet been recreated. You must separately verify the status of the recreating action with the listmanagedinstances method.\n\nIf the group is part of a backend service that has enabled connection draining, it can take up to 60 seconds after the connection draining duration has elapsed before the VM instance is removed or deleted.\n\nYou can specify a maximum of 1000 instances with this method per request.", + "description": "Flags the specified instances in the managed instance group to be immediately recreated. The instances are deleted and recreated using the current instance template for the managed instance group. This operation is marked as DONE when the flag is set even if the instances have not yet been recreated. You must separately verify the status of the recreating action with the listmanagedinstances method.\n\nIf the group is part of a backend service that has enabled connection draining, it can take up to 60 seconds after the connection draining duration has elapsed before the VM instance is removed or deleted.\n\nYou can specify a maximum of 1000 instances with this method per request.", "httpMethod": "POST", "id": "compute.instanceGroupManagers.recreateInstances", "parameterOrder": [ @@ -6505,7 +6590,7 @@ ] }, "resize": { - "description": "Resizes the managed instance group. If you increase the size, the group creates new instances using the current instance template. If you decrease the size, the group deletes instances. The resize operation is marked DONE when the resize actions are scheduled even if the group has not yet added or deleted any instances. You must separately verify the status of the creating or deleting actions with the listmanagedinstances method.\n\nIf the group is part of a backend service that has enabled connection draining, it can take up to 60 seconds after the connection draining duration has elapsed before the VM instance is removed or deleted.", + "description": "Resizes the managed instance group. If you increase the size, the group creates new instances using the current instance template. If you decrease the size, the group deletes instances. The resize operation is marked DONE when the resize actions are scheduled even if the group has not yet added or deleted any instances. You must separately verify the status of the creating or deleting actions with the listmanagedinstances method.\n\nWhen resizing down, the instance group arbitrarily chooses the order in which VMs are deleted. The group takes into account some VM attributes when making the selection including:\n\n+ The status of the VM instance. + The health of the VM instance. + The instance template version the VM is based on. + For regional managed instance groups, the location of the VM instance.\n\nThis list is subject to change.\n\nIf the group is part of a backend service that has enabled connection draining, it can take up to 60 seconds after the connection draining duration has elapsed before the VM instance is removed or deleted.", "httpMethod": "POST", "id": "compute.instanceGroupManagers.resize", "parameterOrder": [ @@ -6604,7 +6689,7 @@ ] }, "setAutoHealingPolicies": { - "description": "Modifies the autohealing policies.", + "description": "Modifies the autohealing policies. [Deprecated] This method is deprecated. Please use Patch instead.", "httpMethod": "POST", "id": "compute.instanceGroupManagers.setAutoHealingPolicies", "parameterOrder": [ @@ -6762,9 +6847,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -7341,9 +7426,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -7444,6 +7529,40 @@ "https://www.googleapis.com/auth/compute.readonly" ] }, + "getIamPolicy": { + "description": "Gets the access control policy for a resource. May be empty if no such policy or resource exists.", + "httpMethod": "GET", + "id": "compute.instanceTemplates.getIamPolicy", + "parameterOrder": [ + "project", + "resource" + ], + "parameters": { + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "resource": { + "description": "Name or id of the resource for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + "required": true, + "type": "string" + } + }, + "path": "{project}/global/instanceTemplates/{resource}/getIamPolicy", + "response": { + "$ref": "Policy" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute", + "https://www.googleapis.com/auth/compute.readonly" + ] + }, "insert": { "description": "Creates an instance template in the specified project using the data that is included in the request. If you are creating a new template to update an existing instance group, your new instance template must use the same network or, if applicable, the same subnetwork as the original template.", "httpMethod": "POST", @@ -7526,6 +7645,42 @@ "https://www.googleapis.com/auth/compute.readonly" ] }, + "setIamPolicy": { + "description": "Sets the access control policy on the specified resource. Replaces any existing policy.", + "httpMethod": "POST", + "id": "compute.instanceTemplates.setIamPolicy", + "parameterOrder": [ + "project", + "resource" + ], + "parameters": { + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "resource": { + "description": "Name or id of the resource for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + "required": true, + "type": "string" + } + }, + "path": "{project}/global/instanceTemplates/{resource}/setIamPolicy", + "request": { + "$ref": "GlobalSetPolicyRequest" + }, + "response": { + "$ref": "Policy" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute" + ] + }, "testIamPermissions": { "description": "Returns permissions that a caller has on the specified resource.", "httpMethod": "POST", @@ -7543,9 +7698,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "(?:[-a-z0-9_]{0,62}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -7581,7 +7736,7 @@ "instance": { "description": "The instance name for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -7636,7 +7791,7 @@ "instance": { "description": "The instance name for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -7673,7 +7828,7 @@ ] }, "aggregatedList": { - "description": "Retrieves aggregated list of instances.", + "description": "Retrieves aggregated list of all of the instances in your project across all regions and zones.", "httpMethod": "GET", "id": "compute.instances.aggregatedList", "parameterOrder": [ @@ -7739,7 +7894,7 @@ "instance": { "description": "The instance name for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -7788,7 +7943,7 @@ "instance": { "description": "Name of the instance resource to delete.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -7842,7 +7997,7 @@ "instance": { "description": "The instance name for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -7893,15 +8048,15 @@ ], "parameters": { "deviceName": { - "description": "Disk device name to detach.", + "description": "The device name of the disk to detach. Make a get() request on the instance to view currently attached disks and device names.", "location": "query", "required": true, "type": "string" }, "instance": { - "description": "Instance name.", + "description": "Instance name for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -7947,7 +8102,7 @@ "instance": { "description": "Name of the instance resource to return.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -7989,7 +8144,7 @@ "instance": { "description": "Name of the instance scoping this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -8000,6 +8155,11 @@ "required": true, "type": "string" }, + "queryPath": { + "description": "Specifies the guest attributes path to be queried.", + "location": "query", + "type": "string" + }, "variableKey": { "description": "Specifies the key for the guest attributes entry.", "location": "query", @@ -8041,9 +8201,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -8066,7 +8226,7 @@ ] }, "getSerialPortOutput": { - "description": "Returns the specified instance's serial port output.", + "description": "Returns the last 1 MB of serial port output from the specified instance.", "httpMethod": "GET", "id": "compute.instances.getSerialPortOutput", "parameterOrder": [ @@ -8078,7 +8238,7 @@ "instance": { "description": "Name of the instance scoping this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -8122,6 +8282,48 @@ "https://www.googleapis.com/auth/compute.readonly" ] }, + "getShieldedVmIdentity": { + "description": "Returns the Shielded VM Identity of an instance", + "httpMethod": "GET", + "id": "compute.instances.getShieldedVmIdentity", + "parameterOrder": [ + "project", + "zone", + "instance" + ], + "parameters": { + "instance": { + "description": "Name of the instance scoping this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + "required": true, + "type": "string" + }, + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "zone": { + "description": "The name of the zone for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + } + }, + "path": "{project}/zones/{zone}/instances/{instance}/getShieldedVmIdentity", + "response": { + "$ref": "ShieldedVmIdentity" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute", + "https://www.googleapis.com/auth/compute.readonly" + ] + }, "insert": { "description": "Creates an instance resource in the specified project using the data included in the request.", "httpMethod": "POST", @@ -8144,7 +8346,12 @@ "type": "string" }, "sourceInstanceTemplate": { - "description": "Specifies instance template to create the instance.\n\nThis field is optional. It can be a full or partial URL. For example, the following are all valid URLs to an instance template: \n- https://www.googleapis.com/compute/v1/projects/project/global/global/instanceTemplates/instanceTemplate \n- projects/project/global/global/instanceTemplates/instanceTemplate \n- global/instancesTemplates/instanceTemplate", + "description": "Specifies instance template to create the instance.\n\nThis field is optional. It can be a full or partial URL. For example, the following are all valid URLs to an instance template: \n- https://www.googleapis.com/compute/v1/projects/project/global/instanceTemplates/instanceTemplate \n- projects/project/global/instanceTemplates/instanceTemplate \n- global/instanceTemplates/instanceTemplate", + "location": "query", + "type": "string" + }, + "sourceMachineImage": { + "description": "Specifies instance machine to create the instance.\n\nThis field is optional. It can be a full or partial URL. For example, the following are all valid URLs to an instance template: \n- https://www.googleapis.com/compute/v1/projects/project/global/global/machineImages/machineImage \n- projects/project/global/global/machineImages/machineImage \n- global/machineImages/machineImage", "location": "query", "type": "string" }, @@ -8226,7 +8433,7 @@ ] }, "listReferrers": { - "description": "Retrieves the list of referrers to instances contained within the specified zone.", + "description": "Retrieves the list of referrers to instances contained within the specified zone. For more information, read Viewing Referrers to VM Instances.", "httpMethod": "GET", "id": "compute.instances.listReferrers", "parameterOrder": [ @@ -8243,7 +8450,7 @@ "instance": { "description": "Name of the target instance scoping this request, or '-' if the request should span over all instances in the container.", "location": "path", - "pattern": "-|[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "-|[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -8303,7 +8510,7 @@ "instance": { "description": "The instance name for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -8352,7 +8559,7 @@ "instance": { "description": "Name of the instance scoping this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -8398,7 +8605,7 @@ "instance": { "description": "Name of the instance resource to resume.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -8463,9 +8670,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -8505,16 +8712,16 @@ "type": "boolean" }, "deviceName": { - "description": "The device name of the disk to modify.", + "description": "The device name of the disk to modify. Make a get() request on the instance to view currently attached disks and device names.", "location": "query", "pattern": "\\w[\\w.-]{0,254}", "required": true, "type": "string" }, "instance": { - "description": "The instance name.", + "description": "The instance name for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -8565,9 +8772,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -8604,7 +8811,7 @@ "instance": { "description": "Name of the instance scoping this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -8653,7 +8860,7 @@ "instance": { "description": "Name of the instance scoping this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -8702,7 +8909,7 @@ "instance": { "description": "Name of the instance scoping this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -8751,7 +8958,7 @@ "instance": { "description": "Name of the instance scoping this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -8800,7 +9007,7 @@ "instance": { "description": "Name of the instance scoping this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -8847,9 +9054,9 @@ ], "parameters": { "instance": { - "description": "Instance name.", + "description": "Instance name for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -8898,7 +9105,7 @@ "instance": { "description": "Name of the instance resource to start.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -8935,7 +9142,7 @@ ] }, "setShieldedVmIntegrityPolicy": { - "description": "Sets the Shielded VM integrity policy for an instance. This method supports PATCH semantics and uses the JSON merge patch format and processing rules.", + "description": "Sets the Shielded VM integrity policy for a VM instance. You can only use this method on a running VM instance. This method supports PATCH semantics and uses the JSON merge patch format and processing rules.", "httpMethod": "PATCH", "id": "compute.instances.setShieldedVmIntegrityPolicy", "parameterOrder": [ @@ -8947,7 +9154,7 @@ "instance": { "description": "Name of the instance scoping this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -8984,7 +9191,7 @@ ] }, "setTags": { - "description": "Sets tags for the specified instance to the data included in the request.", + "description": "Sets network tags for the specified instance to the data included in the request.", "httpMethod": "POST", "id": "compute.instances.setTags", "parameterOrder": [ @@ -8996,7 +9203,7 @@ "instance": { "description": "Name of the instance scoping this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -9045,7 +9252,7 @@ "instance": { "description": "Name of the instance scoping this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -9086,7 +9293,7 @@ "instance": { "description": "Name of the instance resource to start.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -9132,7 +9339,7 @@ "instance": { "description": "Name of the instance resource to start.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -9186,7 +9393,7 @@ "instance": { "description": "Name of the instance resource to stop.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -9237,7 +9444,7 @@ "instance": { "description": "Name of the instance resource to suspend.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -9288,9 +9495,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -9329,7 +9536,7 @@ "instance": { "description": "The instance name for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -9371,6 +9578,55 @@ "https://www.googleapis.com/auth/compute" ] }, + "updateDisplayDevice": { + "description": "Updates the Display config for a VM instance. You can only use this method on a stopped VM instance. This method supports PATCH semantics and uses the JSON merge patch format and processing rules.", + "httpMethod": "PATCH", + "id": "compute.instances.updateDisplayDevice", + "parameterOrder": [ + "project", + "zone", + "instance" + ], + "parameters": { + "instance": { + "description": "Name of the instance scoping this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + }, + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "requestId": { + "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", + "location": "query", + "type": "string" + }, + "zone": { + "description": "The name of the zone for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + } + }, + "path": "{project}/zones/{zone}/instances/{instance}/updateDisplayDevice", + "request": { + "$ref": "DisplayDevice" + }, + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute" + ] + }, "updateNetworkInterface": { "description": "Updates an instance's network interface. This method follows PATCH semantics.", "httpMethod": "PATCH", @@ -9385,7 +9641,7 @@ "instance": { "description": "The instance name for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -9428,7 +9684,7 @@ ] }, "updateShieldedVmConfig": { - "description": "Updates the Shielded VM config for an instance. This method supports PATCH semantics and uses the JSON merge patch format and processing rules.", + "description": "Updates the Shielded VM config for a VM instance. You can only use this method on a stopped VM instance. This method supports PATCH semantics and uses the JSON merge patch format and processing rules.", "httpMethod": "PATCH", "id": "compute.instances.updateShieldedVmConfig", "parameterOrder": [ @@ -9440,7 +9696,7 @@ "instance": { "description": "Name of the instance scoping this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -9642,9 +9898,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -9831,9 +10087,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -9880,9 +10136,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -9924,9 +10180,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -10048,9 +10304,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "(?:[-a-z0-9_]{0,62}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -10144,6 +10400,40 @@ "https://www.googleapis.com/auth/compute.readonly" ] }, + "getDiagnostics": { + "description": "Returns the interconnectDiagnostics for the specified interconnect.", + "httpMethod": "GET", + "id": "compute.interconnects.getDiagnostics", + "parameterOrder": [ + "project", + "interconnect" + ], + "parameters": { + "interconnect": { + "description": "Name of the interconnect resource to query.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + }, + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + } + }, + "path": "{project}/global/interconnects/{interconnect}/getDiagnostics", + "response": { + "$ref": "InterconnectsGetDiagnosticsResponse" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute", + "https://www.googleapis.com/auth/compute.readonly" + ] + }, "getIamPolicy": { "description": "Gets the access control policy for a resource. May be empty if no such policy or resource exists.", "httpMethod": "GET", @@ -10161,9 +10451,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z0-9](?:[-a-z0-9_]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -10318,9 +10608,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z0-9](?:[-a-z0-9_]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -10354,9 +10644,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -10390,9 +10680,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "(?:[-a-z0-9_]{0,62}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -10465,9 +10755,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z0-9](?:[-a-z0-9_]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -10499,9 +10789,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z0-9](?:[-a-z0-9_]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -10535,9 +10825,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "(?:[-a-z0-9_]{0,62}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -10648,9 +10938,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z0-9](?:[-a-z0-9_]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -10767,9 +11057,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z0-9](?:[-a-z0-9_]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -10803,9 +11093,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "(?:[-a-z0-9_]{0,62}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -10825,6 +11115,276 @@ } } }, + "machineImages": { + "methods": { + "delete": { + "description": "Deletes the specified machine image. Deleting a machine image is permanent and cannot be undone.", + "httpMethod": "DELETE", + "id": "compute.machineImages.delete", + "parameterOrder": [ + "project", + "machineImage" + ], + "parameters": { + "machineImage": { + "description": "The name of the machine image to delete.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + }, + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "requestId": { + "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", + "location": "query", + "type": "string" + } + }, + "path": "{project}/global/machineImages/{machineImage}", + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute" + ] + }, + "get": { + "description": "Returns the specified machine image. Gets a list of available machine images by making a list() request.", + "httpMethod": "GET", + "id": "compute.machineImages.get", + "parameterOrder": [ + "project", + "machineImage" + ], + "parameters": { + "machineImage": { + "description": "The name of the machine image.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + }, + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + } + }, + "path": "{project}/global/machineImages/{machineImage}", + "response": { + "$ref": "MachineImage" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute", + "https://www.googleapis.com/auth/compute.readonly" + ] + }, + "getIamPolicy": { + "description": "Gets the access control policy for a resource. May be empty if no such policy or resource exists.", + "httpMethod": "GET", + "id": "compute.machineImages.getIamPolicy", + "parameterOrder": [ + "project", + "resource" + ], + "parameters": { + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "resource": { + "description": "Name or id of the resource for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + "required": true, + "type": "string" + } + }, + "path": "{project}/global/machineImages/{resource}/getIamPolicy", + "response": { + "$ref": "Policy" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute", + "https://www.googleapis.com/auth/compute.readonly" + ] + }, + "insert": { + "description": "Creates a machine image in the specified project using the data that is included in the request. If you are creating a new machine image to update an existing instance, your new machine image should use the same network or, if applicable, the same subnetwork as the original instance.", + "httpMethod": "POST", + "id": "compute.machineImages.insert", + "parameterOrder": [ + "project" + ], + "parameters": { + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "requestId": { + "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", + "location": "query", + "type": "string" + }, + "sourceInstance": { + "description": "Required. Source instance that is used to create the machine image from.", + "location": "query", + "type": "string" + } + }, + "path": "{project}/global/machineImages", + "request": { + "$ref": "MachineImage" + }, + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute" + ] + }, + "list": { + "description": "Retrieves a list of machine images that are contained within the specified project.", + "httpMethod": "GET", + "id": "compute.machineImages.list", + "parameterOrder": [ + "project" + ], + "parameters": { + "filter": { + "description": "A filter expression that filters resources listed in the response. The expression must specify the field name, a comparison operator, and the value that you want to use for filtering. The value must be a string, a number, or a boolean. The comparison operator must be either =, !=, \u003e, or \u003c.\n\nFor example, if you are filtering Compute Engine instances, you can exclude instances named example-instance by specifying name != example-instance.\n\nYou can also filter nested fields. For example, you could specify scheduling.automaticRestart = false to include instances only if they are not scheduled for automatic restarts. You can use filtering on nested fields to filter based on resource labels.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart = true) (cpuPlatform = \"Intel Skylake\"). By default, each expression is an AND expression. However, you can include AND and OR expressions explicitly. For example, (cpuPlatform = \"Intel Skylake\") OR (cpuPlatform = \"Intel Broadwell\") AND (scheduling.automaticRestart = true).", + "location": "query", + "type": "string" + }, + "maxResults": { + "default": "500", + "description": "The maximum number of results per page that should be returned. If the number of available results is larger than maxResults, Compute Engine returns a nextPageToken that can be used to get the next page of results in subsequent list requests. Acceptable values are 0 to 500, inclusive. (Default: 500)", + "format": "uint32", + "location": "query", + "minimum": "0", + "type": "integer" + }, + "orderBy": { + "description": "Sorts list results by a certain order. By default, results are returned in alphanumerical order based on the resource name.\n\nYou can also sort results in descending order based on the creation timestamp using orderBy=\"creationTimestamp desc\". This sorts results based on the creationTimestamp field in reverse chronological order (newest result first). Use this to sort resources like operations so that the newest operation is returned first.\n\nCurrently, only sorting by name or creationTimestamp desc is supported.", + "location": "query", + "type": "string" + }, + "pageToken": { + "description": "Specifies a page token to use. Set pageToken to the nextPageToken returned by a previous list request to get the next page of results.", + "location": "query", + "type": "string" + }, + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + } + }, + "path": "{project}/global/machineImages", + "response": { + "$ref": "MachineImageList" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute", + "https://www.googleapis.com/auth/compute.readonly" + ] + }, + "setIamPolicy": { + "description": "Sets the access control policy on the specified resource. Replaces any existing policy.", + "httpMethod": "POST", + "id": "compute.machineImages.setIamPolicy", + "parameterOrder": [ + "project", + "resource" + ], + "parameters": { + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "resource": { + "description": "Name or id of the resource for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + "required": true, + "type": "string" + } + }, + "path": "{project}/global/machineImages/{resource}/setIamPolicy", + "request": { + "$ref": "GlobalSetPolicyRequest" + }, + "response": { + "$ref": "Policy" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute" + ] + }, + "testIamPermissions": { + "description": "Returns permissions that a caller has on the specified resource.", + "httpMethod": "POST", + "id": "compute.machineImages.testIamPermissions", + "parameterOrder": [ + "project", + "resource" + ], + "parameters": { + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "resource": { + "description": "Name or id of the resource for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + "required": true, + "type": "string" + } + }, + "path": "{project}/global/machineImages/{resource}/testIamPermissions", + "request": { + "$ref": "TestPermissionsRequest" + }, + "response": { + "$ref": "TestPermissionsResponse" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute", + "https://www.googleapis.com/auth/compute.readonly" + ] + } + } + }, "machineTypes": { "methods": { "aggregatedList": { @@ -11386,9 +11946,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -11429,7 +11989,7 @@ "network": { "description": "Name of the network resource to add peering to.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -11470,7 +12030,7 @@ "network": { "description": "Name of the network to delete.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -11508,7 +12068,7 @@ "network": { "description": "Name of the network to return.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -11612,6 +12172,68 @@ "https://www.googleapis.com/auth/compute.readonly" ] }, + "listIpAddresses": { + "description": "Lists the internal IP addresses in the specified network.", + "httpMethod": "GET", + "id": "compute.networks.listIpAddresses", + "parameterOrder": [ + "project", + "network" + ], + "parameters": { + "filter": { + "description": "A filter expression that filters resources listed in the response. The expression must specify the field name, a comparison operator, and the value that you want to use for filtering. The value must be a string, a number, or a boolean. The comparison operator must be either =, !=, \u003e, or \u003c.\n\nFor example, if you are filtering Compute Engine instances, you can exclude instances named example-instance by specifying name != example-instance.\n\nYou can also filter nested fields. For example, you could specify scheduling.automaticRestart = false to include instances only if they are not scheduled for automatic restarts. You can use filtering on nested fields to filter based on resource labels.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart = true) (cpuPlatform = \"Intel Skylake\"). By default, each expression is an AND expression. However, you can include AND and OR expressions explicitly. For example, (cpuPlatform = \"Intel Skylake\") OR (cpuPlatform = \"Intel Broadwell\") AND (scheduling.automaticRestart = true).", + "location": "query", + "type": "string" + }, + "maxResults": { + "default": "500", + "description": "The maximum number of results per page that should be returned. If the number of available results is larger than maxResults, Compute Engine returns a nextPageToken that can be used to get the next page of results in subsequent list requests. Acceptable values are 0 to 500, inclusive. (Default: 500)", + "format": "uint32", + "location": "query", + "minimum": "0", + "type": "integer" + }, + "network": { + "description": "Name of the network for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + "required": true, + "type": "string" + }, + "orderBy": { + "description": "Sorts list results by a certain order. By default, results are returned in alphanumerical order based on the resource name.\n\nYou can also sort results in descending order based on the creation timestamp using orderBy=\"creationTimestamp desc\". This sorts results based on the creationTimestamp field in reverse chronological order (newest result first). Use this to sort resources like operations so that the newest operation is returned first.\n\nCurrently, only sorting by name or creationTimestamp desc is supported.", + "location": "query", + "type": "string" + }, + "pageToken": { + "description": "Specifies a page token to use. Set pageToken to the nextPageToken returned by a previous list request to get the next page of results.", + "location": "query", + "type": "string" + }, + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "types": { + "description": "(Optional) types filter separate by comma, valid values are: SUBNETWORK, RESERVED, PEER_USED, PEER_RESERVED, REMOTE_USED, REMOTE_RESERVED.", + "location": "query", + "type": "string" + } + }, + "path": "{project}/global/networks/{network}/listIpAddresses", + "response": { + "$ref": "IpAddressesList" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute", + "https://www.googleapis.com/auth/compute.readonly" + ] + }, "listIpOwners": { "description": "Lists the internal IP owners in the specified network.", "httpMethod": "GET", @@ -11642,7 +12264,7 @@ "network": { "description": "Name of the network to return.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -11696,6 +12318,86 @@ "https://www.googleapis.com/auth/compute.readonly" ] }, + "listPeeringRoutes": { + "description": "Lists the peering routes exchanged over peering connection.", + "httpMethod": "GET", + "id": "compute.networks.listPeeringRoutes", + "parameterOrder": [ + "project", + "network" + ], + "parameters": { + "direction": { + "description": "The direction of the exchanged routes.", + "enum": [ + "INCOMING", + "OUTGOING" + ], + "enumDescriptions": [ + "", + "" + ], + "location": "query", + "type": "string" + }, + "filter": { + "description": "A filter expression that filters resources listed in the response. The expression must specify the field name, a comparison operator, and the value that you want to use for filtering. The value must be a string, a number, or a boolean. The comparison operator must be either =, !=, \u003e, or \u003c.\n\nFor example, if you are filtering Compute Engine instances, you can exclude instances named example-instance by specifying name != example-instance.\n\nYou can also filter nested fields. For example, you could specify scheduling.automaticRestart = false to include instances only if they are not scheduled for automatic restarts. You can use filtering on nested fields to filter based on resource labels.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart = true) (cpuPlatform = \"Intel Skylake\"). By default, each expression is an AND expression. However, you can include AND and OR expressions explicitly. For example, (cpuPlatform = \"Intel Skylake\") OR (cpuPlatform = \"Intel Broadwell\") AND (scheduling.automaticRestart = true).", + "location": "query", + "type": "string" + }, + "maxResults": { + "default": "500", + "description": "The maximum number of results per page that should be returned. If the number of available results is larger than maxResults, Compute Engine returns a nextPageToken that can be used to get the next page of results in subsequent list requests. Acceptable values are 0 to 500, inclusive. (Default: 500)", + "format": "uint32", + "location": "query", + "minimum": "0", + "type": "integer" + }, + "network": { + "description": "Name of the network for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + "required": true, + "type": "string" + }, + "orderBy": { + "description": "Sorts list results by a certain order. By default, results are returned in alphanumerical order based on the resource name.\n\nYou can also sort results in descending order based on the creation timestamp using orderBy=\"creationTimestamp desc\". This sorts results based on the creationTimestamp field in reverse chronological order (newest result first). Use this to sort resources like operations so that the newest operation is returned first.\n\nCurrently, only sorting by name or creationTimestamp desc is supported.", + "location": "query", + "type": "string" + }, + "pageToken": { + "description": "Specifies a page token to use. Set pageToken to the nextPageToken returned by a previous list request to get the next page of results.", + "location": "query", + "type": "string" + }, + "peeringName": { + "description": "The response will show routes exchanged over the given peering connection.", + "location": "query", + "type": "string" + }, + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "region": { + "description": "The region of the request. The response will include all subnet routes, static routes and dynamic routes in the region.", + "location": "query", + "type": "string" + } + }, + "path": "{project}/global/networks/{network}/listPeeringRoutes", + "response": { + "$ref": "ExchangedPeeringRoutesList" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute", + "https://www.googleapis.com/auth/compute.readonly" + ] + }, "patch": { "description": "Patches the specified network with the data included in the request. Only the following fields can be modified: routingConfig.routingMode.", "httpMethod": "PATCH", @@ -11708,7 +12410,7 @@ "network": { "description": "Name of the network to update.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -11749,7 +12451,7 @@ "network": { "description": "Name of the network resource to remove peering from.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -11790,7 +12492,7 @@ "network": { "description": "Name of the network to be updated.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -11833,9 +12535,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "(?:[-a-z0-9_]{0,62}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -11852,6 +12554,47 @@ "https://www.googleapis.com/auth/compute", "https://www.googleapis.com/auth/compute.readonly" ] + }, + "updatePeering": { + "description": "Updates the specified network peering with the data included in the request Only the following fields can be modified: NetworkPeering.export_custom_routes, and NetworkPeering.import_custom_routes", + "httpMethod": "PATCH", + "id": "compute.networks.updatePeering", + "parameterOrder": [ + "project", + "network" + ], + "parameters": { + "network": { + "description": "Name of the network resource which the updated peering is belonging to.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + "required": true, + "type": "string" + }, + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "requestId": { + "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", + "location": "query", + "type": "string" + } + }, + "path": "{project}/global/networks/{network}/updatePeering", + "request": { + "$ref": "NetworksUpdatePeeringRequest" + }, + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute" + ] } } }, @@ -11868,7 +12611,7 @@ ], "parameters": { "nodeGroup": { - "description": "Name of the NodeGroup resource to delete.", + "description": "Name of the NodeGroup resource.", "location": "path", "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", "required": true, @@ -11907,7 +12650,7 @@ ] }, "aggregatedList": { - "description": "Retrieves an aggregated list of node groups.", + "description": "Retrieves an aggregated list of node groups. Note: use nodeGroups.listNodes for more details about each group.", "httpMethod": "GET", "id": "compute.nodeGroups.aggregatedList", "parameterOrder": [ @@ -12051,7 +12794,7 @@ ] }, "get": { - "description": "Returns the specified NodeGroup. Get a list of available NodeGroups by making a list() request.", + "description": "Returns the specified NodeGroup. Get a list of available NodeGroups by making a list() request. Note: the \"nodes\" field should not be used. Use nodeGroups.listNodes instead.", "httpMethod": "GET", "id": "compute.nodeGroups.get", "parameterOrder": [ @@ -12110,9 +12853,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -12184,7 +12927,7 @@ ] }, "list": { - "description": "Retrieves a list of node groups available to the specified project.", + "description": "Retrieves a list of node groups available to the specified project. Note: use nodeGroups.listNodes for more details about each group.", "httpMethod": "GET", "id": "compute.nodeGroups.list", "parameterOrder": [ @@ -12240,6 +12983,71 @@ "https://www.googleapis.com/auth/compute.readonly" ] }, + "listNodes": { + "description": "Lists nodes in the node group.", + "httpMethod": "POST", + "id": "compute.nodeGroups.listNodes", + "parameterOrder": [ + "project", + "zone", + "nodeGroup" + ], + "parameters": { + "filter": { + "description": "A filter expression that filters resources listed in the response. The expression must specify the field name, a comparison operator, and the value that you want to use for filtering. The value must be a string, a number, or a boolean. The comparison operator must be either =, !=, \u003e, or \u003c.\n\nFor example, if you are filtering Compute Engine instances, you can exclude instances named example-instance by specifying name != example-instance.\n\nYou can also filter nested fields. For example, you could specify scheduling.automaticRestart = false to include instances only if they are not scheduled for automatic restarts. You can use filtering on nested fields to filter based on resource labels.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart = true) (cpuPlatform = \"Intel Skylake\"). By default, each expression is an AND expression. However, you can include AND and OR expressions explicitly. For example, (cpuPlatform = \"Intel Skylake\") OR (cpuPlatform = \"Intel Broadwell\") AND (scheduling.automaticRestart = true).", + "location": "query", + "type": "string" + }, + "maxResults": { + "default": "500", + "description": "The maximum number of results per page that should be returned. If the number of available results is larger than maxResults, Compute Engine returns a nextPageToken that can be used to get the next page of results in subsequent list requests. Acceptable values are 0 to 500, inclusive. (Default: 500)", + "format": "uint32", + "location": "query", + "minimum": "0", + "type": "integer" + }, + "nodeGroup": { + "description": "Name of the NodeGroup resource whose nodes you want to list.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + }, + "orderBy": { + "description": "Sorts list results by a certain order. By default, results are returned in alphanumerical order based on the resource name.\n\nYou can also sort results in descending order based on the creation timestamp using orderBy=\"creationTimestamp desc\". This sorts results based on the creationTimestamp field in reverse chronological order (newest result first). Use this to sort resources like operations so that the newest operation is returned first.\n\nCurrently, only sorting by name or creationTimestamp desc is supported.", + "location": "query", + "type": "string" + }, + "pageToken": { + "description": "Specifies a page token to use. Set pageToken to the nextPageToken returned by a previous list request to get the next page of results.", + "location": "query", + "type": "string" + }, + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "zone": { + "description": "The name of the zone for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + } + }, + "path": "{project}/zones/{zone}/nodeGroups/{nodeGroup}/listNodes", + "response": { + "$ref": "NodeGroupsListNodes" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute", + "https://www.googleapis.com/auth/compute.readonly" + ] + }, "setIamPolicy": { "description": "Sets the access control policy on the specified resource. Replaces any existing policy.", "httpMethod": "POST", @@ -12258,9 +13066,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -12351,9 +13159,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -12544,9 +13352,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -12684,9 +13492,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -12728,9 +13536,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -12902,6 +13710,377 @@ } } }, + "organizationSecurityPolicies": { + "methods": { + "addAssociation": { + "description": "Inserts an association for the specified security policy.", + "httpMethod": "POST", + "id": "compute.organizationSecurityPolicies.addAssociation", + "parameterOrder": [ + "securityPolicy" + ], + "parameters": { + "requestId": { + "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", + "location": "query", + "type": "string" + }, + "securityPolicy": { + "description": "Name of the security policy to update.", + "location": "path", + "pattern": "[0-9]{0,20}", + "required": true, + "type": "string" + } + }, + "path": "locations/global/securityPolicies/{securityPolicy}/addAssociation", + "request": { + "$ref": "SecurityPolicyAssociation" + }, + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute" + ] + }, + "addRule": { + "description": "Inserts a rule into a security policy.", + "httpMethod": "POST", + "id": "compute.organizationSecurityPolicies.addRule", + "parameterOrder": [ + "securityPolicy" + ], + "parameters": { + "requestId": { + "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", + "location": "query", + "type": "string" + }, + "securityPolicy": { + "description": "Name of the security policy to update.", + "location": "path", + "pattern": "[0-9]{0,20}", + "required": true, + "type": "string" + } + }, + "path": "locations/global/securityPolicies/{securityPolicy}/addRule", + "request": { + "$ref": "SecurityPolicyRule" + }, + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute" + ] + }, + "delete": { + "description": "Deletes the specified policy.", + "httpMethod": "DELETE", + "id": "compute.organizationSecurityPolicies.delete", + "parameterOrder": [ + "securityPolicy" + ], + "parameters": { + "requestId": { + "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", + "location": "query", + "type": "string" + }, + "securityPolicy": { + "description": "Name of the security policy to delete.", + "location": "path", + "pattern": "[0-9]{0,20}", + "required": true, + "type": "string" + } + }, + "path": "locations/global/securityPolicies/{securityPolicy}", + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute" + ] + }, + "get": { + "description": "List all of the ordered rules present in a single specified policy.", + "httpMethod": "GET", + "id": "compute.organizationSecurityPolicies.get", + "parameterOrder": [ + "securityPolicy" + ], + "parameters": { + "securityPolicy": { + "description": "Name of the security policy to get.", + "location": "path", + "pattern": "[0-9]{0,20}", + "required": true, + "type": "string" + } + }, + "path": "locations/global/securityPolicies/{securityPolicy}", + "response": { + "$ref": "SecurityPolicy" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute", + "https://www.googleapis.com/auth/compute.readonly" + ] + }, + "getAssociation": { + "description": "Gets an association with the specified name.", + "httpMethod": "GET", + "id": "compute.organizationSecurityPolicies.getAssociation", + "parameterOrder": [ + "securityPolicy" + ], + "parameters": { + "name": { + "description": "The name of the association to get from the security policy.", + "location": "query", + "type": "string" + }, + "securityPolicy": { + "description": "Name of the security policy to which the queried rule belongs.", + "location": "path", + "pattern": "[0-9]{0,20}", + "required": true, + "type": "string" + } + }, + "path": "locations/global/securityPolicies/{securityPolicy}/getAssociation", + "response": { + "$ref": "SecurityPolicyAssociation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute", + "https://www.googleapis.com/auth/compute.readonly" + ] + }, + "getRule": { + "description": "Gets a rule at the specified priority.", + "httpMethod": "GET", + "id": "compute.organizationSecurityPolicies.getRule", + "parameterOrder": [ + "securityPolicy" + ], + "parameters": { + "priority": { + "description": "The priority of the rule to get from the security policy.", + "format": "int32", + "location": "query", + "type": "integer" + }, + "securityPolicy": { + "description": "Name of the security policy to which the queried rule belongs.", + "location": "path", + "pattern": "[0-9]{0,20}", + "required": true, + "type": "string" + } + }, + "path": "locations/global/securityPolicies/{securityPolicy}/getRule", + "response": { + "$ref": "SecurityPolicyRule" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute", + "https://www.googleapis.com/auth/compute.readonly" + ] + }, + "insert": { + "description": "Creates a new policy in the specified project using the data included in the request.", + "httpMethod": "POST", + "id": "compute.organizationSecurityPolicies.insert", + "parameters": { + "parentId": { + "description": "Parent ID for this request.", + "location": "query", + "type": "string" + }, + "requestId": { + "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", + "location": "query", + "type": "string" + } + }, + "path": "locations/global/securityPolicies", + "request": { + "$ref": "SecurityPolicy" + }, + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute" + ] + }, + "list": { + "description": "List all the policies that have been configured for the specified project.", + "httpMethod": "GET", + "id": "compute.organizationSecurityPolicies.list", + "parameters": { + "filter": { + "description": "A filter expression that filters resources listed in the response. The expression must specify the field name, a comparison operator, and the value that you want to use for filtering. The value must be a string, a number, or a boolean. The comparison operator must be either =, !=, \u003e, or \u003c.\n\nFor example, if you are filtering Compute Engine instances, you can exclude instances named example-instance by specifying name != example-instance.\n\nYou can also filter nested fields. For example, you could specify scheduling.automaticRestart = false to include instances only if they are not scheduled for automatic restarts. You can use filtering on nested fields to filter based on resource labels.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart = true) (cpuPlatform = \"Intel Skylake\"). By default, each expression is an AND expression. However, you can include AND and OR expressions explicitly. For example, (cpuPlatform = \"Intel Skylake\") OR (cpuPlatform = \"Intel Broadwell\") AND (scheduling.automaticRestart = true).", + "location": "query", + "type": "string" + }, + "maxResults": { + "default": "500", + "description": "The maximum number of results per page that should be returned. If the number of available results is larger than maxResults, Compute Engine returns a nextPageToken that can be used to get the next page of results in subsequent list requests. Acceptable values are 0 to 500, inclusive. (Default: 500)", + "format": "uint32", + "location": "query", + "minimum": "0", + "type": "integer" + }, + "orderBy": { + "description": "Sorts list results by a certain order. By default, results are returned in alphanumerical order based on the resource name.\n\nYou can also sort results in descending order based on the creation timestamp using orderBy=\"creationTimestamp desc\". This sorts results based on the creationTimestamp field in reverse chronological order (newest result first). Use this to sort resources like operations so that the newest operation is returned first.\n\nCurrently, only sorting by name or creationTimestamp desc is supported.", + "location": "query", + "type": "string" + }, + "pageToken": { + "description": "Specifies a page token to use. Set pageToken to the nextPageToken returned by a previous list request to get the next page of results.", + "location": "query", + "type": "string" + }, + "parentId": { + "description": "Parent ID for this request.", + "location": "query", + "type": "string" + } + }, + "path": "locations/global/securityPolicies", + "response": { + "$ref": "SecurityPolicyList" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute", + "https://www.googleapis.com/auth/compute.readonly" + ] + }, + "patchRule": { + "description": "Patches a rule at the specified priority.", + "httpMethod": "POST", + "id": "compute.organizationSecurityPolicies.patchRule", + "parameterOrder": [ + "securityPolicy" + ], + "parameters": { + "priority": { + "description": "The priority of the rule to patch.", + "format": "int32", + "location": "query", + "type": "integer" + }, + "requestId": { + "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", + "location": "query", + "type": "string" + }, + "securityPolicy": { + "description": "Name of the security policy to update.", + "location": "path", + "pattern": "[0-9]{0,20}", + "required": true, + "type": "string" + } + }, + "path": "locations/global/securityPolicies/{securityPolicy}/patchRule", + "request": { + "$ref": "SecurityPolicyRule" + }, + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute" + ] + }, + "removeAssociation": { + "description": "Removes an association for the specified security policy.", + "httpMethod": "POST", + "id": "compute.organizationSecurityPolicies.removeAssociation", + "parameterOrder": [ + "securityPolicy" + ], + "parameters": { + "name": { + "description": "Name for the attachment that will be removed.", + "location": "query", + "type": "string" + }, + "requestId": { + "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", + "location": "query", + "type": "string" + }, + "securityPolicy": { + "description": "Name of the security policy to update.", + "location": "path", + "pattern": "[0-9]{0,20}", + "required": true, + "type": "string" + } + }, + "path": "locations/global/securityPolicies/{securityPolicy}/removeAssociation", + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute" + ] + }, + "removeRule": { + "description": "Deletes a rule at the specified priority.", + "httpMethod": "POST", + "id": "compute.organizationSecurityPolicies.removeRule", + "parameterOrder": [ + "securityPolicy" + ], + "parameters": { + "priority": { + "description": "The priority of the rule to remove from the security policy.", + "format": "int32", + "location": "query", + "type": "integer" + }, + "requestId": { + "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", + "location": "query", + "type": "string" + }, + "securityPolicy": { + "description": "Name of the security policy to update.", + "location": "path", + "pattern": "[0-9]{0,20}", + "required": true, + "type": "string" + } + }, + "path": "locations/global/securityPolicies/{securityPolicy}/removeRule", + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute" + ] + } + } + }, "projects": { "methods": { "disableXpnHost": { @@ -13090,21 +14269,25 @@ ], "parameters": { "filter": { + "description": "A filter expression that filters resources listed in the response. The expression must specify the field name, a comparison operator, and the value that you want to use for filtering. The value must be a string, a number, or a boolean. The comparison operator must be either =, !=, \u003e, or \u003c.\n\nFor example, if you are filtering Compute Engine instances, you can exclude instances named example-instance by specifying name != example-instance.\n\nYou can also filter nested fields. For example, you could specify scheduling.automaticRestart = false to include instances only if they are not scheduled for automatic restarts. You can use filtering on nested fields to filter based on resource labels.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart = true) (cpuPlatform = \"Intel Skylake\"). By default, each expression is an AND expression. However, you can include AND and OR expressions explicitly. For example, (cpuPlatform = \"Intel Skylake\") OR (cpuPlatform = \"Intel Broadwell\") AND (scheduling.automaticRestart = true).", "location": "query", "type": "string" }, "maxResults": { "default": "500", + "description": "The maximum number of results per page that should be returned. If the number of available results is larger than maxResults, Compute Engine returns a nextPageToken that can be used to get the next page of results in subsequent list requests. Acceptable values are 0 to 500, inclusive. (Default: 500)", "format": "uint32", "location": "query", "minimum": "0", "type": "integer" }, "order_by": { + "description": "Sorts list results by a certain order. By default, results are returned in alphanumerical order based on the resource name.\n\nYou can also sort results in descending order based on the creation timestamp using orderBy=\"creationTimestamp desc\". This sorts results based on the creationTimestamp field in reverse chronological order (newest result first). Use this to sort resources like operations so that the newest operation is returned first.\n\nCurrently, only sorting by name or creationTimestamp desc is supported.", "location": "query", "type": "string" }, "pageToken": { + "description": "Specifies a page token to use. Set pageToken to the nextPageToken returned by a previous list request to get the next page of results.", "location": "query", "type": "string" }, @@ -13134,21 +14317,25 @@ ], "parameters": { "filter": { + "description": "A filter expression that filters resources listed in the response. The expression must specify the field name, a comparison operator, and the value that you want to use for filtering. The value must be a string, a number, or a boolean. The comparison operator must be either =, !=, \u003e, or \u003c.\n\nFor example, if you are filtering Compute Engine instances, you can exclude instances named example-instance by specifying name != example-instance.\n\nYou can also filter nested fields. For example, you could specify scheduling.automaticRestart = false to include instances only if they are not scheduled for automatic restarts. You can use filtering on nested fields to filter based on resource labels.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart = true) (cpuPlatform = \"Intel Skylake\"). By default, each expression is an AND expression. However, you can include AND and OR expressions explicitly. For example, (cpuPlatform = \"Intel Skylake\") OR (cpuPlatform = \"Intel Broadwell\") AND (scheduling.automaticRestart = true).", "location": "query", "type": "string" }, "maxResults": { "default": "500", + "description": "The maximum number of results per page that should be returned. If the number of available results is larger than maxResults, Compute Engine returns a nextPageToken that can be used to get the next page of results in subsequent list requests. Acceptable values are 0 to 500, inclusive. (Default: 500)", "format": "uint32", "location": "query", "minimum": "0", "type": "integer" }, "order_by": { + "description": "Sorts list results by a certain order. By default, results are returned in alphanumerical order based on the resource name.\n\nYou can also sort results in descending order based on the creation timestamp using orderBy=\"creationTimestamp desc\". This sorts results based on the creationTimestamp field in reverse chronological order (newest result first). Use this to sort resources like operations so that the newest operation is returned first.\n\nCurrently, only sorting by name or creationTimestamp desc is supported.", "location": "query", "type": "string" }, "pageToken": { + "description": "Specifies a page token to use. Set pageToken to the nextPageToken returned by a previous list request to get the next page of results.", "location": "query", "type": "string" }, @@ -13635,9 +14822,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -13949,7 +15136,7 @@ "backendService": { "description": "Name of the BackendService resource to patch.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -14010,9 +15197,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -14297,9 +15484,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -14424,6 +15611,55 @@ }, "regionDisks": { "methods": { + "addResourcePolicies": { + "description": "Adds existing resource policies to a regional disk. You can only add one policy which will be applied to this disk for scheduling snapshot creation.", + "httpMethod": "POST", + "id": "compute.regionDisks.addResourcePolicies", + "parameterOrder": [ + "project", + "region", + "disk" + ], + "parameters": { + "disk": { + "description": "The disk name for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + "required": true, + "type": "string" + }, + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "region": { + "description": "The name of the region for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + }, + "requestId": { + "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", + "location": "query", + "type": "string" + } + }, + "path": "{project}/regions/{region}/disks/{disk}/addResourcePolicies", + "request": { + "$ref": "RegionDisksAddResourcePoliciesRequest" + }, + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute" + ] + }, "createSnapshot": { "description": "Creates a snapshot of this regional disk.", "httpMethod": "POST", @@ -14437,7 +15673,7 @@ "disk": { "description": "Name of the regional persistent disk to snapshot.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -14535,7 +15771,7 @@ "disk": { "description": "Name of the regional persistent disk to return.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -14667,6 +15903,55 @@ "https://www.googleapis.com/auth/compute.readonly" ] }, + "removeResourcePolicies": { + "description": "Removes resource policies from a regional disk.", + "httpMethod": "POST", + "id": "compute.regionDisks.removeResourcePolicies", + "parameterOrder": [ + "project", + "region", + "disk" + ], + "parameters": { + "disk": { + "description": "The disk name for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + "required": true, + "type": "string" + }, + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "region": { + "description": "The name of the region for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + }, + "requestId": { + "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", + "location": "query", + "type": "string" + } + }, + "path": "{project}/regions/{region}/disks/{disk}/removeResourcePolicies", + "request": { + "$ref": "RegionDisksRemoveResourcePoliciesRequest" + }, + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute" + ] + }, "resize": { "description": "Resizes the specified regional persistent disk.", "httpMethod": "POST", @@ -14680,7 +15965,7 @@ "disk": { "description": "Name of the regional persistent disk.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -14746,9 +16031,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -14790,9 +16075,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -15074,9 +16359,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -15148,7 +16433,7 @@ "regionInstanceGroupManagers": { "methods": { "abandonInstances": { - "description": "Schedules a group action to remove the specified instances from the managed instance group. Abandoning an instance does not delete the instance, but it does remove the instance from any target pools that are applied by the managed instance group. This method reduces the targetSize of the managed instance group by the number of instances that you abandon. This operation is marked as DONE when the action is scheduled even if the instances have not yet been removed from the group. You must separately verify the status of the abandoning action with the listmanagedinstances method.\n\nIf the group is part of a backend service that has enabled connection draining, it can take up to 60 seconds after the connection draining duration has elapsed before the VM instance is removed or deleted.\n\nYou can specify a maximum of 1000 instances with this method per request.", + "description": "Flags the specified instances to be immediately removed from the managed instance group. Abandoning an instance does not delete the instance, but it does remove the instance from any target pools that are applied by the managed instance group. This method reduces the targetSize of the managed instance group by the number of instances that you abandon. This operation is marked as DONE when the action is scheduled even if the instances have not yet been removed from the group. You must separately verify the status of the abandoning action with the listmanagedinstances method.\n\nIf the group is part of a backend service that has enabled connection draining, it can take up to 60 seconds after the connection draining duration has elapsed before the VM instance is removed or deleted.\n\nYou can specify a maximum of 1000 instances with this method per request.", "httpMethod": "POST", "id": "compute.regionInstanceGroupManagers.abandonInstances", "parameterOrder": [ @@ -15281,7 +16566,7 @@ ] }, "deleteInstances": { - "description": "Schedules a group action to delete the specified instances in the managed instance group. The instances are also removed from any target pools of which they were a member. This method reduces the targetSize of the managed instance group by the number of instances that you delete. This operation is marked as DONE when the action is scheduled even if the instances are still being deleted. You must separately verify the status of the deleting action with the listmanagedinstances method.\n\nIf the group is part of a backend service that has enabled connection draining, it can take up to 60 seconds after the connection draining duration has elapsed before the VM instance is removed or deleted.\n\nYou can specify a maximum of 1000 instances with this method per request.", + "description": "Flags the specified instances in the managed instance group to be immediately deleted. The instances are also removed from any target pools of which they were a member. This method reduces the targetSize of the managed instance group by the number of instances that you delete. The deleteInstances operation is marked DONE if the deleteInstances request is successful. The underlying actions take additional time. You must separately verify the status of the deleting action with the listmanagedinstances method.\n\nIf the group is part of a backend service that has enabled connection draining, it can take up to 60 seconds after the connection draining duration has elapsed before the VM instance is removed or deleted.\n\nYou can specify a maximum of 1000 instances with this method per request.", "httpMethod": "POST", "id": "compute.regionInstanceGroupManagers.deleteInstances", "parameterOrder": [ @@ -15410,7 +16695,7 @@ ] }, "insert": { - "description": "Creates a managed instance group using the information that you specify in the request. After the group is created, it schedules an action to create instances in the group using the specified instance template. This operation is marked as DONE when the group is created even if the instances in the group have not yet been created. You must separately verify the status of the individual instances with the listmanagedinstances method.\n\nA regional managed instance group can contain up to 2000 instances.", + "description": "Creates a managed instance group using the information that you specify in the request. After the group is created, instances in the group are created using the specified instance template. This operation is marked as DONE when the group is created even if the instances in the group have not yet been created. You must separately verify the status of the individual instances with the listmanagedinstances method.\n\nA regional managed instance group can contain up to 2000 instances.", "httpMethod": "POST", "id": "compute.regionInstanceGroupManagers.insert", "parameterOrder": [ @@ -15516,6 +16801,7 @@ ], "parameters": { "filter": { + "description": "A filter expression that filters resources listed in the response. The expression must specify the field name, a comparison operator, and the value that you want to use for filtering. The value must be a string, a number, or a boolean. The comparison operator must be either =, !=, \u003e, or \u003c.\n\nFor example, if you are filtering Compute Engine instances, you can exclude instances named example-instance by specifying name != example-instance.\n\nYou can also filter nested fields. For example, you could specify scheduling.automaticRestart = false to include instances only if they are not scheduled for automatic restarts. You can use filtering on nested fields to filter based on resource labels.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart = true) (cpuPlatform = \"Intel Skylake\"). By default, each expression is an AND expression. However, you can include AND and OR expressions explicitly. For example, (cpuPlatform = \"Intel Skylake\") OR (cpuPlatform = \"Intel Broadwell\") AND (scheduling.automaticRestart = true).", "location": "query", "type": "string" }, @@ -15527,16 +16813,19 @@ }, "maxResults": { "default": "500", + "description": "The maximum number of results per page that should be returned. If the number of available results is larger than maxResults, Compute Engine returns a nextPageToken that can be used to get the next page of results in subsequent list requests. Acceptable values are 0 to 500, inclusive. (Default: 500)", "format": "uint32", "location": "query", "minimum": "0", "type": "integer" }, "order_by": { + "description": "Sorts list results by a certain order. By default, results are returned in alphanumerical order based on the resource name.\n\nYou can also sort results in descending order based on the creation timestamp using orderBy=\"creationTimestamp desc\". This sorts results based on the creationTimestamp field in reverse chronological order (newest result first). Use this to sort resources like operations so that the newest operation is returned first.\n\nCurrently, only sorting by name or creationTimestamp desc is supported.", "location": "query", "type": "string" }, "pageToken": { + "description": "Specifies a page token to use. Set pageToken to the nextPageToken returned by a previous list request to get the next page of results.", "location": "query", "type": "string" }, @@ -15675,7 +16964,7 @@ ] }, "recreateInstances": { - "description": "Schedules a group action to recreate the specified instances in the managed instance group. The instances are deleted and recreated using the current instance template for the managed instance group. This operation is marked as DONE when the action is scheduled even if the instances have not yet been recreated. You must separately verify the status of the recreating action with the listmanagedinstances method.\n\nIf the group is part of a backend service that has enabled connection draining, it can take up to 60 seconds after the connection draining duration has elapsed before the VM instance is removed or deleted.\n\nYou can specify a maximum of 1000 instances with this method per request.", + "description": "Flags the specified instances in the managed instance group to be immediately recreated. The instances are deleted and recreated using the current instance template for the managed instance group. This operation is marked as DONE when the flag is set even if the instances have not yet been recreated. You must separately verify the status of the recreating action with the listmanagedinstances method.\n\nIf the group is part of a backend service that has enabled connection draining, it can take up to 60 seconds after the connection draining duration has elapsed before the VM instance is removed or deleted.\n\nYou can specify a maximum of 1000 instances with this method per request.", "httpMethod": "POST", "id": "compute.regionInstanceGroupManagers.recreateInstances", "parameterOrder": [ @@ -15722,7 +17011,7 @@ ] }, "resize": { - "description": "Changes the intended size for the managed instance group. If you increase the size, the group schedules actions to create new instances using the current instance template. If you decrease the size, the group schedules delete actions on one or more instances. The resize operation is marked DONE when the resize actions are scheduled even if the group has not yet added or deleted any instances. You must separately verify the status of the creating or deleting actions with the listmanagedinstances method.\n\nIf the group is part of a backend service that has enabled connection draining, it can take up to 60 seconds after the connection draining duration has elapsed before the VM instance is removed or deleted.", + "description": "Changes the intended size of the managed instance group. If you increase the size, the group creates new instances using the current instance template. If you decrease the size, the group deletes one or more instances.\n\nThe resize operation is marked DONE if the resize request is successful. The underlying actions take additional time. You must separately verify the status of the creating or deleting actions with the listmanagedinstances method.\n\nIf the group is part of a backend service that has enabled connection draining, it can take up to 60 seconds after the connection draining duration has elapsed before the VM instance is removed or deleted.", "httpMethod": "POST", "id": "compute.regionInstanceGroupManagers.resize", "parameterOrder": [ @@ -15775,7 +17064,7 @@ ] }, "setAutoHealingPolicies": { - "description": "Modifies the autohealing policy for the instances in this managed instance group.", + "description": "Modifies the autohealing policy for the instances in this managed instance group. [Deprecated] This method is deprecated. Please use Patch instead.", "httpMethod": "POST", "id": "compute.regionInstanceGroupManagers.setAutoHealingPolicies", "parameterOrder": [ @@ -15940,9 +17229,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -16035,6 +17324,11 @@ "location": "path", "required": true, "type": "string" + }, + "requestId": { + "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", + "location": "query", + "type": "string" } }, "path": "{project}/regions/{region}/instanceGroupManagers/{instanceGroupManager}/updatePerInstanceConfigs", @@ -16287,9 +17581,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -16492,6 +17786,241 @@ } } }, + "regionSslCertificates": { + "methods": { + "delete": { + "description": "Deletes the specified SslCertificate resource in the region.", + "httpMethod": "DELETE", + "id": "compute.regionSslCertificates.delete", + "parameterOrder": [ + "project", + "region", + "sslCertificate" + ], + "parameters": { + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "region": { + "description": "Name of the region scoping this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + }, + "requestId": { + "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", + "location": "query", + "type": "string" + }, + "sslCertificate": { + "description": "Name of the SslCertificate resource to delete.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + } + }, + "path": "{project}/regions/{region}/sslCertificates/{sslCertificate}", + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute" + ] + }, + "get": { + "description": "Returns the specified SslCertificate resource in the specified region. Get a list of available SSL certificates by making a list() request.", + "httpMethod": "GET", + "id": "compute.regionSslCertificates.get", + "parameterOrder": [ + "project", + "region", + "sslCertificate" + ], + "parameters": { + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "region": { + "description": "Name of the region scoping this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + }, + "sslCertificate": { + "description": "Name of the SslCertificate resource to return.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + } + }, + "path": "{project}/regions/{region}/sslCertificates/{sslCertificate}", + "response": { + "$ref": "SslCertificate" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute", + "https://www.googleapis.com/auth/compute.readonly" + ] + }, + "insert": { + "description": "Creates a SslCertificate resource in the specified project and region using the data included in the request", + "httpMethod": "POST", + "id": "compute.regionSslCertificates.insert", + "parameterOrder": [ + "project", + "region" + ], + "parameters": { + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "region": { + "description": "Name of the region scoping this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + }, + "requestId": { + "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", + "location": "query", + "type": "string" + } + }, + "path": "{project}/regions/{region}/sslCertificates", + "request": { + "$ref": "SslCertificate" + }, + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute" + ] + }, + "list": { + "description": "Retrieves the list of SslCertificate resources available to the specified project in the specified region.", + "httpMethod": "GET", + "id": "compute.regionSslCertificates.list", + "parameterOrder": [ + "project", + "region" + ], + "parameters": { + "filter": { + "description": "A filter expression that filters resources listed in the response. The expression must specify the field name, a comparison operator, and the value that you want to use for filtering. The value must be a string, a number, or a boolean. The comparison operator must be either =, !=, \u003e, or \u003c.\n\nFor example, if you are filtering Compute Engine instances, you can exclude instances named example-instance by specifying name != example-instance.\n\nYou can also filter nested fields. For example, you could specify scheduling.automaticRestart = false to include instances only if they are not scheduled for automatic restarts. You can use filtering on nested fields to filter based on resource labels.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart = true) (cpuPlatform = \"Intel Skylake\"). By default, each expression is an AND expression. However, you can include AND and OR expressions explicitly. For example, (cpuPlatform = \"Intel Skylake\") OR (cpuPlatform = \"Intel Broadwell\") AND (scheduling.automaticRestart = true).", + "location": "query", + "type": "string" + }, + "maxResults": { + "default": "500", + "description": "The maximum number of results per page that should be returned. If the number of available results is larger than maxResults, Compute Engine returns a nextPageToken that can be used to get the next page of results in subsequent list requests. Acceptable values are 0 to 500, inclusive. (Default: 500)", + "format": "uint32", + "location": "query", + "minimum": "0", + "type": "integer" + }, + "orderBy": { + "description": "Sorts list results by a certain order. By default, results are returned in alphanumerical order based on the resource name.\n\nYou can also sort results in descending order based on the creation timestamp using orderBy=\"creationTimestamp desc\". This sorts results based on the creationTimestamp field in reverse chronological order (newest result first). Use this to sort resources like operations so that the newest operation is returned first.\n\nCurrently, only sorting by name or creationTimestamp desc is supported.", + "location": "query", + "type": "string" + }, + "pageToken": { + "description": "Specifies a page token to use. Set pageToken to the nextPageToken returned by a previous list request to get the next page of results.", + "location": "query", + "type": "string" + }, + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "region": { + "description": "Name of the region scoping this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + } + }, + "path": "{project}/regions/{region}/sslCertificates", + "response": { + "$ref": "SslCertificateList" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute", + "https://www.googleapis.com/auth/compute.readonly" + ] + }, + "testIamPermissions": { + "description": "Returns permissions that a caller has on the specified resource and region.", + "httpMethod": "POST", + "id": "compute.regionSslCertificates.testIamPermissions", + "parameterOrder": [ + "project", + "region", + "resource" + ], + "parameters": { + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "region": { + "description": "The name of the region for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + }, + "resource": { + "description": "Name or id of the resource for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + "required": true, + "type": "string" + } + }, + "path": "{project}/regions/{region}/sslCertificates/{resource}/testIamPermissions", + "request": { + "$ref": "TestPermissionsRequest" + }, + "response": { + "$ref": "TestPermissionsResponse" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute", + "https://www.googleapis.com/auth/compute.readonly" + ] + } + } + }, "regionTargetHttpProxies": { "methods": { "delete": { @@ -16754,14 +18283,347 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + "required": true, + "type": "string" + } + }, + "path": "{project}/regions/{region}/targetHttpProxies/{resource}/testIamPermissions", + "request": { + "$ref": "TestPermissionsRequest" + }, + "response": { + "$ref": "TestPermissionsResponse" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute", + "https://www.googleapis.com/auth/compute.readonly" + ] + } + } + }, + "regionTargetHttpsProxies": { + "methods": { + "delete": { + "description": "Deletes the specified TargetHttpsProxy resource.", + "httpMethod": "DELETE", + "id": "compute.regionTargetHttpsProxies.delete", + "parameterOrder": [ + "project", + "region", + "targetHttpsProxy" + ], + "parameters": { + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "region": { + "description": "Name of the region scoping this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + }, + "requestId": { + "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", + "location": "query", + "type": "string" + }, + "targetHttpsProxy": { + "description": "Name of the TargetHttpsProxy resource to delete.", "location": "path", "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", "required": true, "type": "string" } }, - "path": "{project}/regions/{region}/targetHttpProxies/{resource}/testIamPermissions", + "path": "{project}/regions/{region}/targetHttpsProxies/{targetHttpsProxy}", + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute" + ] + }, + "get": { + "description": "Returns the specified TargetHttpsProxy resource in the specified region. Gets a list of available target HTTP proxies by making a list() request.", + "httpMethod": "GET", + "id": "compute.regionTargetHttpsProxies.get", + "parameterOrder": [ + "project", + "region", + "targetHttpsProxy" + ], + "parameters": { + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "region": { + "description": "Name of the region scoping this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + }, + "targetHttpsProxy": { + "description": "Name of the TargetHttpsProxy resource to return.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + } + }, + "path": "{project}/regions/{region}/targetHttpsProxies/{targetHttpsProxy}", + "response": { + "$ref": "TargetHttpsProxy" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute", + "https://www.googleapis.com/auth/compute.readonly" + ] + }, + "insert": { + "description": "Creates a TargetHttpsProxy resource in the specified project and region using the data included in the request.", + "httpMethod": "POST", + "id": "compute.regionTargetHttpsProxies.insert", + "parameterOrder": [ + "project", + "region" + ], + "parameters": { + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "region": { + "description": "Name of the region scoping this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + }, + "requestId": { + "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", + "location": "query", + "type": "string" + } + }, + "path": "{project}/regions/{region}/targetHttpsProxies", + "request": { + "$ref": "TargetHttpsProxy" + }, + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute" + ] + }, + "list": { + "description": "Retrieves the list of TargetHttpsProxy resources available to the specified project in the specified region.", + "httpMethod": "GET", + "id": "compute.regionTargetHttpsProxies.list", + "parameterOrder": [ + "project", + "region" + ], + "parameters": { + "filter": { + "description": "A filter expression that filters resources listed in the response. The expression must specify the field name, a comparison operator, and the value that you want to use for filtering. The value must be a string, a number, or a boolean. The comparison operator must be either =, !=, \u003e, or \u003c.\n\nFor example, if you are filtering Compute Engine instances, you can exclude instances named example-instance by specifying name != example-instance.\n\nYou can also filter nested fields. For example, you could specify scheduling.automaticRestart = false to include instances only if they are not scheduled for automatic restarts. You can use filtering on nested fields to filter based on resource labels.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart = true) (cpuPlatform = \"Intel Skylake\"). By default, each expression is an AND expression. However, you can include AND and OR expressions explicitly. For example, (cpuPlatform = \"Intel Skylake\") OR (cpuPlatform = \"Intel Broadwell\") AND (scheduling.automaticRestart = true).", + "location": "query", + "type": "string" + }, + "maxResults": { + "default": "500", + "description": "The maximum number of results per page that should be returned. If the number of available results is larger than maxResults, Compute Engine returns a nextPageToken that can be used to get the next page of results in subsequent list requests. Acceptable values are 0 to 500, inclusive. (Default: 500)", + "format": "uint32", + "location": "query", + "minimum": "0", + "type": "integer" + }, + "orderBy": { + "description": "Sorts list results by a certain order. By default, results are returned in alphanumerical order based on the resource name.\n\nYou can also sort results in descending order based on the creation timestamp using orderBy=\"creationTimestamp desc\". This sorts results based on the creationTimestamp field in reverse chronological order (newest result first). Use this to sort resources like operations so that the newest operation is returned first.\n\nCurrently, only sorting by name or creationTimestamp desc is supported.", + "location": "query", + "type": "string" + }, + "pageToken": { + "description": "Specifies a page token to use. Set pageToken to the nextPageToken returned by a previous list request to get the next page of results.", + "location": "query", + "type": "string" + }, + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "region": { + "description": "Name of the region scoping this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + } + }, + "path": "{project}/regions/{region}/targetHttpsProxies", + "response": { + "$ref": "TargetHttpsProxyList" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute", + "https://www.googleapis.com/auth/compute.readonly" + ] + }, + "setSslCertificates": { + "description": "Replaces SslCertificates for TargetHttpsProxy.", + "httpMethod": "POST", + "id": "compute.regionTargetHttpsProxies.setSslCertificates", + "parameterOrder": [ + "project", + "region", + "targetHttpsProxy" + ], + "parameters": { + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "region": { + "description": "Name of the region scoping this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + }, + "requestId": { + "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", + "location": "query", + "type": "string" + }, + "targetHttpsProxy": { + "description": "Name of the TargetHttpsProxy resource to set an SslCertificates resource for.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + } + }, + "path": "{project}/regions/{region}/targetHttpsProxies/{targetHttpsProxy}/setSslCertificates", + "request": { + "$ref": "RegionTargetHttpsProxiesSetSslCertificatesRequest" + }, + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute" + ] + }, + "setUrlMap": { + "description": "Changes the URL map for TargetHttpsProxy.", + "httpMethod": "POST", + "id": "compute.regionTargetHttpsProxies.setUrlMap", + "parameterOrder": [ + "project", + "region", + "targetHttpsProxy" + ], + "parameters": { + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "region": { + "description": "Name of the region scoping this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + }, + "requestId": { + "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", + "location": "query", + "type": "string" + }, + "targetHttpsProxy": { + "description": "Name of the TargetHttpsProxy to set a URL map for.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + } + }, + "path": "{project}/regions/{region}/targetHttpsProxies/{targetHttpsProxy}/setUrlMap", + "request": { + "$ref": "UrlMapReference" + }, + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute" + ] + }, + "testIamPermissions": { + "description": "Returns permissions that a caller has on the specified resource.", + "httpMethod": "POST", + "id": "compute.regionTargetHttpsProxies.testIamPermissions", + "parameterOrder": [ + "project", + "region", + "resource" + ], + "parameters": { + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "region": { + "description": "The name of the region for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + }, + "resource": { + "description": "Name or id of the resource for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + "required": true, + "type": "string" + } + }, + "path": "{project}/regions/{region}/targetHttpsProxies/{resource}/testIamPermissions", "request": { "$ref": "TestPermissionsRequest" }, @@ -16907,6 +18769,55 @@ "https://www.googleapis.com/auth/compute" ] }, + "invalidateCache": { + "description": "Initiates a cache invalidation operation, invalidating the specified path, scoped to the specified UrlMap.", + "httpMethod": "POST", + "id": "compute.regionUrlMaps.invalidateCache", + "parameterOrder": [ + "project", + "region", + "urlMap" + ], + "parameters": { + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "region": { + "description": "Name of the region scoping this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + }, + "requestId": { + "description": "begin_interface: MixerMutationRequestBuilder Request ID to support idempotency.", + "location": "query", + "type": "string" + }, + "urlMap": { + "description": "Name of the UrlMap scoping this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + } + }, + "path": "{project}/regions/{region}/urlMaps/{urlMap}/invalidateCache", + "request": { + "$ref": "CacheInvalidationRule" + }, + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute" + ] + }, "list": { "description": "Retrieves the list of UrlMap resources available to the specified project in the specified region.", "httpMethod": "GET", @@ -17038,9 +18949,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -17404,9 +19315,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -17511,7 +19422,7 @@ }, "path": "{project}/regions/{region}/resourcePolicies", "response": { - "$ref": "ResourcePoliciesList" + "$ref": "ResourcePolicyList" }, "scopes": [ "https://www.googleapis.com/auth/cloud-platform", @@ -17544,9 +19455,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -17588,9 +19499,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -18073,9 +19984,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -18170,7 +20081,7 @@ "route": { "description": "Name of the Route resource to delete.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -18203,7 +20114,7 @@ "route": { "description": "Name of the Route resource to return.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -18317,9 +20228,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "(?:[-a-z0-9_]{0,62}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -18773,9 +20684,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -18809,9 +20720,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "(?:[-a-z0-9_]{0,62}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -18834,7 +20745,7 @@ "snapshots": { "methods": { "delete": { - "description": "Deletes the specified Snapshot resource. Keep in mind that deleting a single snapshot might not necessarily delete all the data on that snapshot. If any data on the snapshot that is marked for deletion is needed for subsequent snapshots, the data will be moved to the next corresponding snapshot.\n\nFor more information, see Deleting snaphots.", + "description": "Deletes the specified Snapshot resource. Keep in mind that deleting a single snapshot might not necessarily delete all the data on that snapshot. If any data on the snapshot that is marked for deletion is needed for subsequent snapshots, the data will be moved to the next corresponding snapshot.\n\nFor more information, see Deleting snapshots.", "httpMethod": "DELETE", "id": "compute.snapshots.delete", "parameterOrder": [ @@ -18857,7 +20768,7 @@ "snapshot": { "description": "Name of the Snapshot resource to delete.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -18890,7 +20801,7 @@ "snapshot": { "description": "Name of the Snapshot resource to return.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -18922,9 +20833,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z0-9](?:[-a-z0-9_]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -19005,9 +20916,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z0-9](?:[-a-z0-9_]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -19041,9 +20952,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -19077,9 +20988,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "(?:[-a-z0-9_]{0,62}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -19101,6 +21012,55 @@ }, "sslCertificates": { "methods": { + "aggregatedList": { + "description": "Retrieves the list of all SslCertificate resources, regional and global, available to the specified project.", + "httpMethod": "GET", + "id": "compute.sslCertificates.aggregatedList", + "parameterOrder": [ + "project" + ], + "parameters": { + "filter": { + "description": "A filter expression that filters resources listed in the response. The expression must specify the field name, a comparison operator, and the value that you want to use for filtering. The value must be a string, a number, or a boolean. The comparison operator must be either =, !=, \u003e, or \u003c.\n\nFor example, if you are filtering Compute Engine instances, you can exclude instances named example-instance by specifying name != example-instance.\n\nYou can also filter nested fields. For example, you could specify scheduling.automaticRestart = false to include instances only if they are not scheduled for automatic restarts. You can use filtering on nested fields to filter based on resource labels.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart = true) (cpuPlatform = \"Intel Skylake\"). By default, each expression is an AND expression. However, you can include AND and OR expressions explicitly. For example, (cpuPlatform = \"Intel Skylake\") OR (cpuPlatform = \"Intel Broadwell\") AND (scheduling.automaticRestart = true).", + "location": "query", + "type": "string" + }, + "maxResults": { + "default": "500", + "description": "The maximum number of results per page that should be returned. If the number of available results is larger than maxResults, Compute Engine returns a nextPageToken that can be used to get the next page of results in subsequent list requests. Acceptable values are 0 to 500, inclusive. (Default: 500)", + "format": "uint32", + "location": "query", + "minimum": "0", + "type": "integer" + }, + "orderBy": { + "description": "Sorts list results by a certain order. By default, results are returned in alphanumerical order based on the resource name.\n\nYou can also sort results in descending order based on the creation timestamp using orderBy=\"creationTimestamp desc\". This sorts results based on the creationTimestamp field in reverse chronological order (newest result first). Use this to sort resources like operations so that the newest operation is returned first.\n\nCurrently, only sorting by name or creationTimestamp desc is supported.", + "location": "query", + "type": "string" + }, + "pageToken": { + "description": "Specifies a page token to use. Set pageToken to the nextPageToken returned by a previous list request to get the next page of results.", + "location": "query", + "type": "string" + }, + "project": { + "description": "Name of the project scoping this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + } + }, + "path": "{project}/aggregated/sslCertificates", + "response": { + "$ref": "SslCertificateAggregatedList" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute", + "https://www.googleapis.com/auth/compute.readonly" + ] + }, "delete": { "description": "Deletes the specified SslCertificate resource.", "httpMethod": "DELETE", @@ -19272,9 +21232,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "(?:[-a-z0-9_]{0,62}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -19554,9 +21514,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "(?:[-a-z0-9_]{0,62}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -19789,9 +21749,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -19954,7 +21914,7 @@ ] }, "patch": { - "description": "Patches the specified subnetwork with the data included in the request. Only the following fields within the subnetwork resource can be specified in the request: secondary_ip_range, allow_subnet_cidr_routes_overlap and role. It is also mandatory to specify the current fingeprint of the subnetwork resource being patched.", + "description": "Patches the specified subnetwork with the data included in the request. Only certain fields can up updated with a patch request as indicated in the field descriptions. You must specify the current fingeprint of the subnetwork resource being patched.", "httpMethod": "PATCH", "id": "compute.subnetworks.patch", "parameterOrder": [ @@ -19963,6 +21923,12 @@ "subnetwork" ], "parameters": { + "drainTimeoutSeconds": { + "description": "The drain timeout specifies the upper bound in seconds on the amount of time allowed to drain connections from the current ACTIVE subnetwork to the current BACKUP subnetwork. The drain timeout is only applicable when the following conditions are true: - the subnetwork being patched has purpose = INTERNAL_HTTPS_LOAD_BALANCER - the subnetwork being patched has role = BACKUP - the patch request is setting the role to ACTIVE. Note that after this patch operation the roles of the ACTIVE and BACKUP subnetworks will be swapped.", + "format": "int32", + "location": "query", + "type": "integer" + }, "project": { "description": "Project ID for this request.", "location": "path", @@ -20027,9 +21993,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -20120,9 +22086,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -20405,9 +22371,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "(?:[-a-z0-9_]{0,62}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -20429,6 +22395,55 @@ }, "targetHttpsProxies": { "methods": { + "aggregatedList": { + "description": "Retrieves the list of all TargetHttpsProxy resources, regional and global, available to the specified project.", + "httpMethod": "GET", + "id": "compute.targetHttpsProxies.aggregatedList", + "parameterOrder": [ + "project" + ], + "parameters": { + "filter": { + "description": "A filter expression that filters resources listed in the response. The expression must specify the field name, a comparison operator, and the value that you want to use for filtering. The value must be a string, a number, or a boolean. The comparison operator must be either =, !=, \u003e, or \u003c.\n\nFor example, if you are filtering Compute Engine instances, you can exclude instances named example-instance by specifying name != example-instance.\n\nYou can also filter nested fields. For example, you could specify scheduling.automaticRestart = false to include instances only if they are not scheduled for automatic restarts. You can use filtering on nested fields to filter based on resource labels.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart = true) (cpuPlatform = \"Intel Skylake\"). By default, each expression is an AND expression. However, you can include AND and OR expressions explicitly. For example, (cpuPlatform = \"Intel Skylake\") OR (cpuPlatform = \"Intel Broadwell\") AND (scheduling.automaticRestart = true).", + "location": "query", + "type": "string" + }, + "maxResults": { + "default": "500", + "description": "The maximum number of results per page that should be returned. If the number of available results is larger than maxResults, Compute Engine returns a nextPageToken that can be used to get the next page of results in subsequent list requests. Acceptable values are 0 to 500, inclusive. (Default: 500)", + "format": "uint32", + "location": "query", + "minimum": "0", + "type": "integer" + }, + "orderBy": { + "description": "Sorts list results by a certain order. By default, results are returned in alphanumerical order based on the resource name.\n\nYou can also sort results in descending order based on the creation timestamp using orderBy=\"creationTimestamp desc\". This sorts results based on the creationTimestamp field in reverse chronological order (newest result first). Use this to sort resources like operations so that the newest operation is returned first.\n\nCurrently, only sorting by name or creationTimestamp desc is supported.", + "location": "query", + "type": "string" + }, + "pageToken": { + "description": "Specifies a page token to use. Set pageToken to the nextPageToken returned by a previous list request to get the next page of results.", + "location": "query", + "type": "string" + }, + "project": { + "description": "Name of the project scoping this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + } + }, + "path": "{project}/aggregated/targetHttpsProxies", + "response": { + "$ref": "TargetHttpsProxyAggregatedList" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute", + "https://www.googleapis.com/auth/compute.readonly" + ] + }, "delete": { "description": "Deletes the specified TargetHttpsProxy resource.", "httpMethod": "DELETE", @@ -20762,9 +22777,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "(?:[-a-z0-9_]{0,62}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -21039,9 +23054,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -21626,9 +23641,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -21984,9 +23999,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "(?:[-a-z0-9_]{0,62}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -22261,9 +24276,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "(?:[-a-z0-9_]{0,62}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -22550,9 +24565,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -22594,9 +24609,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -22618,6 +24633,55 @@ }, "urlMaps": { "methods": { + "aggregatedList": { + "description": "Retrieves the list of all UrlMap resources, regional and global, available to the specified project.", + "httpMethod": "GET", + "id": "compute.urlMaps.aggregatedList", + "parameterOrder": [ + "project" + ], + "parameters": { + "filter": { + "description": "A filter expression that filters resources listed in the response. The expression must specify the field name, a comparison operator, and the value that you want to use for filtering. The value must be a string, a number, or a boolean. The comparison operator must be either =, !=, \u003e, or \u003c.\n\nFor example, if you are filtering Compute Engine instances, you can exclude instances named example-instance by specifying name != example-instance.\n\nYou can also filter nested fields. For example, you could specify scheduling.automaticRestart = false to include instances only if they are not scheduled for automatic restarts. You can use filtering on nested fields to filter based on resource labels.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart = true) (cpuPlatform = \"Intel Skylake\"). By default, each expression is an AND expression. However, you can include AND and OR expressions explicitly. For example, (cpuPlatform = \"Intel Skylake\") OR (cpuPlatform = \"Intel Broadwell\") AND (scheduling.automaticRestart = true).", + "location": "query", + "type": "string" + }, + "maxResults": { + "default": "500", + "description": "The maximum number of results per page that should be returned. If the number of available results is larger than maxResults, Compute Engine returns a nextPageToken that can be used to get the next page of results in subsequent list requests. Acceptable values are 0 to 500, inclusive. (Default: 500)", + "format": "uint32", + "location": "query", + "minimum": "0", + "type": "integer" + }, + "orderBy": { + "description": "Sorts list results by a certain order. By default, results are returned in alphanumerical order based on the resource name.\n\nYou can also sort results in descending order based on the creation timestamp using orderBy=\"creationTimestamp desc\". This sorts results based on the creationTimestamp field in reverse chronological order (newest result first). Use this to sort resources like operations so that the newest operation is returned first.\n\nCurrently, only sorting by name or creationTimestamp desc is supported.", + "location": "query", + "type": "string" + }, + "pageToken": { + "description": "Specifies a page token to use. Set pageToken to the nextPageToken returned by a previous list request to get the next page of results.", + "location": "query", + "type": "string" + }, + "project": { + "description": "Name of the project scoping this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + } + }, + "path": "{project}/aggregated/urlMaps", + "response": { + "$ref": "UrlMapsAggregatedList" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute", + "https://www.googleapis.com/auth/compute.readonly" + ] + }, "delete": { "description": "Deletes the specified UrlMap resource.", "httpMethod": "DELETE", @@ -22871,9 +24935,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "(?:[-a-z0-9_]{0,62}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -23237,9 +25301,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -23281,9 +25345,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -23570,9 +25634,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -23614,9 +25678,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -23907,6 +25971,7 @@ } } }, + "revision": "20181130", "rootUrl": "https://www.googleapis.com/", "schemas": { "AcceleratorConfig": { @@ -24408,7 +26473,7 @@ "type": "string" }, "labelFingerprint": { - "description": "A fingerprint for the labels being applied to this Address, which is essentially a hash of the labels set used for optimistic locking. The fingerprint is initially generated by Compute Engine and changes after every request to modify or update labels. You must always provide an up-to-date fingerprint hash in order to update or change labels.\n\nTo see the latest fingerprint, make a get() request to retrieve an Address.", + "description": "A fingerprint for the labels being applied to this Address, which is essentially a hash of the labels set used for optimistic locking. The fingerprint is initially generated by Compute Engine and changes after every request to modify or update labels. You must always provide an up-to-date fingerprint hash in order to update or change labels, otherwise the request will fail with error 412 conditionNotMet.\n\nTo see the latest fingerprint, make a get() request to retrieve an Address.", "format": "byte", "type": "string" }, @@ -24434,7 +26499,7 @@ "type": "string" }, "networkTier": { - "description": "This signifies the networking tier used for configuring this Address and can only take the following values: PREMIUM , STANDARD.\n\nIf this field is not specified, it is assumed to be PREMIUM.", + "description": "This signifies the networking tier used for configuring this Address and can only take the following values: PREMIUM, STANDARD. Global forwarding rules can only be Premium Tier. Regional forwarding rules can be either Premium or Standard Tier. Standard Tier addresses applied to regional forwarding rules can be used with any external load balancer. Regional forwarding rules in Premium Tier can only be used with a Network load balancer.\n\nIf this field is not specified, it is assumed to be PREMIUM.", "enum": [ "PREMIUM", "SELECT", @@ -24457,7 +26522,7 @@ "enum": [ "DNS_RESOLVER", "GCE_ENDPOINT", - "UNSPECIFIED_PURPOSE", + "NAT_AUTO", "VPC_PEERING" ], "enumDescriptions": [ @@ -24837,6 +26902,501 @@ }, "type": "object" }, + "Allocation": { + "description": "Allocation resource", + "id": "Allocation", + "properties": { + "commitment": { + "description": "Full or partial url for commitment in which this allocation is to be created. This field is ignored when allocations are created during committment creation.", + "type": "string" + }, + "creationTimestamp": { + "description": "[Output Only] Creation timestamp in RFC3339 text format.", + "type": "string" + }, + "description": { + "type": "string" + }, + "id": { + "description": "[Output Only] The unique identifier for the resource. This identifier is defined by the server.", + "format": "uint64", + "type": "string" + }, + "kind": { + "default": "compute#allocation", + "description": "[Output Only] Type of the resource. Always compute#allocations for allocations.", + "type": "string" + }, + "name": { + "annotations": { + "required": [ + "compute.instances.insert" + ] + }, + "description": "The name of the resource, provided by the client when initially creating the resource. The resource name must be 1-63 characters long, and comply with RFC1035. Specifically, the name must be 1-63 characters long and match the regular expression `[a-z]([-a-z0-9]*[a-z0-9])?` which means the first character must be a lowercase letter, and all following characters must be a dash, lowercase letter, or digit, except the last character, which cannot be a dash.", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "type": "string" + }, + "selfLink": { + "description": "[Output Only] Server-defined fully-qualified URL for this resource.", + "type": "string" + }, + "specificAllocation": { + "$ref": "AllocationSpecificSKUAllocation" + }, + "specificAllocationRequired": { + "description": "Indicates whether the allocation can be consumed by VMs with \"any allocation\" defined. If the field is set, then only VMs that target the allocation by name using --allocation-affinity can consume this allocation.", + "type": "boolean" + }, + "zone": { + "type": "string" + } + }, + "type": "object" + }, + "AllocationAffinity": { + "description": "AllocationAffinity is the configuration of desired allocation which this instance could take capacity from.", + "id": "AllocationAffinity", + "properties": { + "consumeAllocationType": { + "enum": [ + "ANY_ALLOCATION", + "NO_ALLOCATION", + "SPECIFIC_ALLOCATION", + "UNSPECIFIED" + ], + "enumDescriptions": [ + "", + "", + "", + "" + ], + "type": "string" + }, + "key": { + "description": "Corresponds to the label key of allocation resource.", + "type": "string" + }, + "values": { + "description": "Corresponds to the label values of allocation resource.", + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object" + }, + "AllocationAggregatedList": { + "description": "Contains a list of allocations.", + "id": "AllocationAggregatedList", + "properties": { + "id": { + "description": "[Output Only] Unique identifier for the resource; defined by the server.", + "type": "string" + }, + "items": { + "additionalProperties": { + "$ref": "AllocationsScopedList", + "description": "Name of the scope containing this set of allocations." + }, + "description": "A list of Allocation resources.", + "type": "object" + }, + "kind": { + "default": "compute#allocationAggregatedList", + "description": "Type of resource.", + "type": "string" + }, + "nextPageToken": { + "description": "[Output Only] This token allows you to get the next page of results for list requests. If the number of results is larger than maxResults, use the nextPageToken as a value for the query parameter pageToken in the next list request. Subsequent list requests will have their own nextPageToken to continue paging through the results.", + "type": "string" + }, + "selfLink": { + "description": "[Output Only] Server-defined URL for this resource.", + "type": "string" + }, + "warning": { + "description": "[Output Only] Informational warning message.", + "properties": { + "code": { + "description": "[Output Only] A warning code, if applicable. For example, Compute Engine returns NO_RESULTS_ON_PAGE if there are no results in the response.", + "enum": [ + "CLEANUP_FAILED", + "DEPRECATED_RESOURCE_USED", + "DEPRECATED_TYPE_USED", + "DISK_SIZE_LARGER_THAN_IMAGE_SIZE", + "EXPERIMENTAL_TYPE_USED", + "EXTERNAL_API_WARNING", + "FIELD_VALUE_OVERRIDEN", + "INJECTED_KERNELS_DEPRECATED", + "MISSING_TYPE_DEPENDENCY", + "NEXT_HOP_ADDRESS_NOT_ASSIGNED", + "NEXT_HOP_CANNOT_IP_FORWARD", + "NEXT_HOP_INSTANCE_NOT_FOUND", + "NEXT_HOP_INSTANCE_NOT_ON_NETWORK", + "NEXT_HOP_NOT_RUNNING", + "NOT_CRITICAL_ERROR", + "NO_RESULTS_ON_PAGE", + "REQUIRED_TOS_AGREEMENT", + "RESOURCE_IN_USE_BY_OTHER_RESOURCE_WARNING", + "RESOURCE_NOT_DELETED", + "SCHEMA_VALIDATION_IGNORED", + "SINGLE_INSTANCE_PROPERTY_TEMPLATE", + "UNDECLARED_PROPERTIES", + "UNREACHABLE" + ], + "enumDescriptions": [ + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "" + ], + "type": "string" + }, + "data": { + "description": "[Output Only] Metadata about this warning in key: value format. For example:\n\"data\": [ { \"key\": \"scope\", \"value\": \"zones/us-east1-d\" }", + "items": { + "properties": { + "key": { + "description": "[Output Only] A key that provides more detail on the warning being returned. For example, for warnings where there are no results in a list request for a particular zone, this key might be scope and the key value might be the zone name. Other examples might be a key indicating a deprecated resource and a suggested replacement, or a warning about invalid network settings (for example, if an instance attempts to perform IP forwarding but is not enabled for IP forwarding).", + "type": "string" + }, + "value": { + "description": "[Output Only] A warning data value corresponding to the key.", + "type": "string" + } + }, + "type": "object" + }, + "type": "array" + }, + "message": { + "description": "[Output Only] A human-readable description of the warning code.", + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object" + }, + "AllocationList": { + "id": "AllocationList", + "properties": { + "id": { + "description": "[Output Only] The unique identifier for the resource. This identifier is defined by the server.", + "type": "string" + }, + "items": { + "description": "[Output Only] A list of Allocation resources.", + "items": { + "$ref": "Allocation" + }, + "type": "array" + }, + "kind": { + "default": "compute#allocationList", + "description": "[Output Only] Type of resource.Always compute#allocationsList for listsof allocations", + "type": "string" + }, + "nextPageToken": { + "description": "[Output Only] This token allows you to get the next page of results for list requests. If the number of results is larger than maxResults, use the nextPageToken as a value for the query parameter pageToken in the next list request. Subsequent list requests will have their own nextPageToken to continue paging through the results.", + "type": "string" + }, + "selfLink": { + "description": "[Output Only] Server-defined URL for this resource.", + "type": "string" + }, + "warning": { + "description": "[Output Only] Informational warning message.", + "properties": { + "code": { + "description": "[Output Only] A warning code, if applicable. For example, Compute Engine returns NO_RESULTS_ON_PAGE if there are no results in the response.", + "enum": [ + "CLEANUP_FAILED", + "DEPRECATED_RESOURCE_USED", + "DEPRECATED_TYPE_USED", + "DISK_SIZE_LARGER_THAN_IMAGE_SIZE", + "EXPERIMENTAL_TYPE_USED", + "EXTERNAL_API_WARNING", + "FIELD_VALUE_OVERRIDEN", + "INJECTED_KERNELS_DEPRECATED", + "MISSING_TYPE_DEPENDENCY", + "NEXT_HOP_ADDRESS_NOT_ASSIGNED", + "NEXT_HOP_CANNOT_IP_FORWARD", + "NEXT_HOP_INSTANCE_NOT_FOUND", + "NEXT_HOP_INSTANCE_NOT_ON_NETWORK", + "NEXT_HOP_NOT_RUNNING", + "NOT_CRITICAL_ERROR", + "NO_RESULTS_ON_PAGE", + "REQUIRED_TOS_AGREEMENT", + "RESOURCE_IN_USE_BY_OTHER_RESOURCE_WARNING", + "RESOURCE_NOT_DELETED", + "SCHEMA_VALIDATION_IGNORED", + "SINGLE_INSTANCE_PROPERTY_TEMPLATE", + "UNDECLARED_PROPERTIES", + "UNREACHABLE" + ], + "enumDescriptions": [ + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "" + ], + "type": "string" + }, + "data": { + "description": "[Output Only] Metadata about this warning in key: value format. For example:\n\"data\": [ { \"key\": \"scope\", \"value\": \"zones/us-east1-d\" }", + "items": { + "properties": { + "key": { + "description": "[Output Only] A key that provides more detail on the warning being returned. For example, for warnings where there are no results in a list request for a particular zone, this key might be scope and the key value might be the zone name. Other examples might be a key indicating a deprecated resource and a suggested replacement, or a warning about invalid network settings (for example, if an instance attempts to perform IP forwarding but is not enabled for IP forwarding).", + "type": "string" + }, + "value": { + "description": "[Output Only] A warning data value corresponding to the key.", + "type": "string" + } + }, + "type": "object" + }, + "type": "array" + }, + "message": { + "description": "[Output Only] A human-readable description of the warning code.", + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object" + }, + "AllocationSpecificSKUAllocation": { + "description": "This allocation type allows to pre allocate specific instance configuration.", + "id": "AllocationSpecificSKUAllocation", + "properties": { + "count": { + "description": "Specifies number of resources that are allocated.", + "format": "int64", + "type": "string" + }, + "inUseCount": { + "description": "[OutputOnly] Indicates how many resource are in use.", + "format": "int64", + "type": "string" + }, + "instanceProperties": { + "$ref": "AllocationSpecificSKUAllocationAllocatedInstanceProperties" + } + }, + "type": "object" + }, + "AllocationSpecificSKUAllocationAllocatedInstanceProperties": { + "description": "Properties of the SKU instances being reserved.", + "id": "AllocationSpecificSKUAllocationAllocatedInstanceProperties", + "properties": { + "guestAccelerators": { + "description": "Specifies accelerator type and count.", + "items": { + "$ref": "AcceleratorConfig" + }, + "type": "array" + }, + "localSsds": { + "description": "Specifies amount of local ssd to reserve with each instance. The type of disk is local-ssd.", + "items": { + "$ref": "AllocationSpecificSKUAllocationAllocatedInstancePropertiesAllocatedDisk" + }, + "type": "array" + }, + "machineType": { + "description": "Specifies type of machine (name only) which has fixed number of vCPUs and fixed amount of memory. This also includes specifying custom machine type following custom-NUMBER_OF_CPUS-AMOUNT_OF_MEMORY pattern.", + "type": "string" + }, + "minCpuPlatform": { + "description": "Minimum cpu platform the allocation.", + "type": "string" + } + }, + "type": "object" + }, + "AllocationSpecificSKUAllocationAllocatedInstancePropertiesAllocatedDisk": { + "id": "AllocationSpecificSKUAllocationAllocatedInstancePropertiesAllocatedDisk", + "properties": { + "diskSizeGb": { + "description": "Specifies the size of the disk in base-2 GB.", + "format": "int64", + "type": "string" + }, + "interface": { + "description": "Specifies the disk interface to use for attaching this disk, which is either SCSI or NVME. The default is SCSI. For performance characteristics of SCSI over NVMe, see Local SSD performance.", + "enum": [ + "NVDIMM", + "NVME", + "SCSI" + ], + "enumDescriptions": [ + "", + "", + "" + ], + "type": "string" + } + }, + "type": "object" + }, + "AllocationsScopedList": { + "id": "AllocationsScopedList", + "properties": { + "allocations": { + "description": "A list of allocations contained in this scope.", + "items": { + "$ref": "Allocation" + }, + "type": "array" + }, + "warning": { + "description": "Informational warning which replaces the list of allocations when the list is empty.", + "properties": { + "code": { + "description": "[Output Only] A warning code, if applicable. For example, Compute Engine returns NO_RESULTS_ON_PAGE if there are no results in the response.", + "enum": [ + "CLEANUP_FAILED", + "DEPRECATED_RESOURCE_USED", + "DEPRECATED_TYPE_USED", + "DISK_SIZE_LARGER_THAN_IMAGE_SIZE", + "EXPERIMENTAL_TYPE_USED", + "EXTERNAL_API_WARNING", + "FIELD_VALUE_OVERRIDEN", + "INJECTED_KERNELS_DEPRECATED", + "MISSING_TYPE_DEPENDENCY", + "NEXT_HOP_ADDRESS_NOT_ASSIGNED", + "NEXT_HOP_CANNOT_IP_FORWARD", + "NEXT_HOP_INSTANCE_NOT_FOUND", + "NEXT_HOP_INSTANCE_NOT_ON_NETWORK", + "NEXT_HOP_NOT_RUNNING", + "NOT_CRITICAL_ERROR", + "NO_RESULTS_ON_PAGE", + "REQUIRED_TOS_AGREEMENT", + "RESOURCE_IN_USE_BY_OTHER_RESOURCE_WARNING", + "RESOURCE_NOT_DELETED", + "SCHEMA_VALIDATION_IGNORED", + "SINGLE_INSTANCE_PROPERTY_TEMPLATE", + "UNDECLARED_PROPERTIES", + "UNREACHABLE" + ], + "enumDescriptions": [ + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "" + ], + "type": "string" + }, + "data": { + "description": "[Output Only] Metadata about this warning in key: value format. For example:\n\"data\": [ { \"key\": \"scope\", \"value\": \"zones/us-east1-d\" }", + "items": { + "properties": { + "key": { + "description": "[Output Only] A key that provides more detail on the warning being returned. For example, for warnings where there are no results in a list request for a particular zone, this key might be scope and the key value might be the zone name. Other examples might be a key indicating a deprecated resource and a suggested replacement, or a warning about invalid network settings (for example, if an instance attempts to perform IP forwarding but is not enabled for IP forwarding).", + "type": "string" + }, + "value": { + "description": "[Output Only] A warning data value corresponding to the key.", + "type": "string" + } + }, + "type": "object" + }, + "type": "array" + }, + "message": { + "description": "[Output Only] A human-readable description of the warning code.", + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object" + }, + "AllocationsUpdateResourceShapeRequest": { + "id": "AllocationsUpdateResourceShapeRequest", + "properties": { + "count": { + "description": "Number of allocated resources which are to be updated with minimum = 1 and maximum = 100.", + "format": "int32", + "type": "integer" + }, + "destinationAllocation": { + "description": "The name of destination allocation where the modified machines are added. If existing, its machine spec must match the modified machine spec. If non existing, new allocation with this name and modified machine spec is created automatically.", + "type": "string" + }, + "updatedResourceProperties": { + "$ref": "AllocationSpecificSKUAllocationAllocatedInstanceProperties" + } + }, + "type": "object" + }, "AttachedDisk": { "description": "An instance-attached disk resource.", "id": "AttachedDisk", @@ -24881,10 +27441,12 @@ "interface": { "description": "Specifies the disk interface to use for attaching this disk, which is either SCSI or NVME. The default is SCSI. Persistent disks must always use SCSI and the request will fail if you attempt to attach a persistent disk in any other format than SCSI. Local SSDs can use either NVME or SCSI. For performance characteristics of SCSI over NVMe, see Local SSD performance.", "enum": [ + "NVDIMM", "NVME", "SCSI" ], "enumDescriptions": [ + "", "", "" ], @@ -24949,8 +27511,12 @@ "description": "[Input Only] Specifies the parameters for a new disk that will be created alongside the new instance. Use initialization parameters to create boot disks or local SSDs attached to the new instance.\n\nThis property is mutually exclusive with the source property; you can only define one or the other, but not both.", "id": "AttachedDiskInitializeParams", "properties": { + "description": { + "description": "An optional description. Provide this property when creating the disk.", + "type": "string" + }, "diskName": { - "description": "Specifies the disk name. If not specified, the default is to use the name of the instance.", + "description": "Specifies the disk name. If not specified, the default is to use the name of the instance. If the disk with the instance name exists already in the given zone/region, a new name will be automatically generated.", "type": "string" }, "diskSizeGb": { @@ -24958,18 +27524,6 @@ "format": "int64", "type": "string" }, - "diskStorageType": { - "description": "[Deprecated] Storage type of the disk.", - "enum": [ - "HDD", - "SSD" - ], - "enumDescriptions": [ - "", - "" - ], - "type": "string" - }, "diskType": { "description": "Specifies the disk type to use to create the instance. If not specified, the default is pd-standard, specified using the full URL. For example:\nhttps://www.googleapis.com/compute/v1/projects/project/zones/zone/diskTypes/pd-standard\n\n\nOther values include pd-ssd and local-ssd. If you define this field, you can provide either the full or partial URL. For example, the following are valid values: \n- https://www.googleapis.com/compute/v1/projects/project/zones/zone/diskTypes/diskType \n- projects/project/zones/zone/diskTypes/diskType \n- zones/zone/diskTypes/diskType Note that for InstanceTemplate, this is the name of the disk type, not URL.", "type": "string" @@ -24982,7 +27536,7 @@ "type": "object" }, "sourceImage": { - "description": "The source image to create this disk. When creating a new instance, one of initializeParams.sourceImage or disks.source is required except for local SSD.\n\nTo create a disk with one of the public operating system images, specify the image by its family name. For example, specify family/debian-8 to use the latest Debian 8 image:\nprojects/debian-cloud/global/images/family/debian-8\n\n\nAlternatively, use a specific version of a public operating system image:\nprojects/debian-cloud/global/images/debian-8-jessie-vYYYYMMDD\n\n\nTo create a disk with a custom image that you created, specify the image name in the following format:\nglobal/images/my-custom-image\n\n\nYou can also specify a custom image by its image family, which returns the latest version of the image in that family. Replace the image name with family/family-name:\nglobal/images/family/my-image-family\n\n\nIf the source image is deleted later, this field will not be set.", + "description": "The source image to create this disk. When creating a new instance, one of initializeParams.sourceImage or disks.source is required except for local SSD.\n\nTo create a disk with one of the public operating system images, specify the image by its family name. For example, specify family/debian-9 to use the latest Debian 9 image:\nprojects/debian-cloud/global/images/family/debian-9\n\n\nAlternatively, use a specific version of a public operating system image:\nprojects/debian-cloud/global/images/debian-9-stretch-vYYYYMMDD\n\n\nTo create a disk with a custom image that you created, specify the image name in the following format:\nglobal/images/my-custom-image\n\n\nYou can also specify a custom image by its image family, which returns the latest version of the image in that family. Replace the image name with family/family-name:\nglobal/images/family/my-image-family\n\n\nIf the source image is deleted later, this field will not be set.", "type": "string" }, "sourceImageEncryptionKey": { @@ -24992,6 +27546,10 @@ "sourceSnapshot": { "description": "The source snapshot to create this disk. When creating a new instance, one of initializeParams.sourceSnapshot or disks.source is required except for local SSD.\n\nTo create a disk with a snapshot that you created, specify the snapshot name in the following format:\nglobal/snapshots/my-backup\n\n\nIf the source snapshot is deleted later, this field will not be set.", "type": "string" + }, + "sourceSnapshotEncryptionKey": { + "$ref": "CustomerEncryptionKey", + "description": "The customer-supplied encryption key of the source snapshot." } }, "type": "object" @@ -25617,7 +28175,7 @@ "type": "number" }, "utilizationTargetType": { - "description": "Defines how target utilization value is expressed for a Stackdriver Monitoring metric. Either GAUGE, DELTA_PER_SECOND, or DELTA_PER_MINUTE. If not specified, the default is GAUGE.", + "description": "Defines how target utilization value is expressed for a Stackdriver Monitoring metric. Either GAUGE, DELTA_PER_SECOND, or DELTA_PER_MINUTE.", "enum": [ "DELTA_PER_MINUTE", "DELTA_PER_SECOND", @@ -25713,7 +28271,7 @@ "type": "boolean" }, "group": { - "description": "The fully-qualified URL of a Instance Group resource. This instance group defines the list of instances that serve traffic. Member virtual machine instances from each instance group must live in the same zone as the instance group itself. No two backends in a backend service are allowed to use same Instance Group resource.\n\nNote that you must specify an Instance Group resource using the fully-qualified URL, rather than a partial URL.\n\nWhen the BackendService has load balancing scheme INTERNAL, the instance group must be within the same region as the BackendService.", + "description": "The fully-qualified URL of an Instance Group or Network Endpoint Group resource. In case of instance group this defines the list of instances that serve traffic. Member virtual machine instances from each instance group must live in the same zone as the instance group itself. No two backends in a backend service are allowed to use same Instance Group resource.\n\nFor Network Endpoint Groups this defines list of endpoints. All endpoints of Network Endpoint Group must be hosted on instances located in the same zone as the Network Endpoint Group.\n\nBackend service can not contain mix of Instance Group and Network Endpoint Group backends.\n\nNote that you must specify an Instance Group or Network Endpoint Group resource using the fully-qualified URL, rather than a partial URL.\n\nWhen the BackendService has load balancing scheme INTERNAL, the instance group must be within the same region as the BackendService. Network Endpoint Groups are not supported for INTERNAL load balancing scheme.", "type": "string" }, "maxConnections": { @@ -25764,7 +28322,7 @@ }, "cdnPolicy": { "$ref": "BackendBucketCdnPolicy", - "description": "Cloud CDN Coniguration for this BackendBucket." + "description": "Cloud CDN configuration for this BackendBucket." }, "creationTimestamp": { "description": "[Output Only] Creation timestamp in RFC3339 text format.", @@ -25805,12 +28363,12 @@ "id": "BackendBucketCdnPolicy", "properties": { "signedUrlCacheMaxAgeSec": { - "description": "Number of seconds up to which the response to a signed URL request will be cached in the CDN. After this time period, the Signed URL will be revalidated before being served. Defaults to 1hr (3600s). If this field is set, Cloud CDN will internally act as though all responses from this bucket had a ?Cache-Control: public, max-age=[TTL]? header, regardless of any existing Cache-Control header. The actual headers served in responses will not be altered.", + "description": "Maximum number of seconds the response to a signed URL request will be considered fresh. After this time period, the response will be revalidated before being served. Defaults to 1hr (3600s). When serving responses to signed URL requests, Cloud CDN will internally behave as though all responses from this backend had a \"Cache-Control: public, max-age=[TTL]\" header, regardless of any existing Cache-Control header. The actual headers served in responses will not be altered.", "format": "int64", "type": "string" }, "signedUrlKeyNames": { - "description": "[Output Only] Names of the keys currently configured for Cloud CDN Signed URL on this backend bucket.", + "description": "[Output Only] Names of the keys for signing request URLs.", "items": { "type": "string" }, @@ -25985,7 +28543,7 @@ "$ref": "BackendServiceFailoverPolicy" }, "fingerprint": { - "description": "Fingerprint of this resource. A hash of the contents stored in this object. This field is used in optimistic locking. This field will be ignored when inserting a BackendService. An up-to-date fingerprint must be provided in order to update the BackendService.", + "description": "Fingerprint of this resource. A hash of the contents stored in this object. This field is used in optimistic locking. This field will be ignored when inserting a BackendService. An up-to-date fingerprint must be provided in order to update the BackendService, otherwise the request will fail with error 412 conditionNotMet.\n\nTo see the latest fingerprint, make a get() request to retrieve a BackendService.", "format": "byte", "type": "string" }, @@ -26014,6 +28572,7 @@ "enum": [ "EXTERNAL", "INTERNAL", + "INTERNAL_MANAGED", "INTERNAL_SELF_MANAGED", "INVALID_LOAD_BALANCING_SCHEME" ], @@ -26021,10 +28580,15 @@ "", "", "", + "", "" ], "type": "string" }, + "logConfig": { + "$ref": "BackendServiceLogConfig", + "description": "This field denotes the logging options for the load balancer traffic served by this backend service. If logging is enabled, logs will be exported to Stackdriver." + }, "name": { "description": "Name of the resource. Provided by the client when the resource is created. The name must be 1-63 characters long, and comply with RFC1035. Specifically, the name must be 1-63 characters long and match the regular expression `[a-z]([-a-z0-9]*[a-z0-9])?` which means the first character must be a lowercase letter, and all following characters must be a dash, lowercase letter, or digit, except the last character, which cannot be a dash.", "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", @@ -26238,12 +28802,12 @@ "description": "The CacheKeyPolicy for this CdnPolicy." }, "signedUrlCacheMaxAgeSec": { - "description": "Number of seconds up to which the response to a signed URL request will be cached in the CDN. After this time period, the Signed URL will be revalidated before being served. Defaults to 1hr (3600s). If this field is set, Cloud CDN will internally act as though all responses from this backend had a ?Cache-Control: public, max-age=[TTL]? header, regardless of any existing Cache-Control header. The actual headers served in responses will not be altered.", + "description": "Maximum number of seconds the response to a signed URL request will be considered fresh. After this time period, the response will be revalidated before being served. Defaults to 1hr (3600s). When serving responses to signed URL requests, Cloud CDN will internally behave as though all responses from this backend had a \"Cache-Control: public, max-age=[TTL]\" header, regardless of any existing Cache-Control header. The actual headers served in responses will not be altered.", "format": "int64", "type": "string" }, "signedUrlKeyNames": { - "description": "[Output Only] Names of the keys currently configured for Cloud CDN Signed URL on this backend service.", + "description": "[Output Only] Names of the keys for signing request URLs.", "items": { "type": "string" }, @@ -26289,7 +28853,15 @@ "BackendServiceGroupHealth": { "id": "BackendServiceGroupHealth", "properties": { + "annotations": { + "additionalProperties": { + "type": "string" + }, + "description": "Metadata defined as annotations on the network endpoint group.", + "type": "object" + }, "healthStatus": { + "description": "Health state of the backend instances or endpoints in requested instance or network endpoint group, determined based on configured health checks.", "items": { "$ref": "HealthStatus" }, @@ -26457,6 +29029,22 @@ }, "type": "object" }, + "BackendServiceLogConfig": { + "description": "The available logging options for the load balancer traffic served by this backend service.", + "id": "BackendServiceLogConfig", + "properties": { + "enable": { + "description": "This field denotes whether to enable logging for the load balancer traffic served by this backend service.", + "type": "boolean" + }, + "sampleRate": { + "description": "This field can only be specified if logging is enabled for this backend service. The value of the field must be in [0, 1]. This configures the sampling rate of requests to the load balancer where 1.0 means all logged requests are reported and 0.0 means no logged requests are reported. The default value is 1.0.", + "format": "float", + "type": "number" + } + }, + "type": "object" + }, "BackendServiceReference": { "id": "BackendServiceReference", "properties": { @@ -26566,7 +29154,7 @@ "properties": { "condition": { "$ref": "Expr", - "description": "The condition that is associated with this binding. NOTE: an unsatisfied condition will not allow user access via current binding. Different bindings, including their conditions, are examined independently. This field is only visible as GOOGLE_INTERNAL or CONDITION_TRUSTED_TESTER." + "description": "Unimplemented. The condition that is associated with this binding. NOTE: an unsatisfied condition will not allow user access via current binding. Different bindings, including their conditions, are examined independently." }, "members": { "description": "Specifies the identities requesting access for a Cloud Platform resource. `members` can have the following values:\n\n* `allUsers`: A special identifier that represents anyone who is on the internet; with or without a Google account.\n\n* `allAuthenticatedUsers`: A special identifier that represents anyone who is authenticated with a Google account or a service account.\n\n* `user:{emailid}`: An email address that represents a specific Google account. For example, `alice@gmail.com` .\n\n\n\n* `serviceAccount:{emailid}`: An email address that represents a service account. For example, `my-other-app@appspot.gserviceaccount.com`.\n\n* `group:{emailid}`: An email address that represents a Google group. For example, `admins@example.com`.\n\n\n\n* `domain:{domain}`: A Google Apps domain name that represents all the users of that domain. For example, `google.com` or `example.com`.", @@ -26632,6 +29220,13 @@ "description": "Represents a Commitment resource. Creating a Commitment resource means that you are purchasing a committed use contract with an explicit start and end time. You can create commitments based on vCPUs and memory usage and receive discounted rates. For full details, read Signing Up for Committed Use Discounts.\n\nCommitted use discounts are subject to Google Cloud Platform's Service Specific Terms. By purchasing a committed use discount, you agree to these terms. Committed use discounts will not renew, so you must purchase a new commitment to continue receiving discounts. (== resource_for beta.commitments ==) (== resource_for v1.commitments ==)", "id": "Commitment", "properties": { + "allocations": { + "description": "List of allocations for this commitment.", + "items": { + "$ref": "Allocation" + }, + "type": "array" + }, "creationTimestamp": { "description": "[Output Only] Creation timestamp in RFC3339 text format.", "type": "string" @@ -27249,7 +29844,7 @@ "type": "string" }, "labelFingerprint": { - "description": "A fingerprint for the labels being applied to this disk, which is essentially a hash of the labels set used for optimistic locking. The fingerprint is initially generated by Compute Engine and changes after every request to modify or update labels. You must always provide an up-to-date fingerprint hash in order to update or change labels.\n\nTo see the latest fingerprint, make a get() request to retrieve a disk.", + "description": "A fingerprint for the labels being applied to this disk, which is essentially a hash of the labels set used for optimistic locking. The fingerprint is initially generated by Compute Engine and changes after every request to modify or update labels. You must always provide an up-to-date fingerprint hash in order to update or change labels, otherwise the request will fail with error 412 conditionNotMet.\n\nTo see the latest fingerprint, make a get() request to retrieve a disk.", "format": "byte", "type": "string" }, @@ -27277,7 +29872,7 @@ "type": "array" }, "licenses": { - "description": "Any applicable publicly visible licenses.", + "description": "A list of publicly visible licenses. Reserved for Google's use.", "items": { "type": "string" }, @@ -27298,7 +29893,7 @@ "type": "string" }, "physicalBlockSizeBytes": { - "description": "Physical block size of the persistent disk, in bytes. If not present in a request, a default value is used. Initially only 4096 is supported, but other powers of two may be added. If an unsupported value is requested, the error message will list the supported values, but even a supported value may be allowed for only some projects.", + "description": "Physical block size of the persistent disk, in bytes. If not present in a request, a default value is used. Currently supported sizes are 4096 and 16384, other sizes may be added in the future. If an unsupported value is requested, the error message will list the supported values for the caller's project.", "format": "int64", "type": "string" }, @@ -27330,7 +29925,7 @@ "type": "string" }, "sourceImage": { - "description": "The source image used to create this disk. If the source image is deleted, this field will not be set.\n\nTo create a disk with one of the public operating system images, specify the image by its family name. For example, specify family/debian-8 to use the latest Debian 8 image:\nprojects/debian-cloud/global/images/family/debian-8\n\n\nAlternatively, use a specific version of a public operating system image:\nprojects/debian-cloud/global/images/debian-8-jessie-vYYYYMMDD\n\n\nTo create a disk with a custom image that you created, specify the image name in the following format:\nglobal/images/my-custom-image\n\n\nYou can also specify a custom image by its image family, which returns the latest version of the image in that family. Replace the image name with family/family-name:\nglobal/images/family/my-image-family", + "description": "The source image used to create this disk. If the source image is deleted, this field will not be set.\n\nTo create a disk with one of the public operating system images, specify the image by its family name. For example, specify family/debian-9 to use the latest Debian 9 image:\nprojects/debian-cloud/global/images/family/debian-9\n\n\nAlternatively, use a specific version of a public operating system image:\nprojects/debian-cloud/global/images/debian-9-stretch-vYYYYMMDD\n\n\nTo create a disk with a custom image that you created, specify the image name in the following format:\nglobal/images/my-custom-image\n\n\nYou can also specify a custom image by its image family, which returns the latest version of the image in that family. Replace the image name with family/family-name:\nglobal/images/family/my-image-family", "type": "string" }, "sourceImageEncryptionKey": { @@ -28182,10 +30777,22 @@ }, "type": "object" }, + "DisplayDevice": { + "description": "A set of Display Device options", + "id": "DisplayDevice", + "properties": { + "enableDisplay": { + "description": "Defines whether the instance has Display enabled.", + "type": "boolean" + } + }, + "type": "object" + }, "DistributionPolicy": { "id": "DistributionPolicy", "properties": { "zones": { + "description": "Zones where the regional managed instance group will create and manage instances.", "items": { "$ref": "DistributionPolicyZoneConfiguration" }, @@ -28204,12 +30811,160 @@ "compute.regionInstanceGroupManagers.update" ] }, - "description": "URL of the zone where managed instance group is spawning instances (for regional resources). Zone has to belong to the region where managed instance group is located.", + "description": "The URL of the zone. The zone must exist in the region where the managed instance group is located.", "type": "string" } }, "type": "object" }, + "ExchangedPeeringRoute": { + "id": "ExchangedPeeringRoute", + "properties": { + "destRange": { + "description": "The destination range of the route.", + "type": "string" + }, + "imported": { + "description": "If the peering route is imported if there is no confliction.", + "type": "boolean" + }, + "nextHopRegion": { + "description": "The region of peering route next hop, only applies to dynamic routes.", + "type": "string" + }, + "priority": { + "description": "The priority of the peering route.", + "format": "uint32", + "type": "integer" + }, + "type": { + "description": "The type of the peering route.", + "enum": [ + "DYNAMIC_PEERING_ROUTE", + "STATIC_PEERING_ROUTE", + "SUBNET_PEERING_ROUTE" + ], + "enumDescriptions": [ + "", + "", + "" + ], + "type": "string" + } + }, + "type": "object" + }, + "ExchangedPeeringRoutesList": { + "id": "ExchangedPeeringRoutesList", + "properties": { + "id": { + "description": "[Output Only] Unique identifier for the resource; defined by the server.", + "type": "string" + }, + "items": { + "description": "A list of ExchangedPeeringRoute resources.", + "items": { + "$ref": "ExchangedPeeringRoute" + }, + "type": "array" + }, + "kind": { + "default": "compute#exchangedPeeringRoutesList", + "description": "[Output Only] Type of resource. Always compute#exchangedPeeringRoutesList for exchanged peering routes lists.", + "type": "string" + }, + "nextPageToken": { + "description": "[Output Only] This token allows you to get the next page of results for list requests. If the number of results is larger than maxResults, use the nextPageToken as a value for the query parameter pageToken in the next list request. Subsequent list requests will have their own nextPageToken to continue paging through the results.", + "type": "string" + }, + "selfLink": { + "description": "[Output Only] Server-defined URL for this resource.", + "type": "string" + }, + "warning": { + "description": "[Output Only] Informational warning message.", + "properties": { + "code": { + "description": "[Output Only] A warning code, if applicable. For example, Compute Engine returns NO_RESULTS_ON_PAGE if there are no results in the response.", + "enum": [ + "CLEANUP_FAILED", + "DEPRECATED_RESOURCE_USED", + "DEPRECATED_TYPE_USED", + "DISK_SIZE_LARGER_THAN_IMAGE_SIZE", + "EXPERIMENTAL_TYPE_USED", + "EXTERNAL_API_WARNING", + "FIELD_VALUE_OVERRIDEN", + "INJECTED_KERNELS_DEPRECATED", + "MISSING_TYPE_DEPENDENCY", + "NEXT_HOP_ADDRESS_NOT_ASSIGNED", + "NEXT_HOP_CANNOT_IP_FORWARD", + "NEXT_HOP_INSTANCE_NOT_FOUND", + "NEXT_HOP_INSTANCE_NOT_ON_NETWORK", + "NEXT_HOP_NOT_RUNNING", + "NOT_CRITICAL_ERROR", + "NO_RESULTS_ON_PAGE", + "REQUIRED_TOS_AGREEMENT", + "RESOURCE_IN_USE_BY_OTHER_RESOURCE_WARNING", + "RESOURCE_NOT_DELETED", + "SCHEMA_VALIDATION_IGNORED", + "SINGLE_INSTANCE_PROPERTY_TEMPLATE", + "UNDECLARED_PROPERTIES", + "UNREACHABLE" + ], + "enumDescriptions": [ + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "" + ], + "type": "string" + }, + "data": { + "description": "[Output Only] Metadata about this warning in key: value format. For example:\n\"data\": [ { \"key\": \"scope\", \"value\": \"zones/us-east1-d\" }", + "items": { + "properties": { + "key": { + "description": "[Output Only] A key that provides more detail on the warning being returned. For example, for warnings where there are no results in a list request for a particular zone, this key might be scope and the key value might be the zone name. Other examples might be a key indicating a deprecated resource and a suggested replacement, or a warning about invalid network settings (for example, if an instance attempts to perform IP forwarding but is not enabled for IP forwarding).", + "type": "string" + }, + "value": { + "description": "[Output Only] A warning data value corresponding to the key.", + "type": "string" + } + }, + "type": "object" + }, + "type": "array" + }, + "message": { + "description": "[Output Only] A human-readable description of the warning code.", + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object" + }, "Expr": { "description": "Represents an expression text. Example:\n\ntitle: \"User account presence\" description: \"Determines whether the request has a user account\" expression: \"size(request.user) \u003e 0\"", "id": "Expr", @@ -28309,7 +31064,7 @@ "type": "boolean" }, "enableLogging": { - "description": "This field denotes whether to enable logging for a particular firewall rule. If logging is enabled, logs will be exported to Stackdriver.", + "description": "Deprecated in favor of enable in LogConfig. This field denotes whether to enable logging for a particular firewall rule. If logging is enabled, logs will be exported to Stackdriver.", "type": "boolean" }, "id": { @@ -28322,6 +31077,10 @@ "description": "[Output Only] Type of the resource. Always compute#firewall for firewall rules.", "type": "string" }, + "logConfig": { + "$ref": "FirewallLogConfig", + "description": "This field denotes the logging options for a particular firewall rule. If logging is enabled, logs will be exported to Stackdriver." + }, "name": { "annotations": { "required": [ @@ -28496,6 +31255,17 @@ }, "type": "object" }, + "FirewallLogConfig": { + "description": "The available logging options for a firewall rule.", + "id": "FirewallLogConfig", + "properties": { + "enable": { + "description": "This field denotes whether to enable logging for a particular firewall rule.", + "type": "boolean" + } + }, + "type": "object" + }, "FixedOrPercent": { "description": "Encapsulates numeric value that can be either absolute or relative.", "id": "FixedOrPercent", @@ -28523,11 +31293,11 @@ "id": "ForwardingRule", "properties": { "IPAddress": { - "description": "The IP address that this forwarding rule is serving on behalf of.\n\nAddresses are restricted based on the forwarding rule's load balancing scheme (EXTERNAL or INTERNAL) and scope (global or regional).\n\nWhen the load balancing scheme is EXTERNAL, for global forwarding rules, the address must be a global IP, and for regional forwarding rules, the address must live in the same region as the forwarding rule. If this field is empty, an ephemeral IPv4 address from the same scope (global or regional) will be assigned. A regional forwarding rule supports IPv4 only. A global forwarding rule supports either IPv4 or IPv6.\n\nWhen the load balancing scheme is INTERNAL, this can only be an RFC 1918 IP address belonging to the network/subnet configured for the forwarding rule. By default, if this field is empty, an ephemeral internal IP address will be automatically allocated from the IP range of the subnet or network configured for this forwarding rule.\n\nAn address can be specified either by a literal IP address or a URL reference to an existing Address resource. The following examples are all valid: \n- 100.1.2.3 \n- https://www.googleapis.com/compute/v1/projects/project/regions/region/addresses/address \n- projects/project/regions/region/addresses/address \n- regions/region/addresses/address \n- global/addresses/address \n- address", + "description": "The IP address that this forwarding rule is serving on behalf of.\n\nAddresses are restricted based on the forwarding rule's load balancing scheme (EXTERNAL or INTERNAL) and scope (global or regional).\n\nWhen the load balancing scheme is EXTERNAL, for global forwarding rules, the address must be a global IP, and for regional forwarding rules, the address must live in the same region as the forwarding rule. If this field is empty, an ephemeral IPv4 address from the same scope (global or regional) will be assigned. A regional forwarding rule supports IPv4 only. A global forwarding rule supports either IPv4 or IPv6.\n\nWhen the load balancing scheme is INTERNAL_SELF_MANAGED, this must be a URL reference to an existing Address resource ( internal regional static IP address), with a purpose of GCE_END_POINT and address_type of INTERNAL.\n\nWhen the load balancing scheme is INTERNAL, this can only be an RFC 1918 IP address belonging to the network/subnet configured for the forwarding rule. By default, if this field is empty, an ephemeral internal IP address will be automatically allocated from the IP range of the subnet or network configured for this forwarding rule.\n\nAn address can be specified either by a literal IP address or a URL reference to an existing Address resource. The following examples are all valid: \n- 100.1.2.3 \n- https://www.googleapis.com/compute/v1/projects/project/regions/region/addresses/address \n- projects/project/regions/region/addresses/address \n- regions/region/addresses/address \n- global/addresses/address \n- address", "type": "string" }, "IPProtocol": { - "description": "The IP protocol to which this rule applies. Valid options are TCP, UDP, ESP, AH, SCTP or ICMP.\n\nWhen the load balancing scheme is INTERNAL, only TCP and UDP are valid.", + "description": "The IP protocol to which this rule applies. Valid options are TCP, UDP, ESP, AH, SCTP or ICMP.\n\nWhen the load balancing scheme is INTERNAL, only TCP and UDP are valid. When the load balancing scheme is INTERNAL_SELF_MANAGED, only TCPis valid.", "enum": [ "AH", "ESP", @@ -28550,8 +31320,12 @@ "description": "This field is used along with the backend_service field for internal load balancing or with the target field for internal TargetInstance. This field cannot be used with port or portRange fields.\n\nWhen the load balancing scheme is INTERNAL and protocol is TCP/UDP, specify this field to allow packets addressed to any ports will be forwarded to the backends configured with this forwarding rule.", "type": "boolean" }, + "allowGlobalAccess": { + "description": "This field is used along with the backend_service field for internal load balancing or with the target field for internal TargetInstance. If the field is set to TRUE, clients can access ILB from all regions. Otherwise only allows access from clients in the same region as the internal load balancer.", + "type": "boolean" + }, "backendService": { - "description": "This field is not used for external load balancing.\n\nFor internal load balancing, this field identifies the BackendService resource to receive the matched traffic.", + "description": "This field is only used for INTERNAL load balancing.\n\nFor internal load balancing, this field identifies the BackendService resource to receive the matched traffic.", "type": "string" }, "creationTimestamp": { @@ -28573,7 +31347,7 @@ "type": "string" }, "ipVersion": { - "description": "The IP Version that will be used by this forwarding rule. Valid options are IPV4 or IPV6. This can only be specified for a global forwarding rule.", + "description": "The IP Version that will be used by this forwarding rule. Valid options are IPV4 or IPV6. This can only be specified for an external global forwarding rule.", "enum": [ "IPV4", "IPV6", @@ -28592,7 +31366,7 @@ "type": "string" }, "labelFingerprint": { - "description": "A fingerprint for the labels being applied to this resource, which is essentially a hash of the labels set used for optimistic locking. The fingerprint is initially generated by Compute Engine and changes after every request to modify or update labels. You must always provide an up-to-date fingerprint hash in order to update or change labels.\n\nTo see the latest fingerprint, make a get() request to retrieve a ForwardingRule.", + "description": "A fingerprint for the labels being applied to this resource, which is essentially a hash of the labels set used for optimistic locking. The fingerprint is initially generated by Compute Engine and changes after every request to modify or update labels. You must always provide an up-to-date fingerprint hash in order to update or change labels, otherwise the request will fail with error 412 conditionNotMet.\n\nTo see the latest fingerprint, make a get() request to retrieve a ForwardingRule.", "format": "byte", "type": "string" }, @@ -28604,10 +31378,11 @@ "type": "object" }, "loadBalancingScheme": { - "description": "This signifies what the ForwardingRule will be used for and can only take the following values: INTERNAL, EXTERNAL The value of INTERNAL means that this will be used for Internal Network Load Balancing (TCP, UDP). The value of EXTERNAL means that this will be used for External Load Balancing (HTTP(S) LB, External TCP/UDP LB, SSL Proxy)", + "description": "This signifies what the ForwardingRule will be used for and can only take the following values: INTERNAL, INTERNAL_SELF_MANAGED, EXTERNAL. The value of INTERNAL means that this will be used for Internal Network Load Balancing (TCP, UDP). The value of INTERNAL_SELF_MANAGED means that this will be used for Internal Global HTTP(S) LB. The value of EXTERNAL means that this will be used for External Load Balancing (HTTP(S) LB, External TCP/UDP LB, SSL Proxy)", "enum": [ "EXTERNAL", "INTERNAL", + "INTERNAL_MANAGED", "INTERNAL_SELF_MANAGED", "INVALID" ], @@ -28615,6 +31390,7 @@ "", "", "", + "", "" ], "type": "string" @@ -28625,7 +31401,7 @@ "type": "string" }, "network": { - "description": "This field is not used for external load balancing.\n\nFor internal load balancing, this field identifies the network that the load balanced IP should belong to for this Forwarding Rule. If this field is not specified, the default network will be used.", + "description": "This field is not used for external load balancing.\n\nFor INTERNAL and INTERNAL_SELF_MANAGED load balancing, this field identifies the network that the load balanced IP should belong to for this Forwarding Rule. If this field is not specified, the default network will be used.", "type": "string" }, "networkTier": { @@ -28647,7 +31423,7 @@ "type": "string" }, "ports": { - "description": "This field is used along with the backend_service field for internal load balancing.\n\nWhen the load balancing scheme is INTERNAL, a single port or a comma separated list of ports can be configured. Only packets addressed to these ports will be forwarded to the backends configured with this forwarding rule.\n\nYou may specify a maximum of up to 5 ports.", + "description": "This field is used along with the backend_service field for internal load balancing.\n\nWhen the load balancing scheme is INTERNAL, a list of ports can be configured, for example, ['80'], ['8000','9000'] etc. Only packets addressed to these ports will be forwarded to the backends configured with this forwarding rule.\n\nYou may specify a maximum of up to 5 ports.", "items": { "type": "string" }, @@ -28671,11 +31447,11 @@ "type": "string" }, "subnetwork": { - "description": "This field is not used for external load balancing.\n\nFor internal load balancing, this field identifies the subnetwork that the load balanced IP should belong to for this Forwarding Rule.\n\nIf the network specified is in auto subnet mode, this field is optional. However, if the network is in custom subnet mode, a subnetwork must be specified.", + "description": "This field is only used for INTERNAL load balancing.\n\nFor internal load balancing, this field identifies the subnetwork that the load balanced IP should belong to for this Forwarding Rule.\n\nIf the network specified is in auto subnet mode, this field is optional. However, if the network is in custom subnet mode, a subnetwork must be specified.", "type": "string" }, "target": { - "description": "The URL of the target resource to receive the matched traffic. For regional forwarding rules, this target must live in the same region as the forwarding rule. For global forwarding rules, this target must be a global load balancing resource. The forwarded traffic must be of a type appropriate to the target object.", + "description": "The URL of the target resource to receive the matched traffic. For regional forwarding rules, this target must live in the same region as the forwarding rule. For global forwarding rules, this target must be a global load balancing resource. The forwarded traffic must be of a type appropriate to the target object. For INTERNAL_SELF_MANAGED\" load balancing, only HTTP and HTTPS targets are valid.", "type": "string" } }, @@ -29012,7 +31788,7 @@ "id": "GlobalSetLabelsRequest", "properties": { "labelFingerprint": { - "description": "The fingerprint of the previous set of labels for this resource, used to detect conflicts. The fingerprint is initially generated by Compute Engine and changes after every request to modify or update labels. You must always provide an up-to-date fingerprint hash when updating or changing labels. Make a get() request to the resource to get the latest fingerprint.", + "description": "The fingerprint of the previous set of labels for this resource, used to detect conflicts. The fingerprint is initially generated by Compute Engine and changes after every request to modify or update labels. You must always provide an up-to-date fingerprint hash when updating or changing labels, otherwise the request will fail with error 412 conditionNotMet. Make a get() request to the resource to get the latest fingerprint.", "format": "byte", "type": "string" }, @@ -29030,7 +31806,7 @@ "id": "GlobalSetPolicyRequest", "properties": { "bindings": { - "description": "Flatten Policy to create a backwacd compatible wire-format. Deprecated. Use 'policy' to specify bindings.", + "description": "Flatten Policy to create a backward compatible wire-format. Deprecated. Use 'policy' to specify bindings.", "items": { "$ref": "Binding" }, @@ -29057,6 +31833,14 @@ "description": "[Output Only] Type of the resource. Always compute#guestAttributes for guest attributes entry.", "type": "string" }, + "queryPath": { + "description": "The path to be queried. This can be the default namespace ('/') or a nested namespace ('//') or a specified key ('//')", + "type": "string" + }, + "queryValue": { + "$ref": "GuestAttributesValue", + "description": "[Output Only] The value of the requested queried path." + }, "selfLink": { "description": "[Output Only] Server-defined URL for this resource.", "type": "string" @@ -29072,6 +31856,38 @@ }, "type": "object" }, + "GuestAttributesEntry": { + "description": "A guest attributes namespace/key/value entry.", + "id": "GuestAttributesEntry", + "properties": { + "key": { + "description": "Key for the guest attribute entry.", + "type": "string" + }, + "namespace": { + "description": "Namespace for the guest attribute entry.", + "type": "string" + }, + "value": { + "description": "Value for the guest attribute entry.", + "type": "string" + } + }, + "type": "object" + }, + "GuestAttributesValue": { + "description": "Array of guest attribute namespace/key/value tuples.", + "id": "GuestAttributesValue", + "properties": { + "items": { + "items": { + "$ref": "GuestAttributesEntry" + }, + "type": "array" + } + }, + "type": "object" + }, "GuestOsFeature": { "description": "Guest OS features.", "id": "GuestOsFeature", @@ -29687,6 +32503,13 @@ "HealthStatus": { "id": "HealthStatus", "properties": { + "annotations": { + "additionalProperties": { + "type": "string" + }, + "description": "Metadata defined as annotations for network endpoint.", + "type": "object" + }, "healthState": { "description": "Health state of the instance.", "enum": [ @@ -29749,311 +32572,6 @@ }, "type": "object" }, - "Host": { - "id": "Host", - "properties": { - "creationTimestamp": { - "description": "[Output Only] Creation timestamp in RFC3339 text format.", - "type": "string" - }, - "description": { - "description": "[Output Only] An optional textual description of the resource.", - "type": "string" - }, - "hostType": { - "description": "Full or partial URL of the host type resource to use for this host, in the format: zones/zone/hostTypes/host-type. This is provided by the client when the host is created. For example, the following is a valid partial url to a predefined host type:\nzones/us-central1-b/hostTypes/n1-host-64-416", - "type": "string" - }, - "id": { - "description": "[Output Only] The unique identifier for the resource. This identifier is defined by the server.", - "format": "uint64", - "type": "string" - }, - "instances": { - "description": "A list of resource URLs to the virtual machine instances in this host. They must live in zones contained in the same region as this host.", - "items": { - "type": "string" - }, - "type": "array" - }, - "kind": { - "default": "compute#host", - "description": "[Output Only] The type of the resource. Always compute#host for host.", - "type": "string" - }, - "labelFingerprint": { - "description": "A fingerprint for this request, which is essentially a hash of the metadata's contents and used for optimistic locking. The fingerprint is initially generated by Compute Engine and changes after every request to modify or update metadata. You must always provide an up-to-date fingerprint hash in order to update or change metadata.\n\nTo see the latest fingerprint, make get() request to the host.", - "format": "byte", - "type": "string" - }, - "labels": { - "additionalProperties": { - "type": "string" - }, - "description": "Labels to apply to this host.", - "type": "object" - }, - "name": { - "description": "The name of the resource, provided by the client when initially creating the resource. The resource name must be 1-63 characters long, and comply with RFC1035. Specifically, the name must be 1-63 characters long and match the regular expression `[a-z]([-a-z0-9]*[a-z0-9])?` which means the first character must be a lowercase letter, and all following characters must be a dash, lowercase letter, or digit, except the last character, which cannot be a dash.", - "type": "string" - }, - "selfLink": { - "description": "[Output Only] Server-defined URL for the resource.", - "type": "string" - }, - "status": { - "description": "[Output Only] The status of the host. One of the following values: CREATING, READY, REPAIR, and DELETING.", - "enum": [ - "CREATING", - "DELETING", - "INVALID", - "READY", - "REPAIR" - ], - "enumDescriptions": [ - "", - "", - "", - "", - "" - ], - "type": "string" - }, - "statusMessage": { - "description": "[Output Only] An optional, human-readable explanation of the status.", - "type": "string" - }, - "zone": { - "description": "[Output Only] The name of the zone where the host resides, such as us-central1-a.", - "type": "string" - } - }, - "type": "object" - }, - "HostAggregatedList": { - "id": "HostAggregatedList", - "properties": { - "id": { - "description": "[Output Only] Unique identifier for the resource; defined by the server.", - "type": "string" - }, - "items": { - "additionalProperties": { - "$ref": "HostsScopedList", - "description": "[Output Only] Name of the scope containing this set of hosts." - }, - "description": "A list of HostsScopedList resources.", - "type": "object" - }, - "kind": { - "default": "compute#hostAggregatedList", - "description": "[Output Only] Type of resource. Always compute#hostAggregatedList for aggregated lists of hosts.", - "type": "string" - }, - "nextPageToken": { - "description": "[Output Only] This token allows you to get the next page of results for list requests. If the number of results is larger than maxResults, use the nextPageToken as a value for the query parameter pageToken in the next list request. Subsequent list requests will have their own nextPageToken to continue paging through the results.", - "type": "string" - }, - "selfLink": { - "description": "[Output Only] Server-defined URL for this resource.", - "type": "string" - }, - "warning": { - "description": "[Output Only] Informational warning message.", - "properties": { - "code": { - "description": "[Output Only] A warning code, if applicable. For example, Compute Engine returns NO_RESULTS_ON_PAGE if there are no results in the response.", - "enum": [ - "CLEANUP_FAILED", - "DEPRECATED_RESOURCE_USED", - "DEPRECATED_TYPE_USED", - "DISK_SIZE_LARGER_THAN_IMAGE_SIZE", - "EXPERIMENTAL_TYPE_USED", - "EXTERNAL_API_WARNING", - "FIELD_VALUE_OVERRIDEN", - "INJECTED_KERNELS_DEPRECATED", - "MISSING_TYPE_DEPENDENCY", - "NEXT_HOP_ADDRESS_NOT_ASSIGNED", - "NEXT_HOP_CANNOT_IP_FORWARD", - "NEXT_HOP_INSTANCE_NOT_FOUND", - "NEXT_HOP_INSTANCE_NOT_ON_NETWORK", - "NEXT_HOP_NOT_RUNNING", - "NOT_CRITICAL_ERROR", - "NO_RESULTS_ON_PAGE", - "REQUIRED_TOS_AGREEMENT", - "RESOURCE_IN_USE_BY_OTHER_RESOURCE_WARNING", - "RESOURCE_NOT_DELETED", - "SCHEMA_VALIDATION_IGNORED", - "SINGLE_INSTANCE_PROPERTY_TEMPLATE", - "UNDECLARED_PROPERTIES", - "UNREACHABLE" - ], - "enumDescriptions": [ - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "" - ], - "type": "string" - }, - "data": { - "description": "[Output Only] Metadata about this warning in key: value format. For example:\n\"data\": [ { \"key\": \"scope\", \"value\": \"zones/us-east1-d\" }", - "items": { - "properties": { - "key": { - "description": "[Output Only] A key that provides more detail on the warning being returned. For example, for warnings where there are no results in a list request for a particular zone, this key might be scope and the key value might be the zone name. Other examples might be a key indicating a deprecated resource and a suggested replacement, or a warning about invalid network settings (for example, if an instance attempts to perform IP forwarding but is not enabled for IP forwarding).", - "type": "string" - }, - "value": { - "description": "[Output Only] A warning data value corresponding to the key.", - "type": "string" - } - }, - "type": "object" - }, - "type": "array" - }, - "message": { - "description": "[Output Only] A human-readable description of the warning code.", - "type": "string" - } - }, - "type": "object" - } - }, - "type": "object" - }, - "HostList": { - "description": "Contains a list of hosts.", - "id": "HostList", - "properties": { - "id": { - "description": "[Output Only] Unique identifier for the resource; defined by the server.", - "type": "string" - }, - "items": { - "description": "A list of Host resources.", - "items": { - "$ref": "Host" - }, - "type": "array" - }, - "kind": { - "default": "compute#hostList", - "description": "[Output Only] Type of resource. Always compute#hostList for lists of hosts.", - "type": "string" - }, - "nextPageToken": { - "description": "[Output Only] This token allows you to get the next page of results for list requests. If the number of results is larger than maxResults, use the nextPageToken as a value for the query parameter pageToken in the next list request. Subsequent list requests will have their own nextPageToken to continue paging through the results.", - "type": "string" - }, - "selfLink": { - "description": "[Output Only] Server-defined URL for this resource.", - "type": "string" - }, - "warning": { - "description": "[Output Only] Informational warning message.", - "properties": { - "code": { - "description": "[Output Only] A warning code, if applicable. For example, Compute Engine returns NO_RESULTS_ON_PAGE if there are no results in the response.", - "enum": [ - "CLEANUP_FAILED", - "DEPRECATED_RESOURCE_USED", - "DEPRECATED_TYPE_USED", - "DISK_SIZE_LARGER_THAN_IMAGE_SIZE", - "EXPERIMENTAL_TYPE_USED", - "EXTERNAL_API_WARNING", - "FIELD_VALUE_OVERRIDEN", - "INJECTED_KERNELS_DEPRECATED", - "MISSING_TYPE_DEPENDENCY", - "NEXT_HOP_ADDRESS_NOT_ASSIGNED", - "NEXT_HOP_CANNOT_IP_FORWARD", - "NEXT_HOP_INSTANCE_NOT_FOUND", - "NEXT_HOP_INSTANCE_NOT_ON_NETWORK", - "NEXT_HOP_NOT_RUNNING", - "NOT_CRITICAL_ERROR", - "NO_RESULTS_ON_PAGE", - "REQUIRED_TOS_AGREEMENT", - "RESOURCE_IN_USE_BY_OTHER_RESOURCE_WARNING", - "RESOURCE_NOT_DELETED", - "SCHEMA_VALIDATION_IGNORED", - "SINGLE_INSTANCE_PROPERTY_TEMPLATE", - "UNDECLARED_PROPERTIES", - "UNREACHABLE" - ], - "enumDescriptions": [ - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "" - ], - "type": "string" - }, - "data": { - "description": "[Output Only] Metadata about this warning in key: value format. For example:\n\"data\": [ { \"key\": \"scope\", \"value\": \"zones/us-east1-d\" }", - "items": { - "properties": { - "key": { - "description": "[Output Only] A key that provides more detail on the warning being returned. For example, for warnings where there are no results in a list request for a particular zone, this key might be scope and the key value might be the zone name. Other examples might be a key indicating a deprecated resource and a suggested replacement, or a warning about invalid network settings (for example, if an instance attempts to perform IP forwarding but is not enabled for IP forwarding).", - "type": "string" - }, - "value": { - "description": "[Output Only] A warning data value corresponding to the key.", - "type": "string" - } - }, - "type": "object" - }, - "type": "array" - }, - "message": { - "description": "[Output Only] A human-readable description of the warning code.", - "type": "string" - } - }, - "type": "object" - } - }, - "type": "object" - }, "HostRule": { "description": "UrlMaps A host-matching rule for a URL. If matched, will use the named PathMatcher to select the BackendService.", "id": "HostRule", @@ -30076,479 +32594,6 @@ }, "type": "object" }, - "HostType": { - "description": "A Host Type resource.", - "id": "HostType", - "properties": { - "cpuPlatform": { - "description": "[Output Only] The CPU platform used by this host type.", - "type": "string" - }, - "creationTimestamp": { - "description": "[Output Only] Creation timestamp in RFC3339 text format.", - "type": "string" - }, - "deprecated": { - "$ref": "DeprecationStatus", - "description": "[Output Only] The deprecation status associated with this host type." - }, - "description": { - "description": "[Output Only] An optional textual description of the resource.", - "type": "string" - }, - "guestCpus": { - "description": "[Output Only] The number of virtual CPUs that are available to the host type.", - "format": "int32", - "type": "integer" - }, - "id": { - "description": "[Output Only] The unique identifier for the resource. This identifier is defined by the server.", - "format": "uint64", - "type": "string" - }, - "kind": { - "default": "compute#hostType", - "description": "[Output Only] The type of the resource. Always compute#hostType for host types.", - "type": "string" - }, - "localSsdGb": { - "description": "[Output Only] Local SSD available to the host type, defined in GB.", - "format": "int32", - "type": "integer" - }, - "memoryMb": { - "description": "[Output Only] The amount of physical memory available to the host type, defined in MB.", - "format": "int32", - "type": "integer" - }, - "name": { - "description": "[Output Only] Name of the resource.", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", - "type": "string" - }, - "selfLink": { - "description": "[Output Only] Server-defined URL for the resource.", - "type": "string" - }, - "zone": { - "description": "[Output Only] The name of the zone where the host type resides, such as us-central1-a.", - "type": "string" - } - }, - "type": "object" - }, - "HostTypeAggregatedList": { - "id": "HostTypeAggregatedList", - "properties": { - "id": { - "description": "[Output Only] Unique identifier for the resource; defined by the server.", - "type": "string" - }, - "items": { - "additionalProperties": { - "$ref": "HostTypesScopedList", - "description": "[Output Only] Name of the scope containing this set of host types." - }, - "description": "A list of HostTypesScopedList resources.", - "type": "object" - }, - "kind": { - "default": "compute#hostTypeAggregatedList", - "description": "[Output Only] Type of resource.Always compute#hostTypeAggregatedList for aggregated lists of host types.", - "type": "string" - }, - "nextPageToken": { - "description": "[Output Only] This token allows you to get the next page of results for list requests. If the number of results is larger than maxResults, use the nextPageToken as a value for the query parameter pageToken in the next list request. Subsequent list requests will have their own nextPageToken to continue paging through the results.", - "type": "string" - }, - "selfLink": { - "description": "[Output Only] Server-defined URL for this resource.", - "type": "string" - }, - "warning": { - "description": "[Output Only] Informational warning message.", - "properties": { - "code": { - "description": "[Output Only] A warning code, if applicable. For example, Compute Engine returns NO_RESULTS_ON_PAGE if there are no results in the response.", - "enum": [ - "CLEANUP_FAILED", - "DEPRECATED_RESOURCE_USED", - "DEPRECATED_TYPE_USED", - "DISK_SIZE_LARGER_THAN_IMAGE_SIZE", - "EXPERIMENTAL_TYPE_USED", - "EXTERNAL_API_WARNING", - "FIELD_VALUE_OVERRIDEN", - "INJECTED_KERNELS_DEPRECATED", - "MISSING_TYPE_DEPENDENCY", - "NEXT_HOP_ADDRESS_NOT_ASSIGNED", - "NEXT_HOP_CANNOT_IP_FORWARD", - "NEXT_HOP_INSTANCE_NOT_FOUND", - "NEXT_HOP_INSTANCE_NOT_ON_NETWORK", - "NEXT_HOP_NOT_RUNNING", - "NOT_CRITICAL_ERROR", - "NO_RESULTS_ON_PAGE", - "REQUIRED_TOS_AGREEMENT", - "RESOURCE_IN_USE_BY_OTHER_RESOURCE_WARNING", - "RESOURCE_NOT_DELETED", - "SCHEMA_VALIDATION_IGNORED", - "SINGLE_INSTANCE_PROPERTY_TEMPLATE", - "UNDECLARED_PROPERTIES", - "UNREACHABLE" - ], - "enumDescriptions": [ - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "" - ], - "type": "string" - }, - "data": { - "description": "[Output Only] Metadata about this warning in key: value format. For example:\n\"data\": [ { \"key\": \"scope\", \"value\": \"zones/us-east1-d\" }", - "items": { - "properties": { - "key": { - "description": "[Output Only] A key that provides more detail on the warning being returned. For example, for warnings where there are no results in a list request for a particular zone, this key might be scope and the key value might be the zone name. Other examples might be a key indicating a deprecated resource and a suggested replacement, or a warning about invalid network settings (for example, if an instance attempts to perform IP forwarding but is not enabled for IP forwarding).", - "type": "string" - }, - "value": { - "description": "[Output Only] A warning data value corresponding to the key.", - "type": "string" - } - }, - "type": "object" - }, - "type": "array" - }, - "message": { - "description": "[Output Only] A human-readable description of the warning code.", - "type": "string" - } - }, - "type": "object" - } - }, - "type": "object" - }, - "HostTypeList": { - "description": "Contains a list of host types.", - "id": "HostTypeList", - "properties": { - "id": { - "description": "[Output Only] Unique identifier for the resource; defined by the server.", - "type": "string" - }, - "items": { - "description": "A list of HostType resources.", - "items": { - "$ref": "HostType" - }, - "type": "array" - }, - "kind": { - "default": "compute#hostTypeList", - "description": "[Output Only] Type of resource.Always compute#hostTypeList for lists of host types.", - "type": "string" - }, - "nextPageToken": { - "description": "[Output Only] This token allows you to get the next page of results for list requests. If the number of results is larger than maxResults, use the nextPageToken as a value for the query parameter pageToken in the next list request. Subsequent list requests will have their own nextPageToken to continue paging through the results.", - "type": "string" - }, - "selfLink": { - "description": "[Output Only] Server-defined URL for this resource.", - "type": "string" - }, - "warning": { - "description": "[Output Only] Informational warning message.", - "properties": { - "code": { - "description": "[Output Only] A warning code, if applicable. For example, Compute Engine returns NO_RESULTS_ON_PAGE if there are no results in the response.", - "enum": [ - "CLEANUP_FAILED", - "DEPRECATED_RESOURCE_USED", - "DEPRECATED_TYPE_USED", - "DISK_SIZE_LARGER_THAN_IMAGE_SIZE", - "EXPERIMENTAL_TYPE_USED", - "EXTERNAL_API_WARNING", - "FIELD_VALUE_OVERRIDEN", - "INJECTED_KERNELS_DEPRECATED", - "MISSING_TYPE_DEPENDENCY", - "NEXT_HOP_ADDRESS_NOT_ASSIGNED", - "NEXT_HOP_CANNOT_IP_FORWARD", - "NEXT_HOP_INSTANCE_NOT_FOUND", - "NEXT_HOP_INSTANCE_NOT_ON_NETWORK", - "NEXT_HOP_NOT_RUNNING", - "NOT_CRITICAL_ERROR", - "NO_RESULTS_ON_PAGE", - "REQUIRED_TOS_AGREEMENT", - "RESOURCE_IN_USE_BY_OTHER_RESOURCE_WARNING", - "RESOURCE_NOT_DELETED", - "SCHEMA_VALIDATION_IGNORED", - "SINGLE_INSTANCE_PROPERTY_TEMPLATE", - "UNDECLARED_PROPERTIES", - "UNREACHABLE" - ], - "enumDescriptions": [ - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "" - ], - "type": "string" - }, - "data": { - "description": "[Output Only] Metadata about this warning in key: value format. For example:\n\"data\": [ { \"key\": \"scope\", \"value\": \"zones/us-east1-d\" }", - "items": { - "properties": { - "key": { - "description": "[Output Only] A key that provides more detail on the warning being returned. For example, for warnings where there are no results in a list request for a particular zone, this key might be scope and the key value might be the zone name. Other examples might be a key indicating a deprecated resource and a suggested replacement, or a warning about invalid network settings (for example, if an instance attempts to perform IP forwarding but is not enabled for IP forwarding).", - "type": "string" - }, - "value": { - "description": "[Output Only] A warning data value corresponding to the key.", - "type": "string" - } - }, - "type": "object" - }, - "type": "array" - }, - "message": { - "description": "[Output Only] A human-readable description of the warning code.", - "type": "string" - } - }, - "type": "object" - } - }, - "type": "object" - }, - "HostTypesScopedList": { - "id": "HostTypesScopedList", - "properties": { - "hostTypes": { - "description": "[Output Only] A list of host types contained in this scope.", - "items": { - "$ref": "HostType" - }, - "type": "array" - }, - "warning": { - "description": "[Output Only] An informational warning that appears when the host types list is empty.", - "properties": { - "code": { - "description": "[Output Only] A warning code, if applicable. For example, Compute Engine returns NO_RESULTS_ON_PAGE if there are no results in the response.", - "enum": [ - "CLEANUP_FAILED", - "DEPRECATED_RESOURCE_USED", - "DEPRECATED_TYPE_USED", - "DISK_SIZE_LARGER_THAN_IMAGE_SIZE", - "EXPERIMENTAL_TYPE_USED", - "EXTERNAL_API_WARNING", - "FIELD_VALUE_OVERRIDEN", - "INJECTED_KERNELS_DEPRECATED", - "MISSING_TYPE_DEPENDENCY", - "NEXT_HOP_ADDRESS_NOT_ASSIGNED", - "NEXT_HOP_CANNOT_IP_FORWARD", - "NEXT_HOP_INSTANCE_NOT_FOUND", - "NEXT_HOP_INSTANCE_NOT_ON_NETWORK", - "NEXT_HOP_NOT_RUNNING", - "NOT_CRITICAL_ERROR", - "NO_RESULTS_ON_PAGE", - "REQUIRED_TOS_AGREEMENT", - "RESOURCE_IN_USE_BY_OTHER_RESOURCE_WARNING", - "RESOURCE_NOT_DELETED", - "SCHEMA_VALIDATION_IGNORED", - "SINGLE_INSTANCE_PROPERTY_TEMPLATE", - "UNDECLARED_PROPERTIES", - "UNREACHABLE" - ], - "enumDescriptions": [ - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "" - ], - "type": "string" - }, - "data": { - "description": "[Output Only] Metadata about this warning in key: value format. For example:\n\"data\": [ { \"key\": \"scope\", \"value\": \"zones/us-east1-d\" }", - "items": { - "properties": { - "key": { - "description": "[Output Only] A key that provides more detail on the warning being returned. For example, for warnings where there are no results in a list request for a particular zone, this key might be scope and the key value might be the zone name. Other examples might be a key indicating a deprecated resource and a suggested replacement, or a warning about invalid network settings (for example, if an instance attempts to perform IP forwarding but is not enabled for IP forwarding).", - "type": "string" - }, - "value": { - "description": "[Output Only] A warning data value corresponding to the key.", - "type": "string" - } - }, - "type": "object" - }, - "type": "array" - }, - "message": { - "description": "[Output Only] A human-readable description of the warning code.", - "type": "string" - } - }, - "type": "object" - } - }, - "type": "object" - }, - "HostsScopedList": { - "id": "HostsScopedList", - "properties": { - "hosts": { - "description": "[Output Only] A list of hosts contained in this scope.", - "items": { - "$ref": "Host" - }, - "type": "array" - }, - "warning": { - "description": "[Output Only] An informational warning that appears when the host list is empty.", - "properties": { - "code": { - "description": "[Output Only] A warning code, if applicable. For example, Compute Engine returns NO_RESULTS_ON_PAGE if there are no results in the response.", - "enum": [ - "CLEANUP_FAILED", - "DEPRECATED_RESOURCE_USED", - "DEPRECATED_TYPE_USED", - "DISK_SIZE_LARGER_THAN_IMAGE_SIZE", - "EXPERIMENTAL_TYPE_USED", - "EXTERNAL_API_WARNING", - "FIELD_VALUE_OVERRIDEN", - "INJECTED_KERNELS_DEPRECATED", - "MISSING_TYPE_DEPENDENCY", - "NEXT_HOP_ADDRESS_NOT_ASSIGNED", - "NEXT_HOP_CANNOT_IP_FORWARD", - "NEXT_HOP_INSTANCE_NOT_FOUND", - "NEXT_HOP_INSTANCE_NOT_ON_NETWORK", - "NEXT_HOP_NOT_RUNNING", - "NOT_CRITICAL_ERROR", - "NO_RESULTS_ON_PAGE", - "REQUIRED_TOS_AGREEMENT", - "RESOURCE_IN_USE_BY_OTHER_RESOURCE_WARNING", - "RESOURCE_NOT_DELETED", - "SCHEMA_VALIDATION_IGNORED", - "SINGLE_INSTANCE_PROPERTY_TEMPLATE", - "UNDECLARED_PROPERTIES", - "UNREACHABLE" - ], - "enumDescriptions": [ - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "" - ], - "type": "string" - }, - "data": { - "description": "[Output Only] Metadata about this warning in key: value format. For example:\n\"data\": [ { \"key\": \"scope\", \"value\": \"zones/us-east1-d\" }", - "items": { - "properties": { - "key": { - "description": "[Output Only] A key that provides more detail on the warning being returned. For example, for warnings where there are no results in a list request for a particular zone, this key might be scope and the key value might be the zone name. Other examples might be a key indicating a deprecated resource and a suggested replacement, or a warning about invalid network settings (for example, if an instance attempts to perform IP forwarding but is not enabled for IP forwarding).", - "type": "string" - }, - "value": { - "description": "[Output Only] A warning data value corresponding to the key.", - "type": "string" - } - }, - "type": "object" - }, - "type": "array" - }, - "message": { - "description": "[Output Only] A human-readable description of the warning code.", - "type": "string" - } - }, - "type": "object" - } - }, - "type": "object" - }, "HttpHealthCheck": { "description": "An HttpHealthCheck resource. This resource defines a template for how individual instances should be checked for health, via HTTP.", "id": "HttpHealthCheck", @@ -30959,7 +33004,7 @@ "type": "string" }, "labelFingerprint": { - "description": "A fingerprint for the labels being applied to this image, which is essentially a hash of the labels used for optimistic locking. The fingerprint is initially generated by Compute Engine and changes after every request to modify or update labels. You must always provide an up-to-date fingerprint hash in order to update or change labels.\n\nTo see the latest fingerprint, make a get() request to retrieve an image.", + "description": "A fingerprint for the labels being applied to this image, which is essentially a hash of the labels used for optimistic locking. The fingerprint is initially generated by Compute Engine and changes after every request to modify or update labels. You must always provide an up-to-date fingerprint hash in order to update or change labels, otherwise the request will fail with error 412 conditionNotMet.\n\nTo see the latest fingerprint, make a get() request to retrieve an image.", "format": "byte", "type": "string" }, @@ -31038,7 +33083,7 @@ "description": "The customer-supplied encryption key of the source disk. Required if the source disk is protected by a customer-supplied encryption key." }, "sourceDiskId": { - "description": "The ID value of the disk used to create this image. This value may be used to determine whether the image was taken from the current or a previous instance of a given disk name.", + "description": "[Output Only] The ID value of the disk used to create this image. This value may be used to determine whether the image was taken from the current or a previous instance of a given disk name.", "type": "string" }, "sourceImage": { @@ -31209,6 +33254,10 @@ "description": "An Instance resource. (== resource_for beta.instances ==) (== resource_for v1.instances ==)", "id": "Instance", "properties": { + "allocationAffinity": { + "$ref": "AllocationAffinity", + "description": "The configuration of desired allocations which this Instance could consume capacity from." + }, "canIpForward": { "description": "Allows this instance to send and receive packets with non-matching destination or source IPs. This is required if you plan to use this instance to forward routes. For more information, see Enabling IP Forwarding.", "type": "boolean" @@ -31236,6 +33285,10 @@ }, "type": "array" }, + "displayDevice": { + "$ref": "DisplayDevice", + "description": "Enables display device for the instance." + }, "guestAccelerators": { "description": "A list of the type and count of accelerator cards attached to the instance.", "items": { @@ -31243,8 +33296,7 @@ }, "type": "array" }, - "host": { - "description": "Full or partial URL of the host resource that the instance should be placed on, in the format: zones/zone/hosts/host.\n\nOptional, sole-tenant Host (physical machine) that the instance will be placed on when it's created. The instance is guaranteed to be placed on the same machine as other instances with the same sole-tenant host.\n\nThe request will be rejected if the sole-tenant host has run out of resources.", + "hostname": { "type": "string" }, "id": { @@ -31378,7 +33430,7 @@ }, "tags": { "$ref": "Tags", - "description": "A list of tags to apply to this instance. Tags are used to identify valid sources or targets for network firewalls and are specified by the client during instance creation. The tags can be later modified by the setTags method. Each tag within the list must comply with RFC1035." + "description": "Tags to apply to this instance. Tags are used to identify valid sources or targets for network firewalls and are specified by the client during instance creation. The tags can be later modified by the setTags method. Each tag within the list must comply with RFC1035. Multiple tags can be specified via the 'tags.items' field." }, "zone": { "description": "[Output Only] URL of the zone where the instance resides. You must specify this field as part of the HTTP request URL. It is not settable as a field in the request body.", @@ -31799,9 +33851,6 @@ "description": "An Instance Group Manager resource. (== resource_for beta.instanceGroupManagers ==) (== resource_for v1.instanceGroupManagers ==) (== resource_for beta.regionInstanceGroupManagers ==) (== resource_for v1.regionInstanceGroupManagers ==)", "id": "InstanceGroupManager", "properties": { - "activities": { - "$ref": "InstanceGroupManagerActivities" - }, "autoHealingPolicies": { "description": "The autohealing policy for this managed instance group. You can specify only one value.", "items": { @@ -31833,7 +33882,7 @@ }, "distributionPolicy": { "$ref": "DistributionPolicy", - "description": "Policy valid only for regional managed instance groups." + "description": "Policy specifying intended distribution of instances in regional managed instance group." }, "failoverAction": { "description": "The action to perform in case of zone failure. Only one value is supported, NO_FAILOVER. The default is NO_FAILOVER.", @@ -31848,7 +33897,7 @@ "type": "string" }, "fingerprint": { - "description": "Fingerprint of this resource. This field may be used in optimistic locking. It will be ignored when inserting an InstanceGroupManager. An up-to-date fingerprint must be provided in order to update the InstanceGroupManager.", + "description": "Fingerprint of this resource. This field may be used in optimistic locking. It will be ignored when inserting an InstanceGroupManager. An up-to-date fingerprint must be provided in order to update the InstanceGroupManager, otherwise the request will fail with error 412 conditionNotMet.\n\nTo see the latest fingerprint, make a get() request to retrieve an InstanceGroupManager.", "format": "byte", "type": "string" }, @@ -31908,6 +33957,10 @@ "$ref": "StatefulPolicy", "description": "Stateful configuration for this Instanced Group Manager" }, + "status": { + "$ref": "InstanceGroupManagerStatus", + "description": "[Output Only] The status of this managed instance group." + }, "targetPools": { "description": "The URLs for all TargetPool resources to which instances in the instanceGroup field are added. The target pools automatically apply to all of the instances in the managed instance group.", "items": { @@ -31995,89 +34048,6 @@ }, "type": "object" }, - "InstanceGroupManagerActivities": { - "id": "InstanceGroupManagerActivities", - "properties": { - "autohealing": { - "enum": [ - "PERMITTED", - "PROHIBITED" - ], - "enumDescriptions": [ - "", - "" - ], - "type": "string" - }, - "autohealingHealthCheckBased": { - "enum": [ - "PERMITTED", - "PROHIBITED" - ], - "enumDescriptions": [ - "", - "" - ], - "type": "string" - }, - "autoscalingDown": { - "enum": [ - "PERMITTED", - "PROHIBITED" - ], - "enumDescriptions": [ - "", - "" - ], - "type": "string" - }, - "autoscalingUp": { - "enum": [ - "PERMITTED", - "PROHIBITED" - ], - "enumDescriptions": [ - "", - "" - ], - "type": "string" - }, - "creatingInstances": { - "enum": [ - "PERMITTED", - "PROHIBITED" - ], - "enumDescriptions": [ - "", - "" - ], - "type": "string" - }, - "deletingInstances": { - "enum": [ - "PERMITTED", - "PROHIBITED" - ], - "enumDescriptions": [ - "", - "" - ], - "type": "string" - }, - "recreatingInstances": { - "enum": [ - "PERMITTED", - "PROHIBITED" - ], - "enumDescriptions": [ - "", - "" - ], - "type": "string" - } - }, - "type": "object" - }, "InstanceGroupManagerAggregatedList": { "id": "InstanceGroupManagerAggregatedList", "properties": { @@ -32191,6 +34161,7 @@ "type": "object" }, "InstanceGroupManagerAutoHealingPolicy": { + "description": "", "id": "InstanceGroupManagerAutoHealingPolicy", "properties": { "healthCheck": { @@ -32205,18 +34176,6 @@ "maxUnavailable": { "$ref": "FixedOrPercent", "description": "Maximum number of instances that can be unavailable when autohealing. The instance is considered available if all of the following conditions are satisfied: 1. Instance's status is RUNNING. 2. Instance's liveness health check result was observed to be HEALTHY at least once. By default, a percent value of 100% is used." - }, - "mode": { - "description": "Defines operating mode for this policy.", - "enum": [ - "OFF", - "ON" - ], - "enumDescriptions": [ - "", - "" - ], - "type": "string" } }, "type": "object" @@ -32359,17 +34318,39 @@ }, "type": "object" }, + "InstanceGroupManagerStatus": { + "id": "InstanceGroupManagerStatus", + "properties": { + "isStable": { + "description": "[Output Only] A bit indicating whether the managed instance group is in a stable state. A stable state means that: none of the instances in the managed instance group is currently undergoing any type of change (for example, creation, restart, or deletion); no future changes are scheduled for instances in the managed instance group; and the managed instance group itself is not being modified.", + "type": "boolean" + }, + "versionTarget": { + "$ref": "InstanceGroupManagerStatusVersionTarget", + "description": "[Output Only] A status of consistency of Instances' versions with their target version specified by version field on Instance Group Manager." + } + }, + "type": "object" + }, + "InstanceGroupManagerStatusVersionTarget": { + "id": "InstanceGroupManagerStatusVersionTarget", + "properties": { + "isReached": { + "description": "[Output Only] A bit indicating whether version target has been reached in this managed instance group, i.e. all instances are in their target version. Instances' target version are specified by version field on Instance Group Manager.", + "type": "boolean" + } + }, + "type": "object" + }, "InstanceGroupManagerUpdatePolicy": { "id": "InstanceGroupManagerUpdatePolicy", "properties": { "instanceRedistributionType": { "enum": [ "NONE", - "PROACTIVE", - "UNSPECIFIED_TYPE" + "PROACTIVE" ], "enumDescriptions": [ - "", "", "" ], @@ -32389,7 +34370,7 @@ "type": "integer" }, "minimalAction": { - "description": "Minimal action to be taken on an instance. You can specify either RESTART to restart existing instances or REPLACE to delete and create new instances from the target template. If you specify a code\u003eRESTART, the Updater will attempt to perform that action only. However, if the Updater determines that the minimal action you specify is not enough to perform the update, it might perform a more disruptive action.", + "description": "Minimal action to be taken on an instance. You can specify either RESTART to restart existing instances or REPLACE to delete and create new instances from the target template. If you specify a RESTART, the Updater will attempt to perform that action only. However, if the Updater determines that the minimal action you specify is not enough to perform the update, it might perform a more disruptive action.", "enum": [ "NONE", "REFRESH", @@ -32498,6 +34479,20 @@ }, "type": "object" }, + "InstanceGroupManagersCreateInstancesRequest": { + "description": "InstanceGroupManagers.createInstances", + "id": "InstanceGroupManagersCreateInstancesRequest", + "properties": { + "instances": { + "description": "[Required] List of specifications of per-instance configs.", + "items": { + "$ref": "PerInstanceConfig" + }, + "type": "array" + } + }, + "type": "object" + }, "InstanceGroupManagersDeleteInstancesRequest": { "id": "InstanceGroupManagersDeleteInstancesRequest", "properties": { @@ -32521,6 +34516,13 @@ "type": "string" }, "type": "array" + }, + "names": { + "description": "The list of instance names for which we want to delete per-instance configs on this managed instance group.", + "items": { + "type": "string" + }, + "type": "array" } }, "type": "object" @@ -32657,7 +34659,7 @@ "id": "InstanceGroupManagersResizeAdvancedRequest", "properties": { "noCreationRetries": { - "description": "If this flag is true, the managed instance group attempts to create all instances initiated by this resize request only once. If there is an error during creation, the managed instance group does not retry create this instance, and we will decrease the targetSize of the request instead. If the flag is false, the group attemps to recreate each instance continuously until it succeeds.\n\nThis flag matters only in the first attempt of creation of an instance. After an instance is successfully created while this flag is enabled, the instance behaves the same way as all the other instances created with a regular resize request. In particular, if a running instance dies unexpectedly at a later time and needs to be recreated, this mode does not affect the recreation behavior in that scenario.\n\nThis flag is applicable only to the current resize request. It does not influence other resize requests in any way.\n\nYou can see which instances is being creating in which mode by calling the get or listManagedInstances API.", + "description": "If this flag is true, the managed instance group attempts to create all instances initiated by this resize request only once. If there is an error during creation, the managed instance group does not retry create this instance, and we will decrease the targetSize of the request instead. If the flag is false, the group attempts to recreate each instance continuously until it succeeds.\n\nThis flag matters only in the first attempt of creation of an instance. After an instance is successfully created while this flag is enabled, the instance behaves the same way as all the other instances created with a regular resize request. In particular, if a running instance dies unexpectedly at a later time and needs to be recreated, this mode does not affect the recreation behavior in that scenario.\n\nThis flag is applicable only to the current resize request. It does not influence other resize requests in any way.\n\nYou can see which instances is being creating in which mode by calling the get or listManagedInstances API.", "type": "boolean" }, "targetSize": { @@ -33069,7 +35071,7 @@ "id": "InstanceGroupsSetNamedPortsRequest", "properties": { "fingerprint": { - "description": "The fingerprint of the named ports information for this instance group. Use this optional property to prevent conflicts when multiple users change the named ports settings concurrently. Obtain the fingerprint with the instanceGroups.get method. Then, include the fingerprint in your request to ensure that you do not overwrite changes that were applied from another concurrent request.", + "description": "The fingerprint of the named ports information for this instance group. Use this optional property to prevent conflicts when multiple users change the named ports settings concurrently. Obtain the fingerprint with the instanceGroups.get method. Then, include the fingerprint in your request to ensure that you do not overwrite changes that were applied from another concurrent request. A request with an incorrect fingerprint will fail with error 412 conditionNotMet.", "format": "byte", "type": "string" }, @@ -33325,6 +35327,10 @@ "description": "", "id": "InstanceProperties", "properties": { + "allocationAffinity": { + "$ref": "AllocationAffinity", + "description": "The configuration of desired allocations which this Instance could consume capacity from." + }, "canIpForward": { "description": "Enables instances created based on this template to send packets with source IP addresses other than their own and receive packets with destination IP addresses other than their own. If these instances will be used as an IP gateway or it will be set as the next-hop in a Route resource, specify true. If unsure, leave this set to false. See the Enable IP forwarding documentation for more information.", "type": "boolean" @@ -33909,7 +35915,7 @@ "type": "string" }, "labelFingerprint": { - "description": "A fingerprint for the labels being applied to this Interconnect, which is essentially a hash of the labels set used for optimistic locking. The fingerprint is initially generated by Compute Engine and changes after every request to modify or update labels. You must always provide an up-to-date fingerprint hash in order to update or change labels.\n\nTo see the latest fingerprint, make a get() request to retrieve an Interconnect.", + "description": "A fingerprint for the labels being applied to this Interconnect, which is essentially a hash of the labels set used for optimistic locking. The fingerprint is initially generated by Compute Engine and changes after every request to modify or update labels. You must always provide an up-to-date fingerprint hash in order to update or change labels, otherwise the request will fail with error 412 conditionNotMet.\n\nTo see the latest fingerprint, make a get() request to retrieve an Interconnect.", "format": "byte", "type": "string" }, @@ -34001,22 +36007,8 @@ "description": "Determines whether this Attachment will carry packets. Not present for PARTNER_PROVIDER.", "type": "boolean" }, - "availabilityZone": { - "description": "[Deprecated] Replaced by edge_availability_domain.", - "enum": [ - "ZONE_1", - "ZONE_2", - "ZONE_ANY" - ], - "enumDescriptions": [ - "", - "", - "" - ], - "type": "string" - }, "bandwidth": { - "description": "Provisioned bandwidth capacity for the interconnectAttachment. Can be set by the partner to update the customer's provisioned bandwidth. Output only for for PARTNER type, mutable for PARTNER_PROVIDER, not available for DEDICATED.", + "description": "Provisioned bandwidth capacity for the interconnectAttachment. Can be set by the partner to update the customer's provisioned bandwidth. Output only for PARTNER type, mutable for PARTNER_PROVIDER and DEDICATED.", "enum": [ "BPS_100M", "BPS_10G", @@ -34099,7 +36091,7 @@ "type": "string" }, "labelFingerprint": { - "description": "A fingerprint for the labels being applied to this InterconnectAttachment, which is essentially a hash of the labels set used for optimistic locking. The fingerprint is initially generated by Compute Engine and changes after every request to modify or update labels. You must always provide an up-to-date fingerprint hash in order to update or change labels.\n\nTo see the latest fingerprint, make a get() request to retrieve an InterconnectAttachment.", + "description": "A fingerprint for the labels being applied to this InterconnectAttachment, which is essentially a hash of the labels set used for optimistic locking. The fingerprint is initially generated by Compute Engine and changes after every request to modify or update labels. You must always provide an up-to-date fingerprint hash in order to update or change labels, otherwise the request will fail with error 412 conditionNotMet.\n\nTo see the latest fingerprint, make a get() request to retrieve an InterconnectAttachment.", "format": "byte", "type": "string" }, @@ -34149,7 +36141,7 @@ "type": "string" }, "router": { - "description": "URL of the cloud router to be used for dynamic routing. This router must be in the same region as this InterconnectAttachment. The InterconnectAttachment will automatically connect the Interconnect to the network \u0026 region within which the Cloud Router is configured.", + "description": "URL of the Cloud Router to be used for dynamic routing. This router must be in the same region as this InterconnectAttachment. The InterconnectAttachment will automatically connect the Interconnect to the network \u0026 region within which the Cloud Router is configured.", "type": "string" }, "selfLink": { @@ -34192,7 +36184,7 @@ "type": "string" }, "vlanTag8021q": { - "description": "Available only for DEDICATED and PARTNER_PROVIDER. Desired VLAN tag for this attachment, in the range 2-4094. This field refers to 802.1q VLAN tag, also known as IEEE 802.1Q Only specified at creation time.", + "description": "The IEEE 802.1Q VLAN tag for this attachment, in the range 2-4094. Only specified at creation time.", "format": "int32", "type": "integer" } @@ -34428,7 +36420,7 @@ "id": "InterconnectAttachmentPartnerMetadata", "properties": { "interconnectName": { - "description": "Plain text name of the Interconnect this attachment is connected to, as displayed in the Partner?s portal. For instance ?Chicago 1?. This value may be validated to match approved Partner values.", + "description": "Plain text name of the Interconnect this attachment is connected to, as displayed in the Partner?s portal. For instance \"Chicago 1\". This value may be validated to match approved Partner values.", "type": "string" }, "partnerName": { @@ -34567,6 +36559,129 @@ }, "type": "object" }, + "InterconnectDiagnostics": { + "description": "Diagnostics information about interconnect, contains detailed and current technical information about Google?s side of the connection.", + "id": "InterconnectDiagnostics", + "properties": { + "arpCaches": { + "description": "A list of InterconnectDiagnostics.ARPEntry objects, describing individual neighbors currently seen by the Google router in the ARP cache for the Interconnect. This will be empty when the Interconnect is not bundled.", + "items": { + "$ref": "InterconnectDiagnosticsARPEntry" + }, + "type": "array" + }, + "links": { + "description": "A list of InterconnectDiagnostics.LinkStatus objects, describing the status for each link on the Interconnect.", + "items": { + "$ref": "InterconnectDiagnosticsLinkStatus" + }, + "type": "array" + }, + "macAddress": { + "description": "The MAC address of the Interconnect's bundle interface.", + "type": "string" + } + }, + "type": "object" + }, + "InterconnectDiagnosticsARPEntry": { + "description": "Describing the ARP neighbor entries seen on this link", + "id": "InterconnectDiagnosticsARPEntry", + "properties": { + "ipAddress": { + "description": "The IP address of this ARP neighbor.", + "type": "string" + }, + "macAddress": { + "description": "The MAC address of this ARP neighbor.", + "type": "string" + } + }, + "type": "object" + }, + "InterconnectDiagnosticsLinkLACPStatus": { + "id": "InterconnectDiagnosticsLinkLACPStatus", + "properties": { + "googleSystemId": { + "description": "System ID of the port on Google?s side of the LACP exchange.", + "type": "string" + }, + "neighborSystemId": { + "description": "System ID of the port on the neighbor?s side of the LACP exchange.", + "type": "string" + }, + "state": { + "enum": [ + "ACTIVE", + "DETACHED" + ], + "enumDescriptions": [ + "", + "" + ], + "type": "string" + } + }, + "type": "object" + }, + "InterconnectDiagnosticsLinkOpticalPower": { + "id": "InterconnectDiagnosticsLinkOpticalPower", + "properties": { + "state": { + "enum": [ + "HIGH_ALARM", + "HIGH_WARNING", + "LOW_ALARM", + "LOW_WARNING", + "OK" + ], + "enumDescriptions": [ + "", + "", + "", + "", + "" + ], + "type": "string" + }, + "value": { + "description": "Value of the current optical power, read in dBm. Take a known good optical value, give it a 10% margin and trigger warnings relative to that value. In general, a -7dBm warning and a -11dBm alarm are good optical value estimates for most links.", + "format": "float", + "type": "number" + } + }, + "type": "object" + }, + "InterconnectDiagnosticsLinkStatus": { + "id": "InterconnectDiagnosticsLinkStatus", + "properties": { + "arpCaches": { + "description": "A list of InterconnectDiagnostics.ARPEntry objects, describing the ARP neighbor entries seen on this link. This will be empty if the link is bundled", + "items": { + "$ref": "InterconnectDiagnosticsARPEntry" + }, + "type": "array" + }, + "circuitId": { + "description": "The unique ID for this link assigned during turn up by Google.", + "type": "string" + }, + "googleDemarc": { + "description": "The Demarc address assigned by Google and provided in the LoA.", + "type": "string" + }, + "lacpStatus": { + "$ref": "InterconnectDiagnosticsLinkLACPStatus" + }, + "receivingOpticalPower": { + "$ref": "InterconnectDiagnosticsLinkOpticalPower" + }, + "transmittingOpticalPower": { + "$ref": "InterconnectDiagnosticsLinkOpticalPower" + } + }, + "type": "object" + }, "InterconnectList": { "description": "Response to the list request, and contains a list of interconnects.", "id": "InterconnectList", @@ -34688,7 +36803,7 @@ "type": "string" }, "availabilityZone": { - "description": "[Output Only] Availability zone for this location. Within a metropolitan area (metro), maintenance will not be simultaneously scheduled in more than one availability zone. Example: \"zone1\" or \"zone2\".", + "description": "[Output Only] Availability zone for this InterconnectLocation. Within a metropolitan area (metro), maintenance will not be simultaneously scheduled in more than one availability zone. Example: \"zone1\" or \"zone2\".", "type": "string" }, "city": { @@ -34767,6 +36882,18 @@ "selfLink": { "description": "[Output Only] Server-defined URL for the resource.", "type": "string" + }, + "status": { + "description": "[Output Only] The status of this InterconnectLocation. If the status is AVAILABLE, new Interconnects may be provisioned in this InterconnectLocation. Otherwise, no new Interconnects may be provisioned.", + "enum": [ + "AVAILABLE", + "CLOSED" + ], + "enumDescriptions": [ + "", + "" + ], + "type": "string" } }, "type": "object" @@ -34991,6 +37118,60 @@ }, "type": "object" }, + "InterconnectsGetDiagnosticsResponse": { + "description": "Response for the InterconnectsGetDiagnosticsRequest.", + "id": "InterconnectsGetDiagnosticsResponse", + "properties": { + "result": { + "$ref": "InterconnectDiagnostics" + } + }, + "type": "object" + }, + "InternalIpAddress": { + "id": "InternalIpAddress", + "properties": { + "cidr": { + "description": "IP CIDR address or range.", + "type": "string" + }, + "owner": { + "description": "The owner of the internal IP address.", + "type": "string" + }, + "purpose": { + "description": "The purpose of the internal IP address if applicable.", + "type": "string" + }, + "region": { + "description": "The region of the internal IP address if applicable.", + "type": "string" + }, + "type": { + "description": "The type of the internal IP address.", + "enum": [ + "PEER_RESERVED", + "PEER_USED", + "REMOTE_RESERVED", + "REMOTE_USED", + "RESERVED", + "SUBNETWORK", + "TYPE_UNSPECIFIED" + ], + "enumDescriptions": [ + "", + "", + "", + "", + "", + "", + "" + ], + "type": "string" + } + }, + "type": "object" + }, "InternalIpOwner": { "id": "InternalIpOwner", "properties": { @@ -35012,6 +37193,117 @@ }, "type": "object" }, + "IpAddressesList": { + "id": "IpAddressesList", + "properties": { + "id": { + "description": "[Output Only] Unique identifier for the resource; defined by the server.", + "type": "string" + }, + "items": { + "description": "A list of InternalIpAddress resources.", + "items": { + "$ref": "InternalIpAddress" + }, + "type": "array" + }, + "kind": { + "default": "compute#ipAddressesList", + "description": "[Output Only] Type of resource. Always compute#ipAddressesList for IP addresses lists.", + "type": "string" + }, + "nextPageToken": { + "description": "[Output Only] This token allows you to get the next page of results for list requests. If the number of results is larger than maxResults, use the nextPageToken as a value for the query parameter pageToken in the next list request. Subsequent list requests will have their own nextPageToken to continue paging through the results.", + "type": "string" + }, + "selfLink": { + "description": "[Output Only] Server-defined URL for this resource.", + "type": "string" + }, + "warning": { + "description": "[Output Only] Informational warning message.", + "properties": { + "code": { + "description": "[Output Only] A warning code, if applicable. For example, Compute Engine returns NO_RESULTS_ON_PAGE if there are no results in the response.", + "enum": [ + "CLEANUP_FAILED", + "DEPRECATED_RESOURCE_USED", + "DEPRECATED_TYPE_USED", + "DISK_SIZE_LARGER_THAN_IMAGE_SIZE", + "EXPERIMENTAL_TYPE_USED", + "EXTERNAL_API_WARNING", + "FIELD_VALUE_OVERRIDEN", + "INJECTED_KERNELS_DEPRECATED", + "MISSING_TYPE_DEPENDENCY", + "NEXT_HOP_ADDRESS_NOT_ASSIGNED", + "NEXT_HOP_CANNOT_IP_FORWARD", + "NEXT_HOP_INSTANCE_NOT_FOUND", + "NEXT_HOP_INSTANCE_NOT_ON_NETWORK", + "NEXT_HOP_NOT_RUNNING", + "NOT_CRITICAL_ERROR", + "NO_RESULTS_ON_PAGE", + "REQUIRED_TOS_AGREEMENT", + "RESOURCE_IN_USE_BY_OTHER_RESOURCE_WARNING", + "RESOURCE_NOT_DELETED", + "SCHEMA_VALIDATION_IGNORED", + "SINGLE_INSTANCE_PROPERTY_TEMPLATE", + "UNDECLARED_PROPERTIES", + "UNREACHABLE" + ], + "enumDescriptions": [ + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "" + ], + "type": "string" + }, + "data": { + "description": "[Output Only] Metadata about this warning in key: value format. For example:\n\"data\": [ { \"key\": \"scope\", \"value\": \"zones/us-east1-d\" }", + "items": { + "properties": { + "key": { + "description": "[Output Only] A key that provides more detail on the warning being returned. For example, for warnings where there are no results in a list request for a particular zone, this key might be scope and the key value might be the zone name. Other examples might be a key indicating a deprecated resource and a suggested replacement, or a warning about invalid network settings (for example, if an instance attempts to perform IP forwarding but is not enabled for IP forwarding).", + "type": "string" + }, + "value": { + "description": "[Output Only] A warning data value corresponding to the key.", + "type": "string" + } + }, + "type": "object" + }, + "type": "array" + }, + "message": { + "description": "[Output Only] A human-readable description of the warning code.", + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object" + }, "IpOwnerList": { "description": "Contains a list of IP owners.", "id": "IpOwnerList", @@ -35161,7 +37453,7 @@ "compute.images.insert" ] }, - "description": "[Output Only] Name of the resource. The name is 1-63 characters long and complies with RFC1035.", + "description": "Name of the resource. The name must be 1-63 characters long and comply with RFC1035.", "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", "type": "string" }, @@ -35427,7 +37719,7 @@ "type": "object" }, "LogConfigCounterOptions": { - "description": "Increment a streamz counter with the specified metric and field names.\n\nMetric names should start with a '/', generally be lowercase-only, and end in \"_count\". Field names should not contain an initial slash. The actual exported metric names will have \"/iam/policy\" prepended.\n\nField names correspond to IAM request parameters and field values are their respective values.\n\nAt present the only supported field names are - \"iam_principal\", corresponding to IAMContext.principal; - \"\" (empty string), resulting in one aggretated counter with no field.\n\nExamples: counter { metric: \"/debug_access_count\" field: \"iam_principal\" } ==\u003e increment counter /iam/policy/backend_debug_access_count {iam_principal=[value of IAMContext.principal]}\n\nAt this time we do not support: * multiple field names (though this may be supported in the future) * decrementing the counter * incrementing it by anything other than 1", + "description": "Increment a streamz counter with the specified metric and field names.\n\nMetric names should start with a '/', generally be lowercase-only, and end in \"_count\". Field names should not contain an initial slash. The actual exported metric names will have \"/iam/policy\" prepended.\n\nField names correspond to IAM request parameters and field values are their respective values.\n\nSupported field names: - \"authority\", which is \"[token]\" if IAMContext.token is present, otherwise the value of IAMContext.authority_selector if present, and otherwise a representation of IAMContext.principal; or - \"iam_principal\", a representation of IAMContext.principal even if a token or authority selector is present; or - \"\" (empty string), resulting in a counter with no fields.\n\nExamples: counter { metric: \"/debug_access_count\" field: \"iam_principal\" } ==\u003e increment counter /iam/policy/backend_debug_access_count {iam_principal=[value of IAMContext.principal]}\n\nAt this time we do not support multiple field names (though this may be supported in the future).", "id": "LogConfigCounterOptions", "properties": { "field": { @@ -35446,7 +37738,7 @@ "id": "LogConfigDataAccessOptions", "properties": { "logMode": { - "description": "Whether Gin logging should happen in a fail-closed manner at the caller. This is relevant only in the LocalIAM implementation, for now.", + "description": "Whether Gin logging should happen in a fail-closed manner at the caller. This is relevant only in the LocalIAM implementation, for now.\n\nNOTE: Logging to Gin in a fail-closed manner is currently unsupported while work is being done to satisfy the requirements of go/345. Currently, setting LOG_FAIL_CLOSED mode will have no effect, but still exists because there is active work being done to support it (b/115874152).", "enum": [ "LOG_FAIL_CLOSED", "LOG_MODE_UNSPECIFIED" @@ -35460,6 +37752,193 @@ }, "type": "object" }, + "MachineImage": { + "description": "Machine image resource.", + "id": "MachineImage", + "properties": { + "creationTimestamp": { + "description": "[Output Only] The creation timestamp for this machine image in RFC3339 text format.", + "type": "string" + }, + "description": { + "description": "An optional description of this resource. Provide this property when you create the resource.", + "type": "string" + }, + "id": { + "description": "[Output Only] A unique identifier for this machine image. The server defines this identifier.", + "format": "uint64", + "type": "string" + }, + "kind": { + "default": "compute#machineImage", + "description": "[Output Only] The resource type, which is always compute#machineImage for machine image.", + "type": "string" + }, + "name": { + "annotations": { + "required": [ + "compute.machineImages.insert" + ] + }, + "description": "Name of the resource; provided by the client when the resource is created. The name must be 1-63 characters long, and comply with RFC1035. Specifically, the name must be 1-63 characters long and match the regular expression `[a-z]([-a-z0-9]*[a-z0-9])?` which means the first character must be a lowercase letter, and all following characters must be a dash, lowercase letter, or digit, except the last character, which cannot be a dash.", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "type": "string" + }, + "selfLink": { + "description": "[Output Only] The URL for this machine image. The server defines this URL.", + "type": "string" + }, + "sourceInstance": { + "description": "The source instance used to create the machine image. You can provide this as a partial or full URL to the resource. For example, the following are valid values: \n- https://www.googleapis.com/compute/v1/projects/project/zones/zone/instances/instance \n- projects/project/zones/zone/instances/instance", + "type": "string" + }, + "sourceInstanceProperties": { + "$ref": "SourceInstanceProperties", + "description": "Properties of source instance." + }, + "status": { + "description": "[Output Only] The status of disk creation.", + "enum": [ + "CREATING", + "DELETING", + "INVALID", + "READY", + "UPLOADING" + ], + "enumDescriptions": [ + "", + "", + "", + "", + "" + ], + "type": "string" + }, + "storageLocations": { + "description": "GCS bucket storage location of the snapshot (regional or multi-regional).", + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object" + }, + "MachineImageList": { + "description": "A list of machine images.", + "id": "MachineImageList", + "properties": { + "etag": { + "type": "string" + }, + "id": { + "description": "[Output Only] Unique identifier for the resource; defined by the server.", + "type": "string" + }, + "items": { + "description": "A list of MachineImage resources.", + "items": { + "$ref": "MachineImage" + }, + "type": "array" + }, + "kind": { + "default": "compute#machineImageList", + "description": "[Output Only] The resource type, which is always compute#machineImagesListResponse for machine image lists.", + "type": "string" + }, + "nextPageToken": { + "description": "[Output Only] This token allows you to get the next page of results for list requests. If the number of results is larger than maxResults, use the nextPageToken as a value for the query parameter pageToken in the next list request. Subsequent list requests will have their own nextPageToken to continue paging through the results.", + "type": "string" + }, + "selfLink": { + "description": "[Output Only] Server-defined URL for this resource.", + "type": "string" + }, + "warning": { + "description": "[Output Only] Informational warning message.", + "properties": { + "code": { + "description": "[Output Only] A warning code, if applicable. For example, Compute Engine returns NO_RESULTS_ON_PAGE if there are no results in the response.", + "enum": [ + "CLEANUP_FAILED", + "DEPRECATED_RESOURCE_USED", + "DEPRECATED_TYPE_USED", + "DISK_SIZE_LARGER_THAN_IMAGE_SIZE", + "EXPERIMENTAL_TYPE_USED", + "EXTERNAL_API_WARNING", + "FIELD_VALUE_OVERRIDEN", + "INJECTED_KERNELS_DEPRECATED", + "MISSING_TYPE_DEPENDENCY", + "NEXT_HOP_ADDRESS_NOT_ASSIGNED", + "NEXT_HOP_CANNOT_IP_FORWARD", + "NEXT_HOP_INSTANCE_NOT_FOUND", + "NEXT_HOP_INSTANCE_NOT_ON_NETWORK", + "NEXT_HOP_NOT_RUNNING", + "NOT_CRITICAL_ERROR", + "NO_RESULTS_ON_PAGE", + "REQUIRED_TOS_AGREEMENT", + "RESOURCE_IN_USE_BY_OTHER_RESOURCE_WARNING", + "RESOURCE_NOT_DELETED", + "SCHEMA_VALIDATION_IGNORED", + "SINGLE_INSTANCE_PROPERTY_TEMPLATE", + "UNDECLARED_PROPERTIES", + "UNREACHABLE" + ], + "enumDescriptions": [ + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "" + ], + "type": "string" + }, + "data": { + "description": "[Output Only] Metadata about this warning in key: value format. For example:\n\"data\": [ { \"key\": \"scope\", \"value\": \"zones/us-east1-d\" }", + "items": { + "properties": { + "key": { + "description": "[Output Only] A key that provides more detail on the warning being returned. For example, for warnings where there are no results in a list request for a particular zone, this key might be scope and the key value might be the zone name. Other examples might be a key indicating a deprecated resource and a suggested replacement, or a warning about invalid network settings (for example, if an instance attempts to perform IP forwarding but is not enabled for IP forwarding).", + "type": "string" + }, + "value": { + "description": "[Output Only] A warning data value corresponding to the key.", + "type": "string" + } + }, + "type": "object" + }, + "type": "array" + }, + "message": { + "description": "[Output Only] A human-readable description of the warning code.", + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object" + }, "MachineType": { "description": "A Machine Type resource. (== resource_for v1.machineTypes ==) (== resource_for beta.machineTypes ==)", "id": "MachineType", @@ -35883,6 +38362,13 @@ "description": "[Output Only] The URL of the instance. The URL can exist even if the instance has not yet been created.", "type": "string" }, + "instanceHealth": { + "description": "[Output Only] Health state of the instance per health-check.", + "items": { + "$ref": "ManagedInstanceInstanceHealth" + }, + "type": "array" + }, "instanceStatus": { "description": "[Output Only] The status of the instance. This field is empty when the instance does not exist.", "enum": [ @@ -35919,6 +38405,14 @@ "$ref": "ManagedInstanceOverride", "description": "[Output Only] Override defined for this instance." }, + "preservedStateFromConfig": { + "$ref": "PreservedState", + "description": "[Output Only] Preserved state applied from per-instance config for this instance." + }, + "preservedStateFromPolicy": { + "$ref": "PreservedState", + "description": "[Output Only] Preserved state generated based on stateful policy for this instance." + }, "tag": { "description": "[Output Only] Tag describing the version.", "type": "string" @@ -35930,6 +38424,28 @@ }, "type": "object" }, + "ManagedInstanceInstanceHealth": { + "id": "ManagedInstanceInstanceHealth", + "properties": { + "healthCheck": { + "description": "[Output Only] The URL for the health check that verifies whether the instance is healthy.", + "type": "string" + }, + "healthState": { + "description": "[Output Only] The current instance health state.", + "enum": [ + "HEALTHY", + "UNHEALTHY" + ], + "enumDescriptions": [ + "", + "" + ], + "type": "string" + } + }, + "type": "object" + }, "ManagedInstanceLastAttempt": { "id": "ManagedInstanceLastAttempt", "properties": { @@ -36064,7 +38580,7 @@ "id": "Metadata", "properties": { "fingerprint": { - "description": "Specifies a fingerprint for this request, which is essentially a hash of the metadata's contents and used for optimistic locking. The fingerprint is initially generated by Compute Engine and changes after every request to modify or update metadata. You must always provide an up-to-date fingerprint hash in order to update or change metadata.", + "description": "Specifies a fingerprint for this request, which is essentially a hash of the metadata's contents and used for optimistic locking. The fingerprint is initially generated by Compute Engine and changes after every request to modify or update metadata. You must always provide an up-to-date fingerprint hash in order to update or change metadata, otherwise the request will fail with error 412 conditionNotMet.\n\nTo see the latest fingerprint, make a get() request to retrieve the resource.", "format": "byte", "type": "string" }, @@ -36123,7 +38639,7 @@ "type": "object" }, "Network": { - "description": "Represents a Network resource. Read Networks and Firewalls for more information. (== resource_for v1.networks ==) (== resource_for beta.networks ==)", + "description": "Represents a Network resource. Read Virtual Private Cloud (VPC) Network Overview for more information. (== resource_for v1.networks ==) (== resource_for beta.networks ==)", "id": "Network", "properties": { "IPv4Range": { @@ -36132,7 +38648,7 @@ "type": "string" }, "autoCreateSubnetworks": { - "description": "When set to true, the network is created in \"auto subnet mode\". When set to false, the network is in \"custom subnet mode\".\n\nIn \"auto subnet mode\", a newly created network is assigned the default CIDR of 10.128.0.0/9 and it automatically creates one subnetwork per region.", + "description": "When set to true, the VPC network is created in \"auto\" mode. When set to false, the VPC network is created in \"custom\" mode.\n\nAn auto mode VPC network starts with one subnet per region. Each subnet has a predetermined range as described in Auto mode VPC network IP ranges.", "type": "boolean" }, "creationTimestamp": { @@ -36156,7 +38672,7 @@ "type": "string" }, "gatewayIPv4": { - "description": "A gateway address for default routing to other networks. This value is read only and is selected by the Google Compute Engine, typically as the first usable address in the IPv4Range.", + "description": "[Output Only] The gateway address for default routing out of the network. This value is read only and is selected by GCP.", "pattern": "[0-9]{1,3}(?:\\.[0-9]{1,3}){3}", "type": "string" }, @@ -36208,7 +38724,7 @@ "type": "string" }, "subnetworks": { - "description": "[Output Only] Server-defined fully-qualified URLs for all subnetworks in this network.", + "description": "[Output Only] Server-defined fully-qualified URLs for all subnetworks in this VPC network.", "items": { "type": "string" }, @@ -36221,8 +38737,15 @@ "description": "The network endpoint.", "id": "NetworkEndpoint", "properties": { + "annotations": { + "additionalProperties": { + "type": "string" + }, + "description": "Metadata defined as annotations on the network endpoint.", + "type": "object" + }, "instance": { - "description": "The name for a specific VM instance that the IP address belongs to. This is required for network endpoints of type GCE_VM_IP and GCE_VM_IP_PORT. The instance must be in the same zone of network endpoint group.\n\nThe name must be 1-63 characters long, and comply with RFC1035.", + "description": "The name for a specific VM instance that the IP address belongs to. This is required for network endpoints of type GCE_VM_IP_PORT. The instance must be in the same zone of network endpoint group.\n\nThe name must be 1-63 characters long, and comply with RFC1035.", "type": "string" }, "ipAddress": { @@ -36241,10 +38764,22 @@ "description": "Represents a collection of network endpoints.", "id": "NetworkEndpointGroup", "properties": { + "annotations": { + "additionalProperties": { + "type": "string" + }, + "description": "Metadata defined as annotations on the network endpoint group.", + "type": "object" + }, "creationTimestamp": { "description": "[Output Only] Creation timestamp in RFC3339 text format.", "type": "string" }, + "defaultPort": { + "description": "The default port used if the port number is not specified in the network endpoint.", + "format": "int32", + "type": "integer" + }, "description": { "description": "An optional description of this resource. Provide this property when you create the resource.", "type": "string" @@ -36261,14 +38796,18 @@ }, "loadBalancer": { "$ref": "NetworkEndpointGroupLbNetworkEndpointGroup", - "description": "This field is only valid when the network endpoint group type is LOAD_BALANCING." + "description": "This field is only valid when the network endpoint group is used for load balancing. [Deprecated] This field is deprecated." }, "name": { "description": "Name of the resource; provided by the client when the resource is created. The name must be 1-63 characters long, and comply with RFC1035. Specifically, the name must be 1-63 characters long and match the regular expression `[a-z]([-a-z0-9]*[a-z0-9])?` which means the first character must be a lowercase letter, and all following characters must be a dash, lowercase letter, or digit, except the last character, which cannot be a dash.", "type": "string" }, + "network": { + "description": "The URL of the network to which all network endpoints in the NEG belong. Uses \"default\" project network if unspecified.", + "type": "string" + }, "networkEndpointType": { - "description": "Type of network endpoints in this network endpoint group. Only supported values for LOAD_BALANCING are GCE_VM_IP or GCE_VM_IP_PORT.", + "description": "Type of network endpoints in this network endpoint group. Currently the only supported value is GCE_VM_IP_PORT.", "enum": [ "GCE_VM_IP_PORT" ], @@ -36286,6 +38825,10 @@ "format": "int32", "type": "integer" }, + "subnetwork": { + "description": "Optional URL of the subnetwork to which all network endpoints in the NEG belong.", + "type": "string" + }, "type": { "description": "Specify the type of this network endpoint group. Only LOAD_BALANCING is valid for now.", "enum": [ @@ -36295,6 +38838,10 @@ "" ], "type": "string" + }, + "zone": { + "description": "[Output Only] The URL of the zone where the network endpoint group is located.", + "type": "string" } }, "type": "object" @@ -36412,24 +38959,24 @@ "type": "object" }, "NetworkEndpointGroupLbNetworkEndpointGroup": { - "description": "Load balancing specific fields for network endpoint group of type LOAD_BALANCING.", + "description": "Load balancing specific fields for network endpoint group.", "id": "NetworkEndpointGroupLbNetworkEndpointGroup", "properties": { "defaultPort": { - "description": "The default port used if the port number is not specified in the network endpoint. If the network endpoint type is GCE_VM_IP, this field must not be specified.", + "description": "The default port used if the port number is not specified in the network endpoint. [Deprecated] This field is deprecated.", "format": "int32", "type": "integer" }, "network": { - "description": "The URL of the network to which all network endpoints in the NEG belong. Uses \"default\" project network if unspecified.", + "description": "The URL of the network to which all network endpoints in the NEG belong. Uses \"default\" project network if unspecified. [Deprecated] This field is deprecated.", "type": "string" }, "subnetwork": { - "description": "Optional URL of the subnetwork to which all network endpoints in the NEG belong.", + "description": "Optional URL of the subnetwork to which all network endpoints in the NEG belong. [Deprecated] This field is deprecated.", "type": "string" }, "zone": { - "description": "[Output Only] The URL of the zone where the network endpoint group is located.", + "description": "[Output Only] The URL of the zone where the network endpoint group is located. [Deprecated] This field is deprecated.", "type": "string" } }, @@ -36827,7 +39374,7 @@ "type": "array" }, "fingerprint": { - "description": "Fingerprint hash of contents stored in this network interface. This field will be ignored when inserting an Instance or adding a NetworkInterface. An up-to-date fingerprint must be provided in order to update the NetworkInterface.", + "description": "Fingerprint hash of contents stored in this network interface. This field will be ignored when inserting an Instance or adding a NetworkInterface. An up-to-date fingerprint must be provided in order to update the NetworkInterface, otherwise the request will fail with error 412 conditionNotMet.", "format": "byte", "type": "string" }, @@ -36971,8 +39518,16 @@ "description": "A network peering attached to a network resource. The message includes the peering name, peer network, peering state, and a flag indicating whether Google Compute Engine should automatically create routes for the peering.", "id": "NetworkPeering", "properties": { + "advertisePeerSubnetsViaRouters": { + "description": "Whether Cloud Routers in this network can automatically advertise subnets from the peer network.", + "type": "boolean" + }, "autoCreateRoutes": { - "description": "Whether full mesh connectivity is created and managed automatically. When it is set to true, Google Compute Engine will automatically create and manage the routes between two networks when the state is ACTIVE. Otherwise, user needs to create routes manually to route packets to peer network.", + "description": "Indicates whether full mesh connectivity is created and managed automatically. When it is set to true, Google Compute Engine will automatically create and manage the routes between two networks when the state is ACTIVE. Otherwise, user needs to create routes manually to route packets to peer network.", + "type": "boolean" + }, + "exchangeSubnetRoutes": { + "description": "Whether full mesh connectivity is created and managed automatically. When it is set to true, Google Compute Engine will automatically create and manage the routes between two networks when the peering state is ACTIVE. Otherwise, user needs to create routes manually to route packets to peer network.", "type": "boolean" }, "exportCustomRoutes": { @@ -37015,7 +39570,7 @@ "id": "NetworkRoutingConfig", "properties": { "routingMode": { - "description": "The network-wide routing mode to use. If set to REGIONAL, this network's cloud routers will only advertise routes with subnetworks of this network in the same region as the router. If set to GLOBAL, this network's cloud routers will advertise routes with all subnetworks of this network, across regions.", + "description": "The network-wide routing mode to use. If set to REGIONAL, this network's cloud routers will only advertise routes with subnets of this network in the same region as the router. If set to GLOBAL, this network's cloud routers will advertise routes with all subnets of this network, across regions.", "enum": [ "GLOBAL", "REGIONAL" @@ -37037,11 +39592,11 @@ "type": "boolean" }, "exportCustomRoutes": { - "description": "Whether to export the custom routes to peer network.", + "description": "This field will be deprecated soon. Prefer using export_custom_routes in network_peering instead. Whether to export the custom routes to peer network.", "type": "boolean" }, "importCustomRoutes": { - "description": "Whether to import the custom routes from peer network.", + "description": "This field will be deprecated soon. Prefer using import_custom_routes in network_peering instead. Whether to import the custom routes from peer network.", "type": "boolean" }, "name": { @@ -37053,6 +39608,10 @@ "description": "Name of the peering, which should conform to RFC1035.", "type": "string" }, + "networkPeering": { + "$ref": "NetworkPeering", + "description": "Network peering parameters. In order to specify route policies for peering using import/export custom routes, you will have to fill all peering related parameters (name, peer network, exchange_subnet_routes) in network_peeringfield. Corresponding fields in NetworksAddPeeringRequest will be deprecated soon." + }, "peerNetwork": { "description": "URL of the peer network. It can be either full URL or partial URL. The peer network may belong to a different project. If the partial URL does not contain project, it is assumed that the peer network is in the same project as the current network.", "type": "string" @@ -37070,10 +39629,22 @@ }, "type": "object" }, + "NetworksUpdatePeeringRequest": { + "id": "NetworksUpdatePeeringRequest", + "properties": { + "networkPeering": { + "$ref": "NetworkPeering" + } + }, + "type": "object" + }, "NodeGroup": { "description": "A NodeGroup resource.", "id": "NodeGroup", "properties": { + "autoscalingPolicy": { + "$ref": "NodeGroupAutoscalingPolicy" + }, "creationTimestamp": { "description": "[Output Only] Creation timestamp in RFC3339 text format.", "type": "string" @@ -37100,17 +39671,15 @@ "description": "The URL of the node template to which this node group belongs.", "type": "string" }, - "nodes": { - "description": "[Output Only] A list of nodes in this node group.", - "items": { - "$ref": "NodeGroupNode" - }, - "type": "array" - }, "selfLink": { "description": "[Output Only] Server-defined URL for the resource.", "type": "string" }, + "size": { + "description": "[Output Only] The total number of nodes in the node group.", + "format": "int32", + "type": "integer" + }, "status": { "enum": [ "CREATING", @@ -37245,6 +39814,20 @@ }, "type": "object" }, + "NodeGroupAutoscalingPolicy": { + "id": "NodeGroupAutoscalingPolicy", + "properties": { + "maxSize": { + "format": "int32", + "type": "integer" + }, + "minSize": { + "format": "int32", + "type": "integer" + } + }, + "type": "object" + }, "NodeGroupList": { "description": "Contains a list of nodeGroups.", "id": "NodeGroupList", @@ -37360,10 +39943,6 @@ "NodeGroupNode": { "id": "NodeGroupNode", "properties": { - "index": { - "format": "int32", - "type": "integer" - }, "instances": { "description": "Instances scheduled on this node.", "items": { @@ -37379,17 +39958,23 @@ "description": "The type of this node.", "type": "string" }, + "serverBinding": { + "$ref": "ServerBinding", + "description": "Binding properties for the physical server." + }, "status": { "enum": [ "CREATING", "DELETING", "INVALID", - "READY" + "READY", + "REPAIRING" ], "enumDescriptions": [ "", "", "", + "", "" ], "type": "string" @@ -37411,14 +39996,6 @@ "NodeGroupsDeleteNodesRequest": { "id": "NodeGroupsDeleteNodesRequest", "properties": { - "nodeIndexes": { - "description": "Indexes of the nodes to be deleted from the node group.", - "items": { - "format": "int32", - "type": "integer" - }, - "type": "array" - }, "nodes": { "items": { "type": "string" @@ -37428,6 +40005,117 @@ }, "type": "object" }, + "NodeGroupsListNodes": { + "id": "NodeGroupsListNodes", + "properties": { + "id": { + "description": "[Output Only] Unique identifier for the resource; defined by the server.", + "type": "string" + }, + "items": { + "description": "A list of Node resources.", + "items": { + "$ref": "NodeGroupNode" + }, + "type": "array" + }, + "kind": { + "default": "compute#nodeGroupsListNodes", + "description": "[Output Only] The resource type, which is always compute.nodeGroupsListNodes for the list of nodes in the specified node group.", + "type": "string" + }, + "nextPageToken": { + "description": "[Output Only] This token allows you to get the next page of results for list requests. If the number of results is larger than maxResults, use the nextPageToken as a value for the query parameter pageToken in the next list request. Subsequent list requests will have their own nextPageToken to continue paging through the results.", + "type": "string" + }, + "selfLink": { + "description": "[Output Only] Server-defined URL for this resource.", + "type": "string" + }, + "warning": { + "description": "[Output Only] Informational warning message.", + "properties": { + "code": { + "description": "[Output Only] A warning code, if applicable. For example, Compute Engine returns NO_RESULTS_ON_PAGE if there are no results in the response.", + "enum": [ + "CLEANUP_FAILED", + "DEPRECATED_RESOURCE_USED", + "DEPRECATED_TYPE_USED", + "DISK_SIZE_LARGER_THAN_IMAGE_SIZE", + "EXPERIMENTAL_TYPE_USED", + "EXTERNAL_API_WARNING", + "FIELD_VALUE_OVERRIDEN", + "INJECTED_KERNELS_DEPRECATED", + "MISSING_TYPE_DEPENDENCY", + "NEXT_HOP_ADDRESS_NOT_ASSIGNED", + "NEXT_HOP_CANNOT_IP_FORWARD", + "NEXT_HOP_INSTANCE_NOT_FOUND", + "NEXT_HOP_INSTANCE_NOT_ON_NETWORK", + "NEXT_HOP_NOT_RUNNING", + "NOT_CRITICAL_ERROR", + "NO_RESULTS_ON_PAGE", + "REQUIRED_TOS_AGREEMENT", + "RESOURCE_IN_USE_BY_OTHER_RESOURCE_WARNING", + "RESOURCE_NOT_DELETED", + "SCHEMA_VALIDATION_IGNORED", + "SINGLE_INSTANCE_PROPERTY_TEMPLATE", + "UNDECLARED_PROPERTIES", + "UNREACHABLE" + ], + "enumDescriptions": [ + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "" + ], + "type": "string" + }, + "data": { + "description": "[Output Only] Metadata about this warning in key: value format. For example:\n\"data\": [ { \"key\": \"scope\", \"value\": \"zones/us-east1-d\" }", + "items": { + "properties": { + "key": { + "description": "[Output Only] A key that provides more detail on the warning being returned. For example, for warnings where there are no results in a list request for a particular zone, this key might be scope and the key value might be the zone name. Other examples might be a key indicating a deprecated resource and a suggested replacement, or a warning about invalid network settings (for example, if an instance attempts to perform IP forwarding but is not enabled for IP forwarding).", + "type": "string" + }, + "value": { + "description": "[Output Only] A warning data value corresponding to the key.", + "type": "string" + } + }, + "type": "object" + }, + "type": "array" + }, + "message": { + "description": "[Output Only] A human-readable description of the warning code.", + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object" + }, "NodeGroupsScopedList": { "id": "NodeGroupsScopedList", "properties": { @@ -37555,7 +40243,7 @@ "type": "string" }, "name": { - "description": "The name of the resource, provided by the client when initially creating the resource. The resource name must be 1-63 characters long, and comply with RFC1035. Specifically, the name must be 1-63 characters long and match the regular expression `[a-z]([-a-z0-9]*[a-z0-9])?` which means the first character must be a lowercase letter, and all following characters must be a dash, lowercase letter, or digit, except the last charaicter, which cannot be a dash.", + "description": "The name of the resource, provided by the client when initially creating the resource. The resource name must be 1-63 characters long, and comply with RFC1035. Specifically, the name must be 1-63 characters long and match the regular expression `[a-z]([-a-z0-9]*[a-z0-9])?` which means the first character must be a lowercase letter, and all following characters must be a dash, lowercase letter, or digit, except the last character, which cannot be a dash.", "type": "string" }, "nodeAffinityLabels": { @@ -37581,6 +40269,10 @@ "description": "[Output Only] Server-defined URL for the resource.", "type": "string" }, + "serverBinding": { + "$ref": "ServerBinding", + "description": "Binding properties for the physical server." + }, "status": { "description": "[Output Only] The status of the node template. One of the following values: CREATING, READY, and DELETING.", "enum": [ @@ -38856,7 +41548,7 @@ "id": "PathMatcher", "properties": { "defaultService": { - "description": "The full or partial URL to the BackendService resource. This will be used if none of the pathRules defined by this PathMatcher is matched by the URL's path portion. For example, the following are all valid URLs to a BackendService resource: \n- https://www.googleapis.com/compute/v1/projects/project/global/backendServices/backendService \n- compute/v1/projects/project/global/backendServices/backendService \n- global/backendServices/backendService", + "description": "The full or partial URL to the BackendService resource. This will be used if none of the pathRules or routeRules defined by this PathMatcher are matched. For example, the following are all valid URLs to a BackendService resource: \n- https://www.googleapis.com/compute/v1/projects/project/global/backendServices/backendService \n- compute/v1/projects/project/global/backendServices/backendService \n- global/backendServices/backendService \nUse defaultService instead of defaultRouteAction when simple routing to a backend service is desired and other advanced capabilities like traffic splitting and URL rewrites are not required.\nOnly one of defaultService, defaultRouteAction or defaultUrlRedirect must be set.\nAuthorization requires one or more of the following Google IAM permissions on the specified resource default_service: \n- compute.backendBuckets.use \n- compute.backendServices.use", "type": "string" }, "description": { @@ -38868,7 +41560,7 @@ "type": "string" }, "pathRules": { - "description": "The list of path rules.", + "description": "The list of path rules. Use this list instead of routeRules when routing based on simple path matching is all that's required. The order by which path rules are specified does not matter. Matches are always done on the longest-path-first basis.\nFor example: a pathRule with a path /a/b/c/* will match before /a/b/* irrespective of the order in which those paths appear in this list.\nOnly one of pathRules or routeRules must be set.", "items": { "$ref": "PathRule" }, @@ -38889,7 +41581,7 @@ "type": "array" }, "service": { - "description": "The URL of the BackendService resource if this rule is matched.", + "description": "The URL of the backend service resource if this rule is matched.\nUse service instead of routeAction when simple routing to a backend service is desired and other advanced capabilities like traffic splitting and rewrites are not required.\nOnly one of service, routeAction or urlRedirect should must be set.", "type": "string" } }, @@ -38907,8 +41599,16 @@ "description": "The URL of the instance. Serves as a merge key during UpdatePerInstanceConfigs operation, i.e. if per-instance config with the same instance URL exists then it will be updated, otherwise a new one will be created.", "type": "string" }, + "name": { + "description": "The name of the per-instance config and the corresponding instance. Serves as a merge key during UpdatePerInstanceConfigs operation, i.e. if per-instance config with the same name exists then it will be updated, otherwise a new one will be created for the VM instance with the same name. An attempt to create a per-instance config for a VM instance that either doesn't exist or is not part of the group will result in a failure.", + "type": "string" + }, "override": { "$ref": "ManagedInstanceOverride" + }, + "preservedState": { + "$ref": "PreservedState", + "description": "Intended preserved state for the given instance. Does not contain state generated based on Stateful Policy." } }, "type": "object" @@ -38968,6 +41668,61 @@ }, "type": "object" }, + "PreservedState": { + "description": "Preserved state for a given instance.", + "id": "PreservedState", + "properties": { + "disks": { + "additionalProperties": { + "$ref": "PreservedStatePreservedDisk" + }, + "description": "Preserved disks defined for this instance. This map is keyed with the device names of the disks.", + "type": "object" + }, + "metadata": { + "additionalProperties": { + "type": "string" + }, + "description": "Preserved metadata defined for this instance.", + "type": "object" + } + }, + "type": "object" + }, + "PreservedStatePreservedDisk": { + "id": "PreservedStatePreservedDisk", + "properties": { + "autoDelete": { + "description": "These stateful disks will never be deleted during autohealing, update, instance recreate operations. This flag is used to configure if the disk should be deleted after it is no longer used by the group, e.g. when the given instance or the whole MIG is deleted. Note: disks attached in READ_ONLY mode cannot be auto-deleted.", + "enum": [ + "NEVER", + "WHEN_NOT_IN_USE" + ], + "enumDescriptions": [ + "", + "" + ], + "type": "string" + }, + "mode": { + "description": "The mode in which to attach this disk, either READ_WRITE or READ_ONLY. If not specified, the default is to attach the disk in READ_WRITE mode.", + "enum": [ + "READ_ONLY", + "READ_WRITE" + ], + "enumDescriptions": [ + "", + "" + ], + "type": "string" + }, + "source": { + "description": "The URL of the disk resource that is stateful and should be attached to the VM instance.", + "type": "string" + } + }, + "type": "object" + }, "Project": { "description": "A Project resource. For an overview of projects, see Cloud Platform Resource Hierarchy. (== resource_for v1.projects ==) (== resource_for beta.projects ==)", "id": "Project", @@ -39157,6 +41912,8 @@ "DISKS_TOTAL_GB", "FIREWALLS", "FORWARDING_RULES", + "GLOBAL_INTERNAL_ADDRESSES", + "GPUS_ALL_REGIONS", "HEALTH_CHECKS", "IMAGES", "INSTANCES", @@ -39168,18 +41925,29 @@ "INTERCONNECT_ATTACHMENTS_TOTAL_MBPS", "INTERNAL_ADDRESSES", "IN_USE_ADDRESSES", + "IN_USE_BACKUP_SCHEDULES", "IN_USE_MAINTENANCE_WINDOWS", "LOCAL_SSD_TOTAL_GB", + "MACHINE_IMAGES", "NETWORKS", "NETWORK_ENDPOINT_GROUPS", "NVIDIA_K80_GPUS", "NVIDIA_P100_GPUS", "NVIDIA_P100_VWS_GPUS", + "NVIDIA_P4_GPUS", + "NVIDIA_P4_VWS_GPUS", + "NVIDIA_T4_GPUS", + "NVIDIA_T4_VWS_GPUS", "NVIDIA_V100_GPUS", "PREEMPTIBLE_CPUS", "PREEMPTIBLE_LOCAL_SSD_GB", "PREEMPTIBLE_NVIDIA_K80_GPUS", "PREEMPTIBLE_NVIDIA_P100_GPUS", + "PREEMPTIBLE_NVIDIA_P100_VWS_GPUS", + "PREEMPTIBLE_NVIDIA_P4_GPUS", + "PREEMPTIBLE_NVIDIA_P4_VWS_GPUS", + "PREEMPTIBLE_NVIDIA_T4_GPUS", + "PREEMPTIBLE_NVIDIA_T4_VWS_GPUS", "PREEMPTIBLE_NVIDIA_V100_GPUS", "PRIVATE_V6_ACCESS_SUBNETWORKS", "REGIONAL_AUTOSCALERS", @@ -39202,6 +41970,7 @@ "TARGET_TCP_PROXIES", "TARGET_VPN_GATEWAYS", "URL_MAPS", + "VPN_GATEWAYS", "VPN_TUNNELS" ], "enumDescriptions": [ @@ -39260,6 +42029,20 @@ "", "", "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", "" ], "type": "string" @@ -39582,6 +42365,32 @@ }, "type": "object" }, + "RegionDisksAddResourcePoliciesRequest": { + "id": "RegionDisksAddResourcePoliciesRequest", + "properties": { + "resourcePolicies": { + "description": "Resource policies to be added to this disk.", + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object" + }, + "RegionDisksRemoveResourcePoliciesRequest": { + "id": "RegionDisksRemoveResourcePoliciesRequest", + "properties": { + "resourcePolicies": { + "description": "Resource policies to be removed from this disk.", + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object" + }, "RegionDisksResizeRequest": { "id": "RegionDisksResizeRequest", "properties": { @@ -39715,6 +42524,13 @@ "type": "string" }, "type": "array" + }, + "names": { + "description": "The list of instance names for which we want to delete per-instance configs on this managed instance group.", + "items": { + "type": "string" + }, + "type": "array" } }, "type": "object" @@ -40389,6 +43205,19 @@ }, "type": "object" }, + "RegionTargetHttpsProxiesSetSslCertificatesRequest": { + "id": "RegionTargetHttpsProxiesSetSslCertificatesRequest", + "properties": { + "sslCertificates": { + "description": "New set of SslCertificate resources to associate with this TargetHttpsProxy resource. Currently exactly one SslCertificate resource must be specified.", + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object" + }, "RegionUrlMapsValidateRequest": { "id": "RegionUrlMapsValidateRequest", "properties": { @@ -40403,6 +43232,10 @@ "description": "Commitment for a particular resource (a Commitment is composed of one or more of these).", "id": "ResourceCommitment", "properties": { + "acceleratorType": { + "description": "Name of the accelerator type resource. Applicable only when the type is ACCELERATOR.", + "type": "string" + }, "amount": { "description": "The amount of the resource purchased (in a type-dependent unit, such as bytes). For vCPUs, this can just be an integer. For memory, this must be provided in MB. Memory must be a multiple of 256 MB, with up to 6.5GB of memory per every vCPU.", "format": "int64", @@ -40411,6 +43244,7 @@ "type": { "description": "Type of resource for which this commitment applies. Possible values are VCPU and MEMORY", "enum": [ + "ACCELERATOR", "LOCAL_SSD", "MEMORY", "UNSPECIFIED", @@ -40420,6 +43254,7 @@ "", "", "", + "", "" ], "type": "string" @@ -40431,126 +43266,12 @@ "id": "ResourceGroupReference", "properties": { "group": { - "description": "A URI referencing one of the instance groups listed in the backend service.", + "description": "A URI referencing one of the instance groups or network endpoint groups listed in the backend service.", "type": "string" } }, "type": "object" }, - "ResourcePoliciesList": { - "id": "ResourcePoliciesList", - "properties": { - "etag": { - "type": "string" - }, - "id": { - "description": "[Output Only] The unique identifier for the resource. This identifier is defined by the server.", - "type": "string" - }, - "items": { - "description": "[Output Only] A list of ResourcePolicy resources.", - "items": { - "$ref": "ResourcePolicy" - }, - "type": "array" - }, - "kind": { - "default": "compute#resourcePoliciesList", - "description": "[Output Only] Type of resource.Always compute#resourcePoliciesList for listsof resourcePolicies", - "type": "string" - }, - "nextPageToken": { - "description": "[Output Only] This token allows you to get the next page of results for list requests. If the number of results is larger than maxResults, use the nextPageToken as a value for the query parameter pageToken in the next list request. Subsequent list requests will have their own nextPageToken to continue paging through the results.", - "type": "string" - }, - "selfLink": { - "description": "[Output Only] Server-defined URL for this resource.", - "type": "string" - }, - "warning": { - "description": "[Output Only] Informational warning message.", - "properties": { - "code": { - "description": "[Output Only] A warning code, if applicable. For example, Compute Engine returns NO_RESULTS_ON_PAGE if there are no results in the response.", - "enum": [ - "CLEANUP_FAILED", - "DEPRECATED_RESOURCE_USED", - "DEPRECATED_TYPE_USED", - "DISK_SIZE_LARGER_THAN_IMAGE_SIZE", - "EXPERIMENTAL_TYPE_USED", - "EXTERNAL_API_WARNING", - "FIELD_VALUE_OVERRIDEN", - "INJECTED_KERNELS_DEPRECATED", - "MISSING_TYPE_DEPENDENCY", - "NEXT_HOP_ADDRESS_NOT_ASSIGNED", - "NEXT_HOP_CANNOT_IP_FORWARD", - "NEXT_HOP_INSTANCE_NOT_FOUND", - "NEXT_HOP_INSTANCE_NOT_ON_NETWORK", - "NEXT_HOP_NOT_RUNNING", - "NOT_CRITICAL_ERROR", - "NO_RESULTS_ON_PAGE", - "REQUIRED_TOS_AGREEMENT", - "RESOURCE_IN_USE_BY_OTHER_RESOURCE_WARNING", - "RESOURCE_NOT_DELETED", - "SCHEMA_VALIDATION_IGNORED", - "SINGLE_INSTANCE_PROPERTY_TEMPLATE", - "UNDECLARED_PROPERTIES", - "UNREACHABLE" - ], - "enumDescriptions": [ - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "" - ], - "type": "string" - }, - "data": { - "description": "[Output Only] Metadata about this warning in key: value format. For example:\n\"data\": [ { \"key\": \"scope\", \"value\": \"zones/us-east1-d\" }", - "items": { - "properties": { - "key": { - "description": "[Output Only] A key that provides more detail on the warning being returned. For example, for warnings where there are no results in a list request for a particular zone, this key might be scope and the key value might be the zone name. Other examples might be a key indicating a deprecated resource and a suggested replacement, or a warning about invalid network settings (for example, if an instance attempts to perform IP forwarding but is not enabled for IP forwarding).", - "type": "string" - }, - "value": { - "description": "[Output Only] A warning data value corresponding to the key.", - "type": "string" - } - }, - "type": "object" - }, - "type": "array" - }, - "message": { - "description": "[Output Only] A human-readable description of the warning code.", - "type": "string" - } - }, - "type": "object" - } - }, - "type": "object" - }, "ResourcePoliciesScopedList": { "id": "ResourcePoliciesScopedList", "properties": { @@ -40810,7 +43531,7 @@ "type": "object" }, "ResourcePolicyBackupSchedulePolicy": { - "description": "A backup schedule policy specifies when and how frequently snapshots are to be created for the target disk. Also specifies how many and how long these automatically created snapshot should be retained.", + "description": "A backup schedule policy specifies when and how frequently snapshots are to be created for the target disk. Also specifies how many and how long these scheduled snapshots should be retained.", "id": "ResourcePolicyBackupSchedulePolicy", "properties": { "retentionPolicy": { @@ -40823,19 +43544,47 @@ }, "snapshotProperties": { "$ref": "ResourcePolicyBackupSchedulePolicySnapshotProperties", - "description": "Properties with which snapshots are created such as lables, encryption keys." + "description": "Properties with which snapshots are created such as labels, encryption keys." } }, "type": "object" }, "ResourcePolicyBackupSchedulePolicyRetentionPolicy": { - "description": "Policy for retention of automatically created snapshots.", + "description": "Policy for retention of scheduled snapshots.", "id": "ResourcePolicyBackupSchedulePolicyRetentionPolicy", "properties": { "maxRetentionDays": { "description": "Maximum age of the snapshot that is allowed to be kept.", "format": "int32", "type": "integer" + }, + "onPolicySwitch": { + "description": "Specifies the behavior to apply to existing, scheduled snapshots snapshots if the policy is changed.", + "enum": [ + "DO_NOT_RETROACTIVELY_APPLY", + "RETROACTIVELY_APPLY", + "UNSPECIFIED_ON_POLICY_SWITCH" + ], + "enumDescriptions": [ + "", + "", + "" + ], + "type": "string" + }, + "onSourceDiskDelete": { + "description": "Specifies the behavior to apply to scheduled snapshots when the source disk is deleted.", + "enum": [ + "APPLY_RETENTION_POLICY", + "KEEP_AUTO_SNAPSHOTS", + "UNSPECIFIED_ON_SOURCE_DISK_DELETE" + ], + "enumDescriptions": [ + "", + "", + "" + ], + "type": "string" } }, "type": "object" @@ -40857,7 +43606,7 @@ "type": "object" }, "ResourcePolicyBackupSchedulePolicySnapshotProperties": { - "description": "Specified snapshot properties for automatic snapshots created by this policy.", + "description": "Specified snapshot properties for scheduled snapshots created by this policy.", "id": "ResourcePolicyBackupSchedulePolicySnapshotProperties", "properties": { "guestFlush": { @@ -40868,8 +43617,15 @@ "additionalProperties": { "type": "string" }, - "description": "Labels to apply to automatic snapshots. These can be later modified by the setLabels method. Label values may be empty.", + "description": "Labels to apply to scheduled snapshots. These can be later modified by the setLabels method. Label values may be empty.", "type": "object" + }, + "storageLocations": { + "description": "GCS bucket storage location of the auto snapshot (regional or multi-regional).", + "items": { + "type": "string" + }, + "type": "array" } }, "type": "object" @@ -40888,7 +43644,7 @@ "type": "string" }, "startTime": { - "description": "Time within the window to start the operations. It must be in format \"HH:MM?, where HH : [00-23] and MM : [00-59] GMT.", + "description": "Time within the window to start the operations. It must be in format \"HH:MM\", where HH : [00-23] and MM : [00-00] GMT.", "type": "string" } }, @@ -40908,29 +43664,129 @@ "type": "integer" }, "startTime": { - "description": "Time within the window to start the operations. It must be in format \"HH:MM?, where HH : [00-23] and MM : [00-59] GMT.", + "description": "Time within the window to start the operations. It must be in format \"HH:MM\", where HH : [00-23] and MM : [00-00] GMT.", "type": "string" } }, "type": "object" }, + "ResourcePolicyList": { + "id": "ResourcePolicyList", + "properties": { + "etag": { + "type": "string" + }, + "id": { + "description": "[Output Only] The unique identifier for the resource. This identifier is defined by the server.", + "type": "string" + }, + "items": { + "description": "[Output Only] A list of ResourcePolicy resources.", + "items": { + "$ref": "ResourcePolicy" + }, + "type": "array" + }, + "kind": { + "default": "compute#resourcePolicyList", + "description": "[Output Only] Type of resource.Always compute#resourcePoliciesList for listsof resourcePolicies", + "type": "string" + }, + "nextPageToken": { + "description": "[Output Only] This token allows you to get the next page of results for list requests. If the number of results is larger than maxResults, use the nextPageToken as a value for the query parameter pageToken in the next list request. Subsequent list requests will have their own nextPageToken to continue paging through the results.", + "type": "string" + }, + "selfLink": { + "description": "[Output Only] Server-defined URL for this resource.", + "type": "string" + }, + "warning": { + "description": "[Output Only] Informational warning message.", + "properties": { + "code": { + "description": "[Output Only] A warning code, if applicable. For example, Compute Engine returns NO_RESULTS_ON_PAGE if there are no results in the response.", + "enum": [ + "CLEANUP_FAILED", + "DEPRECATED_RESOURCE_USED", + "DEPRECATED_TYPE_USED", + "DISK_SIZE_LARGER_THAN_IMAGE_SIZE", + "EXPERIMENTAL_TYPE_USED", + "EXTERNAL_API_WARNING", + "FIELD_VALUE_OVERRIDEN", + "INJECTED_KERNELS_DEPRECATED", + "MISSING_TYPE_DEPENDENCY", + "NEXT_HOP_ADDRESS_NOT_ASSIGNED", + "NEXT_HOP_CANNOT_IP_FORWARD", + "NEXT_HOP_INSTANCE_NOT_FOUND", + "NEXT_HOP_INSTANCE_NOT_ON_NETWORK", + "NEXT_HOP_NOT_RUNNING", + "NOT_CRITICAL_ERROR", + "NO_RESULTS_ON_PAGE", + "REQUIRED_TOS_AGREEMENT", + "RESOURCE_IN_USE_BY_OTHER_RESOURCE_WARNING", + "RESOURCE_NOT_DELETED", + "SCHEMA_VALIDATION_IGNORED", + "SINGLE_INSTANCE_PROPERTY_TEMPLATE", + "UNDECLARED_PROPERTIES", + "UNREACHABLE" + ], + "enumDescriptions": [ + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "" + ], + "type": "string" + }, + "data": { + "description": "[Output Only] Metadata about this warning in key: value format. For example:\n\"data\": [ { \"key\": \"scope\", \"value\": \"zones/us-east1-d\" }", + "items": { + "properties": { + "key": { + "description": "[Output Only] A key that provides more detail on the warning being returned. For example, for warnings where there are no results in a list request for a particular zone, this key might be scope and the key value might be the zone name. Other examples might be a key indicating a deprecated resource and a suggested replacement, or a warning about invalid network settings (for example, if an instance attempts to perform IP forwarding but is not enabled for IP forwarding).", + "type": "string" + }, + "value": { + "description": "[Output Only] A warning data value corresponding to the key.", + "type": "string" + } + }, + "type": "object" + }, + "type": "array" + }, + "message": { + "description": "[Output Only] A human-readable description of the warning code.", + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object" + }, "ResourcePolicyVmMaintenancePolicy": { "id": "ResourcePolicyVmMaintenancePolicy", "properties": { - "maintenanceEnvironment": { - "description": "A hint about the environment this VM belongs to (production vs develoment)", - "enum": [ - "DEVELOPMENT", - "MAINTENANCE_ENVIRONMENT_UNSPECIFIED", - "PRODUCTION" - ], - "enumDescriptions": [ - "", - "", - "" - ], - "type": "string" - }, "maintenanceWindow": { "$ref": "ResourcePolicyVmMaintenancePolicyMaintenanceWindow", "description": "Maintenance windows that are applied to VMs covered by this policy." @@ -40944,9 +43800,6 @@ "properties": { "dailyMaintenanceWindow": { "$ref": "ResourcePolicyDailyCycle" - }, - "weeklyMaintenanceWindow": { - "$ref": "ResourcePolicyWeeklyCycle" } }, "type": "object" @@ -40997,7 +43850,7 @@ "type": "string" }, "startTime": { - "description": "Time within the window to start the operations. It must be in format \"HH:MM?, where HH : [00-23] and MM : [00-59] GMT.", + "description": "Time within the window to start the operations. It must be in format \"HH:MM\", where HH : [00-23] and MM : [00-00] GMT.", "type": "string" } }, @@ -41530,9 +44383,13 @@ "description": "User-specified list of prefix groups to advertise in custom mode. This field can only be populated if advertise_mode is CUSTOM and is advertised to all peers of the router. These groups will be advertised in addition to any specified prefixes. Leave this field blank to advertise no custom groups.", "items": { "enum": [ - "ALL_SUBNETS" + "ALL_PEER_VPC_SUBNETS", + "ALL_SUBNETS", + "ALL_VPC_SUBNETS" ], "enumDescriptions": [ + "", + "", "" ], "type": "string" @@ -41573,9 +44430,13 @@ "description": "User-specified list of prefix groups to advertise in custom mode. This field can only be populated if advertise_mode is CUSTOM and overrides the list defined for the router (in Bgp message). These groups will be advertised in addition to any specified prefixes. Leave this field blank to advertise no custom groups.", "items": { "enum": [ - "ALL_SUBNETS" + "ALL_PEER_VPC_SUBNETS", + "ALL_SUBNETS", + "ALL_VPC_SUBNETS" ], "enumDescriptions": [ + "", + "", "" ], "type": "string" @@ -41603,7 +44464,7 @@ "type": "string" }, "managementType": { - "description": "[Output Only] Type of how the resource/configuration of the BGP peer is managed. MANAGED_BY_USER is the default value; MANAGED_BY_ATTACHMENT represents an BGP peer that is automatically created for PARTNER interconnectAttachment, Google will automatically create/delete this type of BGP peer when the PARTNER interconnectAttachment is created/deleted.", + "description": "[Output Only] The resource that configures and manages this BGP peer. MANAGED_BY_USER is the default value and can be managed by you or other users; MANAGED_BY_ATTACHMENT is a BGP peer that is configured and managed by Cloud Interconnect, specifically by an InterconnectAttachment of type PARTNER. Google will automatically create, update, and delete this type of BGP peer when the PARTNER InterconnectAttachment is created, updated, or deleted.", "enum": [ "MANAGED_BY_ATTACHMENT", "MANAGED_BY_USER" @@ -41647,7 +44508,7 @@ "type": "string" }, "managementType": { - "description": "[Output Only] Type of how the resource/configuration of the interface is managed. MANAGED_BY_USER is the default value; MANAGED_BY_ATTACHMENT represents an interface that is automatically created for PARTNER type interconnectAttachment, Google will automatically create/update/delete this type of interface when the PARTNER interconnectAttachment is created/provisioned/deleted.", + "description": "[Output Only] The resource that configures and manages this interface. MANAGED_BY_USER is the default value and can be managed by you or other users; MANAGED_BY_ATTACHMENT is an interface that is configured and managed by Cloud Interconnect, specifically by an InterconnectAttachment of type PARTNER. Google will automatically create, update, and delete this type of interface when the PARTNER InterconnectAttachment is created, updated, or deleted.", "enum": [ "MANAGED_BY_ATTACHMENT", "MANAGED_BY_USER" @@ -41782,18 +44643,15 @@ "description": "Represents a Nat resource. It enables the VMs within the specified subnetworks to access Internet without external IP addresses. It specifies a list of subnetworks (and the ranges within) that want to use NAT. Customers can also provide the external IPs that would be used for NAT. GCP would auto-allocate ephemeral IPs if no external IPs are provided.", "id": "RouterNat", "properties": { - "autoAllocatedNatIps": { - "description": "[Output Only] A list of IPs allocated automatically by GCP for this Nat service. They will be raw IP strings like \"179.12.26.133\". They are ephemeral IPs allocated from the IP blocks managed by the NAT manager. This list can grow and shrink based on the number of VMs configured to use NAT.", - "items": { - "type": "string" - }, - "type": "array" - }, "icmpIdleTimeoutSec": { "description": "Timeout (in seconds) for ICMP connections. Defaults to 30s if not set.", "format": "int32", "type": "integer" }, + "logConfig": { + "$ref": "RouterNatLogConfig", + "description": "Configure logging on this NAT." + }, "minPortsPerVm": { "description": "Minimum number of ports allocated to a VM from this NAT config. If not set, a default number of ports is allocated to a VM. This gets rounded up to the nearest power of 2. Eg. if the value of this field is 50, at least 64 ports will be allocated to a VM.", "format": "int32", @@ -41862,6 +44720,29 @@ }, "type": "object" }, + "RouterNatLogConfig": { + "description": "Configuration of logging on a NAT.", + "id": "RouterNatLogConfig", + "properties": { + "enabled": { + "description": "Indicates whether or not to export logs. This is false by default.", + "type": "boolean" + }, + "filter": { + "description": "Specifies the desired filtering of logs on this NAT. If unspecified, logs are exported for all connections handled by this NAT.", + "enum": [ + "ERRORS_ONLY", + "TRANSLATIONS_ONLY" + ], + "enumDescriptions": [ + "", + "" + ], + "type": "string" + } + }, + "type": "object" + }, "RouterNatSubnetworkToNat": { "description": "Defines the IP ranges that want to use NAT for a subnetwork.", "id": "RouterNatSubnetworkToNat", @@ -41877,7 +44758,7 @@ }, "type": "array" }, - "sourceIpRangesToNats": { + "sourceIpRangesToNat": { "description": "Specify the options for NAT ranges in the Subnetwork. All usages of single value are valid except NAT_IP_RANGE_OPTION_UNSPECIFIED. The only valid option with multiple values is: [\"PRIMARY_IP_RANGE\", \"LIST_OF_SECONDARY_IP_RANGES\"] Default: [ALL_IP_RANGES]", "items": { "enum": [ @@ -42268,6 +45149,133 @@ }, "type": "object" }, + "SavedAttachedDisk": { + "description": "An instance-attached disk resource.", + "id": "SavedAttachedDisk", + "properties": { + "autoDelete": { + "description": "Specifies whether the disk will be auto-deleted when the instance is deleted (but not when the disk is detached from the instance).", + "type": "boolean" + }, + "boot": { + "description": "Indicates that this is a boot disk. The virtual machine will use the first partition of the disk for its root filesystem.", + "type": "boolean" + }, + "deviceName": { + "description": "Specifies a unique device name of your choice that is reflected into the /dev/disk/by-id/google-* tree of a Linux operating system running within the instance. This name can be used to reference the device for mounting, resizing, and so on, from within the instance.\n\nIf not specified, the server chooses a default device name to apply to this disk, in the form persistent-disks-x, where x is a number assigned by Google Compute Engine. This field is only applicable for persistent disks.", + "type": "string" + }, + "diskEncryptionKey": { + "$ref": "CustomerEncryptionKey", + "description": "Encrypts or decrypts a disk using a customer-supplied encryption key.\n\nIf you are creating a new disk, this field encrypts the new disk using an encryption key that you provide. If you are attaching an existing disk that is already encrypted, this field decrypts the disk using the customer-supplied encryption key.\n\nIf you encrypt a disk using a customer-supplied key, you must provide the same key again when you attempt to use this resource at a later time. For example, you must provide the key when you create a snapshot or an image from the disk or when you attach the disk to a virtual machine instance.\n\nIf you do not provide an encryption key, then the disk will be encrypted using an automatically generated key and you do not need to provide a key to use the disk later.\n\nMachine Images do not store customer-supplied encryption keys, so you cannot use your own keys to encrypt disks in a managed instance group." + }, + "diskSizeGb": { + "description": "The size of the disk in base-2 GB. This supersedes disk_size_gb in InitializeParams.", + "format": "int64", + "type": "string" + }, + "guestOsFeatures": { + "description": "A list of features to enable on the guest operating system. Applicable only for bootable images. Read Enabling guest operating system features to see a list of available options.", + "items": { + "$ref": "GuestOsFeature" + }, + "type": "array" + }, + "index": { + "description": "[Output Only] A zero-based index to this disk, where 0 is reserved for the boot disk. If you have many disks attached to an instance, each disk would have a unique index number.", + "format": "int32", + "type": "integer" + }, + "initializeParams": { + "$ref": "AttachedDiskInitializeParams", + "description": "[Input Only] Specifies the parameters for a new disk that will be created alongside the new instance. Use initialization parameters to create boot disks or local SSDs attached to the new instance.\n\nThis property is mutually exclusive with the source property; you can only define one or the other, but not both." + }, + "interface": { + "description": "Specifies the disk interface to use for attaching this disk, which is either SCSI or NVME. The default is SCSI. Persistent disks must always use SCSI and the request will fail if you attempt to attach a persistent disk in any other format than SCSI. Local SSDs can use either NVME or SCSI. For performance characteristics of SCSI over NVMe, see Local SSD performance.", + "enum": [ + "NVDIMM", + "NVME", + "SCSI" + ], + "enumDescriptions": [ + "", + "", + "" + ], + "type": "string" + }, + "kind": { + "default": "compute#savedAttachedDisk", + "description": "[Output Only] Type of the resource. Always compute#attachedDisk for attached disks.", + "type": "string" + }, + "licenses": { + "description": "[Output Only] Any valid publicly visible licenses.", + "items": { + "type": "string" + }, + "type": "array" + }, + "mode": { + "description": "The mode in which to attach this disk, either READ_WRITE or READ_ONLY. If not specified, the default is to attach the disk in READ_WRITE mode.", + "enum": [ + "READ_ONLY", + "READ_WRITE" + ], + "enumDescriptions": [ + "", + "" + ], + "type": "string" + }, + "savedState": { + "description": "For LocalSSD disks on VM Instances in STOPPED or SUSPENDED state, this field is set to PRESERVED if the LocalSSD data has been saved to a persistent location by customer request. (see the discard_local_ssd option on Stop/Suspend). Read-only in the api.", + "enum": [ + "DISK_SAVED_STATE_UNSPECIFIED", + "PRESERVED" + ], + "enumDescriptions": [ + "", + "" + ], + "type": "string" + }, + "source": { + "description": "Specifies a valid partial or full URL to an existing Persistent Disk resource. When creating a new instance, one of initializeParams.sourceImage or disks.source is required except for local SSD.\n\nIf desired, you can also attach existing non-root persistent disks using this property. This field is only applicable for persistent disks.\n\nNote that for sourceMachineImage, specify the disk name, not the URL for the disk.", + "type": "string" + }, + "storageBytes": { + "description": "[Output Only] A size of the storage used by the disk's snapshot.", + "format": "int64", + "type": "string" + }, + "storageBytesStatus": { + "description": "[Output Only] An indicator whether storageBytes is in a stable state or it is being adjusted as a result of shared storage reallocation. This status can either be UPDATING, meaning the size of the snapshot is being updated, or UP_TO_DATE, meaning the size of the snapshot is up-to-date.", + "enum": [ + "UPDATING", + "UP_TO_DATE" + ], + "enumDescriptions": [ + "", + "" + ], + "type": "string" + }, + "type": { + "description": "Specifies the type of the disk, either SCRATCH or PERSISTENT. If not specified, the default is PERSISTENT.", + "enum": [ + "PERSISTENT", + "SCRATCH" + ], + "enumDescriptions": [ + "", + "" + ], + "type": "string" + } + }, + "type": "object" + }, "Scheduling": { "description": "Sets the scheduling options for an Instance.", "id": "Scheduling", @@ -42276,6 +45284,11 @@ "description": "Specifies whether the instance should be automatically restarted if it is terminated by Compute Engine (not terminated by a user). You can only set the automatic restart option for standard instances. Preemptible instances cannot be automatically restarted.\n\nBy default, this is set to true so an instance is automatically restarted if it is terminated by Compute Engine.", "type": "boolean" }, + "minNodeCpus": { + "description": "The minimum number of virtual CPUs this instance will consume when running on a sole-tenant node.", + "format": "int32", + "type": "integer" + }, "nodeAffinities": { "description": "A set of node affinity and anti-affinity.", "items": { @@ -42353,9 +45366,16 @@ "type": "object" }, "SecurityPolicy": { - "description": "A security policy is comprised of one or more rules. It can also be associated with one or more 'targets'. Next available tag: 11", + "description": "A security policy is comprised of one or more rules. It can also be associated with one or more 'targets'. (== resource_for v1.securityPolicies ==) (== resource_for beta.securityPolicies ==)", "id": "SecurityPolicy", "properties": { + "associations": { + "description": "A list of assocations that belong to this policy.", + "items": { + "$ref": "SecurityPolicyAssociation" + }, + "type": "array" + }, "creationTimestamp": { "description": "[Output Only] Creation timestamp in RFC3339 text format.", "type": "string" @@ -42365,7 +45385,7 @@ "type": "string" }, "fingerprint": { - "description": "Specifies a fingerprint for this resource, which is essentially a hash of the metadata's contents and used for optimistic locking. The fingerprint is initially generated by Compute Engine and changes after every request to modify or update metadata. You must always provide an up-to-date fingerprint hash in order to update or change metadata.\n\nTo see the latest fingerprint, make get() request to the security policy.", + "description": "Specifies a fingerprint for this resource, which is essentially a hash of the metadata's contents and used for optimistic locking. The fingerprint is initially generated by Compute Engine and changes after every request to modify or update metadata. You must always provide an up-to-date fingerprint hash in order to update or change metadata, otherwise the request will fail with error 412 conditionNotMet.\n\nTo see the latest fingerprint, make get() request to the security policy.", "format": "byte", "type": "string" }, @@ -42406,6 +45426,32 @@ "selfLink": { "description": "[Output Only] Server-defined URL for the resource.", "type": "string" + }, + "type": { + "description": "The type indicates the intended use of the security policy. CLOUD_ARMOR policies apply to backend services. FIREWALL policies apply to organizations.", + "enum": [ + "CLOUD_ARMOR", + "FIREWALL" + ], + "enumDescriptions": [ + "", + "" + ], + "type": "string" + } + }, + "type": "object" + }, + "SecurityPolicyAssociation": { + "id": "SecurityPolicyAssociation", + "properties": { + "attachmentId": { + "description": "The resource that the security policy is attached to.", + "type": "string" + }, + "name": { + "description": "The name for an association.", + "type": "string" } }, "type": "object" @@ -42538,6 +45584,22 @@ "description": "An optional description of this resource. Provide this property when you create the resource.", "type": "string" }, + "direction": { + "description": "The direction in which this rule applies. This field may only be specified when versioned_expr is set to FIREWALL.", + "enum": [ + "EGRESS", + "INGRESS" + ], + "enumDescriptions": [ + "", + "" + ], + "type": "string" + }, + "enableLogging": { + "description": "Denotes whether to enable logging for a particular rule. If logging is enabled, logs will be exported to the configured export destination in Stackdriver. Logs may be exported to BigQuery or Pub/Sub. Note: you cannot enable logging on \"goto_next\" rules.\n\nThis field may only be specified when the versioned_expr is set to FIREWALL.", + "type": "boolean" + }, "kind": { "default": "compute#securityPolicyRule", "description": "[Output only] Type of the resource. Always compute#securityPolicyRule for security policy rules", @@ -42552,9 +45614,16 @@ "type": "boolean" }, "priority": { - "description": "An integer indicating the priority of a rule in the list. The priority must be a positive value between 0 and 2147483647. Rules are evaluated in the increasing order of priority.", + "description": "An integer indicating the priority of a rule in the list. The priority must be a positive value between 0 and 2147483647. Rules are evaluated from highest to lowest priority where 0 is the highest priority and 2147483647 is the lowest prority.", "format": "int32", "type": "integer" + }, + "targetResources": { + "description": "A list of network resource URLs to which this rule applies. This field allows you to control which network?s VMs get this rule. If this field is left blank, all VMs within the organization will receive the rule.\n\nThis field may only be specified when versioned_expr is set to FIREWALL.", + "items": { + "type": "string" + }, + "type": "array" } }, "type": "object" @@ -42571,18 +45640,11 @@ "$ref": "Expr", "description": "User defined CEVAL expression. A CEVAL expression is used to specify match criteria such as origin.ip, source.region_code and contents in the request header." }, - "srcIpRanges": { - "description": "CIDR IP address range.", - "items": { - "type": "string" - }, - "type": "array" - }, "versionedExpr": { "description": "Preconfigured versioned expression. If this field is specified, config must also be specified. Available preconfigured expressions along with their requirements are: SRC_IPS_V1 - must specify the corresponding src_ip_range field in config.", "enum": [ - "SRC_IPS_V1", - "VERSIONED_EXPR_UNSPECIFIED" + "FIREWALL", + "SRC_IPS_V1" ], "enumDescriptions": [ "", @@ -42596,6 +45658,20 @@ "SecurityPolicyRuleMatcherConfig": { "id": "SecurityPolicyRuleMatcherConfig", "properties": { + "destIpRanges": { + "description": "CIDR IP address range.\n\nThis field may only be specified when versioned_expr is set to FIREWALL.", + "items": { + "type": "string" + }, + "type": "array" + }, + "destPorts": { + "description": "Pairs of IP protocols and ports that the rule should match.\n\nThis field may only be specified when versioned_expr is set to FIREWALL.", + "items": { + "$ref": "SecurityPolicyRuleMatcherConfigDestinationPort" + }, + "type": "array" + }, "srcIpRanges": { "description": "CIDR IP address range.", "items": { @@ -42606,6 +45682,23 @@ }, "type": "object" }, + "SecurityPolicyRuleMatcherConfigDestinationPort": { + "id": "SecurityPolicyRuleMatcherConfigDestinationPort", + "properties": { + "ipProtocol": { + "description": "The IP protocol to which this rule applies. The protocol type is required when creating a firewall rule. This value can either be one of the following well known protocol strings (tcp, udp, icmp, esp, ah, ipip, sctp), or the IP protocol number.", + "type": "string" + }, + "ports": { + "description": "An optional list of ports to which this rule applies. This field is only applicable for UDP or TCP protocol. Each entry must be either an integer or a range. If not specified, this rule applies to connections through any port.\n\nExample inputs include: [\"22\"], [\"80\",\"443\"], and [\"12345-12349\"].\n\nThis field may only be specified when versioned_expr is set to FIREWALL.", + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object" + }, "SerialPortOutput": { "description": "An instance's serial console output.", "id": "SerialPortOutput", @@ -42636,6 +45729,25 @@ }, "type": "object" }, + "ServerBinding": { + "id": "ServerBinding", + "properties": { + "type": { + "enum": [ + "RESTART_NODE_ON_ANY_SERVER", + "RESTART_NODE_ON_MINIMAL_SERVERS", + "SERVER_BINDING_TYPE_UNSPECIFIED" + ], + "enumDescriptions": [ + "", + "", + "" + ], + "type": "string" + } + }, + "type": "object" + }, "ServiceAccount": { "description": "A service account.", "id": "ServiceAccount", @@ -42659,26 +45771,61 @@ "id": "ShieldedVmConfig", "properties": { "enableIntegrityMonitoring": { - "description": "Defines whether the instance should have integrity monitoring enabled.", + "description": "Defines whether the instance has integrity monitoring enabled.", "type": "boolean" }, "enableSecureBoot": { - "description": "Defines whether the instance should have secure boot enabled.", + "description": "Defines whether the instance has Secure Boot enabled.", "type": "boolean" }, "enableVtpm": { - "description": "Defines whether the instance should have the TPM enabled.", + "description": "Defines whether the instance has the vTPM enabled.", "type": "boolean" } }, "type": "object" }, + "ShieldedVmIdentity": { + "description": "A shielded VM identity entry.", + "id": "ShieldedVmIdentity", + "properties": { + "encryptionKey": { + "$ref": "ShieldedVmIdentityEntry", + "description": "An Endorsement Key (EK) issued to the Shielded VM's vTPM." + }, + "kind": { + "default": "compute#shieldedVmIdentity", + "description": "[Output Only] Type of the resource. Always compute#shieldedVmIdentity for shielded VM identity entry.", + "type": "string" + }, + "signingKey": { + "$ref": "ShieldedVmIdentityEntry", + "description": "An Attestation Key (AK) issued to the Shielded VM's vTPM." + } + }, + "type": "object" + }, + "ShieldedVmIdentityEntry": { + "description": "A Shielded VM Identity Entry.", + "id": "ShieldedVmIdentityEntry", + "properties": { + "ekCert": { + "description": "A PEM-encoded X.509 certificate. This field can be empty.", + "type": "string" + }, + "ekPub": { + "description": "A PEM-encoded public key.", + "type": "string" + } + }, + "type": "object" + }, "ShieldedVmIntegrityPolicy": { - "description": "The policy describes how boot integrity measurements are evaluated.", + "description": "The policy describes the baseline against which VM instance boot integrity is measured.", "id": "ShieldedVmIntegrityPolicy", "properties": { "updateAutoLearnPolicy": { - "description": "Triggers an auto relearn event: the integrity monitoring module copies existing guest measurements to the baseline.", + "description": "Updates the integrity policy baseline using the measurements from the VM instance's most recent boot.", "type": "boolean" } }, @@ -42705,7 +45852,7 @@ "id": "Snapshot", "properties": { "autoCreated": { - "description": "[Output Only] Set to true if snapshots are autoamtically by applying resource policy on the target disk.", + "description": "[Output Only] Set to true if snapshots are automatically by applying resource policy on the target disk.", "type": "boolean" }, "creationTimestamp": { @@ -42739,7 +45886,7 @@ "type": "string" }, "labelFingerprint": { - "description": "A fingerprint for the labels being applied to this snapshot, which is essentially a hash of the labels set used for optimistic locking. The fingerprint is initially generated by Compute Engine and changes after every request to modify or update labels. You must always provide an up-to-date fingerprint hash in order to update or change labels.\n\nTo see the latest fingerprint, make a get() request to retrieve a snapshot.", + "description": "A fingerprint for the labels being applied to this snapshot, which is essentially a hash of the labels set used for optimistic locking. The fingerprint is initially generated by Compute Engine and changes after every request to modify or update labels. You must always provide an up-to-date fingerprint hash in order to update or change labels, otherwise the request will fail with error 412 conditionNotMet.\n\nTo see the latest fingerprint, make a get() request to retrieve a snapshot.", "format": "byte", "type": "string" }, @@ -42961,6 +46108,85 @@ }, "type": "object" }, + "SourceInstanceProperties": { + "description": "", + "id": "SourceInstanceProperties", + "properties": { + "canIpForward": { + "description": "Enables instances created based on this machine image to send packets with source IP addresses other than their own and receive packets with destination IP addresses other than their own. If these instances will be used as an IP gateway or it will be set as the next-hop in a Route resource, specify true. If unsure, leave this set to false. See the Enable IP forwarding documentation for more information.", + "type": "boolean" + }, + "deletionProtection": { + "description": "Whether the instance created from the machine image should be protected against deletion.", + "type": "boolean" + }, + "description": { + "description": "An optional text description for the instances that are created from this machine image.", + "type": "string" + }, + "disks": { + "description": "An array of disks that are associated with the instances that are created from this machine image.", + "items": { + "$ref": "SavedAttachedDisk" + }, + "type": "array" + }, + "guestAccelerators": { + "description": "A list of guest accelerator cards' type and count to use for instances created from the machine image.", + "items": { + "$ref": "AcceleratorConfig" + }, + "type": "array" + }, + "labels": { + "additionalProperties": { + "type": "string" + }, + "description": "Labels to apply to instances that are created from this machine image.", + "type": "object" + }, + "machineType": { + "annotations": { + "required": [ + "compute.machineImages.insert" + ] + }, + "description": "The machine type to use for instances that are created from this machine image.", + "type": "string" + }, + "metadata": { + "$ref": "Metadata", + "description": "The metadata key/value pairs to assign to instances that are created from this machine image. These pairs can consist of custom metadata or predefined keys. See Project and instance metadata for more information." + }, + "minCpuPlatform": { + "description": "Minimum cpu/platform to be used by this instance. The instance may be scheduled on the specified or newer cpu/platform. Applicable values are the friendly names of CPU platforms, such as minCpuPlatform: \"Intel Haswell\" or minCpuPlatform: \"Intel Sandy Bridge\". For more information, read Specifying a Minimum CPU Platform.", + "type": "string" + }, + "networkInterfaces": { + "description": "An array of network access configurations for this interface.", + "items": { + "$ref": "NetworkInterface" + }, + "type": "array" + }, + "scheduling": { + "$ref": "Scheduling", + "description": "Specifies the scheduling options for the instances that are created from this machine image." + }, + "serviceAccounts": { + "description": "A list of service accounts with specified scopes. Access tokens for these service accounts are available to the instances that are created from this machine image. Use metadata queries to obtain the access tokens for these instances.", + "items": { + "$ref": "ServiceAccount" + }, + "type": "array" + }, + "tags": { + "$ref": "Tags", + "description": "A list of tags to apply to the instances that are created from this machine image. The tags identify valid sources or targets for network firewalls. The setTags method can modify this list of tags. Each tag within the list must comply with RFC1035." + } + }, + "type": "object" + }, "SslCertificate": { "description": "An SslCertificate resource. This resource provides a mechanism to upload an SSL key and certificate to the load balancer to serve secure connections from the user. (== resource_for beta.sslCertificates ==) (== resource_for v1.sslCertificates ==)", "id": "SslCertificate", @@ -43004,6 +46230,10 @@ "description": "A write-only private key in PEM format. Only insert requests will include this field.", "type": "string" }, + "region": { + "description": "[Output Only] URL of the region where the regional SSL Certificate resides. This field is not applicable to global SSL Certificate.", + "type": "string" + }, "selfLink": { "description": "[Output only] Server-defined URL for the resource.", "type": "string" @@ -43036,6 +46266,118 @@ }, "type": "object" }, + "SslCertificateAggregatedList": { + "id": "SslCertificateAggregatedList", + "properties": { + "id": { + "description": "[Output Only] Unique identifier for the resource; defined by the server.", + "type": "string" + }, + "items": { + "additionalProperties": { + "$ref": "SslCertificatesScopedList", + "description": "Name of the scope containing this set of SslCertificates." + }, + "description": "A list of SslCertificatesScopedList resources.", + "type": "object" + }, + "kind": { + "default": "compute#sslCertificateAggregatedList", + "description": "[Output Only] Type of resource. Always compute#sslCertificateAggregatedList for lists of SSL Certificates.", + "type": "string" + }, + "nextPageToken": { + "description": "[Output Only] This token allows you to get the next page of results for list requests. If the number of results is larger than maxResults, use the nextPageToken as a value for the query parameter pageToken in the next list request. Subsequent list requests will have their own nextPageToken to continue paging through the results.", + "type": "string" + }, + "selfLink": { + "description": "[Output Only] Server-defined URL for this resource.", + "type": "string" + }, + "warning": { + "description": "[Output Only] Informational warning message.", + "properties": { + "code": { + "description": "[Output Only] A warning code, if applicable. For example, Compute Engine returns NO_RESULTS_ON_PAGE if there are no results in the response.", + "enum": [ + "CLEANUP_FAILED", + "DEPRECATED_RESOURCE_USED", + "DEPRECATED_TYPE_USED", + "DISK_SIZE_LARGER_THAN_IMAGE_SIZE", + "EXPERIMENTAL_TYPE_USED", + "EXTERNAL_API_WARNING", + "FIELD_VALUE_OVERRIDEN", + "INJECTED_KERNELS_DEPRECATED", + "MISSING_TYPE_DEPENDENCY", + "NEXT_HOP_ADDRESS_NOT_ASSIGNED", + "NEXT_HOP_CANNOT_IP_FORWARD", + "NEXT_HOP_INSTANCE_NOT_FOUND", + "NEXT_HOP_INSTANCE_NOT_ON_NETWORK", + "NEXT_HOP_NOT_RUNNING", + "NOT_CRITICAL_ERROR", + "NO_RESULTS_ON_PAGE", + "REQUIRED_TOS_AGREEMENT", + "RESOURCE_IN_USE_BY_OTHER_RESOURCE_WARNING", + "RESOURCE_NOT_DELETED", + "SCHEMA_VALIDATION_IGNORED", + "SINGLE_INSTANCE_PROPERTY_TEMPLATE", + "UNDECLARED_PROPERTIES", + "UNREACHABLE" + ], + "enumDescriptions": [ + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "" + ], + "type": "string" + }, + "data": { + "description": "[Output Only] Metadata about this warning in key: value format. For example:\n\"data\": [ { \"key\": \"scope\", \"value\": \"zones/us-east1-d\" }", + "items": { + "properties": { + "key": { + "description": "[Output Only] A key that provides more detail on the warning being returned. For example, for warnings where there are no results in a list request for a particular zone, this key might be scope and the key value might be the zone name. Other examples might be a key indicating a deprecated resource and a suggested replacement, or a warning about invalid network settings (for example, if an instance attempts to perform IP forwarding but is not enabled for IP forwarding).", + "type": "string" + }, + "value": { + "description": "[Output Only] A warning data value corresponding to the key.", + "type": "string" + } + }, + "type": "object" + }, + "type": "array" + }, + "message": { + "description": "[Output Only] A human-readable description of the warning code.", + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object" + }, "SslCertificateList": { "description": "Contains a list of SslCertificate resources.", "id": "SslCertificateList", @@ -43157,6 +46499,7 @@ "enum": [ "ACTIVE", "DOMAIN_STATUS_UNSPECIFIED", + "FAILED_CAA_CHECKING", "FAILED_CAA_FORBIDDEN", "FAILED_NOT_VISIBLE", "FAILED_RATE_LIMITED", @@ -43168,6 +46511,7 @@ "", "", "", + "", "" ], "type": "string" @@ -43220,6 +46564,100 @@ }, "type": "object" }, + "SslCertificatesScopedList": { + "id": "SslCertificatesScopedList", + "properties": { + "sslCertificates": { + "description": "List of SslCertificates contained in this scope.", + "items": { + "$ref": "SslCertificate" + }, + "type": "array" + }, + "warning": { + "description": "Informational warning which replaces the list of backend services when the list is empty.", + "properties": { + "code": { + "description": "[Output Only] A warning code, if applicable. For example, Compute Engine returns NO_RESULTS_ON_PAGE if there are no results in the response.", + "enum": [ + "CLEANUP_FAILED", + "DEPRECATED_RESOURCE_USED", + "DEPRECATED_TYPE_USED", + "DISK_SIZE_LARGER_THAN_IMAGE_SIZE", + "EXPERIMENTAL_TYPE_USED", + "EXTERNAL_API_WARNING", + "FIELD_VALUE_OVERRIDEN", + "INJECTED_KERNELS_DEPRECATED", + "MISSING_TYPE_DEPENDENCY", + "NEXT_HOP_ADDRESS_NOT_ASSIGNED", + "NEXT_HOP_CANNOT_IP_FORWARD", + "NEXT_HOP_INSTANCE_NOT_FOUND", + "NEXT_HOP_INSTANCE_NOT_ON_NETWORK", + "NEXT_HOP_NOT_RUNNING", + "NOT_CRITICAL_ERROR", + "NO_RESULTS_ON_PAGE", + "REQUIRED_TOS_AGREEMENT", + "RESOURCE_IN_USE_BY_OTHER_RESOURCE_WARNING", + "RESOURCE_NOT_DELETED", + "SCHEMA_VALIDATION_IGNORED", + "SINGLE_INSTANCE_PROPERTY_TEMPLATE", + "UNDECLARED_PROPERTIES", + "UNREACHABLE" + ], + "enumDescriptions": [ + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "" + ], + "type": "string" + }, + "data": { + "description": "[Output Only] Metadata about this warning in key: value format. For example:\n\"data\": [ { \"key\": \"scope\", \"value\": \"zones/us-east1-d\" }", + "items": { + "properties": { + "key": { + "description": "[Output Only] A key that provides more detail on the warning being returned. For example, for warnings where there are no results in a list request for a particular zone, this key might be scope and the key value might be the zone name. Other examples might be a key indicating a deprecated resource and a suggested replacement, or a warning about invalid network settings (for example, if an instance attempts to perform IP forwarding but is not enabled for IP forwarding).", + "type": "string" + }, + "value": { + "description": "[Output Only] A warning data value corresponding to the key.", + "type": "string" + } + }, + "type": "object" + }, + "type": "array" + }, + "message": { + "description": "[Output Only] A human-readable description of the warning code.", + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object" + }, "SslPoliciesList": { "id": "SslPoliciesList", "properties": { @@ -43370,7 +46808,7 @@ "type": "array" }, "fingerprint": { - "description": "Fingerprint of this resource. A hash of the contents stored in this object. This field is used in optimistic locking. This field will be ignored when inserting a SslPolicy. An up-to-date fingerprint must be provided in order to update the SslPolicy.", + "description": "Fingerprint of this resource. A hash of the contents stored in this object. This field is used in optimistic locking. This field will be ignored when inserting a SslPolicy. An up-to-date fingerprint must be provided in order to update the SslPolicy, otherwise the request will fail with error 412 conditionNotMet.\n\nTo see the latest fingerprint, make a get() request to retrieve an SslPolicy.", "format": "byte", "type": "string" }, @@ -43525,6 +46963,9 @@ "properties": { "preservedResources": { "$ref": "StatefulPolicyPreservedResources" + }, + "preservedState": { + "$ref": "StatefulPolicyPreservedState" } }, "type": "object" @@ -43553,10 +46994,62 @@ }, "type": "object" }, + "StatefulPolicyPreservedState": { + "description": "Configuration of preserved resources.", + "id": "StatefulPolicyPreservedState", + "properties": { + "disks": { + "additionalProperties": { + "$ref": "StatefulPolicyPreservedStateDiskDevice" + }, + "description": "Disks created on the instances that will be preserved on instance delete, resize down, etc. This map is keyed with the device names of the disks.", + "type": "object" + } + }, + "type": "object" + }, + "StatefulPolicyPreservedStateDiskDevice": { + "id": "StatefulPolicyPreservedStateDiskDevice", + "properties": { + "autoDelete": { + "description": "These stateful disks will never be deleted during autohealing, update or VM instance recreate operations. This flag is used to configure if the disk should be deleted after it is no longer used by the group, e.g. when the given instance or the whole group is deleted. Note: disks attached in READ_ONLY mode cannot be auto-deleted.", + "enum": [ + "NEVER", + "WHEN_NOT_IN_USE" + ], + "enumDescriptions": [ + "", + "" + ], + "type": "string" + } + }, + "type": "object" + }, "Subnetwork": { "description": "A Subnetwork resource. (== resource_for beta.subnetworks ==) (== resource_for v1.subnetworks ==)", "id": "Subnetwork", "properties": { + "aggregationInterval": { + "description": "Can only be specified if VPC flow logging for this subnetwork is enabled. Toggles the aggregation interval for collecting flow logs. Increasing the interval time will reduce the amount of generated flow logs for long lasting connections. Default is an interval of 5 seconds per connection.", + "enum": [ + "INTERVAL_10_MIN", + "INTERVAL_15_MIN", + "INTERVAL_1_MIN", + "INTERVAL_30_SEC", + "INTERVAL_5_MIN", + "INTERVAL_5_SEC" + ], + "enumDescriptions": [ + "", + "", + "", + "", + "", + "" + ], + "type": "string" + }, "allowSubnetCidrRoutesOverlap": { "description": "Whether this subnetwork can conflict with static routes. Setting this to true allows this subnetwork's primary and secondary ranges to conflict with routes that have already been configured on the corresponding network. Static routes will take precedence over the subnetwork route if the route prefix length is at least as large as the subnetwork prefix length.\n\nAlso, packets destined to IPs within subnetwork may contain private/sensitive data and are prevented from leaving the virtual network. Setting this field to true will disable this feature.\n\nThe default value is false and applies to all existing subnetworks and automatically created subnetworks.\n\nThis field cannot be set to true at resource creation time.", "type": "boolean" @@ -43570,7 +47063,7 @@ "type": "string" }, "enableFlowLogs": { - "description": "Whether to enable flow logging for this subnetwork.", + "description": "Whether to enable flow logging for this subnetwork. If this field is not explicitly set, it will not appear in get listings. If not set the default behavior is to disable flow logging.", "type": "boolean" }, "enablePrivateV6Access": { @@ -43578,10 +47071,15 @@ "type": "boolean" }, "fingerprint": { - "description": "Fingerprint of this resource. A hash of the contents stored in this object. This field is used in optimistic locking. This field will be ignored when inserting a Subnetwork. An up-to-date fingerprint must be provided in order to update the Subnetwork.", + "description": "Fingerprint of this resource. A hash of the contents stored in this object. This field is used in optimistic locking. This field will be ignored when inserting a Subnetwork. An up-to-date fingerprint must be provided in order to update the Subnetwork, otherwise the request will fail with error 412 conditionNotMet.\n\nTo see the latest fingerprint, make a get() request to retrieve a Subnetwork.", "format": "byte", "type": "string" }, + "flowSampling": { + "description": "Can only be specified if VPC flow logging for this subnetwork is enabled. The value of the field must be in [0, 1]. Set the sampling rate of VPC flow logs within the subnetwork where 1.0 means all collected logs are reported and 0.0 means no logs are reported. Default is 0.5 which means half of all collected logs are reported.", + "format": "float", + "type": "number" + }, "gatewayAddress": { "description": "[Output Only] The gateway address for default routes to reach destination addresses outside this subnetwork.", "type": "string" @@ -43604,6 +47102,22 @@ "description": "[Output Only] Type of the resource. Always compute#subnetwork for Subnetwork resources.", "type": "string" }, + "logConfig": { + "$ref": "SubnetworkLogConfig", + "description": "This field denotes the logging options for the load balancer traffic served by this backend service. If logging is enabled, logs will be exported to Stackdriver." + }, + "metadata": { + "description": "Can only be specified if VPC flow logging for this subnetwork is enabled. Configures whether metadata fields should be added to the reported VPC flow logs. Default is INCLUDE_ALL_METADATA.", + "enum": [ + "EXCLUDE_ALL_METADATA", + "INCLUDE_ALL_METADATA" + ], + "enumDescriptions": [ + "", + "" + ], + "type": "string" + }, "name": { "description": "The name of the resource, provided by the client when initially creating the resource. The name must be 1-63 characters long, and comply with RFC1035. Specifically, the name must be 1-63 characters long and match the regular expression `[a-z]([-a-z0-9]*[a-z0-9])?` which means the first character must be a lowercase letter, and all following characters must be a dash, lowercase letter, or digit, except the last character, which cannot be a dash.", "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", @@ -43621,9 +47135,11 @@ "description": "The purpose of the resource. This field can be either PRIVATE_RFC_1918 or INTERNAL_HTTPS_LOAD_BALANCER. A subnetwork with purpose set to INTERNAL_HTTPS_LOAD_BALANCER is a user-created subnetwork that is reserved for Internal HTTP(S) Load Balancing. If unspecified, the purpose defaults to PRIVATE_RFC_1918.", "enum": [ "INTERNAL_HTTPS_LOAD_BALANCER", + "PRIVATE", "PRIVATE_RFC_1918" ], "enumDescriptions": [ + "", "", "" ], @@ -43634,7 +47150,7 @@ "type": "string" }, "role": { - "description": "The role of subnetwork. Currenly, this field is only used when purpose = INTERNAL_HTTPS_LOAD_BALANCER. The value can be set to ACTIVE or BACKUP. An ACTIVE subnetwork is one that is currently being used for Internal HTTP(S) Load Balancing. A BACKUP subnetwork is one that is ready to be promoted to ACTIVE or is currently draining.", + "description": "The role of subnetwork. Currenly, this field is only used when purpose = INTERNAL_HTTPS_LOAD_BALANCER. The value can be set to ACTIVE or BACKUP. An ACTIVE subnetwork is one that is currently being used for Internal HTTP(S) Load Balancing. A BACKUP subnetwork is one that is ready to be promoted to ACTIVE or is currently draining. This field can be updated with a patch request.", "enum": [ "ACTIVE", "BACKUP" @@ -43646,7 +47162,7 @@ "type": "string" }, "secondaryIpRanges": { - "description": "An array of configurations for secondary IP ranges for VM instances contained in this subnetwork. The primary IP of such VM must belong to the primary ipCidrRange of the subnetwork. The alias IPs may belong to either primary or secondary ranges.", + "description": "An array of configurations for secondary IP ranges for VM instances contained in this subnetwork. The primary IP of such VM must belong to the primary ipCidrRange of the subnetwork. The alias IPs may belong to either primary or secondary ranges. This field can be updated with a patch request.", "items": { "$ref": "SubnetworkSecondaryRange" }, @@ -43655,6 +47171,18 @@ "selfLink": { "description": "[Output Only] Server-defined URL for the resource.", "type": "string" + }, + "state": { + "description": "[Output Only] The state of the subnetwork, which can be one of READY or DRAINING. A subnetwork that is READY is ready to be used. The state of DRAINING is only applicable to subnetworks that have the purpose set to INTERNAL_HTTPS_LOAD_BALANCER and indicates that connections to the load balancer are being drained. A subnetwork that is draining cannot be used or modified until it reaches a status of READY.", + "enum": [ + "DRAINING", + "READY" + ], + "enumDescriptions": [ + "", + "" + ], + "type": "string" } }, "type": "object" @@ -43883,6 +47411,54 @@ }, "type": "object" }, + "SubnetworkLogConfig": { + "description": "The available logging options for this subnetwork.", + "id": "SubnetworkLogConfig", + "properties": { + "aggregationInterval": { + "description": "Can only be specified if VPC flow logging for this subnetwork is enabled. Toggles the aggregation interval for collecting flow logs. Increasing the interval time will reduce the amount of generated flow logs for long lasting connections. Default is an interval of 5 seconds per connection.", + "enum": [ + "INTERVAL_10_MIN", + "INTERVAL_15_MIN", + "INTERVAL_1_MIN", + "INTERVAL_30_SEC", + "INTERVAL_5_MIN", + "INTERVAL_5_SEC" + ], + "enumDescriptions": [ + "", + "", + "", + "", + "", + "" + ], + "type": "string" + }, + "enable": { + "description": "Whether to enable flow logging for this subnetwork. If this field is not explicitly set, it will not appear in get listings. If not set the default behavior is to disable flow logging.", + "type": "boolean" + }, + "flowSampling": { + "description": "Can only be specified if VPC flow logging for this subnetwork is enabled. The value of the field must be in [0, 1]. Set the sampling rate of VPC flow logs within the subnetwork where 1.0 means all collected logs are reported and 0.0 means no logs are reported. Default is 0.5 which means half of all collected logs are reported.", + "format": "float", + "type": "number" + }, + "metadata": { + "description": "Can only be specified if VPC flow logging for this subnetwork is enabled. Configures whether metadata fields should be added to the reported VPC flow logs. Default is INCLUDE_ALL_METADATA.", + "enum": [ + "EXCLUDE_ALL_METADATA", + "INCLUDE_ALL_METADATA" + ], + "enumDescriptions": [ + "", + "" + ], + "type": "string" + } + }, + "type": "object" + }, "SubnetworkSecondaryRange": { "description": "Represents a secondary IP range of a subnetwork.", "id": "SubnetworkSecondaryRange", @@ -44439,6 +48015,100 @@ }, "type": "object" }, + "TargetHttpsProxiesScopedList": { + "id": "TargetHttpsProxiesScopedList", + "properties": { + "targetHttpsProxies": { + "description": "A list of TargetHttpsProxies contained in this scope.", + "items": { + "$ref": "TargetHttpsProxy" + }, + "type": "array" + }, + "warning": { + "description": "Informational warning which replaces the list of backend services when the list is empty.", + "properties": { + "code": { + "description": "[Output Only] A warning code, if applicable. For example, Compute Engine returns NO_RESULTS_ON_PAGE if there are no results in the response.", + "enum": [ + "CLEANUP_FAILED", + "DEPRECATED_RESOURCE_USED", + "DEPRECATED_TYPE_USED", + "DISK_SIZE_LARGER_THAN_IMAGE_SIZE", + "EXPERIMENTAL_TYPE_USED", + "EXTERNAL_API_WARNING", + "FIELD_VALUE_OVERRIDEN", + "INJECTED_KERNELS_DEPRECATED", + "MISSING_TYPE_DEPENDENCY", + "NEXT_HOP_ADDRESS_NOT_ASSIGNED", + "NEXT_HOP_CANNOT_IP_FORWARD", + "NEXT_HOP_INSTANCE_NOT_FOUND", + "NEXT_HOP_INSTANCE_NOT_ON_NETWORK", + "NEXT_HOP_NOT_RUNNING", + "NOT_CRITICAL_ERROR", + "NO_RESULTS_ON_PAGE", + "REQUIRED_TOS_AGREEMENT", + "RESOURCE_IN_USE_BY_OTHER_RESOURCE_WARNING", + "RESOURCE_NOT_DELETED", + "SCHEMA_VALIDATION_IGNORED", + "SINGLE_INSTANCE_PROPERTY_TEMPLATE", + "UNDECLARED_PROPERTIES", + "UNREACHABLE" + ], + "enumDescriptions": [ + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "" + ], + "type": "string" + }, + "data": { + "description": "[Output Only] Metadata about this warning in key: value format. For example:\n\"data\": [ { \"key\": \"scope\", \"value\": \"zones/us-east1-d\" }", + "items": { + "properties": { + "key": { + "description": "[Output Only] A key that provides more detail on the warning being returned. For example, for warnings where there are no results in a list request for a particular zone, this key might be scope and the key value might be the zone name. Other examples might be a key indicating a deprecated resource and a suggested replacement, or a warning about invalid network settings (for example, if an instance attempts to perform IP forwarding but is not enabled for IP forwarding).", + "type": "string" + }, + "value": { + "description": "[Output Only] A warning data value corresponding to the key.", + "type": "string" + } + }, + "type": "object" + }, + "type": "array" + }, + "message": { + "description": "[Output Only] A human-readable description of the warning code.", + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object" + }, "TargetHttpsProxiesSetQuicOverrideRequest": { "id": "TargetHttpsProxiesSetQuicOverrideRequest", "properties": { @@ -44513,12 +48183,16 @@ ], "type": "string" }, + "region": { + "description": "[Output Only] URL of the region where the regional TargetHttpsProxy resides. This field is not applicable to global TargetHttpsProxies.", + "type": "string" + }, "selfLink": { "description": "[Output Only] Server-defined URL for the resource.", "type": "string" }, "sslCertificates": { - "description": "URLs to SslCertificate resources that are used to authenticate connections between users and the load balancer. Currently, exactly one SSL certificate must be specified.", + "description": "URLs to SslCertificate resources that are used to authenticate connections between users and the load balancer. At least one SSL certificate must be specified. Currently, you may specify up to 15 SSL certificates.", "items": { "type": "string" }, @@ -44535,6 +48209,118 @@ }, "type": "object" }, + "TargetHttpsProxyAggregatedList": { + "id": "TargetHttpsProxyAggregatedList", + "properties": { + "id": { + "description": "[Output Only] Unique identifier for the resource; defined by the server.", + "type": "string" + }, + "items": { + "additionalProperties": { + "$ref": "TargetHttpsProxiesScopedList", + "description": "Name of the scope containing this set of TargetHttpsProxies." + }, + "description": "A list of TargetHttpsProxiesScopedList resources.", + "type": "object" + }, + "kind": { + "default": "compute#targetHttpsProxyAggregatedList", + "description": "[Output Only] Type of resource. Always compute#targetHttpsProxyAggregatedList for lists of Target HTTP Proxies.", + "type": "string" + }, + "nextPageToken": { + "description": "[Output Only] This token allows you to get the next page of results for list requests. If the number of results is larger than maxResults, use the nextPageToken as a value for the query parameter pageToken in the next list request. Subsequent list requests will have their own nextPageToken to continue paging through the results.", + "type": "string" + }, + "selfLink": { + "description": "[Output Only] Server-defined URL for this resource.", + "type": "string" + }, + "warning": { + "description": "[Output Only] Informational warning message.", + "properties": { + "code": { + "description": "[Output Only] A warning code, if applicable. For example, Compute Engine returns NO_RESULTS_ON_PAGE if there are no results in the response.", + "enum": [ + "CLEANUP_FAILED", + "DEPRECATED_RESOURCE_USED", + "DEPRECATED_TYPE_USED", + "DISK_SIZE_LARGER_THAN_IMAGE_SIZE", + "EXPERIMENTAL_TYPE_USED", + "EXTERNAL_API_WARNING", + "FIELD_VALUE_OVERRIDEN", + "INJECTED_KERNELS_DEPRECATED", + "MISSING_TYPE_DEPENDENCY", + "NEXT_HOP_ADDRESS_NOT_ASSIGNED", + "NEXT_HOP_CANNOT_IP_FORWARD", + "NEXT_HOP_INSTANCE_NOT_FOUND", + "NEXT_HOP_INSTANCE_NOT_ON_NETWORK", + "NEXT_HOP_NOT_RUNNING", + "NOT_CRITICAL_ERROR", + "NO_RESULTS_ON_PAGE", + "REQUIRED_TOS_AGREEMENT", + "RESOURCE_IN_USE_BY_OTHER_RESOURCE_WARNING", + "RESOURCE_NOT_DELETED", + "SCHEMA_VALIDATION_IGNORED", + "SINGLE_INSTANCE_PROPERTY_TEMPLATE", + "UNDECLARED_PROPERTIES", + "UNREACHABLE" + ], + "enumDescriptions": [ + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "" + ], + "type": "string" + }, + "data": { + "description": "[Output Only] Metadata about this warning in key: value format. For example:\n\"data\": [ { \"key\": \"scope\", \"value\": \"zones/us-east1-d\" }", + "items": { + "properties": { + "key": { + "description": "[Output Only] A key that provides more detail on the warning being returned. For example, for warnings where there are no results in a list request for a particular zone, this key might be scope and the key value might be the zone name. Other examples might be a key indicating a deprecated resource and a suggested replacement, or a warning about invalid network settings (for example, if an instance attempts to perform IP forwarding but is not enabled for IP forwarding).", + "type": "string" + }, + "value": { + "description": "[Output Only] A warning data value corresponding to the key.", + "type": "string" + } + }, + "type": "object" + }, + "type": "array" + }, + "message": { + "description": "[Output Only] A human-readable description of the warning code.", + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object" + }, "TargetHttpsProxyList": { "description": "Contains a list of TargetHttpsProxy resources.", "id": "TargetHttpsProxyList", @@ -45076,7 +48862,7 @@ "type": "string" }, "sessionAffinity": { - "description": "Sesssion affinity option, must be one of the following values:\nNONE: Connections from the same client IP may go to any instance in the pool.\nCLIENT_IP: Connections from the same client IP will go to the same instance in the pool while that instance remains healthy.\nCLIENT_IP_PROTO: Connections from the same client IP with the same IP protocol will go to the same instance in the pool while that instance remains healthy.", + "description": "Session affinity option, must be one of the following values:\nNONE: Connections from the same client IP may go to any instance in the pool.\nCLIENT_IP: Connections from the same client IP will go to the same instance in the pool while that instance remains healthy.\nCLIENT_IP_PROTO: Connections from the same client IP with the same IP protocol will go to the same instance in the pool while that instance remains healthy.", "enum": [ "CLIENT_IP", "CLIENT_IP_PORT_PROTO", @@ -45581,7 +49367,7 @@ "type": "string" }, "sslCertificates": { - "description": "URLs to SslCertificate resources that are used to authenticate connections to Backends. Currently exactly one SSL certificate must be specified.", + "description": "URLs to SslCertificate resources that are used to authenticate connections to Backends. At least one SSL certificate must be specified. Currently, you may specify up to 15 SSL certificates.", "items": { "type": "string" }, @@ -45926,7 +49712,7 @@ "type": "string" }, "labelFingerprint": { - "description": "A fingerprint for the labels being applied to this TargetVpnGateway, which is essentially a hash of the labels set used for optimistic locking. The fingerprint is initially generated by Compute Engine and changes after every request to modify or update labels. You must always provide an up-to-date fingerprint hash in order to update or change labels.\n\nTo see the latest fingerprint, make a get() request to retrieve an TargetVpnGateway.", + "description": "A fingerprint for the labels being applied to this TargetVpnGateway, which is essentially a hash of the labels set used for optimistic locking. The fingerprint is initially generated by Compute Engine and changes after every request to modify or update labels. You must always provide an up-to-date fingerprint hash in order to update or change labels, otherwise the request will fail with error 412 conditionNotMet.\n\nTo see the latest fingerprint, make a get() request to retrieve a TargetVpnGateway.", "format": "byte", "type": "string" }, @@ -46384,7 +50170,7 @@ "type": "string" }, "defaultService": { - "description": "The URL of the BackendService resource if none of the hostRules match.", + "description": "The URL of the backendService resource if none of the hostRules match.\nUse defaultService instead of defaultRouteAction when simple routing to a backendService is desired and other advanced capabilities like traffic splitting and rewrites are not required.\nOnly one of defaultService, defaultRouteAction or defaultUrlRedirect should must be set.", "type": "string" }, "description": { @@ -46392,7 +50178,7 @@ "type": "string" }, "fingerprint": { - "description": "Fingerprint of this resource. A hash of the contents stored in this object. This field is used in optimistic locking. This field will be ignored when inserting a UrlMap. An up-to-date fingerprint must be provided in order to update the UrlMap.", + "description": "Fingerprint of this resource. A hash of the contents stored in this object. This field is used in optimistic locking. This field will be ignored when inserting a UrlMap. An up-to-date fingerprint must be provided in order to update the UrlMap, otherwise the request will fail with error 412 conditionNotMet.\n\nTo see the latest fingerprint, make a get() request to retrieve a UrlMap.", "format": "byte", "type": "string" }, @@ -46614,6 +50400,212 @@ }, "type": "object" }, + "UrlMapsAggregatedList": { + "id": "UrlMapsAggregatedList", + "properties": { + "id": { + "description": "[Output Only] Unique identifier for the resource; defined by the server.", + "type": "string" + }, + "items": { + "additionalProperties": { + "$ref": "UrlMapsScopedList", + "description": "Name of the scope containing this set of UrlMaps." + }, + "description": "A list of UrlMapsScopedList resources.", + "type": "object" + }, + "kind": { + "default": "compute#urlMapsAggregatedList", + "description": "Type of resource.", + "type": "string" + }, + "nextPageToken": { + "description": "[Output Only] This token allows you to get the next page of results for list requests. If the number of results is larger than maxResults, use the nextPageToken as a value for the query parameter pageToken in the next list request. Subsequent list requests will have their own nextPageToken to continue paging through the results.", + "type": "string" + }, + "selfLink": { + "description": "[Output Only] Server-defined URL for this resource.", + "type": "string" + }, + "warning": { + "description": "[Output Only] Informational warning message.", + "properties": { + "code": { + "description": "[Output Only] A warning code, if applicable. For example, Compute Engine returns NO_RESULTS_ON_PAGE if there are no results in the response.", + "enum": [ + "CLEANUP_FAILED", + "DEPRECATED_RESOURCE_USED", + "DEPRECATED_TYPE_USED", + "DISK_SIZE_LARGER_THAN_IMAGE_SIZE", + "EXPERIMENTAL_TYPE_USED", + "EXTERNAL_API_WARNING", + "FIELD_VALUE_OVERRIDEN", + "INJECTED_KERNELS_DEPRECATED", + "MISSING_TYPE_DEPENDENCY", + "NEXT_HOP_ADDRESS_NOT_ASSIGNED", + "NEXT_HOP_CANNOT_IP_FORWARD", + "NEXT_HOP_INSTANCE_NOT_FOUND", + "NEXT_HOP_INSTANCE_NOT_ON_NETWORK", + "NEXT_HOP_NOT_RUNNING", + "NOT_CRITICAL_ERROR", + "NO_RESULTS_ON_PAGE", + "REQUIRED_TOS_AGREEMENT", + "RESOURCE_IN_USE_BY_OTHER_RESOURCE_WARNING", + "RESOURCE_NOT_DELETED", + "SCHEMA_VALIDATION_IGNORED", + "SINGLE_INSTANCE_PROPERTY_TEMPLATE", + "UNDECLARED_PROPERTIES", + "UNREACHABLE" + ], + "enumDescriptions": [ + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "" + ], + "type": "string" + }, + "data": { + "description": "[Output Only] Metadata about this warning in key: value format. For example:\n\"data\": [ { \"key\": \"scope\", \"value\": \"zones/us-east1-d\" }", + "items": { + "properties": { + "key": { + "description": "[Output Only] A key that provides more detail on the warning being returned. For example, for warnings where there are no results in a list request for a particular zone, this key might be scope and the key value might be the zone name. Other examples might be a key indicating a deprecated resource and a suggested replacement, or a warning about invalid network settings (for example, if an instance attempts to perform IP forwarding but is not enabled for IP forwarding).", + "type": "string" + }, + "value": { + "description": "[Output Only] A warning data value corresponding to the key.", + "type": "string" + } + }, + "type": "object" + }, + "type": "array" + }, + "message": { + "description": "[Output Only] A human-readable description of the warning code.", + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object" + }, + "UrlMapsScopedList": { + "id": "UrlMapsScopedList", + "properties": { + "urlMaps": { + "description": "A list of UrlMaps contained in this scope.", + "items": { + "$ref": "UrlMap" + }, + "type": "array" + }, + "warning": { + "description": "Informational warning which replaces the list of backend services when the list is empty.", + "properties": { + "code": { + "description": "[Output Only] A warning code, if applicable. For example, Compute Engine returns NO_RESULTS_ON_PAGE if there are no results in the response.", + "enum": [ + "CLEANUP_FAILED", + "DEPRECATED_RESOURCE_USED", + "DEPRECATED_TYPE_USED", + "DISK_SIZE_LARGER_THAN_IMAGE_SIZE", + "EXPERIMENTAL_TYPE_USED", + "EXTERNAL_API_WARNING", + "FIELD_VALUE_OVERRIDEN", + "INJECTED_KERNELS_DEPRECATED", + "MISSING_TYPE_DEPENDENCY", + "NEXT_HOP_ADDRESS_NOT_ASSIGNED", + "NEXT_HOP_CANNOT_IP_FORWARD", + "NEXT_HOP_INSTANCE_NOT_FOUND", + "NEXT_HOP_INSTANCE_NOT_ON_NETWORK", + "NEXT_HOP_NOT_RUNNING", + "NOT_CRITICAL_ERROR", + "NO_RESULTS_ON_PAGE", + "REQUIRED_TOS_AGREEMENT", + "RESOURCE_IN_USE_BY_OTHER_RESOURCE_WARNING", + "RESOURCE_NOT_DELETED", + "SCHEMA_VALIDATION_IGNORED", + "SINGLE_INSTANCE_PROPERTY_TEMPLATE", + "UNDECLARED_PROPERTIES", + "UNREACHABLE" + ], + "enumDescriptions": [ + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "" + ], + "type": "string" + }, + "data": { + "description": "[Output Only] Metadata about this warning in key: value format. For example:\n\"data\": [ { \"key\": \"scope\", \"value\": \"zones/us-east1-d\" }", + "items": { + "properties": { + "key": { + "description": "[Output Only] A key that provides more detail on the warning being returned. For example, for warnings where there are no results in a list request for a particular zone, this key might be scope and the key value might be the zone name. Other examples might be a key indicating a deprecated resource and a suggested replacement, or a warning about invalid network settings (for example, if an instance attempts to perform IP forwarding but is not enabled for IP forwarding).", + "type": "string" + }, + "value": { + "description": "[Output Only] A warning data value corresponding to the key.", + "type": "string" + } + }, + "type": "object" + }, + "type": "array" + }, + "message": { + "description": "[Output Only] A human-readable description of the warning code.", + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object" + }, "UrlMapsValidateRequest": { "id": "UrlMapsValidateRequest", "properties": { @@ -46979,7 +50971,7 @@ "type": "string" }, "labelFingerprint": { - "description": "A fingerprint for the labels being applied to this VpnGateway, which is essentially a hash of the labels set used for optimistic locking. The fingerprint is initially generated by Compute Engine and changes after every request to modify or update labels. You must always provide an up-to-date fingerprint hash in order to update or change labels.\n\nTo see the latest fingerprint, make a get() request to retrieve an VpnGateway.", + "description": "A fingerprint for the labels being applied to this VpnGateway, which is essentially a hash of the labels set used for optimistic locking. The fingerprint is initially generated by Compute Engine and changes after every request to modify or update labels. You must always provide an up-to-date fingerprint hash in order to update or change labels, otherwise the request will fail with error 412 conditionNotMet.\n\nTo see the latest fingerprint, make a get() request to retrieve an VpnGateway.", "format": "byte", "type": "string" }, @@ -47393,7 +51385,7 @@ "type": "string" }, "labelFingerprint": { - "description": "A fingerprint for the labels being applied to this VpnTunnel, which is essentially a hash of the labels set used for optimistic locking. The fingerprint is initially generated by Compute Engine and changes after every request to modify or update labels. You must always provide an up-to-date fingerprint hash in order to update or change labels.\n\nTo see the latest fingerprint, make a get() request to retrieve a VpnTunnel.", + "description": "A fingerprint for the labels being applied to this VpnTunnel, which is essentially a hash of the labels set used for optimistic locking. The fingerprint is initially generated by Compute Engine and changes after every request to modify or update labels. You must always provide an up-to-date fingerprint hash in order to update or change labels, otherwise the request will fail with error 412 conditionNotMet.\n\nTo see the latest fingerprint, make a get() request to retrieve a VpnTunnel.", "format": "byte", "type": "string" }, @@ -47968,7 +51960,7 @@ "id": "XpnResourceId", "properties": { "id": { - "description": "The ID of the service resource. In the case of projects, this field matches the project ID (e.g., my-project), not the project number (e.g., 12345678).", + "description": "The ID of the service resource. In the case of projects, this field supports project id (e.g., my-project-123) and project number (e.g. 12345678).", "type": "string" }, "type": { diff --git a/vendor/google.golang.org/api/compute/v0.alpha/compute-gen.go b/vendor/google.golang.org/api/compute/v0.alpha/compute-gen.go index 88d030a0c27..d233540db72 100644 --- a/vendor/google.golang.org/api/compute/v0.alpha/compute-gen.go +++ b/vendor/google.golang.org/api/compute/v0.alpha/compute-gen.go @@ -1,3 +1,9 @@ +// Copyright 2018 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Code generated file. DO NOT EDIT. + // Package compute provides access to the Compute Engine API. // // See https://developers.google.com/compute/docs/reference/latest/ @@ -11,18 +17,18 @@ package compute import ( "bytes" + "context" "encoding/json" "errors" "fmt" - context "golang.org/x/net/context" - ctxhttp "golang.org/x/net/context/ctxhttp" - gensupport "google.golang.org/api/gensupport" - googleapi "google.golang.org/api/googleapi" "io" "net/http" "net/url" "strconv" "strings" + + gensupport "google.golang.org/api/gensupport" + googleapi "google.golang.org/api/googleapi" ) // Always reference these packages, just in case the auto-generated code @@ -38,7 +44,6 @@ var _ = googleapi.Version var _ = errors.New var _ = strings.Replace var _ = context.Canceled -var _ = ctxhttp.Do const apiId = "compute:alpha" const apiName = "compute" @@ -73,6 +78,7 @@ func New(client *http.Client) (*Service, error) { s := &Service{client: client, BasePath: basePath} s.AcceleratorTypes = NewAcceleratorTypesService(s) s.Addresses = NewAddressesService(s) + s.Allocations = NewAllocationsService(s) s.Autoscalers = NewAutoscalersService(s) s.BackendBuckets = NewBackendBucketsService(s) s.BackendServices = NewBackendServicesService(s) @@ -83,9 +89,8 @@ func New(client *http.Client) (*Service, error) { s.GlobalAddresses = NewGlobalAddressesService(s) s.GlobalForwardingRules = NewGlobalForwardingRulesService(s) s.GlobalOperations = NewGlobalOperationsService(s) + s.GlobalOrganizationOperations = NewGlobalOrganizationOperationsService(s) s.HealthChecks = NewHealthChecksService(s) - s.HostTypes = NewHostTypesService(s) - s.Hosts = NewHostsService(s) s.HttpHealthChecks = NewHttpHealthChecksService(s) s.HttpsHealthChecks = NewHttpsHealthChecksService(s) s.Images = NewImagesService(s) @@ -98,12 +103,14 @@ func New(client *http.Client) (*Service, error) { s.Interconnects = NewInterconnectsService(s) s.LicenseCodes = NewLicenseCodesService(s) s.Licenses = NewLicensesService(s) + s.MachineImages = NewMachineImagesService(s) s.MachineTypes = NewMachineTypesService(s) s.NetworkEndpointGroups = NewNetworkEndpointGroupsService(s) s.Networks = NewNetworksService(s) s.NodeGroups = NewNodeGroupsService(s) s.NodeTemplates = NewNodeTemplatesService(s) s.NodeTypes = NewNodeTypesService(s) + s.OrganizationSecurityPolicies = NewOrganizationSecurityPoliciesService(s) s.Projects = NewProjectsService(s) s.RegionAutoscalers = NewRegionAutoscalersService(s) s.RegionBackendServices = NewRegionBackendServicesService(s) @@ -114,7 +121,9 @@ func New(client *http.Client) (*Service, error) { s.RegionInstanceGroupManagers = NewRegionInstanceGroupManagersService(s) s.RegionInstanceGroups = NewRegionInstanceGroupsService(s) s.RegionOperations = NewRegionOperationsService(s) + s.RegionSslCertificates = NewRegionSslCertificatesService(s) s.RegionTargetHttpProxies = NewRegionTargetHttpProxiesService(s) + s.RegionTargetHttpsProxies = NewRegionTargetHttpsProxiesService(s) s.RegionUrlMaps = NewRegionUrlMapsService(s) s.Regions = NewRegionsService(s) s.ResourcePolicies = NewResourcePoliciesService(s) @@ -149,6 +158,8 @@ type Service struct { Addresses *AddressesService + Allocations *AllocationsService + Autoscalers *AutoscalersService BackendBuckets *BackendBucketsService @@ -169,12 +180,10 @@ type Service struct { GlobalOperations *GlobalOperationsService + GlobalOrganizationOperations *GlobalOrganizationOperationsService + HealthChecks *HealthChecksService - HostTypes *HostTypesService - - Hosts *HostsService - HttpHealthChecks *HttpHealthChecksService HttpsHealthChecks *HttpsHealthChecksService @@ -199,6 +208,8 @@ type Service struct { Licenses *LicensesService + MachineImages *MachineImagesService + MachineTypes *MachineTypesService NetworkEndpointGroups *NetworkEndpointGroupsService @@ -211,6 +222,8 @@ type Service struct { NodeTypes *NodeTypesService + OrganizationSecurityPolicies *OrganizationSecurityPoliciesService + Projects *ProjectsService RegionAutoscalers *RegionAutoscalersService @@ -231,8 +244,12 @@ type Service struct { RegionOperations *RegionOperationsService + RegionSslCertificates *RegionSslCertificatesService + RegionTargetHttpProxies *RegionTargetHttpProxiesService + RegionTargetHttpsProxies *RegionTargetHttpsProxiesService + RegionUrlMaps *RegionUrlMapsService Regions *RegionsService @@ -303,6 +320,15 @@ type AddressesService struct { s *Service } +func NewAllocationsService(s *Service) *AllocationsService { + rs := &AllocationsService{s: s} + return rs +} + +type AllocationsService struct { + s *Service +} + func NewAutoscalersService(s *Service) *AutoscalersService { rs := &AutoscalersService{s: s} return rs @@ -393,6 +419,15 @@ type GlobalOperationsService struct { s *Service } +func NewGlobalOrganizationOperationsService(s *Service) *GlobalOrganizationOperationsService { + rs := &GlobalOrganizationOperationsService{s: s} + return rs +} + +type GlobalOrganizationOperationsService struct { + s *Service +} + func NewHealthChecksService(s *Service) *HealthChecksService { rs := &HealthChecksService{s: s} return rs @@ -402,24 +437,6 @@ type HealthChecksService struct { s *Service } -func NewHostTypesService(s *Service) *HostTypesService { - rs := &HostTypesService{s: s} - return rs -} - -type HostTypesService struct { - s *Service -} - -func NewHostsService(s *Service) *HostsService { - rs := &HostsService{s: s} - return rs -} - -type HostsService struct { - s *Service -} - func NewHttpHealthChecksService(s *Service) *HttpHealthChecksService { rs := &HttpHealthChecksService{s: s} return rs @@ -528,6 +545,15 @@ type LicensesService struct { s *Service } +func NewMachineImagesService(s *Service) *MachineImagesService { + rs := &MachineImagesService{s: s} + return rs +} + +type MachineImagesService struct { + s *Service +} + func NewMachineTypesService(s *Service) *MachineTypesService { rs := &MachineTypesService{s: s} return rs @@ -582,6 +608,15 @@ type NodeTypesService struct { s *Service } +func NewOrganizationSecurityPoliciesService(s *Service) *OrganizationSecurityPoliciesService { + rs := &OrganizationSecurityPoliciesService{s: s} + return rs +} + +type OrganizationSecurityPoliciesService struct { + s *Service +} + func NewProjectsService(s *Service) *ProjectsService { rs := &ProjectsService{s: s} return rs @@ -672,6 +707,15 @@ type RegionOperationsService struct { s *Service } +func NewRegionSslCertificatesService(s *Service) *RegionSslCertificatesService { + rs := &RegionSslCertificatesService{s: s} + return rs +} + +type RegionSslCertificatesService struct { + s *Service +} + func NewRegionTargetHttpProxiesService(s *Service) *RegionTargetHttpProxiesService { rs := &RegionTargetHttpProxiesService{s: s} return rs @@ -681,6 +725,15 @@ type RegionTargetHttpProxiesService struct { s *Service } +func NewRegionTargetHttpsProxiesService(s *Service) *RegionTargetHttpsProxiesService { + rs := &RegionTargetHttpsProxiesService{s: s} + return rs +} + +type RegionTargetHttpsProxiesService struct { + s *Service +} + func NewRegionUrlMapsService(s *Service) *RegionUrlMapsService { rs := &RegionUrlMapsService{s: s} return rs @@ -1561,7 +1614,8 @@ type Address struct { // optimistic locking. The fingerprint is initially generated by Compute // Engine and changes after every request to modify or update labels. // You must always provide an up-to-date fingerprint hash in order to - // update or change labels. + // update or change labels, otherwise the request will fail with error + // 412 conditionNotMet. // // To see the latest fingerprint, make a get() request to retrieve an // Address. @@ -1586,8 +1640,12 @@ type Address struct { Network string `json:"network,omitempty"` // NetworkTier: This signifies the networking tier used for configuring - // this Address and can only take the following values: PREMIUM , - // STANDARD. + // this Address and can only take the following values: PREMIUM, + // STANDARD. Global forwarding rules can only be Premium Tier. Regional + // forwarding rules can be either Premium or Standard Tier. Standard + // Tier addresses applied to regional forwarding rules can be used with + // any external load balancer. Regional forwarding rules in Premium Tier + // can only be used with a Network load balancer. // // If this field is not specified, it is assumed to be PREMIUM. // @@ -1606,7 +1664,7 @@ type Address struct { // Possible values: // "DNS_RESOLVER" // "GCE_ENDPOINT" - // "UNSPECIFIED_PURPOSE" + // "NAT_AUTO" // "VPC_PEERING" Purpose string `json:"purpose,omitempty"` @@ -2150,6 +2208,712 @@ func (s *AliasIpRange) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +// Allocation: Allocation resource +type Allocation struct { + // Commitment: Full or partial url for commitment in which this + // allocation is to be created. This field is ignored when allocations + // are created during committment creation. + Commitment string `json:"commitment,omitempty"` + + // CreationTimestamp: [Output Only] Creation timestamp in RFC3339 text + // format. + CreationTimestamp string `json:"creationTimestamp,omitempty"` + + Description string `json:"description,omitempty"` + + // Id: [Output Only] The unique identifier for the resource. This + // identifier is defined by the server. + Id uint64 `json:"id,omitempty,string"` + + // Kind: [Output Only] Type of the resource. Always compute#allocations + // for allocations. + Kind string `json:"kind,omitempty"` + + // Name: The name of the resource, provided by the client when initially + // creating the resource. The resource name must be 1-63 characters + // long, and comply with RFC1035. Specifically, the name must be 1-63 + // characters long and match the regular expression + // `[a-z]([-a-z0-9]*[a-z0-9])?` which means the first character must be + // a lowercase letter, and all following characters must be a dash, + // lowercase letter, or digit, except the last character, which cannot + // be a dash. + Name string `json:"name,omitempty"` + + // SelfLink: [Output Only] Server-defined fully-qualified URL for this + // resource. + SelfLink string `json:"selfLink,omitempty"` + + SpecificAllocation *AllocationSpecificSKUAllocation `json:"specificAllocation,omitempty"` + + // SpecificAllocationRequired: Indicates whether the allocation can be + // consumed by VMs with "any allocation" defined. If the field is set, + // then only VMs that target the allocation by name using + // --allocation-affinity can consume this allocation. + SpecificAllocationRequired bool `json:"specificAllocationRequired,omitempty"` + + Zone string `json:"zone,omitempty"` + + // ServerResponse contains the HTTP response code and headers from the + // server. + googleapi.ServerResponse `json:"-"` + + // ForceSendFields is a list of field names (e.g. "Commitment") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Commitment") to include in + // API requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *Allocation) MarshalJSON() ([]byte, error) { + type NoMethod Allocation + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// AllocationAffinity: AllocationAffinity is the configuration of +// desired allocation which this instance could take capacity from. +type AllocationAffinity struct { + // Possible values: + // "ANY_ALLOCATION" + // "NO_ALLOCATION" + // "SPECIFIC_ALLOCATION" + // "UNSPECIFIED" + ConsumeAllocationType string `json:"consumeAllocationType,omitempty"` + + // Key: Corresponds to the label key of allocation resource. + Key string `json:"key,omitempty"` + + // Values: Corresponds to the label values of allocation resource. + Values []string `json:"values,omitempty"` + + // ForceSendFields is a list of field names (e.g. + // "ConsumeAllocationType") to unconditionally include in API requests. + // By default, fields with empty values are omitted from API requests. + // However, any non-pointer, non-interface field appearing in + // ForceSendFields will be sent to the server regardless of whether the + // field is empty or not. This may be used to include empty fields in + // Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "ConsumeAllocationType") to + // include in API requests with the JSON null value. By default, fields + // with empty values are omitted from API requests. However, any field + // with an empty value appearing in NullFields will be sent to the + // server as null. It is an error if a field in this list has a + // non-empty value. This may be used to include null fields in Patch + // requests. + NullFields []string `json:"-"` +} + +func (s *AllocationAffinity) MarshalJSON() ([]byte, error) { + type NoMethod AllocationAffinity + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// AllocationAggregatedList: Contains a list of allocations. +type AllocationAggregatedList struct { + // Id: [Output Only] Unique identifier for the resource; defined by the + // server. + Id string `json:"id,omitempty"` + + // Items: A list of Allocation resources. + Items map[string]AllocationsScopedList `json:"items,omitempty"` + + // Kind: Type of resource. + Kind string `json:"kind,omitempty"` + + // NextPageToken: [Output Only] This token allows you to get the next + // page of results for list requests. If the number of results is larger + // than maxResults, use the nextPageToken as a value for the query + // parameter pageToken in the next list request. Subsequent list + // requests will have their own nextPageToken to continue paging through + // the results. + NextPageToken string `json:"nextPageToken,omitempty"` + + // SelfLink: [Output Only] Server-defined URL for this resource. + SelfLink string `json:"selfLink,omitempty"` + + // Warning: [Output Only] Informational warning message. + Warning *AllocationAggregatedListWarning `json:"warning,omitempty"` + + // ServerResponse contains the HTTP response code and headers from the + // server. + googleapi.ServerResponse `json:"-"` + + // ForceSendFields is a list of field names (e.g. "Id") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Id") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *AllocationAggregatedList) MarshalJSON() ([]byte, error) { + type NoMethod AllocationAggregatedList + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// AllocationAggregatedListWarning: [Output Only] Informational warning +// message. +type AllocationAggregatedListWarning struct { + // Code: [Output Only] A warning code, if applicable. For example, + // Compute Engine returns NO_RESULTS_ON_PAGE if there are no results in + // the response. + // + // Possible values: + // "CLEANUP_FAILED" + // "DEPRECATED_RESOURCE_USED" + // "DEPRECATED_TYPE_USED" + // "DISK_SIZE_LARGER_THAN_IMAGE_SIZE" + // "EXPERIMENTAL_TYPE_USED" + // "EXTERNAL_API_WARNING" + // "FIELD_VALUE_OVERRIDEN" + // "INJECTED_KERNELS_DEPRECATED" + // "MISSING_TYPE_DEPENDENCY" + // "NEXT_HOP_ADDRESS_NOT_ASSIGNED" + // "NEXT_HOP_CANNOT_IP_FORWARD" + // "NEXT_HOP_INSTANCE_NOT_FOUND" + // "NEXT_HOP_INSTANCE_NOT_ON_NETWORK" + // "NEXT_HOP_NOT_RUNNING" + // "NOT_CRITICAL_ERROR" + // "NO_RESULTS_ON_PAGE" + // "REQUIRED_TOS_AGREEMENT" + // "RESOURCE_IN_USE_BY_OTHER_RESOURCE_WARNING" + // "RESOURCE_NOT_DELETED" + // "SCHEMA_VALIDATION_IGNORED" + // "SINGLE_INSTANCE_PROPERTY_TEMPLATE" + // "UNDECLARED_PROPERTIES" + // "UNREACHABLE" + Code string `json:"code,omitempty"` + + // Data: [Output Only] Metadata about this warning in key: value format. + // For example: + // "data": [ { "key": "scope", "value": "zones/us-east1-d" } + Data []*AllocationAggregatedListWarningData `json:"data,omitempty"` + + // Message: [Output Only] A human-readable description of the warning + // code. + Message string `json:"message,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Code") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Code") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *AllocationAggregatedListWarning) MarshalJSON() ([]byte, error) { + type NoMethod AllocationAggregatedListWarning + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type AllocationAggregatedListWarningData struct { + // Key: [Output Only] A key that provides more detail on the warning + // being returned. For example, for warnings where there are no results + // in a list request for a particular zone, this key might be scope and + // the key value might be the zone name. Other examples might be a key + // indicating a deprecated resource and a suggested replacement, or a + // warning about invalid network settings (for example, if an instance + // attempts to perform IP forwarding but is not enabled for IP + // forwarding). + Key string `json:"key,omitempty"` + + // Value: [Output Only] A warning data value corresponding to the key. + Value string `json:"value,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Key") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Key") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *AllocationAggregatedListWarningData) MarshalJSON() ([]byte, error) { + type NoMethod AllocationAggregatedListWarningData + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type AllocationList struct { + // Id: [Output Only] The unique identifier for the resource. This + // identifier is defined by the server. + Id string `json:"id,omitempty"` + + // Items: [Output Only] A list of Allocation resources. + Items []*Allocation `json:"items,omitempty"` + + // Kind: [Output Only] Type of resource.Always compute#allocationsList + // for listsof allocations + Kind string `json:"kind,omitempty"` + + // NextPageToken: [Output Only] This token allows you to get the next + // page of results for list requests. If the number of results is larger + // than maxResults, use the nextPageToken as a value for the query + // parameter pageToken in the next list request. Subsequent list + // requests will have their own nextPageToken to continue paging through + // the results. + NextPageToken string `json:"nextPageToken,omitempty"` + + // SelfLink: [Output Only] Server-defined URL for this resource. + SelfLink string `json:"selfLink,omitempty"` + + // Warning: [Output Only] Informational warning message. + Warning *AllocationListWarning `json:"warning,omitempty"` + + // ServerResponse contains the HTTP response code and headers from the + // server. + googleapi.ServerResponse `json:"-"` + + // ForceSendFields is a list of field names (e.g. "Id") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Id") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *AllocationList) MarshalJSON() ([]byte, error) { + type NoMethod AllocationList + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// AllocationListWarning: [Output Only] Informational warning message. +type AllocationListWarning struct { + // Code: [Output Only] A warning code, if applicable. For example, + // Compute Engine returns NO_RESULTS_ON_PAGE if there are no results in + // the response. + // + // Possible values: + // "CLEANUP_FAILED" + // "DEPRECATED_RESOURCE_USED" + // "DEPRECATED_TYPE_USED" + // "DISK_SIZE_LARGER_THAN_IMAGE_SIZE" + // "EXPERIMENTAL_TYPE_USED" + // "EXTERNAL_API_WARNING" + // "FIELD_VALUE_OVERRIDEN" + // "INJECTED_KERNELS_DEPRECATED" + // "MISSING_TYPE_DEPENDENCY" + // "NEXT_HOP_ADDRESS_NOT_ASSIGNED" + // "NEXT_HOP_CANNOT_IP_FORWARD" + // "NEXT_HOP_INSTANCE_NOT_FOUND" + // "NEXT_HOP_INSTANCE_NOT_ON_NETWORK" + // "NEXT_HOP_NOT_RUNNING" + // "NOT_CRITICAL_ERROR" + // "NO_RESULTS_ON_PAGE" + // "REQUIRED_TOS_AGREEMENT" + // "RESOURCE_IN_USE_BY_OTHER_RESOURCE_WARNING" + // "RESOURCE_NOT_DELETED" + // "SCHEMA_VALIDATION_IGNORED" + // "SINGLE_INSTANCE_PROPERTY_TEMPLATE" + // "UNDECLARED_PROPERTIES" + // "UNREACHABLE" + Code string `json:"code,omitempty"` + + // Data: [Output Only] Metadata about this warning in key: value format. + // For example: + // "data": [ { "key": "scope", "value": "zones/us-east1-d" } + Data []*AllocationListWarningData `json:"data,omitempty"` + + // Message: [Output Only] A human-readable description of the warning + // code. + Message string `json:"message,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Code") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Code") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *AllocationListWarning) MarshalJSON() ([]byte, error) { + type NoMethod AllocationListWarning + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type AllocationListWarningData struct { + // Key: [Output Only] A key that provides more detail on the warning + // being returned. For example, for warnings where there are no results + // in a list request for a particular zone, this key might be scope and + // the key value might be the zone name. Other examples might be a key + // indicating a deprecated resource and a suggested replacement, or a + // warning about invalid network settings (for example, if an instance + // attempts to perform IP forwarding but is not enabled for IP + // forwarding). + Key string `json:"key,omitempty"` + + // Value: [Output Only] A warning data value corresponding to the key. + Value string `json:"value,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Key") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Key") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *AllocationListWarningData) MarshalJSON() ([]byte, error) { + type NoMethod AllocationListWarningData + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// AllocationSpecificSKUAllocation: This allocation type allows to pre +// allocate specific instance configuration. +type AllocationSpecificSKUAllocation struct { + // Count: Specifies number of resources that are allocated. + Count int64 `json:"count,omitempty,string"` + + // InUseCount: [OutputOnly] Indicates how many resource are in use. + InUseCount int64 `json:"inUseCount,omitempty,string"` + + InstanceProperties *AllocationSpecificSKUAllocationAllocatedInstanceProperties `json:"instanceProperties,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Count") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Count") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *AllocationSpecificSKUAllocation) MarshalJSON() ([]byte, error) { + type NoMethod AllocationSpecificSKUAllocation + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// AllocationSpecificSKUAllocationAllocatedInstanceProperties: +// Properties of the SKU instances being reserved. +type AllocationSpecificSKUAllocationAllocatedInstanceProperties struct { + // GuestAccelerators: Specifies accelerator type and count. + GuestAccelerators []*AcceleratorConfig `json:"guestAccelerators,omitempty"` + + // LocalSsds: Specifies amount of local ssd to reserve with each + // instance. The type of disk is local-ssd. + LocalSsds []*AllocationSpecificSKUAllocationAllocatedInstancePropertiesAllocatedDisk `json:"localSsds,omitempty"` + + // MachineType: Specifies type of machine (name only) which has fixed + // number of vCPUs and fixed amount of memory. This also includes + // specifying custom machine type following + // custom-NUMBER_OF_CPUS-AMOUNT_OF_MEMORY pattern. + MachineType string `json:"machineType,omitempty"` + + // MinCpuPlatform: Minimum cpu platform the allocation. + MinCpuPlatform string `json:"minCpuPlatform,omitempty"` + + // ForceSendFields is a list of field names (e.g. "GuestAccelerators") + // to unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "GuestAccelerators") to + // include in API requests with the JSON null value. By default, fields + // with empty values are omitted from API requests. However, any field + // with an empty value appearing in NullFields will be sent to the + // server as null. It is an error if a field in this list has a + // non-empty value. This may be used to include null fields in Patch + // requests. + NullFields []string `json:"-"` +} + +func (s *AllocationSpecificSKUAllocationAllocatedInstanceProperties) MarshalJSON() ([]byte, error) { + type NoMethod AllocationSpecificSKUAllocationAllocatedInstanceProperties + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type AllocationSpecificSKUAllocationAllocatedInstancePropertiesAllocatedDisk struct { + // DiskSizeGb: Specifies the size of the disk in base-2 GB. + DiskSizeGb int64 `json:"diskSizeGb,omitempty,string"` + + // Interface: Specifies the disk interface to use for attaching this + // disk, which is either SCSI or NVME. The default is SCSI. For + // performance characteristics of SCSI over NVMe, see Local SSD + // performance. + // + // Possible values: + // "NVDIMM" + // "NVME" + // "SCSI" + Interface string `json:"interface,omitempty"` + + // ForceSendFields is a list of field names (e.g. "DiskSizeGb") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "DiskSizeGb") to include in + // API requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *AllocationSpecificSKUAllocationAllocatedInstancePropertiesAllocatedDisk) MarshalJSON() ([]byte, error) { + type NoMethod AllocationSpecificSKUAllocationAllocatedInstancePropertiesAllocatedDisk + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type AllocationsScopedList struct { + // Allocations: A list of allocations contained in this scope. + Allocations []*Allocation `json:"allocations,omitempty"` + + // Warning: Informational warning which replaces the list of allocations + // when the list is empty. + Warning *AllocationsScopedListWarning `json:"warning,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Allocations") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Allocations") to include + // in API requests with the JSON null value. By default, fields with + // empty values are omitted from API requests. However, any field with + // an empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *AllocationsScopedList) MarshalJSON() ([]byte, error) { + type NoMethod AllocationsScopedList + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// AllocationsScopedListWarning: Informational warning which replaces +// the list of allocations when the list is empty. +type AllocationsScopedListWarning struct { + // Code: [Output Only] A warning code, if applicable. For example, + // Compute Engine returns NO_RESULTS_ON_PAGE if there are no results in + // the response. + // + // Possible values: + // "CLEANUP_FAILED" + // "DEPRECATED_RESOURCE_USED" + // "DEPRECATED_TYPE_USED" + // "DISK_SIZE_LARGER_THAN_IMAGE_SIZE" + // "EXPERIMENTAL_TYPE_USED" + // "EXTERNAL_API_WARNING" + // "FIELD_VALUE_OVERRIDEN" + // "INJECTED_KERNELS_DEPRECATED" + // "MISSING_TYPE_DEPENDENCY" + // "NEXT_HOP_ADDRESS_NOT_ASSIGNED" + // "NEXT_HOP_CANNOT_IP_FORWARD" + // "NEXT_HOP_INSTANCE_NOT_FOUND" + // "NEXT_HOP_INSTANCE_NOT_ON_NETWORK" + // "NEXT_HOP_NOT_RUNNING" + // "NOT_CRITICAL_ERROR" + // "NO_RESULTS_ON_PAGE" + // "REQUIRED_TOS_AGREEMENT" + // "RESOURCE_IN_USE_BY_OTHER_RESOURCE_WARNING" + // "RESOURCE_NOT_DELETED" + // "SCHEMA_VALIDATION_IGNORED" + // "SINGLE_INSTANCE_PROPERTY_TEMPLATE" + // "UNDECLARED_PROPERTIES" + // "UNREACHABLE" + Code string `json:"code,omitempty"` + + // Data: [Output Only] Metadata about this warning in key: value format. + // For example: + // "data": [ { "key": "scope", "value": "zones/us-east1-d" } + Data []*AllocationsScopedListWarningData `json:"data,omitempty"` + + // Message: [Output Only] A human-readable description of the warning + // code. + Message string `json:"message,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Code") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Code") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *AllocationsScopedListWarning) MarshalJSON() ([]byte, error) { + type NoMethod AllocationsScopedListWarning + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type AllocationsScopedListWarningData struct { + // Key: [Output Only] A key that provides more detail on the warning + // being returned. For example, for warnings where there are no results + // in a list request for a particular zone, this key might be scope and + // the key value might be the zone name. Other examples might be a key + // indicating a deprecated resource and a suggested replacement, or a + // warning about invalid network settings (for example, if an instance + // attempts to perform IP forwarding but is not enabled for IP + // forwarding). + Key string `json:"key,omitempty"` + + // Value: [Output Only] A warning data value corresponding to the key. + Value string `json:"value,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Key") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Key") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *AllocationsScopedListWarningData) MarshalJSON() ([]byte, error) { + type NoMethod AllocationsScopedListWarningData + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type AllocationsUpdateResourceShapeRequest struct { + // Count: Number of allocated resources which are to be updated with + // minimum = 1 and maximum = 100. + Count int64 `json:"count,omitempty"` + + // DestinationAllocation: The name of destination allocation where the + // modified machines are added. If existing, its machine spec must match + // the modified machine spec. If non existing, new allocation with this + // name and modified machine spec is created automatically. + DestinationAllocation string `json:"destinationAllocation,omitempty"` + + UpdatedResourceProperties *AllocationSpecificSKUAllocationAllocatedInstanceProperties `json:"updatedResourceProperties,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Count") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Count") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *AllocationsUpdateResourceShapeRequest) MarshalJSON() ([]byte, error) { + type NoMethod AllocationsUpdateResourceShapeRequest + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + // AttachedDisk: An instance-attached disk resource. type AttachedDisk struct { // AutoDelete: Specifies whether the disk will be auto-deleted when the @@ -2227,6 +2991,7 @@ type AttachedDisk struct { // over NVMe, see Local SSD performance. // // Possible values: + // "NVDIMM" // "NVME" // "SCSI" Interface string `json:"interface,omitempty"` @@ -2309,20 +3074,19 @@ func (s *AttachedDisk) MarshalJSON() ([]byte, error) { // This property is mutually exclusive with the source property; you can // only define one or the other, but not both. type AttachedDiskInitializeParams struct { + // Description: An optional description. Provide this property when + // creating the disk. + Description string `json:"description,omitempty"` + // DiskName: Specifies the disk name. If not specified, the default is - // to use the name of the instance. + // to use the name of the instance. If the disk with the instance name + // exists already in the given zone/region, a new name will be + // automatically generated. DiskName string `json:"diskName,omitempty"` // DiskSizeGb: Specifies the size of the disk in base-2 GB. DiskSizeGb int64 `json:"diskSizeGb,omitempty,string"` - // DiskStorageType: [Deprecated] Storage type of the disk. - // - // Possible values: - // "HDD" - // "SSD" - DiskStorageType string `json:"diskStorageType,omitempty"` - // DiskType: Specifies the disk type to use to create the instance. If // not specified, the default is pd-standard, specified using the full // URL. For @@ -2352,15 +3116,15 @@ type AttachedDiskInitializeParams struct { // // To create a disk with one of the public operating system images, // specify the image by its family name. For example, specify - // family/debian-8 to use the latest Debian 8 + // family/debian-9 to use the latest Debian 9 // image: - // projects/debian-cloud/global/images/family/debian-8 + // projects/debian-cloud/global/images/family/debian-9 // // // Alternati // vely, use a specific version of a public operating system // image: - // projects/debian-cloud/global/images/debian-8-jessie-vYYYYMMDD + // projects/debian-cloud/global/images/debian-9-stretch-vYYYYMMDD // // // @@ -2402,7 +3166,11 @@ type AttachedDiskInitializeParams struct { // If the source snapshot is deleted later, this field will not be set. SourceSnapshot string `json:"sourceSnapshot,omitempty"` - // ForceSendFields is a list of field names (e.g. "DiskName") to + // SourceSnapshotEncryptionKey: The customer-supplied encryption key of + // the source snapshot. + SourceSnapshotEncryptionKey *CustomerEncryptionKey `json:"sourceSnapshotEncryptionKey,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Description") to // unconditionally include in API requests. By default, fields with // empty values are omitted from API requests. However, any non-pointer, // non-interface field appearing in ForceSendFields will be sent to the @@ -2410,10 +3178,10 @@ type AttachedDiskInitializeParams struct { // used to include empty fields in Patch requests. ForceSendFields []string `json:"-"` - // NullFields is a list of field names (e.g. "DiskName") to include in - // API requests with the JSON null value. By default, fields with empty - // values are omitted from API requests. However, any field with an - // empty value appearing in NullFields will be sent to the server as + // NullFields is a list of field names (e.g. "Description") to include + // in API requests with the JSON null value. By default, fields with + // empty values are omitted from API requests. However, any field with + // an empty value appearing in NullFields will be sent to the server as // null. It is an error if a field in this list has a non-empty value. // This may be used to include null fields in Patch requests. NullFields []string `json:"-"` @@ -3371,8 +4139,7 @@ type AutoscalingPolicyCustomMetricUtilization struct { // UtilizationTargetType: Defines how target utilization value is // expressed for a Stackdriver Monitoring metric. Either GAUGE, - // DELTA_PER_SECOND, or DELTA_PER_MINUTE. If not specified, the default - // is GAUGE. + // DELTA_PER_SECOND, or DELTA_PER_MINUTE. // // Possible values: // "DELTA_PER_MINUTE" @@ -3599,18 +4366,28 @@ type Backend struct { // BackendService. Failover bool `json:"failover,omitempty"` - // Group: The fully-qualified URL of a Instance Group resource. This - // instance group defines the list of instances that serve traffic. - // Member virtual machine instances from each instance group must live - // in the same zone as the instance group itself. No two backends in a - // backend service are allowed to use same Instance Group - // resource. + // Group: The fully-qualified URL of an Instance Group or Network + // Endpoint Group resource. In case of instance group this defines the + // list of instances that serve traffic. Member virtual machine + // instances from each instance group must live in the same zone as the + // instance group itself. No two backends in a backend service are + // allowed to use same Instance Group resource. // - // Note that you must specify an Instance Group resource using the - // fully-qualified URL, rather than a partial URL. + // For Network Endpoint Groups this defines list of endpoints. All + // endpoints of Network Endpoint Group must be hosted on instances + // located in the same zone as the Network Endpoint Group. + // + // Backend service can not contain mix of Instance Group and Network + // Endpoint Group backends. + // + // Note that you must specify an Instance Group or Network Endpoint + // Group resource using the fully-qualified URL, rather than a partial + // URL. // // When the BackendService has load balancing scheme INTERNAL, the // instance group must be within the same region as the BackendService. + // Network Endpoint Groups are not supported for INTERNAL load balancing + // scheme. Group string `json:"group,omitempty"` // MaxConnections: The max number of simultaneous connections for the @@ -3719,7 +4496,7 @@ type BackendBucket struct { // BucketName: Cloud Storage bucket name. BucketName string `json:"bucketName,omitempty"` - // CdnPolicy: Cloud CDN Coniguration for this BackendBucket. + // CdnPolicy: Cloud CDN configuration for this BackendBucket. CdnPolicy *BackendBucketCdnPolicy `json:"cdnPolicy,omitempty"` // CreationTimestamp: [Output Only] Creation timestamp in RFC3339 text @@ -3782,18 +4559,18 @@ func (s *BackendBucket) MarshalJSON() ([]byte, error) { // BackendBucketCdnPolicy: Message containing Cloud CDN configuration // for a backend bucket. type BackendBucketCdnPolicy struct { - // SignedUrlCacheMaxAgeSec: Number of seconds up to which the response - // to a signed URL request will be cached in the CDN. After this time - // period, the Signed URL will be revalidated before being served. - // Defaults to 1hr (3600s). If this field is set, Cloud CDN will - // internally act as though all responses from this bucket had a - // ?Cache-Control: public, max-age=[TTL]? header, regardless of any + // SignedUrlCacheMaxAgeSec: Maximum number of seconds the response to a + // signed URL request will be considered fresh. After this time period, + // the response will be revalidated before being served. Defaults to 1hr + // (3600s). When serving responses to signed URL requests, Cloud CDN + // will internally behave as though all responses from this backend had + // a "Cache-Control: public, max-age=[TTL]" header, regardless of any // existing Cache-Control header. The actual headers served in responses // will not be altered. SignedUrlCacheMaxAgeSec int64 `json:"signedUrlCacheMaxAgeSec,omitempty,string"` - // SignedUrlKeyNames: [Output Only] Names of the keys currently - // configured for Cloud CDN Signed URL on this backend bucket. + // SignedUrlKeyNames: [Output Only] Names of the keys for signing + // request URLs. SignedUrlKeyNames []string `json:"signedUrlKeyNames,omitempty"` // ForceSendFields is a list of field names (e.g. @@ -4027,7 +4804,11 @@ type BackendService struct { // Fingerprint: Fingerprint of this resource. A hash of the contents // stored in this object. This field is used in optimistic locking. This // field will be ignored when inserting a BackendService. An up-to-date - // fingerprint must be provided in order to update the BackendService. + // fingerprint must be provided in order to update the BackendService, + // otherwise the request will fail with error 412 conditionNotMet. + // + // To see the latest fingerprint, make a get() request to retrieve a + // BackendService. Fingerprint string `json:"fingerprint,omitempty"` // HealthChecks: The list of URLs to the HttpHealthCheck or @@ -4059,10 +4840,16 @@ type BackendService struct { // Possible values: // "EXTERNAL" // "INTERNAL" + // "INTERNAL_MANAGED" // "INTERNAL_SELF_MANAGED" // "INVALID_LOAD_BALANCING_SCHEME" LoadBalancingScheme string `json:"loadBalancingScheme,omitempty"` + // LogConfig: This field denotes the logging options for the load + // balancer traffic served by this backend service. If logging is + // enabled, logs will be exported to Stackdriver. + LogConfig *BackendServiceLogConfig `json:"logConfig,omitempty"` + // Name: Name of the resource. Provided by the client when the resource // is created. The name must be 1-63 characters long, and comply with // RFC1035. Specifically, the name must be 1-63 characters long and @@ -4369,18 +5156,18 @@ type BackendServiceCdnPolicy struct { // CacheKeyPolicy: The CacheKeyPolicy for this CdnPolicy. CacheKeyPolicy *CacheKeyPolicy `json:"cacheKeyPolicy,omitempty"` - // SignedUrlCacheMaxAgeSec: Number of seconds up to which the response - // to a signed URL request will be cached in the CDN. After this time - // period, the Signed URL will be revalidated before being served. - // Defaults to 1hr (3600s). If this field is set, Cloud CDN will - // internally act as though all responses from this backend had a - // ?Cache-Control: public, max-age=[TTL]? header, regardless of any + // SignedUrlCacheMaxAgeSec: Maximum number of seconds the response to a + // signed URL request will be considered fresh. After this time period, + // the response will be revalidated before being served. Defaults to 1hr + // (3600s). When serving responses to signed URL requests, Cloud CDN + // will internally behave as though all responses from this backend had + // a "Cache-Control: public, max-age=[TTL]" header, regardless of any // existing Cache-Control header. The actual headers served in responses // will not be altered. SignedUrlCacheMaxAgeSec int64 `json:"signedUrlCacheMaxAgeSec,omitempty,string"` - // SignedUrlKeyNames: [Output Only] Names of the keys currently - // configured for Cloud CDN Signed URL on this backend service. + // SignedUrlKeyNames: [Output Only] Names of the keys for signing + // request URLs. SignedUrlKeyNames []string `json:"signedUrlKeyNames,omitempty"` // ForceSendFields is a list of field names (e.g. "CacheKeyPolicy") to @@ -4517,6 +5304,13 @@ func (s *BackendServiceFailoverPolicy) UnmarshalJSON(data []byte) error { } type BackendServiceGroupHealth struct { + // Annotations: Metadata defined as annotations on the network endpoint + // group. + Annotations map[string]string `json:"annotations,omitempty"` + + // HealthStatus: Health state of the backend instances or endpoints in + // requested instance or network endpoint group, determined based on + // configured health checks. HealthStatus []*HealthStatus `json:"healthStatus,omitempty"` // Kind: [Output Only] Type of resource. Always @@ -4527,7 +5321,7 @@ type BackendServiceGroupHealth struct { // server. googleapi.ServerResponse `json:"-"` - // ForceSendFields is a list of field names (e.g. "HealthStatus") to + // ForceSendFields is a list of field names (e.g. "Annotations") to // unconditionally include in API requests. By default, fields with // empty values are omitted from API requests. However, any non-pointer, // non-interface field appearing in ForceSendFields will be sent to the @@ -4535,7 +5329,7 @@ type BackendServiceGroupHealth struct { // used to include empty fields in Patch requests. ForceSendFields []string `json:"-"` - // NullFields is a list of field names (e.g. "HealthStatus") to include + // NullFields is a list of field names (e.g. "Annotations") to include // in API requests with the JSON null value. By default, fields with // empty values are omitted from API requests. However, any field with // an empty value appearing in NullFields will be sent to the server as @@ -4781,6 +5575,57 @@ func (s *BackendServiceListWarningData) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +// BackendServiceLogConfig: The available logging options for the load +// balancer traffic served by this backend service. +type BackendServiceLogConfig struct { + // Enable: This field denotes whether to enable logging for the load + // balancer traffic served by this backend service. + Enable bool `json:"enable,omitempty"` + + // SampleRate: This field can only be specified if logging is enabled + // for this backend service. The value of the field must be in [0, 1]. + // This configures the sampling rate of requests to the load balancer + // where 1.0 means all logged requests are reported and 0.0 means no + // logged requests are reported. The default value is 1.0. + SampleRate float64 `json:"sampleRate,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Enable") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Enable") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *BackendServiceLogConfig) MarshalJSON() ([]byte, error) { + type NoMethod BackendServiceLogConfig + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +func (s *BackendServiceLogConfig) UnmarshalJSON(data []byte) error { + type NoMethod BackendServiceLogConfig + var s1 struct { + SampleRate gensupport.JSONFloat64 `json:"sampleRate"` + *NoMethod + } + s1.NoMethod = (*NoMethod)(s) + if err := json.Unmarshal(data, &s1); err != nil { + return err + } + s.SampleRate = float64(s1.SampleRate) + return nil +} + type BackendServiceReference struct { BackendService string `json:"backendService,omitempty"` @@ -4944,11 +5789,10 @@ func (s *BackendServicesScopedListWarningData) MarshalJSON() ([]byte, error) { // Binding: Associates `members` with a `role`. type Binding struct { - // Condition: The condition that is associated with this binding. NOTE: - // an unsatisfied condition will not allow user access via current - // binding. Different bindings, including their conditions, are examined - // independently. This field is only visible as GOOGLE_INTERNAL or - // CONDITION_TRUSTED_TESTER. + // Condition: Unimplemented. The condition that is associated with this + // binding. NOTE: an unsatisfied condition will not allow user access + // via current binding. Different bindings, including their conditions, + // are examined independently. Condition *Expr `json:"condition,omitempty"` // Members: Specifies the identities requesting access for a Cloud @@ -5101,6 +5945,9 @@ func (s *CacheKeyPolicy) MarshalJSON() ([]byte, error) { // must purchase a new commitment to continue receiving discounts. (== // resource_for beta.commitments ==) (== resource_for v1.commitments ==) type Commitment struct { + // Allocations: List of allocations for this commitment. + Allocations []*Allocation `json:"allocations,omitempty"` + // CreationTimestamp: [Output Only] Creation timestamp in RFC3339 text // format. CreationTimestamp string `json:"creationTimestamp,omitempty"` @@ -5184,21 +6031,20 @@ type Commitment struct { // server. googleapi.ServerResponse `json:"-"` - // ForceSendFields is a list of field names (e.g. "CreationTimestamp") - // to unconditionally include in API requests. By default, fields with + // ForceSendFields is a list of field names (e.g. "Allocations") to + // unconditionally include in API requests. By default, fields with // empty values are omitted from API requests. However, any non-pointer, // non-interface field appearing in ForceSendFields will be sent to the // server regardless of whether the field is empty or not. This may be // used to include empty fields in Patch requests. ForceSendFields []string `json:"-"` - // NullFields is a list of field names (e.g. "CreationTimestamp") to - // include in API requests with the JSON null value. By default, fields - // with empty values are omitted from API requests. However, any field - // with an empty value appearing in NullFields will be sent to the - // server as null. It is an error if a field in this list has a - // non-empty value. This may be used to include null fields in Patch - // requests. + // NullFields is a list of field names (e.g. "Allocations") to include + // in API requests with the JSON null value. By default, fields with + // empty values are omitted from API requests. However, any field with + // an empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. NullFields []string `json:"-"` } @@ -5944,7 +6790,8 @@ type Disk struct { // optimistic locking. The fingerprint is initially generated by Compute // Engine and changes after every request to modify or update labels. // You must always provide an up-to-date fingerprint hash in order to - // update or change labels. + // update or change labels, otherwise the request will fail with error + // 412 conditionNotMet. // // To see the latest fingerprint, make a get() request to retrieve a // disk. @@ -5966,7 +6813,8 @@ type Disk struct { // attached to this disk. LicenseCodes googleapi.Int64s `json:"licenseCodes,omitempty"` - // Licenses: Any applicable publicly visible licenses. + // Licenses: A list of publicly visible licenses. Reserved for Google's + // use. Licenses []string `json:"licenses,omitempty"` // Name: Name of the resource. Provided by the client when the resource @@ -5983,10 +6831,9 @@ type Disk struct { // PhysicalBlockSizeBytes: Physical block size of the persistent disk, // in bytes. If not present in a request, a default value is used. - // Initially only 4096 is supported, but other powers of two may be - // added. If an unsupported value is requested, the error message will - // list the supported values, but even a supported value may be allowed - // for only some projects. + // Currently supported sizes are 4096 and 16384, other sizes may be + // added in the future. If an unsupported value is requested, the error + // message will list the supported values for the caller's project. PhysicalBlockSizeBytes int64 `json:"physicalBlockSizeBytes,omitempty,string"` // Region: [Output Only] URL of the region where the disk resides. Only @@ -6023,15 +6870,15 @@ type Disk struct { // // To create a disk with one of the public operating system images, // specify the image by its family name. For example, specify - // family/debian-8 to use the latest Debian 8 + // family/debian-9 to use the latest Debian 9 // image: - // projects/debian-cloud/global/images/family/debian-8 + // projects/debian-cloud/global/images/family/debian-9 // // // Alternati // vely, use a specific version of a public operating system // image: - // projects/debian-cloud/global/images/debian-8-jessie-vYYYYMMDD + // projects/debian-cloud/global/images/debian-9-stretch-vYYYYMMDD // // // @@ -7295,7 +8142,37 @@ func (s *DisksScopedListWarningData) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +// DisplayDevice: A set of Display Device options +type DisplayDevice struct { + // EnableDisplay: Defines whether the instance has Display enabled. + EnableDisplay bool `json:"enableDisplay,omitempty"` + + // ForceSendFields is a list of field names (e.g. "EnableDisplay") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "EnableDisplay") to include + // in API requests with the JSON null value. By default, fields with + // empty values are omitted from API requests. However, any field with + // an empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *DisplayDevice) MarshalJSON() ([]byte, error) { + type NoMethod DisplayDevice + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + type DistributionPolicy struct { + // Zones: Zones where the regional managed instance group will create + // and manage instances. Zones []*DistributionPolicyZoneConfiguration `json:"zones,omitempty"` // ForceSendFields is a list of field names (e.g. "Zones") to @@ -7322,9 +8199,8 @@ func (s *DistributionPolicy) MarshalJSON() ([]byte, error) { } type DistributionPolicyZoneConfiguration struct { - // Zone: URL of the zone where managed instance group is spawning - // instances (for regional resources). Zone has to belong to the region - // where managed instance group is located. + // Zone: The URL of the zone. The zone must exist in the region where + // the managed instance group is located. Zone string `json:"zone,omitempty"` // ForceSendFields is a list of field names (e.g. "Zone") to @@ -7350,6 +8226,208 @@ func (s *DistributionPolicyZoneConfiguration) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +type ExchangedPeeringRoute struct { + // DestRange: The destination range of the route. + DestRange string `json:"destRange,omitempty"` + + // Imported: If the peering route is imported if there is no + // confliction. + Imported bool `json:"imported,omitempty"` + + // NextHopRegion: The region of peering route next hop, only applies to + // dynamic routes. + NextHopRegion string `json:"nextHopRegion,omitempty"` + + // Priority: The priority of the peering route. + Priority int64 `json:"priority,omitempty"` + + // Type: The type of the peering route. + // + // Possible values: + // "DYNAMIC_PEERING_ROUTE" + // "STATIC_PEERING_ROUTE" + // "SUBNET_PEERING_ROUTE" + Type string `json:"type,omitempty"` + + // ForceSendFields is a list of field names (e.g. "DestRange") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "DestRange") to include in + // API requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *ExchangedPeeringRoute) MarshalJSON() ([]byte, error) { + type NoMethod ExchangedPeeringRoute + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type ExchangedPeeringRoutesList struct { + // Id: [Output Only] Unique identifier for the resource; defined by the + // server. + Id string `json:"id,omitempty"` + + // Items: A list of ExchangedPeeringRoute resources. + Items []*ExchangedPeeringRoute `json:"items,omitempty"` + + // Kind: [Output Only] Type of resource. Always + // compute#exchangedPeeringRoutesList for exchanged peering routes + // lists. + Kind string `json:"kind,omitempty"` + + // NextPageToken: [Output Only] This token allows you to get the next + // page of results for list requests. If the number of results is larger + // than maxResults, use the nextPageToken as a value for the query + // parameter pageToken in the next list request. Subsequent list + // requests will have their own nextPageToken to continue paging through + // the results. + NextPageToken string `json:"nextPageToken,omitempty"` + + // SelfLink: [Output Only] Server-defined URL for this resource. + SelfLink string `json:"selfLink,omitempty"` + + // Warning: [Output Only] Informational warning message. + Warning *ExchangedPeeringRoutesListWarning `json:"warning,omitempty"` + + // ServerResponse contains the HTTP response code and headers from the + // server. + googleapi.ServerResponse `json:"-"` + + // ForceSendFields is a list of field names (e.g. "Id") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Id") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *ExchangedPeeringRoutesList) MarshalJSON() ([]byte, error) { + type NoMethod ExchangedPeeringRoutesList + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// ExchangedPeeringRoutesListWarning: [Output Only] Informational +// warning message. +type ExchangedPeeringRoutesListWarning struct { + // Code: [Output Only] A warning code, if applicable. For example, + // Compute Engine returns NO_RESULTS_ON_PAGE if there are no results in + // the response. + // + // Possible values: + // "CLEANUP_FAILED" + // "DEPRECATED_RESOURCE_USED" + // "DEPRECATED_TYPE_USED" + // "DISK_SIZE_LARGER_THAN_IMAGE_SIZE" + // "EXPERIMENTAL_TYPE_USED" + // "EXTERNAL_API_WARNING" + // "FIELD_VALUE_OVERRIDEN" + // "INJECTED_KERNELS_DEPRECATED" + // "MISSING_TYPE_DEPENDENCY" + // "NEXT_HOP_ADDRESS_NOT_ASSIGNED" + // "NEXT_HOP_CANNOT_IP_FORWARD" + // "NEXT_HOP_INSTANCE_NOT_FOUND" + // "NEXT_HOP_INSTANCE_NOT_ON_NETWORK" + // "NEXT_HOP_NOT_RUNNING" + // "NOT_CRITICAL_ERROR" + // "NO_RESULTS_ON_PAGE" + // "REQUIRED_TOS_AGREEMENT" + // "RESOURCE_IN_USE_BY_OTHER_RESOURCE_WARNING" + // "RESOURCE_NOT_DELETED" + // "SCHEMA_VALIDATION_IGNORED" + // "SINGLE_INSTANCE_PROPERTY_TEMPLATE" + // "UNDECLARED_PROPERTIES" + // "UNREACHABLE" + Code string `json:"code,omitempty"` + + // Data: [Output Only] Metadata about this warning in key: value format. + // For example: + // "data": [ { "key": "scope", "value": "zones/us-east1-d" } + Data []*ExchangedPeeringRoutesListWarningData `json:"data,omitempty"` + + // Message: [Output Only] A human-readable description of the warning + // code. + Message string `json:"message,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Code") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Code") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *ExchangedPeeringRoutesListWarning) MarshalJSON() ([]byte, error) { + type NoMethod ExchangedPeeringRoutesListWarning + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type ExchangedPeeringRoutesListWarningData struct { + // Key: [Output Only] A key that provides more detail on the warning + // being returned. For example, for warnings where there are no results + // in a list request for a particular zone, this key might be scope and + // the key value might be the zone name. Other examples might be a key + // indicating a deprecated resource and a suggested replacement, or a + // warning about invalid network settings (for example, if an instance + // attempts to perform IP forwarding but is not enabled for IP + // forwarding). + Key string `json:"key,omitempty"` + + // Value: [Output Only] A warning data value corresponding to the key. + Value string `json:"value,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Key") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Key") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *ExchangedPeeringRoutesListWarningData) MarshalJSON() ([]byte, error) { + type NoMethod ExchangedPeeringRoutesListWarningData + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + // Expr: Represents an expression text. Example: // // title: "User account presence" description: "Determines whether the @@ -7442,9 +8520,9 @@ type Firewall struct { // not exist. If this is unspecified, the firewall rule will be enabled. Disabled bool `json:"disabled,omitempty"` - // EnableLogging: This field denotes whether to enable logging for a - // particular firewall rule. If logging is enabled, logs will be - // exported to Stackdriver. + // EnableLogging: Deprecated in favor of enable in LogConfig. This field + // denotes whether to enable logging for a particular firewall rule. If + // logging is enabled, logs will be exported to Stackdriver. EnableLogging bool `json:"enableLogging,omitempty"` // Id: [Output Only] The unique identifier for the resource. This @@ -7455,6 +8533,11 @@ type Firewall struct { // firewall rules. Kind string `json:"kind,omitempty"` + // LogConfig: This field denotes the logging options for a particular + // firewall rule. If logging is enabled, logs will be exported to + // Stackdriver. + LogConfig *FirewallLogConfig `json:"logConfig,omitempty"` + // Name: Name of the resource; provided by the client when the resource // is created. The name must be 1-63 characters long, and comply with // RFC1035. Specifically, the name must be 1-63 characters long and @@ -7799,6 +8882,35 @@ func (s *FirewallListWarningData) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +// FirewallLogConfig: The available logging options for a firewall rule. +type FirewallLogConfig struct { + // Enable: This field denotes whether to enable logging for a particular + // firewall rule. + Enable bool `json:"enable,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Enable") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Enable") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *FirewallLogConfig) MarshalJSON() ([]byte, error) { + type NoMethod FirewallLogConfig + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + // FixedOrPercent: Encapsulates numeric value that can be either // absolute or relative. type FixedOrPercent struct { @@ -7869,6 +8981,11 @@ type ForwardingRule struct { // rule supports IPv4 only. A global forwarding rule supports either // IPv4 or IPv6. // + // When the load balancing scheme is INTERNAL_SELF_MANAGED, this must be + // a URL reference to an existing Address resource ( internal regional + // static IP address), with a purpose of GCE_END_POINT and address_type + // of INTERNAL. + // // When the load balancing scheme is INTERNAL, this can only be an RFC // 1918 IP address belonging to the network/subnet configured for the // forwarding rule. By default, if this field is empty, an ephemeral @@ -7891,7 +9008,8 @@ type ForwardingRule struct { // are TCP, UDP, ESP, AH, SCTP or ICMP. // // When the load balancing scheme is INTERNAL, only TCP and UDP are - // valid. + // valid. When the load balancing scheme is INTERNAL_SELF_MANAGED, only + // TCPis valid. // // Possible values: // "AH" @@ -7912,7 +9030,14 @@ type ForwardingRule struct { // forwarded to the backends configured with this forwarding rule. AllPorts bool `json:"allPorts,omitempty"` - // BackendService: This field is not used for external load + // AllowGlobalAccess: This field is used along with the backend_service + // field for internal load balancing or with the target field for + // internal TargetInstance. If the field is set to TRUE, clients can + // access ILB from all regions. Otherwise only allows access from + // clients in the same region as the internal load balancer. + AllowGlobalAccess bool `json:"allowGlobalAccess,omitempty"` + + // BackendService: This field is only used for INTERNAL load // balancing. // // For internal load balancing, this field identifies the BackendService @@ -7942,8 +9067,8 @@ type ForwardingRule struct { Id uint64 `json:"id,omitempty,string"` // IpVersion: The IP Version that will be used by this forwarding rule. - // Valid options are IPV4 or IPV6. This can only be specified for a - // global forwarding rule. + // Valid options are IPV4 or IPV6. This can only be specified for an + // external global forwarding rule. // // Possible values: // "IPV4" @@ -7960,7 +9085,8 @@ type ForwardingRule struct { // optimistic locking. The fingerprint is initially generated by Compute // Engine and changes after every request to modify or update labels. // You must always provide an up-to-date fingerprint hash in order to - // update or change labels. + // update or change labels, otherwise the request will fail with error + // 412 conditionNotMet. // // To see the latest fingerprint, make a get() request to retrieve a // ForwardingRule. @@ -7972,15 +9098,18 @@ type ForwardingRule struct { Labels map[string]string `json:"labels,omitempty"` // LoadBalancingScheme: This signifies what the ForwardingRule will be - // used for and can only take the following values: INTERNAL, EXTERNAL - // The value of INTERNAL means that this will be used for Internal - // Network Load Balancing (TCP, UDP). The value of EXTERNAL means that - // this will be used for External Load Balancing (HTTP(S) LB, External + // used for and can only take the following values: INTERNAL, + // INTERNAL_SELF_MANAGED, EXTERNAL. The value of INTERNAL means that + // this will be used for Internal Network Load Balancing (TCP, UDP). The + // value of INTERNAL_SELF_MANAGED means that this will be used for + // Internal Global HTTP(S) LB. The value of EXTERNAL means that this + // will be used for External Load Balancing (HTTP(S) LB, External // TCP/UDP LB, SSL Proxy) // // Possible values: // "EXTERNAL" // "INTERNAL" + // "INTERNAL_MANAGED" // "INTERNAL_SELF_MANAGED" // "INVALID" LoadBalancingScheme string `json:"loadBalancingScheme,omitempty"` @@ -7996,9 +9125,10 @@ type ForwardingRule struct { // Network: This field is not used for external load balancing. // - // For internal load balancing, this field identifies the network that - // the load balanced IP should belong to for this Forwarding Rule. If - // this field is not specified, the default network will be used. + // For INTERNAL and INTERNAL_SELF_MANAGED load balancing, this field + // identifies the network that the load balanced IP should belong to for + // this Forwarding Rule. If this field is not specified, the default + // network will be used. Network string `json:"network,omitempty"` // NetworkTier: This signifies the networking tier used for configuring @@ -8041,10 +9171,10 @@ type ForwardingRule struct { // Ports: This field is used along with the backend_service field for // internal load balancing. // - // When the load balancing scheme is INTERNAL, a single port or a comma - // separated list of ports can be configured. Only packets addressed to - // these ports will be forwarded to the backends configured with this - // forwarding rule. + // When the load balancing scheme is INTERNAL, a list of ports can be + // configured, for example, ['80'], ['8000','9000'] etc. Only packets + // addressed to these ports will be forwarded to the backends configured + // with this forwarding rule. // // You may specify a maximum of up to 5 ports. Ports []string `json:"ports,omitempty"` @@ -8078,7 +9208,7 @@ type ForwardingRule struct { // This field is only used for internal load balancing. ServiceName string `json:"serviceName,omitempty"` - // Subnetwork: This field is not used for external load balancing. + // Subnetwork: This field is only used for INTERNAL load balancing. // // For internal load balancing, this field identifies the subnetwork // that the load balanced IP should belong to for this Forwarding @@ -8093,7 +9223,9 @@ type ForwardingRule struct { // traffic. For regional forwarding rules, this target must live in the // same region as the forwarding rule. For global forwarding rules, this // target must be a global load balancing resource. The forwarded - // traffic must be of a type appropriate to the target object. + // traffic must be of a type appropriate to the target object. For + // INTERNAL_SELF_MANAGED" load balancing, only HTTP and HTTPS targets + // are valid. Target string `json:"target,omitempty"` // ServerResponse contains the HTTP response code and headers from the @@ -8599,7 +9731,8 @@ type GlobalSetLabelsRequest struct { // this resource, used to detect conflicts. The fingerprint is initially // generated by Compute Engine and changes after every request to modify // or update labels. You must always provide an up-to-date fingerprint - // hash when updating or changing labels. Make a get() request to the + // hash when updating or changing labels, otherwise the request will + // fail with error 412 conditionNotMet. Make a get() request to the // resource to get the latest fingerprint. LabelFingerprint string `json:"labelFingerprint,omitempty"` @@ -8638,7 +9771,7 @@ func (s *GlobalSetLabelsRequest) MarshalJSON() ([]byte, error) { } type GlobalSetPolicyRequest struct { - // Bindings: Flatten Policy to create a backwacd compatible wire-format. + // Bindings: Flatten Policy to create a backward compatible wire-format. // Deprecated. Use 'policy' to specify bindings. Bindings []*Binding `json:"bindings,omitempty"` @@ -8681,6 +9814,13 @@ type GuestAttributes struct { // compute#guestAttributes for guest attributes entry. Kind string `json:"kind,omitempty"` + // QueryPath: The path to be queried. This can be the default namespace + // ('/') or a nested namespace ('//') or a specified key ('//') + QueryPath string `json:"queryPath,omitempty"` + + // QueryValue: [Output Only] The value of the requested queried path. + QueryValue *GuestAttributesValue `json:"queryValue,omitempty"` + // SelfLink: [Output Only] Server-defined URL for this resource. SelfLink string `json:"selfLink,omitempty"` @@ -8717,6 +9857,68 @@ func (s *GuestAttributes) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +// GuestAttributesEntry: A guest attributes namespace/key/value entry. +type GuestAttributesEntry struct { + // Key: Key for the guest attribute entry. + Key string `json:"key,omitempty"` + + // Namespace: Namespace for the guest attribute entry. + Namespace string `json:"namespace,omitempty"` + + // Value: Value for the guest attribute entry. + Value string `json:"value,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Key") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Key") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *GuestAttributesEntry) MarshalJSON() ([]byte, error) { + type NoMethod GuestAttributesEntry + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// GuestAttributesValue: Array of guest attribute namespace/key/value +// tuples. +type GuestAttributesValue struct { + Items []*GuestAttributesEntry `json:"items,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Items") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Items") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *GuestAttributesValue) MarshalJSON() ([]byte, error) { + type NoMethod GuestAttributesValue + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + // GuestOsFeature: Guest OS features. type GuestOsFeature struct { // Type: The ID of a supported feature. Read Enabling guest operating @@ -9582,6 +10784,9 @@ func (s *HealthChecksScopedListWarningData) MarshalJSON() ([]byte, error) { } type HealthStatus struct { + // Annotations: Metadata defined as annotations for network endpoint. + Annotations map[string]string `json:"annotations,omitempty"` + // HealthState: Health state of the instance. // // Possible values: @@ -9598,7 +10803,7 @@ type HealthStatus struct { // Port: The port on the instance. Port int64 `json:"port,omitempty"` - // ForceSendFields is a list of field names (e.g. "HealthState") to + // ForceSendFields is a list of field names (e.g. "Annotations") to // unconditionally include in API requests. By default, fields with // empty values are omitted from API requests. However, any non-pointer, // non-interface field appearing in ForceSendFields will be sent to the @@ -9606,7 +10811,7 @@ type HealthStatus struct { // used to include empty fields in Patch requests. ForceSendFields []string `json:"-"` - // NullFields is a list of field names (e.g. "HealthState") to include + // NullFields is a list of field names (e.g. "Annotations") to include // in API requests with the JSON null value. By default, fields with // empty values are omitted from API requests. However, any field with // an empty value appearing in NullFields will be sent to the server as @@ -9668,419 +10873,6 @@ func (s *HealthStatusForNetworkEndpoint) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } -type Host struct { - // CreationTimestamp: [Output Only] Creation timestamp in RFC3339 text - // format. - CreationTimestamp string `json:"creationTimestamp,omitempty"` - - // Description: [Output Only] An optional textual description of the - // resource. - Description string `json:"description,omitempty"` - - // HostType: Full or partial URL of the host type resource to use for - // this host, in the format: zones/zone/hostTypes/host-type. This is - // provided by the client when the host is created. For example, the - // following is a valid partial url to a predefined host - // type: - // zones/us-central1-b/hostTypes/n1-host-64-416 - HostType string `json:"hostType,omitempty"` - - // Id: [Output Only] The unique identifier for the resource. This - // identifier is defined by the server. - Id uint64 `json:"id,omitempty,string"` - - // Instances: A list of resource URLs to the virtual machine instances - // in this host. They must live in zones contained in the same region as - // this host. - Instances []string `json:"instances,omitempty"` - - // Kind: [Output Only] The type of the resource. Always compute#host for - // host. - Kind string `json:"kind,omitempty"` - - // LabelFingerprint: A fingerprint for this request, which is - // essentially a hash of the metadata's contents and used for optimistic - // locking. The fingerprint is initially generated by Compute Engine and - // changes after every request to modify or update metadata. You must - // always provide an up-to-date fingerprint hash in order to update or - // change metadata. - // - // To see the latest fingerprint, make get() request to the host. - LabelFingerprint string `json:"labelFingerprint,omitempty"` - - // Labels: Labels to apply to this host. - Labels map[string]string `json:"labels,omitempty"` - - // Name: The name of the resource, provided by the client when initially - // creating the resource. The resource name must be 1-63 characters - // long, and comply with RFC1035. Specifically, the name must be 1-63 - // characters long and match the regular expression - // `[a-z]([-a-z0-9]*[a-z0-9])?` which means the first character must be - // a lowercase letter, and all following characters must be a dash, - // lowercase letter, or digit, except the last character, which cannot - // be a dash. - Name string `json:"name,omitempty"` - - // SelfLink: [Output Only] Server-defined URL for the resource. - SelfLink string `json:"selfLink,omitempty"` - - // Status: [Output Only] The status of the host. One of the following - // values: CREATING, READY, REPAIR, and DELETING. - // - // Possible values: - // "CREATING" - // "DELETING" - // "INVALID" - // "READY" - // "REPAIR" - Status string `json:"status,omitempty"` - - // StatusMessage: [Output Only] An optional, human-readable explanation - // of the status. - StatusMessage string `json:"statusMessage,omitempty"` - - // Zone: [Output Only] The name of the zone where the host resides, such - // as us-central1-a. - Zone string `json:"zone,omitempty"` - - // ServerResponse contains the HTTP response code and headers from the - // server. - googleapi.ServerResponse `json:"-"` - - // ForceSendFields is a list of field names (e.g. "CreationTimestamp") - // to unconditionally include in API requests. By default, fields with - // empty values are omitted from API requests. However, any non-pointer, - // non-interface field appearing in ForceSendFields will be sent to the - // server regardless of whether the field is empty or not. This may be - // used to include empty fields in Patch requests. - ForceSendFields []string `json:"-"` - - // NullFields is a list of field names (e.g. "CreationTimestamp") to - // include in API requests with the JSON null value. By default, fields - // with empty values are omitted from API requests. However, any field - // with an empty value appearing in NullFields will be sent to the - // server as null. It is an error if a field in this list has a - // non-empty value. This may be used to include null fields in Patch - // requests. - NullFields []string `json:"-"` -} - -func (s *Host) MarshalJSON() ([]byte, error) { - type NoMethod Host - raw := NoMethod(*s) - return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) -} - -type HostAggregatedList struct { - // Id: [Output Only] Unique identifier for the resource; defined by the - // server. - Id string `json:"id,omitempty"` - - // Items: A list of HostsScopedList resources. - Items map[string]HostsScopedList `json:"items,omitempty"` - - // Kind: [Output Only] Type of resource. Always - // compute#hostAggregatedList for aggregated lists of hosts. - Kind string `json:"kind,omitempty"` - - // NextPageToken: [Output Only] This token allows you to get the next - // page of results for list requests. If the number of results is larger - // than maxResults, use the nextPageToken as a value for the query - // parameter pageToken in the next list request. Subsequent list - // requests will have their own nextPageToken to continue paging through - // the results. - NextPageToken string `json:"nextPageToken,omitempty"` - - // SelfLink: [Output Only] Server-defined URL for this resource. - SelfLink string `json:"selfLink,omitempty"` - - // Warning: [Output Only] Informational warning message. - Warning *HostAggregatedListWarning `json:"warning,omitempty"` - - // ServerResponse contains the HTTP response code and headers from the - // server. - googleapi.ServerResponse `json:"-"` - - // ForceSendFields is a list of field names (e.g. "Id") to - // unconditionally include in API requests. By default, fields with - // empty values are omitted from API requests. However, any non-pointer, - // non-interface field appearing in ForceSendFields will be sent to the - // server regardless of whether the field is empty or not. This may be - // used to include empty fields in Patch requests. - ForceSendFields []string `json:"-"` - - // NullFields is a list of field names (e.g. "Id") to include in API - // requests with the JSON null value. By default, fields with empty - // values are omitted from API requests. However, any field with an - // empty value appearing in NullFields will be sent to the server as - // null. It is an error if a field in this list has a non-empty value. - // This may be used to include null fields in Patch requests. - NullFields []string `json:"-"` -} - -func (s *HostAggregatedList) MarshalJSON() ([]byte, error) { - type NoMethod HostAggregatedList - raw := NoMethod(*s) - return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) -} - -// HostAggregatedListWarning: [Output Only] Informational warning -// message. -type HostAggregatedListWarning struct { - // Code: [Output Only] A warning code, if applicable. For example, - // Compute Engine returns NO_RESULTS_ON_PAGE if there are no results in - // the response. - // - // Possible values: - // "CLEANUP_FAILED" - // "DEPRECATED_RESOURCE_USED" - // "DEPRECATED_TYPE_USED" - // "DISK_SIZE_LARGER_THAN_IMAGE_SIZE" - // "EXPERIMENTAL_TYPE_USED" - // "EXTERNAL_API_WARNING" - // "FIELD_VALUE_OVERRIDEN" - // "INJECTED_KERNELS_DEPRECATED" - // "MISSING_TYPE_DEPENDENCY" - // "NEXT_HOP_ADDRESS_NOT_ASSIGNED" - // "NEXT_HOP_CANNOT_IP_FORWARD" - // "NEXT_HOP_INSTANCE_NOT_FOUND" - // "NEXT_HOP_INSTANCE_NOT_ON_NETWORK" - // "NEXT_HOP_NOT_RUNNING" - // "NOT_CRITICAL_ERROR" - // "NO_RESULTS_ON_PAGE" - // "REQUIRED_TOS_AGREEMENT" - // "RESOURCE_IN_USE_BY_OTHER_RESOURCE_WARNING" - // "RESOURCE_NOT_DELETED" - // "SCHEMA_VALIDATION_IGNORED" - // "SINGLE_INSTANCE_PROPERTY_TEMPLATE" - // "UNDECLARED_PROPERTIES" - // "UNREACHABLE" - Code string `json:"code,omitempty"` - - // Data: [Output Only] Metadata about this warning in key: value format. - // For example: - // "data": [ { "key": "scope", "value": "zones/us-east1-d" } - Data []*HostAggregatedListWarningData `json:"data,omitempty"` - - // Message: [Output Only] A human-readable description of the warning - // code. - Message string `json:"message,omitempty"` - - // ForceSendFields is a list of field names (e.g. "Code") to - // unconditionally include in API requests. By default, fields with - // empty values are omitted from API requests. However, any non-pointer, - // non-interface field appearing in ForceSendFields will be sent to the - // server regardless of whether the field is empty or not. This may be - // used to include empty fields in Patch requests. - ForceSendFields []string `json:"-"` - - // NullFields is a list of field names (e.g. "Code") to include in API - // requests with the JSON null value. By default, fields with empty - // values are omitted from API requests. However, any field with an - // empty value appearing in NullFields will be sent to the server as - // null. It is an error if a field in this list has a non-empty value. - // This may be used to include null fields in Patch requests. - NullFields []string `json:"-"` -} - -func (s *HostAggregatedListWarning) MarshalJSON() ([]byte, error) { - type NoMethod HostAggregatedListWarning - raw := NoMethod(*s) - return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) -} - -type HostAggregatedListWarningData struct { - // Key: [Output Only] A key that provides more detail on the warning - // being returned. For example, for warnings where there are no results - // in a list request for a particular zone, this key might be scope and - // the key value might be the zone name. Other examples might be a key - // indicating a deprecated resource and a suggested replacement, or a - // warning about invalid network settings (for example, if an instance - // attempts to perform IP forwarding but is not enabled for IP - // forwarding). - Key string `json:"key,omitempty"` - - // Value: [Output Only] A warning data value corresponding to the key. - Value string `json:"value,omitempty"` - - // ForceSendFields is a list of field names (e.g. "Key") to - // unconditionally include in API requests. By default, fields with - // empty values are omitted from API requests. However, any non-pointer, - // non-interface field appearing in ForceSendFields will be sent to the - // server regardless of whether the field is empty or not. This may be - // used to include empty fields in Patch requests. - ForceSendFields []string `json:"-"` - - // NullFields is a list of field names (e.g. "Key") to include in API - // requests with the JSON null value. By default, fields with empty - // values are omitted from API requests. However, any field with an - // empty value appearing in NullFields will be sent to the server as - // null. It is an error if a field in this list has a non-empty value. - // This may be used to include null fields in Patch requests. - NullFields []string `json:"-"` -} - -func (s *HostAggregatedListWarningData) MarshalJSON() ([]byte, error) { - type NoMethod HostAggregatedListWarningData - raw := NoMethod(*s) - return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) -} - -// HostList: Contains a list of hosts. -type HostList struct { - // Id: [Output Only] Unique identifier for the resource; defined by the - // server. - Id string `json:"id,omitempty"` - - // Items: A list of Host resources. - Items []*Host `json:"items,omitempty"` - - // Kind: [Output Only] Type of resource. Always compute#hostList for - // lists of hosts. - Kind string `json:"kind,omitempty"` - - // NextPageToken: [Output Only] This token allows you to get the next - // page of results for list requests. If the number of results is larger - // than maxResults, use the nextPageToken as a value for the query - // parameter pageToken in the next list request. Subsequent list - // requests will have their own nextPageToken to continue paging through - // the results. - NextPageToken string `json:"nextPageToken,omitempty"` - - // SelfLink: [Output Only] Server-defined URL for this resource. - SelfLink string `json:"selfLink,omitempty"` - - // Warning: [Output Only] Informational warning message. - Warning *HostListWarning `json:"warning,omitempty"` - - // ServerResponse contains the HTTP response code and headers from the - // server. - googleapi.ServerResponse `json:"-"` - - // ForceSendFields is a list of field names (e.g. "Id") to - // unconditionally include in API requests. By default, fields with - // empty values are omitted from API requests. However, any non-pointer, - // non-interface field appearing in ForceSendFields will be sent to the - // server regardless of whether the field is empty or not. This may be - // used to include empty fields in Patch requests. - ForceSendFields []string `json:"-"` - - // NullFields is a list of field names (e.g. "Id") to include in API - // requests with the JSON null value. By default, fields with empty - // values are omitted from API requests. However, any field with an - // empty value appearing in NullFields will be sent to the server as - // null. It is an error if a field in this list has a non-empty value. - // This may be used to include null fields in Patch requests. - NullFields []string `json:"-"` -} - -func (s *HostList) MarshalJSON() ([]byte, error) { - type NoMethod HostList - raw := NoMethod(*s) - return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) -} - -// HostListWarning: [Output Only] Informational warning message. -type HostListWarning struct { - // Code: [Output Only] A warning code, if applicable. For example, - // Compute Engine returns NO_RESULTS_ON_PAGE if there are no results in - // the response. - // - // Possible values: - // "CLEANUP_FAILED" - // "DEPRECATED_RESOURCE_USED" - // "DEPRECATED_TYPE_USED" - // "DISK_SIZE_LARGER_THAN_IMAGE_SIZE" - // "EXPERIMENTAL_TYPE_USED" - // "EXTERNAL_API_WARNING" - // "FIELD_VALUE_OVERRIDEN" - // "INJECTED_KERNELS_DEPRECATED" - // "MISSING_TYPE_DEPENDENCY" - // "NEXT_HOP_ADDRESS_NOT_ASSIGNED" - // "NEXT_HOP_CANNOT_IP_FORWARD" - // "NEXT_HOP_INSTANCE_NOT_FOUND" - // "NEXT_HOP_INSTANCE_NOT_ON_NETWORK" - // "NEXT_HOP_NOT_RUNNING" - // "NOT_CRITICAL_ERROR" - // "NO_RESULTS_ON_PAGE" - // "REQUIRED_TOS_AGREEMENT" - // "RESOURCE_IN_USE_BY_OTHER_RESOURCE_WARNING" - // "RESOURCE_NOT_DELETED" - // "SCHEMA_VALIDATION_IGNORED" - // "SINGLE_INSTANCE_PROPERTY_TEMPLATE" - // "UNDECLARED_PROPERTIES" - // "UNREACHABLE" - Code string `json:"code,omitempty"` - - // Data: [Output Only] Metadata about this warning in key: value format. - // For example: - // "data": [ { "key": "scope", "value": "zones/us-east1-d" } - Data []*HostListWarningData `json:"data,omitempty"` - - // Message: [Output Only] A human-readable description of the warning - // code. - Message string `json:"message,omitempty"` - - // ForceSendFields is a list of field names (e.g. "Code") to - // unconditionally include in API requests. By default, fields with - // empty values are omitted from API requests. However, any non-pointer, - // non-interface field appearing in ForceSendFields will be sent to the - // server regardless of whether the field is empty or not. This may be - // used to include empty fields in Patch requests. - ForceSendFields []string `json:"-"` - - // NullFields is a list of field names (e.g. "Code") to include in API - // requests with the JSON null value. By default, fields with empty - // values are omitted from API requests. However, any field with an - // empty value appearing in NullFields will be sent to the server as - // null. It is an error if a field in this list has a non-empty value. - // This may be used to include null fields in Patch requests. - NullFields []string `json:"-"` -} - -func (s *HostListWarning) MarshalJSON() ([]byte, error) { - type NoMethod HostListWarning - raw := NoMethod(*s) - return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) -} - -type HostListWarningData struct { - // Key: [Output Only] A key that provides more detail on the warning - // being returned. For example, for warnings where there are no results - // in a list request for a particular zone, this key might be scope and - // the key value might be the zone name. Other examples might be a key - // indicating a deprecated resource and a suggested replacement, or a - // warning about invalid network settings (for example, if an instance - // attempts to perform IP forwarding but is not enabled for IP - // forwarding). - Key string `json:"key,omitempty"` - - // Value: [Output Only] A warning data value corresponding to the key. - Value string `json:"value,omitempty"` - - // ForceSendFields is a list of field names (e.g. "Key") to - // unconditionally include in API requests. By default, fields with - // empty values are omitted from API requests. However, any non-pointer, - // non-interface field appearing in ForceSendFields will be sent to the - // server regardless of whether the field is empty or not. This may be - // used to include empty fields in Patch requests. - ForceSendFields []string `json:"-"` - - // NullFields is a list of field names (e.g. "Key") to include in API - // requests with the JSON null value. By default, fields with empty - // values are omitted from API requests. However, any field with an - // empty value appearing in NullFields will be sent to the server as - // null. It is an error if a field in this list has a non-empty value. - // This may be used to include null fields in Patch requests. - NullFields []string `json:"-"` -} - -func (s *HostListWarningData) MarshalJSON() ([]byte, error) { - type NoMethod HostListWarningData - raw := NoMethod(*s) - return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) -} - // HostRule: UrlMaps A host-matching rule for a URL. If matched, will // use the named PathMatcher to select the BackendService. type HostRule struct { @@ -10121,657 +10913,6 @@ func (s *HostRule) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } -// HostType: A Host Type resource. -type HostType struct { - // CpuPlatform: [Output Only] The CPU platform used by this host type. - CpuPlatform string `json:"cpuPlatform,omitempty"` - - // CreationTimestamp: [Output Only] Creation timestamp in RFC3339 text - // format. - CreationTimestamp string `json:"creationTimestamp,omitempty"` - - // Deprecated: [Output Only] The deprecation status associated with this - // host type. - Deprecated *DeprecationStatus `json:"deprecated,omitempty"` - - // Description: [Output Only] An optional textual description of the - // resource. - Description string `json:"description,omitempty"` - - // GuestCpus: [Output Only] The number of virtual CPUs that are - // available to the host type. - GuestCpus int64 `json:"guestCpus,omitempty"` - - // Id: [Output Only] The unique identifier for the resource. This - // identifier is defined by the server. - Id uint64 `json:"id,omitempty,string"` - - // Kind: [Output Only] The type of the resource. Always compute#hostType - // for host types. - Kind string `json:"kind,omitempty"` - - // LocalSsdGb: [Output Only] Local SSD available to the host type, - // defined in GB. - LocalSsdGb int64 `json:"localSsdGb,omitempty"` - - // MemoryMb: [Output Only] The amount of physical memory available to - // the host type, defined in MB. - MemoryMb int64 `json:"memoryMb,omitempty"` - - // Name: [Output Only] Name of the resource. - Name string `json:"name,omitempty"` - - // SelfLink: [Output Only] Server-defined URL for the resource. - SelfLink string `json:"selfLink,omitempty"` - - // Zone: [Output Only] The name of the zone where the host type resides, - // such as us-central1-a. - Zone string `json:"zone,omitempty"` - - // ServerResponse contains the HTTP response code and headers from the - // server. - googleapi.ServerResponse `json:"-"` - - // ForceSendFields is a list of field names (e.g. "CpuPlatform") to - // unconditionally include in API requests. By default, fields with - // empty values are omitted from API requests. However, any non-pointer, - // non-interface field appearing in ForceSendFields will be sent to the - // server regardless of whether the field is empty or not. This may be - // used to include empty fields in Patch requests. - ForceSendFields []string `json:"-"` - - // NullFields is a list of field names (e.g. "CpuPlatform") to include - // in API requests with the JSON null value. By default, fields with - // empty values are omitted from API requests. However, any field with - // an empty value appearing in NullFields will be sent to the server as - // null. It is an error if a field in this list has a non-empty value. - // This may be used to include null fields in Patch requests. - NullFields []string `json:"-"` -} - -func (s *HostType) MarshalJSON() ([]byte, error) { - type NoMethod HostType - raw := NoMethod(*s) - return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) -} - -type HostTypeAggregatedList struct { - // Id: [Output Only] Unique identifier for the resource; defined by the - // server. - Id string `json:"id,omitempty"` - - // Items: A list of HostTypesScopedList resources. - Items map[string]HostTypesScopedList `json:"items,omitempty"` - - // Kind: [Output Only] Type of resource.Always - // compute#hostTypeAggregatedList for aggregated lists of host types. - Kind string `json:"kind,omitempty"` - - // NextPageToken: [Output Only] This token allows you to get the next - // page of results for list requests. If the number of results is larger - // than maxResults, use the nextPageToken as a value for the query - // parameter pageToken in the next list request. Subsequent list - // requests will have their own nextPageToken to continue paging through - // the results. - NextPageToken string `json:"nextPageToken,omitempty"` - - // SelfLink: [Output Only] Server-defined URL for this resource. - SelfLink string `json:"selfLink,omitempty"` - - // Warning: [Output Only] Informational warning message. - Warning *HostTypeAggregatedListWarning `json:"warning,omitempty"` - - // ServerResponse contains the HTTP response code and headers from the - // server. - googleapi.ServerResponse `json:"-"` - - // ForceSendFields is a list of field names (e.g. "Id") to - // unconditionally include in API requests. By default, fields with - // empty values are omitted from API requests. However, any non-pointer, - // non-interface field appearing in ForceSendFields will be sent to the - // server regardless of whether the field is empty or not. This may be - // used to include empty fields in Patch requests. - ForceSendFields []string `json:"-"` - - // NullFields is a list of field names (e.g. "Id") to include in API - // requests with the JSON null value. By default, fields with empty - // values are omitted from API requests. However, any field with an - // empty value appearing in NullFields will be sent to the server as - // null. It is an error if a field in this list has a non-empty value. - // This may be used to include null fields in Patch requests. - NullFields []string `json:"-"` -} - -func (s *HostTypeAggregatedList) MarshalJSON() ([]byte, error) { - type NoMethod HostTypeAggregatedList - raw := NoMethod(*s) - return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) -} - -// HostTypeAggregatedListWarning: [Output Only] Informational warning -// message. -type HostTypeAggregatedListWarning struct { - // Code: [Output Only] A warning code, if applicable. For example, - // Compute Engine returns NO_RESULTS_ON_PAGE if there are no results in - // the response. - // - // Possible values: - // "CLEANUP_FAILED" - // "DEPRECATED_RESOURCE_USED" - // "DEPRECATED_TYPE_USED" - // "DISK_SIZE_LARGER_THAN_IMAGE_SIZE" - // "EXPERIMENTAL_TYPE_USED" - // "EXTERNAL_API_WARNING" - // "FIELD_VALUE_OVERRIDEN" - // "INJECTED_KERNELS_DEPRECATED" - // "MISSING_TYPE_DEPENDENCY" - // "NEXT_HOP_ADDRESS_NOT_ASSIGNED" - // "NEXT_HOP_CANNOT_IP_FORWARD" - // "NEXT_HOP_INSTANCE_NOT_FOUND" - // "NEXT_HOP_INSTANCE_NOT_ON_NETWORK" - // "NEXT_HOP_NOT_RUNNING" - // "NOT_CRITICAL_ERROR" - // "NO_RESULTS_ON_PAGE" - // "REQUIRED_TOS_AGREEMENT" - // "RESOURCE_IN_USE_BY_OTHER_RESOURCE_WARNING" - // "RESOURCE_NOT_DELETED" - // "SCHEMA_VALIDATION_IGNORED" - // "SINGLE_INSTANCE_PROPERTY_TEMPLATE" - // "UNDECLARED_PROPERTIES" - // "UNREACHABLE" - Code string `json:"code,omitempty"` - - // Data: [Output Only] Metadata about this warning in key: value format. - // For example: - // "data": [ { "key": "scope", "value": "zones/us-east1-d" } - Data []*HostTypeAggregatedListWarningData `json:"data,omitempty"` - - // Message: [Output Only] A human-readable description of the warning - // code. - Message string `json:"message,omitempty"` - - // ForceSendFields is a list of field names (e.g. "Code") to - // unconditionally include in API requests. By default, fields with - // empty values are omitted from API requests. However, any non-pointer, - // non-interface field appearing in ForceSendFields will be sent to the - // server regardless of whether the field is empty or not. This may be - // used to include empty fields in Patch requests. - ForceSendFields []string `json:"-"` - - // NullFields is a list of field names (e.g. "Code") to include in API - // requests with the JSON null value. By default, fields with empty - // values are omitted from API requests. However, any field with an - // empty value appearing in NullFields will be sent to the server as - // null. It is an error if a field in this list has a non-empty value. - // This may be used to include null fields in Patch requests. - NullFields []string `json:"-"` -} - -func (s *HostTypeAggregatedListWarning) MarshalJSON() ([]byte, error) { - type NoMethod HostTypeAggregatedListWarning - raw := NoMethod(*s) - return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) -} - -type HostTypeAggregatedListWarningData struct { - // Key: [Output Only] A key that provides more detail on the warning - // being returned. For example, for warnings where there are no results - // in a list request for a particular zone, this key might be scope and - // the key value might be the zone name. Other examples might be a key - // indicating a deprecated resource and a suggested replacement, or a - // warning about invalid network settings (for example, if an instance - // attempts to perform IP forwarding but is not enabled for IP - // forwarding). - Key string `json:"key,omitempty"` - - // Value: [Output Only] A warning data value corresponding to the key. - Value string `json:"value,omitempty"` - - // ForceSendFields is a list of field names (e.g. "Key") to - // unconditionally include in API requests. By default, fields with - // empty values are omitted from API requests. However, any non-pointer, - // non-interface field appearing in ForceSendFields will be sent to the - // server regardless of whether the field is empty or not. This may be - // used to include empty fields in Patch requests. - ForceSendFields []string `json:"-"` - - // NullFields is a list of field names (e.g. "Key") to include in API - // requests with the JSON null value. By default, fields with empty - // values are omitted from API requests. However, any field with an - // empty value appearing in NullFields will be sent to the server as - // null. It is an error if a field in this list has a non-empty value. - // This may be used to include null fields in Patch requests. - NullFields []string `json:"-"` -} - -func (s *HostTypeAggregatedListWarningData) MarshalJSON() ([]byte, error) { - type NoMethod HostTypeAggregatedListWarningData - raw := NoMethod(*s) - return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) -} - -// HostTypeList: Contains a list of host types. -type HostTypeList struct { - // Id: [Output Only] Unique identifier for the resource; defined by the - // server. - Id string `json:"id,omitempty"` - - // Items: A list of HostType resources. - Items []*HostType `json:"items,omitempty"` - - // Kind: [Output Only] Type of resource.Always compute#hostTypeList for - // lists of host types. - Kind string `json:"kind,omitempty"` - - // NextPageToken: [Output Only] This token allows you to get the next - // page of results for list requests. If the number of results is larger - // than maxResults, use the nextPageToken as a value for the query - // parameter pageToken in the next list request. Subsequent list - // requests will have their own nextPageToken to continue paging through - // the results. - NextPageToken string `json:"nextPageToken,omitempty"` - - // SelfLink: [Output Only] Server-defined URL for this resource. - SelfLink string `json:"selfLink,omitempty"` - - // Warning: [Output Only] Informational warning message. - Warning *HostTypeListWarning `json:"warning,omitempty"` - - // ServerResponse contains the HTTP response code and headers from the - // server. - googleapi.ServerResponse `json:"-"` - - // ForceSendFields is a list of field names (e.g. "Id") to - // unconditionally include in API requests. By default, fields with - // empty values are omitted from API requests. However, any non-pointer, - // non-interface field appearing in ForceSendFields will be sent to the - // server regardless of whether the field is empty or not. This may be - // used to include empty fields in Patch requests. - ForceSendFields []string `json:"-"` - - // NullFields is a list of field names (e.g. "Id") to include in API - // requests with the JSON null value. By default, fields with empty - // values are omitted from API requests. However, any field with an - // empty value appearing in NullFields will be sent to the server as - // null. It is an error if a field in this list has a non-empty value. - // This may be used to include null fields in Patch requests. - NullFields []string `json:"-"` -} - -func (s *HostTypeList) MarshalJSON() ([]byte, error) { - type NoMethod HostTypeList - raw := NoMethod(*s) - return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) -} - -// HostTypeListWarning: [Output Only] Informational warning message. -type HostTypeListWarning struct { - // Code: [Output Only] A warning code, if applicable. For example, - // Compute Engine returns NO_RESULTS_ON_PAGE if there are no results in - // the response. - // - // Possible values: - // "CLEANUP_FAILED" - // "DEPRECATED_RESOURCE_USED" - // "DEPRECATED_TYPE_USED" - // "DISK_SIZE_LARGER_THAN_IMAGE_SIZE" - // "EXPERIMENTAL_TYPE_USED" - // "EXTERNAL_API_WARNING" - // "FIELD_VALUE_OVERRIDEN" - // "INJECTED_KERNELS_DEPRECATED" - // "MISSING_TYPE_DEPENDENCY" - // "NEXT_HOP_ADDRESS_NOT_ASSIGNED" - // "NEXT_HOP_CANNOT_IP_FORWARD" - // "NEXT_HOP_INSTANCE_NOT_FOUND" - // "NEXT_HOP_INSTANCE_NOT_ON_NETWORK" - // "NEXT_HOP_NOT_RUNNING" - // "NOT_CRITICAL_ERROR" - // "NO_RESULTS_ON_PAGE" - // "REQUIRED_TOS_AGREEMENT" - // "RESOURCE_IN_USE_BY_OTHER_RESOURCE_WARNING" - // "RESOURCE_NOT_DELETED" - // "SCHEMA_VALIDATION_IGNORED" - // "SINGLE_INSTANCE_PROPERTY_TEMPLATE" - // "UNDECLARED_PROPERTIES" - // "UNREACHABLE" - Code string `json:"code,omitempty"` - - // Data: [Output Only] Metadata about this warning in key: value format. - // For example: - // "data": [ { "key": "scope", "value": "zones/us-east1-d" } - Data []*HostTypeListWarningData `json:"data,omitempty"` - - // Message: [Output Only] A human-readable description of the warning - // code. - Message string `json:"message,omitempty"` - - // ForceSendFields is a list of field names (e.g. "Code") to - // unconditionally include in API requests. By default, fields with - // empty values are omitted from API requests. However, any non-pointer, - // non-interface field appearing in ForceSendFields will be sent to the - // server regardless of whether the field is empty or not. This may be - // used to include empty fields in Patch requests. - ForceSendFields []string `json:"-"` - - // NullFields is a list of field names (e.g. "Code") to include in API - // requests with the JSON null value. By default, fields with empty - // values are omitted from API requests. However, any field with an - // empty value appearing in NullFields will be sent to the server as - // null. It is an error if a field in this list has a non-empty value. - // This may be used to include null fields in Patch requests. - NullFields []string `json:"-"` -} - -func (s *HostTypeListWarning) MarshalJSON() ([]byte, error) { - type NoMethod HostTypeListWarning - raw := NoMethod(*s) - return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) -} - -type HostTypeListWarningData struct { - // Key: [Output Only] A key that provides more detail on the warning - // being returned. For example, for warnings where there are no results - // in a list request for a particular zone, this key might be scope and - // the key value might be the zone name. Other examples might be a key - // indicating a deprecated resource and a suggested replacement, or a - // warning about invalid network settings (for example, if an instance - // attempts to perform IP forwarding but is not enabled for IP - // forwarding). - Key string `json:"key,omitempty"` - - // Value: [Output Only] A warning data value corresponding to the key. - Value string `json:"value,omitempty"` - - // ForceSendFields is a list of field names (e.g. "Key") to - // unconditionally include in API requests. By default, fields with - // empty values are omitted from API requests. However, any non-pointer, - // non-interface field appearing in ForceSendFields will be sent to the - // server regardless of whether the field is empty or not. This may be - // used to include empty fields in Patch requests. - ForceSendFields []string `json:"-"` - - // NullFields is a list of field names (e.g. "Key") to include in API - // requests with the JSON null value. By default, fields with empty - // values are omitted from API requests. However, any field with an - // empty value appearing in NullFields will be sent to the server as - // null. It is an error if a field in this list has a non-empty value. - // This may be used to include null fields in Patch requests. - NullFields []string `json:"-"` -} - -func (s *HostTypeListWarningData) MarshalJSON() ([]byte, error) { - type NoMethod HostTypeListWarningData - raw := NoMethod(*s) - return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) -} - -type HostTypesScopedList struct { - // HostTypes: [Output Only] A list of host types contained in this - // scope. - HostTypes []*HostType `json:"hostTypes,omitempty"` - - // Warning: [Output Only] An informational warning that appears when the - // host types list is empty. - Warning *HostTypesScopedListWarning `json:"warning,omitempty"` - - // ForceSendFields is a list of field names (e.g. "HostTypes") to - // unconditionally include in API requests. By default, fields with - // empty values are omitted from API requests. However, any non-pointer, - // non-interface field appearing in ForceSendFields will be sent to the - // server regardless of whether the field is empty or not. This may be - // used to include empty fields in Patch requests. - ForceSendFields []string `json:"-"` - - // NullFields is a list of field names (e.g. "HostTypes") to include in - // API requests with the JSON null value. By default, fields with empty - // values are omitted from API requests. However, any field with an - // empty value appearing in NullFields will be sent to the server as - // null. It is an error if a field in this list has a non-empty value. - // This may be used to include null fields in Patch requests. - NullFields []string `json:"-"` -} - -func (s *HostTypesScopedList) MarshalJSON() ([]byte, error) { - type NoMethod HostTypesScopedList - raw := NoMethod(*s) - return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) -} - -// HostTypesScopedListWarning: [Output Only] An informational warning -// that appears when the host types list is empty. -type HostTypesScopedListWarning struct { - // Code: [Output Only] A warning code, if applicable. For example, - // Compute Engine returns NO_RESULTS_ON_PAGE if there are no results in - // the response. - // - // Possible values: - // "CLEANUP_FAILED" - // "DEPRECATED_RESOURCE_USED" - // "DEPRECATED_TYPE_USED" - // "DISK_SIZE_LARGER_THAN_IMAGE_SIZE" - // "EXPERIMENTAL_TYPE_USED" - // "EXTERNAL_API_WARNING" - // "FIELD_VALUE_OVERRIDEN" - // "INJECTED_KERNELS_DEPRECATED" - // "MISSING_TYPE_DEPENDENCY" - // "NEXT_HOP_ADDRESS_NOT_ASSIGNED" - // "NEXT_HOP_CANNOT_IP_FORWARD" - // "NEXT_HOP_INSTANCE_NOT_FOUND" - // "NEXT_HOP_INSTANCE_NOT_ON_NETWORK" - // "NEXT_HOP_NOT_RUNNING" - // "NOT_CRITICAL_ERROR" - // "NO_RESULTS_ON_PAGE" - // "REQUIRED_TOS_AGREEMENT" - // "RESOURCE_IN_USE_BY_OTHER_RESOURCE_WARNING" - // "RESOURCE_NOT_DELETED" - // "SCHEMA_VALIDATION_IGNORED" - // "SINGLE_INSTANCE_PROPERTY_TEMPLATE" - // "UNDECLARED_PROPERTIES" - // "UNREACHABLE" - Code string `json:"code,omitempty"` - - // Data: [Output Only] Metadata about this warning in key: value format. - // For example: - // "data": [ { "key": "scope", "value": "zones/us-east1-d" } - Data []*HostTypesScopedListWarningData `json:"data,omitempty"` - - // Message: [Output Only] A human-readable description of the warning - // code. - Message string `json:"message,omitempty"` - - // ForceSendFields is a list of field names (e.g. "Code") to - // unconditionally include in API requests. By default, fields with - // empty values are omitted from API requests. However, any non-pointer, - // non-interface field appearing in ForceSendFields will be sent to the - // server regardless of whether the field is empty or not. This may be - // used to include empty fields in Patch requests. - ForceSendFields []string `json:"-"` - - // NullFields is a list of field names (e.g. "Code") to include in API - // requests with the JSON null value. By default, fields with empty - // values are omitted from API requests. However, any field with an - // empty value appearing in NullFields will be sent to the server as - // null. It is an error if a field in this list has a non-empty value. - // This may be used to include null fields in Patch requests. - NullFields []string `json:"-"` -} - -func (s *HostTypesScopedListWarning) MarshalJSON() ([]byte, error) { - type NoMethod HostTypesScopedListWarning - raw := NoMethod(*s) - return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) -} - -type HostTypesScopedListWarningData struct { - // Key: [Output Only] A key that provides more detail on the warning - // being returned. For example, for warnings where there are no results - // in a list request for a particular zone, this key might be scope and - // the key value might be the zone name. Other examples might be a key - // indicating a deprecated resource and a suggested replacement, or a - // warning about invalid network settings (for example, if an instance - // attempts to perform IP forwarding but is not enabled for IP - // forwarding). - Key string `json:"key,omitempty"` - - // Value: [Output Only] A warning data value corresponding to the key. - Value string `json:"value,omitempty"` - - // ForceSendFields is a list of field names (e.g. "Key") to - // unconditionally include in API requests. By default, fields with - // empty values are omitted from API requests. However, any non-pointer, - // non-interface field appearing in ForceSendFields will be sent to the - // server regardless of whether the field is empty or not. This may be - // used to include empty fields in Patch requests. - ForceSendFields []string `json:"-"` - - // NullFields is a list of field names (e.g. "Key") to include in API - // requests with the JSON null value. By default, fields with empty - // values are omitted from API requests. However, any field with an - // empty value appearing in NullFields will be sent to the server as - // null. It is an error if a field in this list has a non-empty value. - // This may be used to include null fields in Patch requests. - NullFields []string `json:"-"` -} - -func (s *HostTypesScopedListWarningData) MarshalJSON() ([]byte, error) { - type NoMethod HostTypesScopedListWarningData - raw := NoMethod(*s) - return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) -} - -type HostsScopedList struct { - // Hosts: [Output Only] A list of hosts contained in this scope. - Hosts []*Host `json:"hosts,omitempty"` - - // Warning: [Output Only] An informational warning that appears when the - // host list is empty. - Warning *HostsScopedListWarning `json:"warning,omitempty"` - - // ForceSendFields is a list of field names (e.g. "Hosts") to - // unconditionally include in API requests. By default, fields with - // empty values are omitted from API requests. However, any non-pointer, - // non-interface field appearing in ForceSendFields will be sent to the - // server regardless of whether the field is empty or not. This may be - // used to include empty fields in Patch requests. - ForceSendFields []string `json:"-"` - - // NullFields is a list of field names (e.g. "Hosts") to include in API - // requests with the JSON null value. By default, fields with empty - // values are omitted from API requests. However, any field with an - // empty value appearing in NullFields will be sent to the server as - // null. It is an error if a field in this list has a non-empty value. - // This may be used to include null fields in Patch requests. - NullFields []string `json:"-"` -} - -func (s *HostsScopedList) MarshalJSON() ([]byte, error) { - type NoMethod HostsScopedList - raw := NoMethod(*s) - return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) -} - -// HostsScopedListWarning: [Output Only] An informational warning that -// appears when the host list is empty. -type HostsScopedListWarning struct { - // Code: [Output Only] A warning code, if applicable. For example, - // Compute Engine returns NO_RESULTS_ON_PAGE if there are no results in - // the response. - // - // Possible values: - // "CLEANUP_FAILED" - // "DEPRECATED_RESOURCE_USED" - // "DEPRECATED_TYPE_USED" - // "DISK_SIZE_LARGER_THAN_IMAGE_SIZE" - // "EXPERIMENTAL_TYPE_USED" - // "EXTERNAL_API_WARNING" - // "FIELD_VALUE_OVERRIDEN" - // "INJECTED_KERNELS_DEPRECATED" - // "MISSING_TYPE_DEPENDENCY" - // "NEXT_HOP_ADDRESS_NOT_ASSIGNED" - // "NEXT_HOP_CANNOT_IP_FORWARD" - // "NEXT_HOP_INSTANCE_NOT_FOUND" - // "NEXT_HOP_INSTANCE_NOT_ON_NETWORK" - // "NEXT_HOP_NOT_RUNNING" - // "NOT_CRITICAL_ERROR" - // "NO_RESULTS_ON_PAGE" - // "REQUIRED_TOS_AGREEMENT" - // "RESOURCE_IN_USE_BY_OTHER_RESOURCE_WARNING" - // "RESOURCE_NOT_DELETED" - // "SCHEMA_VALIDATION_IGNORED" - // "SINGLE_INSTANCE_PROPERTY_TEMPLATE" - // "UNDECLARED_PROPERTIES" - // "UNREACHABLE" - Code string `json:"code,omitempty"` - - // Data: [Output Only] Metadata about this warning in key: value format. - // For example: - // "data": [ { "key": "scope", "value": "zones/us-east1-d" } - Data []*HostsScopedListWarningData `json:"data,omitempty"` - - // Message: [Output Only] A human-readable description of the warning - // code. - Message string `json:"message,omitempty"` - - // ForceSendFields is a list of field names (e.g. "Code") to - // unconditionally include in API requests. By default, fields with - // empty values are omitted from API requests. However, any non-pointer, - // non-interface field appearing in ForceSendFields will be sent to the - // server regardless of whether the field is empty or not. This may be - // used to include empty fields in Patch requests. - ForceSendFields []string `json:"-"` - - // NullFields is a list of field names (e.g. "Code") to include in API - // requests with the JSON null value. By default, fields with empty - // values are omitted from API requests. However, any field with an - // empty value appearing in NullFields will be sent to the server as - // null. It is an error if a field in this list has a non-empty value. - // This may be used to include null fields in Patch requests. - NullFields []string `json:"-"` -} - -func (s *HostsScopedListWarning) MarshalJSON() ([]byte, error) { - type NoMethod HostsScopedListWarning - raw := NoMethod(*s) - return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) -} - -type HostsScopedListWarningData struct { - // Key: [Output Only] A key that provides more detail on the warning - // being returned. For example, for warnings where there are no results - // in a list request for a particular zone, this key might be scope and - // the key value might be the zone name. Other examples might be a key - // indicating a deprecated resource and a suggested replacement, or a - // warning about invalid network settings (for example, if an instance - // attempts to perform IP forwarding but is not enabled for IP - // forwarding). - Key string `json:"key,omitempty"` - - // Value: [Output Only] A warning data value corresponding to the key. - Value string `json:"value,omitempty"` - - // ForceSendFields is a list of field names (e.g. "Key") to - // unconditionally include in API requests. By default, fields with - // empty values are omitted from API requests. However, any non-pointer, - // non-interface field appearing in ForceSendFields will be sent to the - // server regardless of whether the field is empty or not. This may be - // used to include empty fields in Patch requests. - ForceSendFields []string `json:"-"` - - // NullFields is a list of field names (e.g. "Key") to include in API - // requests with the JSON null value. By default, fields with empty - // values are omitted from API requests. However, any field with an - // empty value appearing in NullFields will be sent to the server as - // null. It is an error if a field in this list has a non-empty value. - // This may be used to include null fields in Patch requests. - NullFields []string `json:"-"` -} - -func (s *HostsScopedListWarningData) MarshalJSON() ([]byte, error) { - type NoMethod HostsScopedListWarningData - raw := NoMethod(*s) - return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) -} - // HttpHealthCheck: An HttpHealthCheck resource. This resource defines a // template for how individual instances should be checked for health, // via HTTP. @@ -11325,7 +11466,8 @@ type Image struct { // locking. The fingerprint is initially generated by Compute Engine and // changes after every request to modify or update labels. You must // always provide an up-to-date fingerprint hash in order to update or - // change labels. + // change labels, otherwise the request will fail with error 412 + // conditionNotMet. // // To see the latest fingerprint, make a get() request to retrieve an // image. @@ -11372,9 +11514,9 @@ type Image struct { // customer-supplied encryption key. SourceDiskEncryptionKey *CustomerEncryptionKey `json:"sourceDiskEncryptionKey,omitempty"` - // SourceDiskId: The ID value of the disk used to create this image. - // This value may be used to determine whether the image was taken from - // the current or a previous instance of a given disk name. + // SourceDiskId: [Output Only] The ID value of the disk used to create + // this image. This value may be used to determine whether the image was + // taken from the current or a previous instance of a given disk name. SourceDiskId string `json:"sourceDiskId,omitempty"` // SourceImage: URL of the source image used to create this image. This @@ -11661,6 +11803,10 @@ func (s *ImageListWarningData) MarshalJSON() ([]byte, error) { // Instance: An Instance resource. (== resource_for beta.instances ==) // (== resource_for v1.instances ==) type Instance struct { + // AllocationAffinity: The configuration of desired allocations which + // this Instance could consume capacity from. + AllocationAffinity *AllocationAffinity `json:"allocationAffinity,omitempty"` + // CanIpForward: Allows this instance to send and receive packets with // non-matching destination or source IPs. This is required if you plan // to use this instance to forward routes. For more information, see @@ -11686,21 +11832,14 @@ type Instance struct { // must be created before you can assign them. Disks []*AttachedDisk `json:"disks,omitempty"` + // DisplayDevice: Enables display device for the instance. + DisplayDevice *DisplayDevice `json:"displayDevice,omitempty"` + // GuestAccelerators: A list of the type and count of accelerator cards // attached to the instance. GuestAccelerators []*AcceleratorConfig `json:"guestAccelerators,omitempty"` - // Host: Full or partial URL of the host resource that the instance - // should be placed on, in the format: zones/zone/hosts/host. - // - // Optional, sole-tenant Host (physical machine) that the instance will - // be placed on when it's created. The instance is guaranteed to be - // placed on the same machine as other instances with the same - // sole-tenant host. - // - // The request will be rejected if the sole-tenant host has run out of - // resources. - Host string `json:"host,omitempty"` + Hostname string `json:"hostname,omitempty"` // Id: [Output Only] The unique identifier for the resource. This // identifier is defined by the server. @@ -11847,11 +11986,11 @@ type Instance struct { // of the status. StatusMessage string `json:"statusMessage,omitempty"` - // Tags: A list of tags to apply to this instance. Tags are used to - // identify valid sources or targets for network firewalls and are - // specified by the client during instance creation. The tags can be - // later modified by the setTags method. Each tag within the list must - // comply with RFC1035. + // Tags: Tags to apply to this instance. Tags are used to identify valid + // sources or targets for network firewalls and are specified by the + // client during instance creation. The tags can be later modified by + // the setTags method. Each tag within the list must comply with + // RFC1035. Multiple tags can be specified via the 'tags.items' field. Tags *Tags `json:"tags,omitempty"` // Zone: [Output Only] URL of the zone where the instance resides. You @@ -11863,20 +12002,21 @@ type Instance struct { // server. googleapi.ServerResponse `json:"-"` - // ForceSendFields is a list of field names (e.g. "CanIpForward") to - // unconditionally include in API requests. By default, fields with + // ForceSendFields is a list of field names (e.g. "AllocationAffinity") + // to unconditionally include in API requests. By default, fields with // empty values are omitted from API requests. However, any non-pointer, // non-interface field appearing in ForceSendFields will be sent to the // server regardless of whether the field is empty or not. This may be // used to include empty fields in Patch requests. ForceSendFields []string `json:"-"` - // NullFields is a list of field names (e.g. "CanIpForward") to include - // in API requests with the JSON null value. By default, fields with - // empty values are omitted from API requests. However, any field with - // an empty value appearing in NullFields will be sent to the server as - // null. It is an error if a field in this list has a non-empty value. - // This may be used to include null fields in Patch requests. + // NullFields is a list of field names (e.g. "AllocationAffinity") to + // include in API requests with the JSON null value. By default, fields + // with empty values are omitted from API requests. However, any field + // with an empty value appearing in NullFields will be sent to the + // server as null. It is an error if a field in this list has a + // non-empty value. This may be used to include null fields in Patch + // requests. NullFields []string `json:"-"` } @@ -12453,8 +12593,6 @@ func (s *InstanceGroupListWarningData) MarshalJSON() ([]byte, error) { // beta.regionInstanceGroupManagers ==) (== resource_for // v1.regionInstanceGroupManagers ==) type InstanceGroupManager struct { - Activities *InstanceGroupManagerActivities `json:"activities,omitempty"` - // AutoHealingPolicies: The autohealing policy for this managed instance // group. You can specify only one value. AutoHealingPolicies []*InstanceGroupManagerAutoHealingPolicy `json:"autoHealingPolicies,omitempty"` @@ -12478,8 +12616,8 @@ type InstanceGroupManager struct { // property when you create the resource. Description string `json:"description,omitempty"` - // DistributionPolicy: Policy valid only for regional managed instance - // groups. + // DistributionPolicy: Policy specifying intended distribution of + // instances in regional managed instance group. DistributionPolicy *DistributionPolicy `json:"distributionPolicy,omitempty"` // FailoverAction: The action to perform in case of zone failure. Only @@ -12493,7 +12631,11 @@ type InstanceGroupManager struct { // Fingerprint: Fingerprint of this resource. This field may be used in // optimistic locking. It will be ignored when inserting an // InstanceGroupManager. An up-to-date fingerprint must be provided in - // order to update the InstanceGroupManager. + // order to update the InstanceGroupManager, otherwise the request will + // fail with error 412 conditionNotMet. + // + // To see the latest fingerprint, make a get() request to retrieve an + // InstanceGroupManager. Fingerprint string `json:"fingerprint,omitempty"` // Id: [Output Only] A unique identifier for this resource type. The @@ -12544,6 +12686,9 @@ type InstanceGroupManager struct { // Manager StatefulPolicy *StatefulPolicy `json:"statefulPolicy,omitempty"` + // Status: [Output Only] The status of this managed instance group. + Status *InstanceGroupManagerStatus `json:"status,omitempty"` + // TargetPools: The URLs for all TargetPool resources to which instances // in the instanceGroup field are added. The target pools automatically // apply to all of the instances in the managed instance group. @@ -12576,20 +12721,21 @@ type InstanceGroupManager struct { // server. googleapi.ServerResponse `json:"-"` - // ForceSendFields is a list of field names (e.g. "Activities") to - // unconditionally include in API requests. By default, fields with + // ForceSendFields is a list of field names (e.g. "AutoHealingPolicies") + // to unconditionally include in API requests. By default, fields with // empty values are omitted from API requests. However, any non-pointer, // non-interface field appearing in ForceSendFields will be sent to the // server regardless of whether the field is empty or not. This may be // used to include empty fields in Patch requests. ForceSendFields []string `json:"-"` - // NullFields is a list of field names (e.g. "Activities") to include in - // API requests with the JSON null value. By default, fields with empty - // values are omitted from API requests. However, any field with an - // empty value appearing in NullFields will be sent to the server as - // null. It is an error if a field in this list has a non-empty value. - // This may be used to include null fields in Patch requests. + // NullFields is a list of field names (e.g. "AutoHealingPolicies") to + // include in API requests with the JSON null value. By default, fields + // with empty values are omitted from API requests. However, any field + // with an empty value appearing in NullFields will be sent to the + // server as null. It is an error if a field in this list has a + // non-empty value. This may be used to include null fields in Patch + // requests. NullFields []string `json:"-"` } @@ -12679,65 +12825,6 @@ func (s *InstanceGroupManagerActionsSummary) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } -type InstanceGroupManagerActivities struct { - // Possible values: - // "PERMITTED" - // "PROHIBITED" - Autohealing string `json:"autohealing,omitempty"` - - // Possible values: - // "PERMITTED" - // "PROHIBITED" - AutohealingHealthCheckBased string `json:"autohealingHealthCheckBased,omitempty"` - - // Possible values: - // "PERMITTED" - // "PROHIBITED" - AutoscalingDown string `json:"autoscalingDown,omitempty"` - - // Possible values: - // "PERMITTED" - // "PROHIBITED" - AutoscalingUp string `json:"autoscalingUp,omitempty"` - - // Possible values: - // "PERMITTED" - // "PROHIBITED" - CreatingInstances string `json:"creatingInstances,omitempty"` - - // Possible values: - // "PERMITTED" - // "PROHIBITED" - DeletingInstances string `json:"deletingInstances,omitempty"` - - // Possible values: - // "PERMITTED" - // "PROHIBITED" - RecreatingInstances string `json:"recreatingInstances,omitempty"` - - // ForceSendFields is a list of field names (e.g. "Autohealing") to - // unconditionally include in API requests. By default, fields with - // empty values are omitted from API requests. However, any non-pointer, - // non-interface field appearing in ForceSendFields will be sent to the - // server regardless of whether the field is empty or not. This may be - // used to include empty fields in Patch requests. - ForceSendFields []string `json:"-"` - - // NullFields is a list of field names (e.g. "Autohealing") to include - // in API requests with the JSON null value. By default, fields with - // empty values are omitted from API requests. However, any field with - // an empty value appearing in NullFields will be sent to the server as - // null. It is an error if a field in this list has a non-empty value. - // This may be used to include null fields in Patch requests. - NullFields []string `json:"-"` -} - -func (s *InstanceGroupManagerActivities) MarshalJSON() ([]byte, error) { - type NoMethod InstanceGroupManagerActivities - raw := NoMethod(*s) - return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) -} - type InstanceGroupManagerAggregatedList struct { // Id: [Output Only] Unique identifier for the resource; defined by the // server. @@ -12914,13 +13001,6 @@ type InstanceGroupManagerAutoHealingPolicy struct { // at least once. By default, a percent value of 100% is used. MaxUnavailable *FixedOrPercent `json:"maxUnavailable,omitempty"` - // Mode: Defines operating mode for this policy. - // - // Possible values: - // "OFF" - // "ON" - Mode string `json:"mode,omitempty"` - // ForceSendFields is a list of field names (e.g. "HealthCheck") to // unconditionally include in API requests. By default, fields with // empty values are omitted from API requests. However, any non-pointer, @@ -13142,11 +13222,77 @@ func (s *InstanceGroupManagerPendingActionsSummary) MarshalJSON() ([]byte, error return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +type InstanceGroupManagerStatus struct { + // IsStable: [Output Only] A bit indicating whether the managed instance + // group is in a stable state. A stable state means that: none of the + // instances in the managed instance group is currently undergoing any + // type of change (for example, creation, restart, or deletion); no + // future changes are scheduled for instances in the managed instance + // group; and the managed instance group itself is not being modified. + IsStable bool `json:"isStable,omitempty"` + + // VersionTarget: [Output Only] A status of consistency of Instances' + // versions with their target version specified by version field on + // Instance Group Manager. + VersionTarget *InstanceGroupManagerStatusVersionTarget `json:"versionTarget,omitempty"` + + // ForceSendFields is a list of field names (e.g. "IsStable") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "IsStable") to include in + // API requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *InstanceGroupManagerStatus) MarshalJSON() ([]byte, error) { + type NoMethod InstanceGroupManagerStatus + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type InstanceGroupManagerStatusVersionTarget struct { + // IsReached: [Output Only] A bit indicating whether version target has + // been reached in this managed instance group, i.e. all instances are + // in their target version. Instances' target version are specified by + // version field on Instance Group Manager. + IsReached bool `json:"isReached,omitempty"` + + // ForceSendFields is a list of field names (e.g. "IsReached") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "IsReached") to include in + // API requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *InstanceGroupManagerStatusVersionTarget) MarshalJSON() ([]byte, error) { + type NoMethod InstanceGroupManagerStatusVersionTarget + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + type InstanceGroupManagerUpdatePolicy struct { // Possible values: // "NONE" // "PROACTIVE" - // "UNSPECIFIED_TYPE" InstanceRedistributionType string `json:"instanceRedistributionType,omitempty"` // MaxSurge: The maximum number of instances that can be created above @@ -13187,10 +13333,10 @@ type InstanceGroupManagerUpdatePolicy struct { // MinimalAction: Minimal action to be taken on an instance. You can // specify either RESTART to restart existing instances or REPLACE to // delete and create new instances from the target template. If you - // specify a code>RESTART, the Updater will attempt to perform that - // action only. However, if the Updater determines that the minimal - // action you specify is not enough to perform the update, it might - // perform a more disruptive action. + // specify a RESTART, the Updater will attempt to perform that action + // only. However, if the Updater determines that the minimal action you + // specify is not enough to perform the update, it might perform a more + // disruptive action. // // Possible values: // "NONE" @@ -13358,6 +13504,35 @@ func (s *InstanceGroupManagersApplyUpdatesRequest) MarshalJSON() ([]byte, error) return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +// InstanceGroupManagersCreateInstancesRequest: +// InstanceGroupManagers.createInstances +type InstanceGroupManagersCreateInstancesRequest struct { + // Instances: [Required] List of specifications of per-instance configs. + Instances []*PerInstanceConfig `json:"instances,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Instances") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Instances") to include in + // API requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *InstanceGroupManagersCreateInstancesRequest) MarshalJSON() ([]byte, error) { + type NoMethod InstanceGroupManagersCreateInstancesRequest + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + type InstanceGroupManagersDeleteInstancesRequest struct { // Instances: The URLs of one or more instances to delete. This can be a // full URL or a partial URL, such as @@ -13394,6 +13569,10 @@ type InstanceGroupManagersDeletePerInstanceConfigsReq struct { // per-instance configs on this managed instance group. Instances []string `json:"instances,omitempty"` + // Names: The list of instance names for which we want to delete + // per-instance configs on this managed instance group. + Names []string `json:"names,omitempty"` + // ForceSendFields is a list of field names (e.g. "Instances") to // unconditionally include in API requests. By default, fields with // empty values are omitted from API requests. However, any non-pointer, @@ -13637,7 +13816,7 @@ type InstanceGroupManagersResizeAdvancedRequest struct { // only once. If there is an error during creation, the managed instance // group does not retry create this instance, and we will decrease the // targetSize of the request instead. If the flag is false, the group - // attemps to recreate each instance continuously until it + // attempts to recreate each instance continuously until it // succeeds. // // This flag matters only in the first attempt of creation of an @@ -14335,7 +14514,9 @@ type InstanceGroupsSetNamedPortsRequest struct { // multiple users change the named ports settings concurrently. Obtain // the fingerprint with the instanceGroups.get method. Then, include the // fingerprint in your request to ensure that you do not overwrite - // changes that were applied from another concurrent request. + // changes that were applied from another concurrent request. A request + // with an incorrect fingerprint will fail with error 412 + // conditionNotMet. Fingerprint string `json:"fingerprint,omitempty"` // NamedPorts: The list of named ports to set for this instance group. @@ -14719,6 +14900,10 @@ func (s *InstanceMoveRequest) MarshalJSON() ([]byte, error) { } type InstanceProperties struct { + // AllocationAffinity: The configuration of desired allocations which + // this Instance could consume capacity from. + AllocationAffinity *AllocationAffinity `json:"allocationAffinity,omitempty"` + // CanIpForward: Enables instances created based on this template to // send packets with source IP addresses other than their own and // receive packets with destination IP addresses other than their own. @@ -14786,20 +14971,21 @@ type InstanceProperties struct { // within the list must comply with RFC1035. Tags *Tags `json:"tags,omitempty"` - // ForceSendFields is a list of field names (e.g. "CanIpForward") to - // unconditionally include in API requests. By default, fields with + // ForceSendFields is a list of field names (e.g. "AllocationAffinity") + // to unconditionally include in API requests. By default, fields with // empty values are omitted from API requests. However, any non-pointer, // non-interface field appearing in ForceSendFields will be sent to the // server regardless of whether the field is empty or not. This may be // used to include empty fields in Patch requests. ForceSendFields []string `json:"-"` - // NullFields is a list of field names (e.g. "CanIpForward") to include - // in API requests with the JSON null value. By default, fields with - // empty values are omitted from API requests. However, any field with - // an empty value appearing in NullFields will be sent to the server as - // null. It is an error if a field in this list has a non-empty value. - // This may be used to include null fields in Patch requests. + // NullFields is a list of field names (e.g. "AllocationAffinity") to + // include in API requests with the JSON null value. By default, fields + // with empty values are omitted from API requests. However, any field + // with an empty value appearing in NullFields will be sent to the + // server as null. It is an error if a field in this list has a + // non-empty value. This may be used to include null fields in Patch + // requests. NullFields []string `json:"-"` } @@ -15602,7 +15788,8 @@ type Interconnect struct { // optimistic locking. The fingerprint is initially generated by Compute // Engine and changes after every request to modify or update labels. // You must always provide an up-to-date fingerprint hash in order to - // update or change labels. + // update or change labels, otherwise the request will fail with error + // 412 conditionNotMet. // // To see the latest fingerprint, make a get() request to retrieve an // Interconnect. @@ -15710,18 +15897,10 @@ type InterconnectAttachment struct { // Not present for PARTNER_PROVIDER. AdminEnabled bool `json:"adminEnabled,omitempty"` - // AvailabilityZone: [Deprecated] Replaced by edge_availability_domain. - // - // Possible values: - // "ZONE_1" - // "ZONE_2" - // "ZONE_ANY" - AvailabilityZone string `json:"availabilityZone,omitempty"` - // Bandwidth: Provisioned bandwidth capacity for the // interconnectAttachment. Can be set by the partner to update the - // customer's provisioned bandwidth. Output only for for PARTNER type, - // mutable for PARTNER_PROVIDER, not available for DEDICATED. + // customer's provisioned bandwidth. Output only for PARTNER type, + // mutable for PARTNER_PROVIDER and DEDICATED. // // Possible values: // "BPS_100M" @@ -15799,7 +15978,8 @@ type InterconnectAttachment struct { // used for optimistic locking. The fingerprint is initially generated // by Compute Engine and changes after every request to modify or update // labels. You must always provide an up-to-date fingerprint hash in - // order to update or change labels. + // order to update or change labels, otherwise the request will fail + // with error 412 conditionNotMet. // // To see the latest fingerprint, make a get() request to retrieve an // InterconnectAttachment. @@ -15855,7 +16035,7 @@ type InterconnectAttachment struct { // body. Region string `json:"region,omitempty"` - // Router: URL of the cloud router to be used for dynamic routing. This + // Router: URL of the Cloud Router to be used for dynamic routing. This // router must be in the same region as this InterconnectAttachment. The // InterconnectAttachment will automatically connect the Interconnect to // the network & region within which the Cloud Router is configured. @@ -15883,10 +16063,8 @@ type InterconnectAttachment struct { // "PARTNER_PROVIDER" Type string `json:"type,omitempty"` - // VlanTag8021q: Available only for DEDICATED and PARTNER_PROVIDER. - // Desired VLAN tag for this attachment, in the range 2-4094. This field - // refers to 802.1q VLAN tag, also known as IEEE 802.1Q Only specified - // at creation time. + // VlanTag8021q: The IEEE 802.1Q VLAN tag for this attachment, in the + // range 2-4094. Only specified at creation time. VlanTag8021q int64 `json:"vlanTag8021q,omitempty"` // ServerResponse contains the HTTP response code and headers from the @@ -16237,7 +16415,7 @@ func (s *InterconnectAttachmentListWarningData) MarshalJSON() ([]byte, error) { type InterconnectAttachmentPartnerMetadata struct { // InterconnectName: Plain text name of the Interconnect this attachment // is connected to, as displayed in the Partner?s portal. For instance - // ?Chicago 1?. This value may be validated to match approved Partner + // "Chicago 1". This value may be validated to match approved Partner // values. InterconnectName string `json:"interconnectName,omitempty"` @@ -16482,6 +16660,211 @@ func (s *InterconnectCircuitInfo) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +// InterconnectDiagnostics: Diagnostics information about interconnect, +// contains detailed and current technical information about Google?s +// side of the connection. +type InterconnectDiagnostics struct { + // ArpCaches: A list of InterconnectDiagnostics.ARPEntry objects, + // describing individual neighbors currently seen by the Google router + // in the ARP cache for the Interconnect. This will be empty when the + // Interconnect is not bundled. + ArpCaches []*InterconnectDiagnosticsARPEntry `json:"arpCaches,omitempty"` + + // Links: A list of InterconnectDiagnostics.LinkStatus objects, + // describing the status for each link on the Interconnect. + Links []*InterconnectDiagnosticsLinkStatus `json:"links,omitempty"` + + // MacAddress: The MAC address of the Interconnect's bundle interface. + MacAddress string `json:"macAddress,omitempty"` + + // ForceSendFields is a list of field names (e.g. "ArpCaches") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "ArpCaches") to include in + // API requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *InterconnectDiagnostics) MarshalJSON() ([]byte, error) { + type NoMethod InterconnectDiagnostics + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// InterconnectDiagnosticsARPEntry: Describing the ARP neighbor entries +// seen on this link +type InterconnectDiagnosticsARPEntry struct { + // IpAddress: The IP address of this ARP neighbor. + IpAddress string `json:"ipAddress,omitempty"` + + // MacAddress: The MAC address of this ARP neighbor. + MacAddress string `json:"macAddress,omitempty"` + + // ForceSendFields is a list of field names (e.g. "IpAddress") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "IpAddress") to include in + // API requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *InterconnectDiagnosticsARPEntry) MarshalJSON() ([]byte, error) { + type NoMethod InterconnectDiagnosticsARPEntry + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type InterconnectDiagnosticsLinkLACPStatus struct { + // GoogleSystemId: System ID of the port on Google?s side of the LACP + // exchange. + GoogleSystemId string `json:"googleSystemId,omitempty"` + + // NeighborSystemId: System ID of the port on the neighbor?s side of the + // LACP exchange. + NeighborSystemId string `json:"neighborSystemId,omitempty"` + + // Possible values: + // "ACTIVE" + // "DETACHED" + State string `json:"state,omitempty"` + + // ForceSendFields is a list of field names (e.g. "GoogleSystemId") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "GoogleSystemId") to + // include in API requests with the JSON null value. By default, fields + // with empty values are omitted from API requests. However, any field + // with an empty value appearing in NullFields will be sent to the + // server as null. It is an error if a field in this list has a + // non-empty value. This may be used to include null fields in Patch + // requests. + NullFields []string `json:"-"` +} + +func (s *InterconnectDiagnosticsLinkLACPStatus) MarshalJSON() ([]byte, error) { + type NoMethod InterconnectDiagnosticsLinkLACPStatus + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type InterconnectDiagnosticsLinkOpticalPower struct { + // Possible values: + // "HIGH_ALARM" + // "HIGH_WARNING" + // "LOW_ALARM" + // "LOW_WARNING" + // "OK" + State string `json:"state,omitempty"` + + // Value: Value of the current optical power, read in dBm. Take a known + // good optical value, give it a 10% margin and trigger warnings + // relative to that value. In general, a -7dBm warning and a -11dBm + // alarm are good optical value estimates for most links. + Value float64 `json:"value,omitempty"` + + // ForceSendFields is a list of field names (e.g. "State") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "State") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *InterconnectDiagnosticsLinkOpticalPower) MarshalJSON() ([]byte, error) { + type NoMethod InterconnectDiagnosticsLinkOpticalPower + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +func (s *InterconnectDiagnosticsLinkOpticalPower) UnmarshalJSON(data []byte) error { + type NoMethod InterconnectDiagnosticsLinkOpticalPower + var s1 struct { + Value gensupport.JSONFloat64 `json:"value"` + *NoMethod + } + s1.NoMethod = (*NoMethod)(s) + if err := json.Unmarshal(data, &s1); err != nil { + return err + } + s.Value = float64(s1.Value) + return nil +} + +type InterconnectDiagnosticsLinkStatus struct { + // ArpCaches: A list of InterconnectDiagnostics.ARPEntry objects, + // describing the ARP neighbor entries seen on this link. This will be + // empty if the link is bundled + ArpCaches []*InterconnectDiagnosticsARPEntry `json:"arpCaches,omitempty"` + + // CircuitId: The unique ID for this link assigned during turn up by + // Google. + CircuitId string `json:"circuitId,omitempty"` + + // GoogleDemarc: The Demarc address assigned by Google and provided in + // the LoA. + GoogleDemarc string `json:"googleDemarc,omitempty"` + + LacpStatus *InterconnectDiagnosticsLinkLACPStatus `json:"lacpStatus,omitempty"` + + ReceivingOpticalPower *InterconnectDiagnosticsLinkOpticalPower `json:"receivingOpticalPower,omitempty"` + + TransmittingOpticalPower *InterconnectDiagnosticsLinkOpticalPower `json:"transmittingOpticalPower,omitempty"` + + // ForceSendFields is a list of field names (e.g. "ArpCaches") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "ArpCaches") to include in + // API requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *InterconnectDiagnosticsLinkStatus) MarshalJSON() ([]byte, error) { + type NoMethod InterconnectDiagnosticsLinkStatus + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + // InterconnectList: Response to the list request, and contains a list // of interconnects. type InterconnectList struct { @@ -16647,10 +17030,10 @@ type InterconnectLocation struct { // each line in the address is separated by a newline character. Address string `json:"address,omitempty"` - // AvailabilityZone: [Output Only] Availability zone for this location. - // Within a metropolitan area (metro), maintenance will not be - // simultaneously scheduled in more than one availability zone. Example: - // "zone1" or "zone2". + // AvailabilityZone: [Output Only] Availability zone for this + // InterconnectLocation. Within a metropolitan area (metro), maintenance + // will not be simultaneously scheduled in more than one availability + // zone. Example: "zone1" or "zone2". AvailabilityZone string `json:"availabilityZone,omitempty"` // City: [Output Only] Metropolitan area designator that indicates which @@ -16711,6 +17094,16 @@ type InterconnectLocation struct { // SelfLink: [Output Only] Server-defined URL for the resource. SelfLink string `json:"selfLink,omitempty"` + // Status: [Output Only] The status of this InterconnectLocation. If the + // status is AVAILABLE, new Interconnects may be provisioned in this + // InterconnectLocation. Otherwise, no new Interconnects may be + // provisioned. + // + // Possible values: + // "AVAILABLE" + // "CLOSED" + Status string `json:"status,omitempty"` + // ServerResponse contains the HTTP response code and headers from the // server. googleapi.ServerResponse `json:"-"` @@ -17012,6 +17405,86 @@ func (s *InterconnectOutageNotification) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +// InterconnectsGetDiagnosticsResponse: Response for the +// InterconnectsGetDiagnosticsRequest. +type InterconnectsGetDiagnosticsResponse struct { + Result *InterconnectDiagnostics `json:"result,omitempty"` + + // ServerResponse contains the HTTP response code and headers from the + // server. + googleapi.ServerResponse `json:"-"` + + // ForceSendFields is a list of field names (e.g. "Result") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Result") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *InterconnectsGetDiagnosticsResponse) MarshalJSON() ([]byte, error) { + type NoMethod InterconnectsGetDiagnosticsResponse + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type InternalIpAddress struct { + // Cidr: IP CIDR address or range. + Cidr string `json:"cidr,omitempty"` + + // Owner: The owner of the internal IP address. + Owner string `json:"owner,omitempty"` + + // Purpose: The purpose of the internal IP address if applicable. + Purpose string `json:"purpose,omitempty"` + + // Region: The region of the internal IP address if applicable. + Region string `json:"region,omitempty"` + + // Type: The type of the internal IP address. + // + // Possible values: + // "PEER_RESERVED" + // "PEER_USED" + // "REMOTE_RESERVED" + // "REMOTE_USED" + // "RESERVED" + // "SUBNETWORK" + // "TYPE_UNSPECIFIED" + Type string `json:"type,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Cidr") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Cidr") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *InternalIpAddress) MarshalJSON() ([]byte, error) { + type NoMethod InternalIpAddress + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + type InternalIpOwner struct { // IpCidrRange: IP CIDR range being owned. IpCidrRange string `json:"ipCidrRange,omitempty"` @@ -17045,6 +17518,160 @@ func (s *InternalIpOwner) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +type IpAddressesList struct { + // Id: [Output Only] Unique identifier for the resource; defined by the + // server. + Id string `json:"id,omitempty"` + + // Items: A list of InternalIpAddress resources. + Items []*InternalIpAddress `json:"items,omitempty"` + + // Kind: [Output Only] Type of resource. Always compute#ipAddressesList + // for IP addresses lists. + Kind string `json:"kind,omitempty"` + + // NextPageToken: [Output Only] This token allows you to get the next + // page of results for list requests. If the number of results is larger + // than maxResults, use the nextPageToken as a value for the query + // parameter pageToken in the next list request. Subsequent list + // requests will have their own nextPageToken to continue paging through + // the results. + NextPageToken string `json:"nextPageToken,omitempty"` + + // SelfLink: [Output Only] Server-defined URL for this resource. + SelfLink string `json:"selfLink,omitempty"` + + // Warning: [Output Only] Informational warning message. + Warning *IpAddressesListWarning `json:"warning,omitempty"` + + // ServerResponse contains the HTTP response code and headers from the + // server. + googleapi.ServerResponse `json:"-"` + + // ForceSendFields is a list of field names (e.g. "Id") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Id") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *IpAddressesList) MarshalJSON() ([]byte, error) { + type NoMethod IpAddressesList + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// IpAddressesListWarning: [Output Only] Informational warning message. +type IpAddressesListWarning struct { + // Code: [Output Only] A warning code, if applicable. For example, + // Compute Engine returns NO_RESULTS_ON_PAGE if there are no results in + // the response. + // + // Possible values: + // "CLEANUP_FAILED" + // "DEPRECATED_RESOURCE_USED" + // "DEPRECATED_TYPE_USED" + // "DISK_SIZE_LARGER_THAN_IMAGE_SIZE" + // "EXPERIMENTAL_TYPE_USED" + // "EXTERNAL_API_WARNING" + // "FIELD_VALUE_OVERRIDEN" + // "INJECTED_KERNELS_DEPRECATED" + // "MISSING_TYPE_DEPENDENCY" + // "NEXT_HOP_ADDRESS_NOT_ASSIGNED" + // "NEXT_HOP_CANNOT_IP_FORWARD" + // "NEXT_HOP_INSTANCE_NOT_FOUND" + // "NEXT_HOP_INSTANCE_NOT_ON_NETWORK" + // "NEXT_HOP_NOT_RUNNING" + // "NOT_CRITICAL_ERROR" + // "NO_RESULTS_ON_PAGE" + // "REQUIRED_TOS_AGREEMENT" + // "RESOURCE_IN_USE_BY_OTHER_RESOURCE_WARNING" + // "RESOURCE_NOT_DELETED" + // "SCHEMA_VALIDATION_IGNORED" + // "SINGLE_INSTANCE_PROPERTY_TEMPLATE" + // "UNDECLARED_PROPERTIES" + // "UNREACHABLE" + Code string `json:"code,omitempty"` + + // Data: [Output Only] Metadata about this warning in key: value format. + // For example: + // "data": [ { "key": "scope", "value": "zones/us-east1-d" } + Data []*IpAddressesListWarningData `json:"data,omitempty"` + + // Message: [Output Only] A human-readable description of the warning + // code. + Message string `json:"message,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Code") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Code") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *IpAddressesListWarning) MarshalJSON() ([]byte, error) { + type NoMethod IpAddressesListWarning + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type IpAddressesListWarningData struct { + // Key: [Output Only] A key that provides more detail on the warning + // being returned. For example, for warnings where there are no results + // in a list request for a particular zone, this key might be scope and + // the key value might be the zone name. Other examples might be a key + // indicating a deprecated resource and a suggested replacement, or a + // warning about invalid network settings (for example, if an instance + // attempts to perform IP forwarding but is not enabled for IP + // forwarding). + Key string `json:"key,omitempty"` + + // Value: [Output Only] A warning data value corresponding to the key. + Value string `json:"value,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Key") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Key") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *IpAddressesListWarningData) MarshalJSON() ([]byte, error) { + type NoMethod IpAddressesListWarningData + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + // IpOwnerList: Contains a list of IP owners. type IpOwnerList struct { // Id: [Output Only] Unique identifier for the resource; defined by the @@ -17226,8 +17853,8 @@ type License struct { // license to images, snapshots, and disks. LicenseCode uint64 `json:"licenseCode,omitempty,string"` - // Name: [Output Only] Name of the resource. The name is 1-63 characters - // long and complies with RFC1035. + // Name: Name of the resource. The name must be 1-63 characters long and + // comply with RFC1035. Name string `json:"name,omitempty"` ResourceRequirements *LicenseResourceRequirements `json:"resourceRequirements,omitempty"` @@ -17636,18 +18263,21 @@ func (s *LogConfigCloudAuditOptions) MarshalJSON() ([]byte, error) { // Field names correspond to IAM request parameters and field values are // their respective values. // -// At present the only supported field names are - "iam_principal", -// corresponding to IAMContext.principal; - "" (empty string), resulting -// in one aggretated counter with no field. +// Supported field names: - "authority", which is "[token]" if +// IAMContext.token is present, otherwise the value of +// IAMContext.authority_selector if present, and otherwise a +// representation of IAMContext.principal; or - "iam_principal", a +// representation of IAMContext.principal even if a token or authority +// selector is present; or - "" (empty string), resulting in a counter +// with no fields. // // Examples: counter { metric: "/debug_access_count" field: // "iam_principal" } ==> increment counter // /iam/policy/backend_debug_access_count {iam_principal=[value of // IAMContext.principal]} // -// At this time we do not support: * multiple field names (though this -// may be supported in the future) * decrementing the counter * -// incrementing it by anything other than 1 +// At this time we do not support multiple field names (though this may +// be supported in the future). type LogConfigCounterOptions struct { // Field: The field value to attribute. Field string `json:"field,omitempty"` @@ -17684,6 +18314,12 @@ type LogConfigDataAccessOptions struct { // the caller. This is relevant only in the LocalIAM implementation, for // now. // + // NOTE: Logging to Gin in a fail-closed manner is currently unsupported + // while work is being done to satisfy the requirements of go/345. + // Currently, setting LOG_FAIL_CLOSED mode will have no effect, but + // still exists because there is active work being done to support it + // (b/115874152). + // // Possible values: // "LOG_FAIL_CLOSED" // "LOG_MODE_UNSPECIFIED" @@ -17712,6 +18348,247 @@ func (s *LogConfigDataAccessOptions) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +// MachineImage: Machine image resource. +type MachineImage struct { + // CreationTimestamp: [Output Only] The creation timestamp for this + // machine image in RFC3339 text format. + CreationTimestamp string `json:"creationTimestamp,omitempty"` + + // Description: An optional description of this resource. Provide this + // property when you create the resource. + Description string `json:"description,omitempty"` + + // Id: [Output Only] A unique identifier for this machine image. The + // server defines this identifier. + Id uint64 `json:"id,omitempty,string"` + + // Kind: [Output Only] The resource type, which is always + // compute#machineImage for machine image. + Kind string `json:"kind,omitempty"` + + // Name: Name of the resource; provided by the client when the resource + // is created. The name must be 1-63 characters long, and comply with + // RFC1035. Specifically, the name must be 1-63 characters long and + // match the regular expression `[a-z]([-a-z0-9]*[a-z0-9])?` which means + // the first character must be a lowercase letter, and all following + // characters must be a dash, lowercase letter, or digit, except the + // last character, which cannot be a dash. + Name string `json:"name,omitempty"` + + // SelfLink: [Output Only] The URL for this machine image. The server + // defines this URL. + SelfLink string `json:"selfLink,omitempty"` + + // SourceInstance: The source instance used to create the machine image. + // You can provide this as a partial or full URL to the resource. For + // example, the following are valid values: + // - + // https://www.googleapis.com/compute/v1/projects/project/zones/zone/instances/instance + // - projects/project/zones/zone/instances/instance + SourceInstance string `json:"sourceInstance,omitempty"` + + // SourceInstanceProperties: Properties of source instance. + SourceInstanceProperties *SourceInstanceProperties `json:"sourceInstanceProperties,omitempty"` + + // Status: [Output Only] The status of disk creation. + // + // Possible values: + // "CREATING" + // "DELETING" + // "INVALID" + // "READY" + // "UPLOADING" + Status string `json:"status,omitempty"` + + // StorageLocations: GCS bucket storage location of the snapshot + // (regional or multi-regional). + StorageLocations []string `json:"storageLocations,omitempty"` + + // ServerResponse contains the HTTP response code and headers from the + // server. + googleapi.ServerResponse `json:"-"` + + // ForceSendFields is a list of field names (e.g. "CreationTimestamp") + // to unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "CreationTimestamp") to + // include in API requests with the JSON null value. By default, fields + // with empty values are omitted from API requests. However, any field + // with an empty value appearing in NullFields will be sent to the + // server as null. It is an error if a field in this list has a + // non-empty value. This may be used to include null fields in Patch + // requests. + NullFields []string `json:"-"` +} + +func (s *MachineImage) MarshalJSON() ([]byte, error) { + type NoMethod MachineImage + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// MachineImageList: A list of machine images. +type MachineImageList struct { + Etag string `json:"etag,omitempty"` + + // Id: [Output Only] Unique identifier for the resource; defined by the + // server. + Id string `json:"id,omitempty"` + + // Items: A list of MachineImage resources. + Items []*MachineImage `json:"items,omitempty"` + + // Kind: [Output Only] The resource type, which is always + // compute#machineImagesListResponse for machine image lists. + Kind string `json:"kind,omitempty"` + + // NextPageToken: [Output Only] This token allows you to get the next + // page of results for list requests. If the number of results is larger + // than maxResults, use the nextPageToken as a value for the query + // parameter pageToken in the next list request. Subsequent list + // requests will have their own nextPageToken to continue paging through + // the results. + NextPageToken string `json:"nextPageToken,omitempty"` + + // SelfLink: [Output Only] Server-defined URL for this resource. + SelfLink string `json:"selfLink,omitempty"` + + // Warning: [Output Only] Informational warning message. + Warning *MachineImageListWarning `json:"warning,omitempty"` + + // ServerResponse contains the HTTP response code and headers from the + // server. + googleapi.ServerResponse `json:"-"` + + // ForceSendFields is a list of field names (e.g. "Etag") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Etag") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *MachineImageList) MarshalJSON() ([]byte, error) { + type NoMethod MachineImageList + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// MachineImageListWarning: [Output Only] Informational warning message. +type MachineImageListWarning struct { + // Code: [Output Only] A warning code, if applicable. For example, + // Compute Engine returns NO_RESULTS_ON_PAGE if there are no results in + // the response. + // + // Possible values: + // "CLEANUP_FAILED" + // "DEPRECATED_RESOURCE_USED" + // "DEPRECATED_TYPE_USED" + // "DISK_SIZE_LARGER_THAN_IMAGE_SIZE" + // "EXPERIMENTAL_TYPE_USED" + // "EXTERNAL_API_WARNING" + // "FIELD_VALUE_OVERRIDEN" + // "INJECTED_KERNELS_DEPRECATED" + // "MISSING_TYPE_DEPENDENCY" + // "NEXT_HOP_ADDRESS_NOT_ASSIGNED" + // "NEXT_HOP_CANNOT_IP_FORWARD" + // "NEXT_HOP_INSTANCE_NOT_FOUND" + // "NEXT_HOP_INSTANCE_NOT_ON_NETWORK" + // "NEXT_HOP_NOT_RUNNING" + // "NOT_CRITICAL_ERROR" + // "NO_RESULTS_ON_PAGE" + // "REQUIRED_TOS_AGREEMENT" + // "RESOURCE_IN_USE_BY_OTHER_RESOURCE_WARNING" + // "RESOURCE_NOT_DELETED" + // "SCHEMA_VALIDATION_IGNORED" + // "SINGLE_INSTANCE_PROPERTY_TEMPLATE" + // "UNDECLARED_PROPERTIES" + // "UNREACHABLE" + Code string `json:"code,omitempty"` + + // Data: [Output Only] Metadata about this warning in key: value format. + // For example: + // "data": [ { "key": "scope", "value": "zones/us-east1-d" } + Data []*MachineImageListWarningData `json:"data,omitempty"` + + // Message: [Output Only] A human-readable description of the warning + // code. + Message string `json:"message,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Code") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Code") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *MachineImageListWarning) MarshalJSON() ([]byte, error) { + type NoMethod MachineImageListWarning + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type MachineImageListWarningData struct { + // Key: [Output Only] A key that provides more detail on the warning + // being returned. For example, for warnings where there are no results + // in a list request for a particular zone, this key might be scope and + // the key value might be the zone name. Other examples might be a key + // indicating a deprecated resource and a suggested replacement, or a + // warning about invalid network settings (for example, if an instance + // attempts to perform IP forwarding but is not enabled for IP + // forwarding). + Key string `json:"key,omitempty"` + + // Value: [Output Only] A warning data value corresponding to the key. + Value string `json:"value,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Key") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Key") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *MachineImageListWarningData) MarshalJSON() ([]byte, error) { + type NoMethod MachineImageListWarningData + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + // MachineType: A Machine Type resource. (== resource_for // v1.machineTypes ==) (== resource_for beta.machineTypes ==) type MachineType struct { @@ -18287,6 +19164,10 @@ type ManagedInstance struct { // even if the instance has not yet been created. Instance string `json:"instance,omitempty"` + // InstanceHealth: [Output Only] Health state of the instance per + // health-check. + InstanceHealth []*ManagedInstanceInstanceHealth `json:"instanceHealth,omitempty"` + // InstanceStatus: [Output Only] The status of the instance. This field // is empty when the instance does not exist. // @@ -18313,6 +19194,14 @@ type ManagedInstance struct { // Override: [Output Only] Override defined for this instance. Override *ManagedInstanceOverride `json:"override,omitempty"` + // PreservedStateFromConfig: [Output Only] Preserved state applied from + // per-instance config for this instance. + PreservedStateFromConfig *PreservedState `json:"preservedStateFromConfig,omitempty"` + + // PreservedStateFromPolicy: [Output Only] Preserved state generated + // based on stateful policy for this instance. + PreservedStateFromPolicy *PreservedState `json:"preservedStateFromPolicy,omitempty"` + // Tag: [Output Only] Tag describing the version. Tag string `json:"tag,omitempty"` @@ -18342,6 +19231,41 @@ func (s *ManagedInstance) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +type ManagedInstanceInstanceHealth struct { + // HealthCheck: [Output Only] The URL for the health check that verifies + // whether the instance is healthy. + HealthCheck string `json:"healthCheck,omitempty"` + + // HealthState: [Output Only] The current instance health state. + // + // Possible values: + // "HEALTHY" + // "UNHEALTHY" + HealthState string `json:"healthState,omitempty"` + + // ForceSendFields is a list of field names (e.g. "HealthCheck") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "HealthCheck") to include + // in API requests with the JSON null value. By default, fields with + // empty values are omitted from API requests. However, any field with + // an empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *ManagedInstanceInstanceHealth) MarshalJSON() ([]byte, error) { + type NoMethod ManagedInstanceInstanceHealth + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + type ManagedInstanceLastAttempt struct { // Errors: [Output Only] Encountered errors during the last attempt to // create or delete the instance. @@ -18593,7 +19517,11 @@ type Metadata struct { // locking. The fingerprint is initially generated by Compute Engine and // changes after every request to modify or update metadata. You must // always provide an up-to-date fingerprint hash in order to update or - // change metadata. + // change metadata, otherwise the request will fail with error 412 + // conditionNotMet. + // + // To see the latest fingerprint, make a get() request to retrieve the + // resource. Fingerprint string `json:"fingerprint,omitempty"` // Items: Array of key/value pairs. The total size of all keys and @@ -18696,22 +19624,22 @@ func (s *NamedPort) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } -// Network: Represents a Network resource. Read Networks and Firewalls -// for more information. (== resource_for v1.networks ==) (== -// resource_for beta.networks ==) +// Network: Represents a Network resource. Read Virtual Private Cloud +// (VPC) Network Overview for more information. (== resource_for +// v1.networks ==) (== resource_for beta.networks ==) type Network struct { // IPv4Range: The range of internal addresses that are legal on this // network. This range is a CIDR specification, for example: // 192.168.0.0/16. Provided by the client when the network is created. IPv4Range string `json:"IPv4Range,omitempty"` - // AutoCreateSubnetworks: When set to true, the network is created in - // "auto subnet mode". When set to false, the network is in "custom - // subnet mode". + // AutoCreateSubnetworks: When set to true, the VPC network is created + // in "auto" mode. When set to false, the VPC network is created in + // "custom" mode. // - // In "auto subnet mode", a newly created network is assigned the - // default CIDR of 10.128.0.0/9 and it automatically creates one - // subnetwork per region. + // An auto mode VPC network starts with one subnet per region. Each + // subnet has a predetermined range as described in Auto mode VPC + // network IP ranges. AutoCreateSubnetworks bool `json:"autoCreateSubnetworks,omitempty"` // CreationTimestamp: [Output Only] Creation timestamp in RFC3339 text @@ -18730,9 +19658,8 @@ type Network struct { // property when you create the resource. Description string `json:"description,omitempty"` - // GatewayIPv4: A gateway address for default routing to other networks. - // This value is read only and is selected by the Google Compute Engine, - // typically as the first usable address in the IPv4Range. + // GatewayIPv4: [Output Only] The gateway address for default routing + // out of the network. This value is read only and is selected by GCP. GatewayIPv4 string `json:"gatewayIPv4,omitempty"` // Id: [Output Only] The unique identifier for the resource. This @@ -18772,7 +19699,7 @@ type Network struct { SelfLink string `json:"selfLink,omitempty"` // Subnetworks: [Output Only] Server-defined fully-qualified URLs for - // all subnetworks in this network. + // all subnetworks in this VPC network. Subnetworks []string `json:"subnetworks,omitempty"` // ServerResponse contains the HTTP response code and headers from the @@ -18804,9 +19731,12 @@ func (s *Network) MarshalJSON() ([]byte, error) { // NetworkEndpoint: The network endpoint. type NetworkEndpoint struct { + // Annotations: Metadata defined as annotations on the network endpoint. + Annotations map[string]string `json:"annotations,omitempty"` + // Instance: The name for a specific VM instance that the IP address - // belongs to. This is required for network endpoints of type GCE_VM_IP - // and GCE_VM_IP_PORT. The instance must be in the same zone of network + // belongs to. This is required for network endpoints of type + // GCE_VM_IP_PORT. The instance must be in the same zone of network // endpoint group. // // The name must be 1-63 characters long, and comply with RFC1035. @@ -18824,7 +19754,7 @@ type NetworkEndpoint struct { // defaultPort for the network endpoint group will be used. Port int64 `json:"port,omitempty"` - // ForceSendFields is a list of field names (e.g. "Instance") to + // ForceSendFields is a list of field names (e.g. "Annotations") to // unconditionally include in API requests. By default, fields with // empty values are omitted from API requests. However, any non-pointer, // non-interface field appearing in ForceSendFields will be sent to the @@ -18832,10 +19762,10 @@ type NetworkEndpoint struct { // used to include empty fields in Patch requests. ForceSendFields []string `json:"-"` - // NullFields is a list of field names (e.g. "Instance") to include in - // API requests with the JSON null value. By default, fields with empty - // values are omitted from API requests. However, any field with an - // empty value appearing in NullFields will be sent to the server as + // NullFields is a list of field names (e.g. "Annotations") to include + // in API requests with the JSON null value. By default, fields with + // empty values are omitted from API requests. However, any field with + // an empty value appearing in NullFields will be sent to the server as // null. It is an error if a field in this list has a non-empty value. // This may be used to include null fields in Patch requests. NullFields []string `json:"-"` @@ -18849,10 +19779,18 @@ func (s *NetworkEndpoint) MarshalJSON() ([]byte, error) { // NetworkEndpointGroup: Represents a collection of network endpoints. type NetworkEndpointGroup struct { + // Annotations: Metadata defined as annotations on the network endpoint + // group. + Annotations map[string]string `json:"annotations,omitempty"` + // CreationTimestamp: [Output Only] Creation timestamp in RFC3339 text // format. CreationTimestamp string `json:"creationTimestamp,omitempty"` + // DefaultPort: The default port used if the port number is not + // specified in the network endpoint. + DefaultPort int64 `json:"defaultPort,omitempty"` + // Description: An optional description of this resource. Provide this // property when you create the resource. Description string `json:"description,omitempty"` @@ -18866,7 +19804,8 @@ type NetworkEndpointGroup struct { Kind string `json:"kind,omitempty"` // LoadBalancer: This field is only valid when the network endpoint - // group type is LOAD_BALANCING. + // group is used for load balancing. [Deprecated] This field is + // deprecated. LoadBalancer *NetworkEndpointGroupLbNetworkEndpointGroup `json:"loadBalancer,omitempty"` // Name: Name of the resource; provided by the client when the resource @@ -18878,9 +19817,12 @@ type NetworkEndpointGroup struct { // last character, which cannot be a dash. Name string `json:"name,omitempty"` + // Network: The URL of the network to which all network endpoints in the + // NEG belong. Uses "default" project network if unspecified. + Network string `json:"network,omitempty"` + // NetworkEndpointType: Type of network endpoints in this network - // endpoint group. Only supported values for LOAD_BALANCING are - // GCE_VM_IP or GCE_VM_IP_PORT. + // endpoint group. Currently the only supported value is GCE_VM_IP_PORT. // // Possible values: // "GCE_VM_IP_PORT" @@ -18893,6 +19835,10 @@ type NetworkEndpointGroup struct { // endpoint group. Size int64 `json:"size,omitempty"` + // Subnetwork: Optional URL of the subnetwork to which all network + // endpoints in the NEG belong. + Subnetwork string `json:"subnetwork,omitempty"` + // Type: Specify the type of this network endpoint group. Only // LOAD_BALANCING is valid for now. // @@ -18900,25 +19846,28 @@ type NetworkEndpointGroup struct { // "LOAD_BALANCING" Type string `json:"type,omitempty"` + // Zone: [Output Only] The URL of the zone where the network endpoint + // group is located. + Zone string `json:"zone,omitempty"` + // ServerResponse contains the HTTP response code and headers from the // server. googleapi.ServerResponse `json:"-"` - // ForceSendFields is a list of field names (e.g. "CreationTimestamp") - // to unconditionally include in API requests. By default, fields with + // ForceSendFields is a list of field names (e.g. "Annotations") to + // unconditionally include in API requests. By default, fields with // empty values are omitted from API requests. However, any non-pointer, // non-interface field appearing in ForceSendFields will be sent to the // server regardless of whether the field is empty or not. This may be // used to include empty fields in Patch requests. ForceSendFields []string `json:"-"` - // NullFields is a list of field names (e.g. "CreationTimestamp") to - // include in API requests with the JSON null value. By default, fields - // with empty values are omitted from API requests. However, any field - // with an empty value appearing in NullFields will be sent to the - // server as null. It is an error if a field in this list has a - // non-empty value. This may be used to include null fields in Patch - // requests. + // NullFields is a list of field names (e.g. "Annotations") to include + // in API requests with the JSON null value. By default, fields with + // empty values are omitted from API requests. However, any field with + // an empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. NullFields []string `json:"-"` } @@ -19085,23 +20034,24 @@ func (s *NetworkEndpointGroupAggregatedListWarningData) MarshalJSON() ([]byte, e } // NetworkEndpointGroupLbNetworkEndpointGroup: Load balancing specific -// fields for network endpoint group of type LOAD_BALANCING. +// fields for network endpoint group. type NetworkEndpointGroupLbNetworkEndpointGroup struct { // DefaultPort: The default port used if the port number is not - // specified in the network endpoint. If the network endpoint type is - // GCE_VM_IP, this field must not be specified. + // specified in the network endpoint. [Deprecated] This field is + // deprecated. DefaultPort int64 `json:"defaultPort,omitempty"` // Network: The URL of the network to which all network endpoints in the // NEG belong. Uses "default" project network if unspecified. + // [Deprecated] This field is deprecated. Network string `json:"network,omitempty"` // Subnetwork: Optional URL of the subnetwork to which all network - // endpoints in the NEG belong. + // endpoints in the NEG belong. [Deprecated] This field is deprecated. Subnetwork string `json:"subnetwork,omitempty"` // Zone: [Output Only] The URL of the zone where the network endpoint - // group is located. + // group is located. [Deprecated] This field is deprecated. Zone string `json:"zone,omitempty"` // ForceSendFields is a list of field names (e.g. "DefaultPort") to @@ -19709,7 +20659,8 @@ type NetworkInterface struct { // Fingerprint: Fingerprint hash of contents stored in this network // interface. This field will be ignored when inserting an Instance or // adding a NetworkInterface. An up-to-date fingerprint must be provided - // in order to update the NetworkInterface. + // in order to update the NetworkInterface, otherwise the request will + // fail with error 412 conditionNotMet. Fingerprint string `json:"fingerprint,omitempty"` // Kind: [Output Only] Type of the resource. Always @@ -19938,12 +20889,23 @@ func (s *NetworkListWarningData) MarshalJSON() ([]byte, error) { // flag indicating whether Google Compute Engine should automatically // create routes for the peering. type NetworkPeering struct { - // AutoCreateRoutes: Whether full mesh connectivity is created and + // AdvertisePeerSubnetsViaRouters: Whether Cloud Routers in this network + // can automatically advertise subnets from the peer network. + AdvertisePeerSubnetsViaRouters bool `json:"advertisePeerSubnetsViaRouters,omitempty"` + + // AutoCreateRoutes: Indicates whether full mesh connectivity is created + // and managed automatically. When it is set to true, Google Compute + // Engine will automatically create and manage the routes between two + // networks when the state is ACTIVE. Otherwise, user needs to create + // routes manually to route packets to peer network. + AutoCreateRoutes bool `json:"autoCreateRoutes,omitempty"` + + // ExchangeSubnetRoutes: Whether full mesh connectivity is created and // managed automatically. When it is set to true, Google Compute Engine // will automatically create and manage the routes between two networks - // when the state is ACTIVE. Otherwise, user needs to create routes - // manually to route packets to peer network. - AutoCreateRoutes bool `json:"autoCreateRoutes,omitempty"` + // when the peering state is ACTIVE. Otherwise, user needs to create + // routes manually to route packets to peer network. + ExchangeSubnetRoutes bool `json:"exchangeSubnetRoutes,omitempty"` // ExportCustomRoutes: Whether to export the custom routes to peer // network. @@ -19979,21 +20941,22 @@ type NetworkPeering struct { // peering. StateDetails string `json:"stateDetails,omitempty"` - // ForceSendFields is a list of field names (e.g. "AutoCreateRoutes") to - // unconditionally include in API requests. By default, fields with - // empty values are omitted from API requests. However, any non-pointer, - // non-interface field appearing in ForceSendFields will be sent to the - // server regardless of whether the field is empty or not. This may be - // used to include empty fields in Patch requests. + // ForceSendFields is a list of field names (e.g. + // "AdvertisePeerSubnetsViaRouters") to unconditionally include in API + // requests. By default, fields with empty values are omitted from API + // requests. However, any non-pointer, non-interface field appearing in + // ForceSendFields will be sent to the server regardless of whether the + // field is empty or not. This may be used to include empty fields in + // Patch requests. ForceSendFields []string `json:"-"` - // NullFields is a list of field names (e.g. "AutoCreateRoutes") to - // include in API requests with the JSON null value. By default, fields - // with empty values are omitted from API requests. However, any field - // with an empty value appearing in NullFields will be sent to the - // server as null. It is an error if a field in this list has a - // non-empty value. This may be used to include null fields in Patch - // requests. + // NullFields is a list of field names (e.g. + // "AdvertisePeerSubnetsViaRouters") to include in API requests with the + // JSON null value. By default, fields with empty values are omitted + // from API requests. However, any field with an empty value appearing + // in NullFields will be sent to the server as null. It is an error if a + // field in this list has a non-empty value. This may be used to include + // null fields in Patch requests. NullFields []string `json:"-"` } @@ -20010,9 +20973,9 @@ func (s *NetworkPeering) MarshalJSON() ([]byte, error) { type NetworkRoutingConfig struct { // RoutingMode: The network-wide routing mode to use. If set to // REGIONAL, this network's cloud routers will only advertise routes - // with subnetworks of this network in the same region as the router. If - // set to GLOBAL, this network's cloud routers will advertise routes - // with all subnetworks of this network, across regions. + // with subnets of this network in the same region as the router. If set + // to GLOBAL, this network's cloud routers will advertise routes with + // all subnets of this network, across regions. // // Possible values: // "GLOBAL" @@ -20047,17 +21010,26 @@ type NetworksAddPeeringRequest struct { // automatically. AutoCreateRoutes bool `json:"autoCreateRoutes,omitempty"` - // ExportCustomRoutes: Whether to export the custom routes to peer - // network. + // ExportCustomRoutes: This field will be deprecated soon. Prefer using + // export_custom_routes in network_peering instead. Whether to export + // the custom routes to peer network. ExportCustomRoutes bool `json:"exportCustomRoutes,omitempty"` - // ImportCustomRoutes: Whether to import the custom routes from peer - // network. + // ImportCustomRoutes: This field will be deprecated soon. Prefer using + // import_custom_routes in network_peering instead. Whether to import + // the custom routes from peer network. ImportCustomRoutes bool `json:"importCustomRoutes,omitempty"` // Name: Name of the peering, which should conform to RFC1035. Name string `json:"name,omitempty"` + // NetworkPeering: Network peering parameters. In order to specify route + // policies for peering using import/export custom routes, you will have + // to fill all peering related parameters (name, peer network, + // exchange_subnet_routes) in network_peeringfield. Corresponding fields + // in NetworksAddPeeringRequest will be deprecated soon. + NetworkPeering *NetworkPeering `json:"networkPeering,omitempty"` + // PeerNetwork: URL of the peer network. It can be either full URL or // partial URL. The peer network may belong to a different project. If // the partial URL does not contain project, it is assumed that the peer @@ -20115,8 +21087,37 @@ func (s *NetworksRemovePeeringRequest) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +type NetworksUpdatePeeringRequest struct { + NetworkPeering *NetworkPeering `json:"networkPeering,omitempty"` + + // ForceSendFields is a list of field names (e.g. "NetworkPeering") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "NetworkPeering") to + // include in API requests with the JSON null value. By default, fields + // with empty values are omitted from API requests. However, any field + // with an empty value appearing in NullFields will be sent to the + // server as null. It is an error if a field in this list has a + // non-empty value. This may be used to include null fields in Patch + // requests. + NullFields []string `json:"-"` +} + +func (s *NetworksUpdatePeeringRequest) MarshalJSON() ([]byte, error) { + type NoMethod NetworksUpdatePeeringRequest + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + // NodeGroup: A NodeGroup resource. type NodeGroup struct { + AutoscalingPolicy *NodeGroupAutoscalingPolicy `json:"autoscalingPolicy,omitempty"` + // CreationTimestamp: [Output Only] Creation timestamp in RFC3339 text // format. CreationTimestamp string `json:"creationTimestamp,omitempty"` @@ -20147,12 +21148,12 @@ type NodeGroup struct { // belongs. NodeTemplate string `json:"nodeTemplate,omitempty"` - // Nodes: [Output Only] A list of nodes in this node group. - Nodes []*NodeGroupNode `json:"nodes,omitempty"` - // SelfLink: [Output Only] Server-defined URL for the resource. SelfLink string `json:"selfLink,omitempty"` + // Size: [Output Only] The total number of nodes in the node group. + Size int64 `json:"size,omitempty"` + // Possible values: // "CREATING" // "DELETING" @@ -20168,7 +21169,7 @@ type NodeGroup struct { // server. googleapi.ServerResponse `json:"-"` - // ForceSendFields is a list of field names (e.g. "CreationTimestamp") + // ForceSendFields is a list of field names (e.g. "AutoscalingPolicy") // to unconditionally include in API requests. By default, fields with // empty values are omitted from API requests. However, any non-pointer, // non-interface field appearing in ForceSendFields will be sent to the @@ -20176,7 +21177,7 @@ type NodeGroup struct { // used to include empty fields in Patch requests. ForceSendFields []string `json:"-"` - // NullFields is a list of field names (e.g. "CreationTimestamp") to + // NullFields is a list of field names (e.g. "AutoscalingPolicy") to // include in API requests with the JSON null value. By default, fields // with empty values are omitted from API requests. However, any field // with an empty value appearing in NullFields will be sent to the @@ -20347,6 +21348,34 @@ func (s *NodeGroupAggregatedListWarningData) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +type NodeGroupAutoscalingPolicy struct { + MaxSize int64 `json:"maxSize,omitempty"` + + MinSize int64 `json:"minSize,omitempty"` + + // ForceSendFields is a list of field names (e.g. "MaxSize") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "MaxSize") to include in + // API requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *NodeGroupAutoscalingPolicy) MarshalJSON() ([]byte, error) { + type NoMethod NodeGroupAutoscalingPolicy + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + // NodeGroupList: Contains a list of nodeGroups. type NodeGroupList struct { // Id: [Output Only] Unique identifier for the resource; defined by the @@ -20503,8 +21532,6 @@ func (s *NodeGroupListWarningData) MarshalJSON() ([]byte, error) { } type NodeGroupNode struct { - Index int64 `json:"index,omitempty"` - // Instances: Instances scheduled on this node. Instances []string `json:"instances,omitempty"` @@ -20514,14 +21541,18 @@ type NodeGroupNode struct { // NodeType: The type of this node. NodeType string `json:"nodeType,omitempty"` + // ServerBinding: Binding properties for the physical server. + ServerBinding *ServerBinding `json:"serverBinding,omitempty"` + // Possible values: // "CREATING" // "DELETING" // "INVALID" // "READY" + // "REPAIRING" Status string `json:"status,omitempty"` - // ForceSendFields is a list of field names (e.g. "Index") to + // ForceSendFields is a list of field names (e.g. "Instances") to // unconditionally include in API requests. By default, fields with // empty values are omitted from API requests. However, any non-pointer, // non-interface field appearing in ForceSendFields will be sent to the @@ -20529,8 +21560,8 @@ type NodeGroupNode struct { // used to include empty fields in Patch requests. ForceSendFields []string `json:"-"` - // NullFields is a list of field names (e.g. "Index") to include in API - // requests with the JSON null value. By default, fields with empty + // NullFields is a list of field names (e.g. "Instances") to include in + // API requests with the JSON null value. By default, fields with empty // values are omitted from API requests. However, any field with an // empty value appearing in NullFields will be sent to the server as // null. It is an error if a field in this list has a non-empty value. @@ -20574,12 +21605,9 @@ func (s *NodeGroupsAddNodesRequest) MarshalJSON() ([]byte, error) { } type NodeGroupsDeleteNodesRequest struct { - // NodeIndexes: Indexes of the nodes to be deleted from the node group. - NodeIndexes []int64 `json:"nodeIndexes,omitempty"` - Nodes []string `json:"nodes,omitempty"` - // ForceSendFields is a list of field names (e.g. "NodeIndexes") to + // ForceSendFields is a list of field names (e.g. "Nodes") to // unconditionally include in API requests. By default, fields with // empty values are omitted from API requests. However, any non-pointer, // non-interface field appearing in ForceSendFields will be sent to the @@ -20587,10 +21615,10 @@ type NodeGroupsDeleteNodesRequest struct { // used to include empty fields in Patch requests. ForceSendFields []string `json:"-"` - // NullFields is a list of field names (e.g. "NodeIndexes") to include - // in API requests with the JSON null value. By default, fields with - // empty values are omitted from API requests. However, any field with - // an empty value appearing in NullFields will be sent to the server as + // NullFields is a list of field names (e.g. "Nodes") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as // null. It is an error if a field in this list has a non-empty value. // This may be used to include null fields in Patch requests. NullFields []string `json:"-"` @@ -20602,6 +21630,162 @@ func (s *NodeGroupsDeleteNodesRequest) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +type NodeGroupsListNodes struct { + // Id: [Output Only] Unique identifier for the resource; defined by the + // server. + Id string `json:"id,omitempty"` + + // Items: A list of Node resources. + Items []*NodeGroupNode `json:"items,omitempty"` + + // Kind: [Output Only] The resource type, which is always + // compute.nodeGroupsListNodes for the list of nodes in the specified + // node group. + Kind string `json:"kind,omitempty"` + + // NextPageToken: [Output Only] This token allows you to get the next + // page of results for list requests. If the number of results is larger + // than maxResults, use the nextPageToken as a value for the query + // parameter pageToken in the next list request. Subsequent list + // requests will have their own nextPageToken to continue paging through + // the results. + NextPageToken string `json:"nextPageToken,omitempty"` + + // SelfLink: [Output Only] Server-defined URL for this resource. + SelfLink string `json:"selfLink,omitempty"` + + // Warning: [Output Only] Informational warning message. + Warning *NodeGroupsListNodesWarning `json:"warning,omitempty"` + + // ServerResponse contains the HTTP response code and headers from the + // server. + googleapi.ServerResponse `json:"-"` + + // ForceSendFields is a list of field names (e.g. "Id") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Id") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *NodeGroupsListNodes) MarshalJSON() ([]byte, error) { + type NoMethod NodeGroupsListNodes + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// NodeGroupsListNodesWarning: [Output Only] Informational warning +// message. +type NodeGroupsListNodesWarning struct { + // Code: [Output Only] A warning code, if applicable. For example, + // Compute Engine returns NO_RESULTS_ON_PAGE if there are no results in + // the response. + // + // Possible values: + // "CLEANUP_FAILED" + // "DEPRECATED_RESOURCE_USED" + // "DEPRECATED_TYPE_USED" + // "DISK_SIZE_LARGER_THAN_IMAGE_SIZE" + // "EXPERIMENTAL_TYPE_USED" + // "EXTERNAL_API_WARNING" + // "FIELD_VALUE_OVERRIDEN" + // "INJECTED_KERNELS_DEPRECATED" + // "MISSING_TYPE_DEPENDENCY" + // "NEXT_HOP_ADDRESS_NOT_ASSIGNED" + // "NEXT_HOP_CANNOT_IP_FORWARD" + // "NEXT_HOP_INSTANCE_NOT_FOUND" + // "NEXT_HOP_INSTANCE_NOT_ON_NETWORK" + // "NEXT_HOP_NOT_RUNNING" + // "NOT_CRITICAL_ERROR" + // "NO_RESULTS_ON_PAGE" + // "REQUIRED_TOS_AGREEMENT" + // "RESOURCE_IN_USE_BY_OTHER_RESOURCE_WARNING" + // "RESOURCE_NOT_DELETED" + // "SCHEMA_VALIDATION_IGNORED" + // "SINGLE_INSTANCE_PROPERTY_TEMPLATE" + // "UNDECLARED_PROPERTIES" + // "UNREACHABLE" + Code string `json:"code,omitempty"` + + // Data: [Output Only] Metadata about this warning in key: value format. + // For example: + // "data": [ { "key": "scope", "value": "zones/us-east1-d" } + Data []*NodeGroupsListNodesWarningData `json:"data,omitempty"` + + // Message: [Output Only] A human-readable description of the warning + // code. + Message string `json:"message,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Code") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Code") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *NodeGroupsListNodesWarning) MarshalJSON() ([]byte, error) { + type NoMethod NodeGroupsListNodesWarning + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type NodeGroupsListNodesWarningData struct { + // Key: [Output Only] A key that provides more detail on the warning + // being returned. For example, for warnings where there are no results + // in a list request for a particular zone, this key might be scope and + // the key value might be the zone name. Other examples might be a key + // indicating a deprecated resource and a suggested replacement, or a + // warning about invalid network settings (for example, if an instance + // attempts to perform IP forwarding but is not enabled for IP + // forwarding). + Key string `json:"key,omitempty"` + + // Value: [Output Only] A warning data value corresponding to the key. + Value string `json:"value,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Key") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Key") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *NodeGroupsListNodesWarningData) MarshalJSON() ([]byte, error) { + type NoMethod NodeGroupsListNodesWarningData + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + type NodeGroupsScopedList struct { // NodeGroups: [Output Only] A list of node groups contained in this // scope. @@ -20788,7 +21972,7 @@ type NodeTemplate struct { // characters long and match the regular expression // `[a-z]([-a-z0-9]*[a-z0-9])?` which means the first character must be // a lowercase letter, and all following characters must be a dash, - // lowercase letter, or digit, except the last charaicter, which cannot + // lowercase letter, or digit, except the last character, which cannot // be a dash. Name string `json:"name,omitempty"` @@ -20815,6 +21999,9 @@ type NodeTemplate struct { // SelfLink: [Output Only] Server-defined URL for the resource. SelfLink string `json:"selfLink,omitempty"` + // ServerBinding: Binding properties for the physical server. + ServerBinding *ServerBinding `json:"serverBinding,omitempty"` + // Status: [Output Only] The status of the node template. One of the // following values: CREATING, READY, and DELETING. // @@ -22600,14 +23787,23 @@ func (s *OperationsScopedListWarningData) MarshalJSON() ([]byte, error) { // no rule was matched, the default service will be used. type PathMatcher struct { // DefaultService: The full or partial URL to the BackendService - // resource. This will be used if none of the pathRules defined by this - // PathMatcher is matched by the URL's path portion. For example, the - // following are all valid URLs to a BackendService resource: + // resource. This will be used if none of the pathRules or routeRules + // defined by this PathMatcher are matched. For example, the following + // are all valid URLs to a BackendService resource: // - // https://www.googleapis.com/compute/v1/projects/project/global/backendServices/backendService // - compute/v1/projects/project/global/backendServices/backendService // // - global/backendServices/backendService + // Use defaultService instead of defaultRouteAction when simple routing + // to a backend service is desired and other advanced capabilities like + // traffic splitting and URL rewrites are not required. + // Only one of defaultService, defaultRouteAction or defaultUrlRedirect + // must be set. + // Authorization requires one or more of the following Google IAM + // permissions on the specified resource default_service: + // - compute.backendBuckets.use + // - compute.backendServices.use DefaultService string `json:"defaultService,omitempty"` // Description: An optional description of this resource. Provide this @@ -22617,7 +23813,14 @@ type PathMatcher struct { // Name: The name to which this PathMatcher is referred by the HostRule. Name string `json:"name,omitempty"` - // PathRules: The list of path rules. + // PathRules: The list of path rules. Use this list instead of + // routeRules when routing based on simple path matching is all that's + // required. The order by which path rules are specified does not + // matter. Matches are always done on the longest-path-first basis. + // For example: a pathRule with a path /a/b/c/* will match before /a/b/* + // irrespective of the order in which those paths appear in this + // list. + // Only one of pathRules or routeRules must be set. PathRules []*PathRule `json:"pathRules,omitempty"` // ForceSendFields is a list of field names (e.g. "DefaultService") to @@ -22653,8 +23856,12 @@ type PathRule struct { // or #, and those chars are not allowed here. Paths []string `json:"paths,omitempty"` - // Service: The URL of the BackendService resource if this rule is + // Service: The URL of the backend service resource if this rule is // matched. + // Use service instead of routeAction when simple routing to a backend + // service is desired and other advanced capabilities like traffic + // splitting and rewrites are not required. + // Only one of service, routeAction or urlRedirect should must be set. Service string `json:"service,omitempty"` // ForceSendFields is a list of field names (e.g. "Paths") to @@ -22694,8 +23901,21 @@ type PerInstanceConfig struct { // one will be created. Instance string `json:"instance,omitempty"` + // Name: The name of the per-instance config and the corresponding + // instance. Serves as a merge key during UpdatePerInstanceConfigs + // operation, i.e. if per-instance config with the same name exists then + // it will be updated, otherwise a new one will be created for the VM + // instance with the same name. An attempt to create a per-instance + // config for a VM instance that either doesn't exist or is not part of + // the group will result in a failure. + Name string `json:"name,omitempty"` + Override *ManagedInstanceOverride `json:"override,omitempty"` + // PreservedState: Intended preserved state for the given instance. Does + // not contain state generated based on Stateful Policy. + PreservedState *PreservedState `json:"preservedState,omitempty"` + // ForceSendFields is a list of field names (e.g. "Fingerprint") to // unconditionally include in API requests. By default, fields with // empty values are omitted from API requests. However, any non-pointer, @@ -22844,6 +24064,87 @@ func (s *PreconfiguredWafSet) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +// PreservedState: Preserved state for a given instance. +type PreservedState struct { + // Disks: Preserved disks defined for this instance. This map is keyed + // with the device names of the disks. + Disks map[string]PreservedStatePreservedDisk `json:"disks,omitempty"` + + // Metadata: Preserved metadata defined for this instance. + Metadata map[string]string `json:"metadata,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Disks") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Disks") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *PreservedState) MarshalJSON() ([]byte, error) { + type NoMethod PreservedState + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type PreservedStatePreservedDisk struct { + // AutoDelete: These stateful disks will never be deleted during + // autohealing, update, instance recreate operations. This flag is used + // to configure if the disk should be deleted after it is no longer used + // by the group, e.g. when the given instance or the whole MIG is + // deleted. Note: disks attached in READ_ONLY mode cannot be + // auto-deleted. + // + // Possible values: + // "NEVER" + // "WHEN_NOT_IN_USE" + AutoDelete string `json:"autoDelete,omitempty"` + + // Mode: The mode in which to attach this disk, either READ_WRITE or + // READ_ONLY. If not specified, the default is to attach the disk in + // READ_WRITE mode. + // + // Possible values: + // "READ_ONLY" + // "READ_WRITE" + Mode string `json:"mode,omitempty"` + + // Source: The URL of the disk resource that is stateful and should be + // attached to the VM instance. + Source string `json:"source,omitempty"` + + // ForceSendFields is a list of field names (e.g. "AutoDelete") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "AutoDelete") to include in + // API requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *PreservedStatePreservedDisk) MarshalJSON() ([]byte, error) { + type NoMethod PreservedStatePreservedDisk + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + // Project: A Project resource. For an overview of projects, see Cloud // Platform Resource Hierarchy. (== resource_for v1.projects ==) (== // resource_for beta.projects ==) @@ -23143,6 +24444,8 @@ type Quota struct { // "DISKS_TOTAL_GB" // "FIREWALLS" // "FORWARDING_RULES" + // "GLOBAL_INTERNAL_ADDRESSES" + // "GPUS_ALL_REGIONS" // "HEALTH_CHECKS" // "IMAGES" // "INSTANCES" @@ -23154,18 +24457,29 @@ type Quota struct { // "INTERCONNECT_ATTACHMENTS_TOTAL_MBPS" // "INTERNAL_ADDRESSES" // "IN_USE_ADDRESSES" + // "IN_USE_BACKUP_SCHEDULES" // "IN_USE_MAINTENANCE_WINDOWS" // "LOCAL_SSD_TOTAL_GB" + // "MACHINE_IMAGES" // "NETWORKS" // "NETWORK_ENDPOINT_GROUPS" // "NVIDIA_K80_GPUS" // "NVIDIA_P100_GPUS" // "NVIDIA_P100_VWS_GPUS" + // "NVIDIA_P4_GPUS" + // "NVIDIA_P4_VWS_GPUS" + // "NVIDIA_T4_GPUS" + // "NVIDIA_T4_VWS_GPUS" // "NVIDIA_V100_GPUS" // "PREEMPTIBLE_CPUS" // "PREEMPTIBLE_LOCAL_SSD_GB" // "PREEMPTIBLE_NVIDIA_K80_GPUS" // "PREEMPTIBLE_NVIDIA_P100_GPUS" + // "PREEMPTIBLE_NVIDIA_P100_VWS_GPUS" + // "PREEMPTIBLE_NVIDIA_P4_GPUS" + // "PREEMPTIBLE_NVIDIA_P4_VWS_GPUS" + // "PREEMPTIBLE_NVIDIA_T4_GPUS" + // "PREEMPTIBLE_NVIDIA_T4_VWS_GPUS" // "PREEMPTIBLE_NVIDIA_V100_GPUS" // "PRIVATE_V6_ACCESS_SUBNETWORKS" // "REGIONAL_AUTOSCALERS" @@ -23188,6 +24502,7 @@ type Quota struct { // "TARGET_TCP_PROXIES" // "TARGET_VPN_GATEWAYS" // "URL_MAPS" + // "VPN_GATEWAYS" // "VPN_TUNNELS" Metric string `json:"metric,omitempty"` @@ -23653,6 +24968,62 @@ func (s *RegionDiskTypeListWarningData) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +type RegionDisksAddResourcePoliciesRequest struct { + // ResourcePolicies: Resource policies to be added to this disk. + ResourcePolicies []string `json:"resourcePolicies,omitempty"` + + // ForceSendFields is a list of field names (e.g. "ResourcePolicies") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "ResourcePolicies") to + // include in API requests with the JSON null value. By default, fields + // with empty values are omitted from API requests. However, any field + // with an empty value appearing in NullFields will be sent to the + // server as null. It is an error if a field in this list has a + // non-empty value. This may be used to include null fields in Patch + // requests. + NullFields []string `json:"-"` +} + +func (s *RegionDisksAddResourcePoliciesRequest) MarshalJSON() ([]byte, error) { + type NoMethod RegionDisksAddResourcePoliciesRequest + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type RegionDisksRemoveResourcePoliciesRequest struct { + // ResourcePolicies: Resource policies to be removed from this disk. + ResourcePolicies []string `json:"resourcePolicies,omitempty"` + + // ForceSendFields is a list of field names (e.g. "ResourcePolicies") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "ResourcePolicies") to + // include in API requests with the JSON null value. By default, fields + // with empty values are omitted from API requests. However, any field + // with an empty value appearing in NullFields will be sent to the + // server as null. It is an error if a field in this list has a + // non-empty value. This may be used to include null fields in Patch + // requests. + NullFields []string `json:"-"` +} + +func (s *RegionDisksRemoveResourcePoliciesRequest) MarshalJSON() ([]byte, error) { + type NoMethod RegionDisksRemoveResourcePoliciesRequest + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + type RegionDisksResizeRequest struct { // SizeGb: The new size of the regional persistent disk, which is // specified in GB. @@ -23843,6 +25214,10 @@ type RegionInstanceGroupManagerDeleteInstanceConfigReq struct { // per-instance configs on this managed instance group. Instances []string `json:"instances,omitempty"` + // Names: The list of instance names for which we want to delete + // per-instance configs on this managed instance group. + Names []string `json:"names,omitempty"` + // ForceSendFields is a list of field names (e.g. "Instances") to // unconditionally include in API requests. By default, fields with // empty values are omitted from API requests. However, any non-pointer, @@ -24922,6 +26297,36 @@ func (s *RegionSetPolicyRequest) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +type RegionTargetHttpsProxiesSetSslCertificatesRequest struct { + // SslCertificates: New set of SslCertificate resources to associate + // with this TargetHttpsProxy resource. Currently exactly one + // SslCertificate resource must be specified. + SslCertificates []string `json:"sslCertificates,omitempty"` + + // ForceSendFields is a list of field names (e.g. "SslCertificates") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "SslCertificates") to + // include in API requests with the JSON null value. By default, fields + // with empty values are omitted from API requests. However, any field + // with an empty value appearing in NullFields will be sent to the + // server as null. It is an error if a field in this list has a + // non-empty value. This may be used to include null fields in Patch + // requests. + NullFields []string `json:"-"` +} + +func (s *RegionTargetHttpsProxiesSetSslCertificatesRequest) MarshalJSON() ([]byte, error) { + type NoMethod RegionTargetHttpsProxiesSetSslCertificatesRequest + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + type RegionUrlMapsValidateRequest struct { // Resource: Content of the UrlMap to be validated. Resource *UrlMap `json:"resource,omitempty"` @@ -24952,6 +26357,10 @@ func (s *RegionUrlMapsValidateRequest) MarshalJSON() ([]byte, error) { // ResourceCommitment: Commitment for a particular resource (a // Commitment is composed of one or more of these). type ResourceCommitment struct { + // AcceleratorType: Name of the accelerator type resource. Applicable + // only when the type is ACCELERATOR. + AcceleratorType string `json:"acceleratorType,omitempty"` + // Amount: The amount of the resource purchased (in a type-dependent // unit, such as bytes). For vCPUs, this can just be an integer. For // memory, this must be provided in MB. Memory must be a multiple of 256 @@ -24962,13 +26371,14 @@ type ResourceCommitment struct { // values are VCPU and MEMORY // // Possible values: + // "ACCELERATOR" // "LOCAL_SSD" // "MEMORY" // "UNSPECIFIED" // "VCPU" Type string `json:"type,omitempty"` - // ForceSendFields is a list of field names (e.g. "Amount") to + // ForceSendFields is a list of field names (e.g. "AcceleratorType") to // unconditionally include in API requests. By default, fields with // empty values are omitted from API requests. However, any non-pointer, // non-interface field appearing in ForceSendFields will be sent to the @@ -24976,12 +26386,13 @@ type ResourceCommitment struct { // used to include empty fields in Patch requests. ForceSendFields []string `json:"-"` - // NullFields is a list of field names (e.g. "Amount") to include in API - // requests with the JSON null value. By default, fields with empty - // values are omitted from API requests. However, any field with an - // empty value appearing in NullFields will be sent to the server as - // null. It is an error if a field in this list has a non-empty value. - // This may be used to include null fields in Patch requests. + // NullFields is a list of field names (e.g. "AcceleratorType") to + // include in API requests with the JSON null value. By default, fields + // with empty values are omitted from API requests. However, any field + // with an empty value appearing in NullFields will be sent to the + // server as null. It is an error if a field in this list has a + // non-empty value. This may be used to include null fields in Patch + // requests. NullFields []string `json:"-"` } @@ -24992,8 +26403,8 @@ func (s *ResourceCommitment) MarshalJSON() ([]byte, error) { } type ResourceGroupReference struct { - // Group: A URI referencing one of the instance groups listed in the - // backend service. + // Group: A URI referencing one of the instance groups or network + // endpoint groups listed in the backend service. Group string `json:"group,omitempty"` // ForceSendFields is a list of field names (e.g. "Group") to @@ -25019,163 +26430,6 @@ func (s *ResourceGroupReference) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } -type ResourcePoliciesList struct { - Etag string `json:"etag,omitempty"` - - // Id: [Output Only] The unique identifier for the resource. This - // identifier is defined by the server. - Id string `json:"id,omitempty"` - - // Items: [Output Only] A list of ResourcePolicy resources. - Items []*ResourcePolicy `json:"items,omitempty"` - - // Kind: [Output Only] Type of resource.Always - // compute#resourcePoliciesList for listsof resourcePolicies - Kind string `json:"kind,omitempty"` - - // NextPageToken: [Output Only] This token allows you to get the next - // page of results for list requests. If the number of results is larger - // than maxResults, use the nextPageToken as a value for the query - // parameter pageToken in the next list request. Subsequent list - // requests will have their own nextPageToken to continue paging through - // the results. - NextPageToken string `json:"nextPageToken,omitempty"` - - // SelfLink: [Output Only] Server-defined URL for this resource. - SelfLink string `json:"selfLink,omitempty"` - - // Warning: [Output Only] Informational warning message. - Warning *ResourcePoliciesListWarning `json:"warning,omitempty"` - - // ServerResponse contains the HTTP response code and headers from the - // server. - googleapi.ServerResponse `json:"-"` - - // ForceSendFields is a list of field names (e.g. "Etag") to - // unconditionally include in API requests. By default, fields with - // empty values are omitted from API requests. However, any non-pointer, - // non-interface field appearing in ForceSendFields will be sent to the - // server regardless of whether the field is empty or not. This may be - // used to include empty fields in Patch requests. - ForceSendFields []string `json:"-"` - - // NullFields is a list of field names (e.g. "Etag") to include in API - // requests with the JSON null value. By default, fields with empty - // values are omitted from API requests. However, any field with an - // empty value appearing in NullFields will be sent to the server as - // null. It is an error if a field in this list has a non-empty value. - // This may be used to include null fields in Patch requests. - NullFields []string `json:"-"` -} - -func (s *ResourcePoliciesList) MarshalJSON() ([]byte, error) { - type NoMethod ResourcePoliciesList - raw := NoMethod(*s) - return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) -} - -// ResourcePoliciesListWarning: [Output Only] Informational warning -// message. -type ResourcePoliciesListWarning struct { - // Code: [Output Only] A warning code, if applicable. For example, - // Compute Engine returns NO_RESULTS_ON_PAGE if there are no results in - // the response. - // - // Possible values: - // "CLEANUP_FAILED" - // "DEPRECATED_RESOURCE_USED" - // "DEPRECATED_TYPE_USED" - // "DISK_SIZE_LARGER_THAN_IMAGE_SIZE" - // "EXPERIMENTAL_TYPE_USED" - // "EXTERNAL_API_WARNING" - // "FIELD_VALUE_OVERRIDEN" - // "INJECTED_KERNELS_DEPRECATED" - // "MISSING_TYPE_DEPENDENCY" - // "NEXT_HOP_ADDRESS_NOT_ASSIGNED" - // "NEXT_HOP_CANNOT_IP_FORWARD" - // "NEXT_HOP_INSTANCE_NOT_FOUND" - // "NEXT_HOP_INSTANCE_NOT_ON_NETWORK" - // "NEXT_HOP_NOT_RUNNING" - // "NOT_CRITICAL_ERROR" - // "NO_RESULTS_ON_PAGE" - // "REQUIRED_TOS_AGREEMENT" - // "RESOURCE_IN_USE_BY_OTHER_RESOURCE_WARNING" - // "RESOURCE_NOT_DELETED" - // "SCHEMA_VALIDATION_IGNORED" - // "SINGLE_INSTANCE_PROPERTY_TEMPLATE" - // "UNDECLARED_PROPERTIES" - // "UNREACHABLE" - Code string `json:"code,omitempty"` - - // Data: [Output Only] Metadata about this warning in key: value format. - // For example: - // "data": [ { "key": "scope", "value": "zones/us-east1-d" } - Data []*ResourcePoliciesListWarningData `json:"data,omitempty"` - - // Message: [Output Only] A human-readable description of the warning - // code. - Message string `json:"message,omitempty"` - - // ForceSendFields is a list of field names (e.g. "Code") to - // unconditionally include in API requests. By default, fields with - // empty values are omitted from API requests. However, any non-pointer, - // non-interface field appearing in ForceSendFields will be sent to the - // server regardless of whether the field is empty or not. This may be - // used to include empty fields in Patch requests. - ForceSendFields []string `json:"-"` - - // NullFields is a list of field names (e.g. "Code") to include in API - // requests with the JSON null value. By default, fields with empty - // values are omitted from API requests. However, any field with an - // empty value appearing in NullFields will be sent to the server as - // null. It is an error if a field in this list has a non-empty value. - // This may be used to include null fields in Patch requests. - NullFields []string `json:"-"` -} - -func (s *ResourcePoliciesListWarning) MarshalJSON() ([]byte, error) { - type NoMethod ResourcePoliciesListWarning - raw := NoMethod(*s) - return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) -} - -type ResourcePoliciesListWarningData struct { - // Key: [Output Only] A key that provides more detail on the warning - // being returned. For example, for warnings where there are no results - // in a list request for a particular zone, this key might be scope and - // the key value might be the zone name. Other examples might be a key - // indicating a deprecated resource and a suggested replacement, or a - // warning about invalid network settings (for example, if an instance - // attempts to perform IP forwarding but is not enabled for IP - // forwarding). - Key string `json:"key,omitempty"` - - // Value: [Output Only] A warning data value corresponding to the key. - Value string `json:"value,omitempty"` - - // ForceSendFields is a list of field names (e.g. "Key") to - // unconditionally include in API requests. By default, fields with - // empty values are omitted from API requests. However, any non-pointer, - // non-interface field appearing in ForceSendFields will be sent to the - // server regardless of whether the field is empty or not. This may be - // used to include empty fields in Patch requests. - ForceSendFields []string `json:"-"` - - // NullFields is a list of field names (e.g. "Key") to include in API - // requests with the JSON null value. By default, fields with empty - // values are omitted from API requests. However, any field with an - // empty value appearing in NullFields will be sent to the server as - // null. It is an error if a field in this list has a non-empty value. - // This may be used to include null fields in Patch requests. - NullFields []string `json:"-"` -} - -func (s *ResourcePoliciesListWarningData) MarshalJSON() ([]byte, error) { - type NoMethod ResourcePoliciesListWarningData - raw := NoMethod(*s) - return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) -} - type ResourcePoliciesScopedList struct { // ResourcePolicies: A list of resourcePolicies contained in this scope. ResourcePolicies []*ResourcePolicy `json:"resourcePolicies,omitempty"` @@ -25537,8 +26791,8 @@ func (s *ResourcePolicyAggregatedListWarningData) MarshalJSON() ([]byte, error) // ResourcePolicyBackupSchedulePolicy: A backup schedule policy // specifies when and how frequently snapshots are to be created for the -// target disk. Also specifies how many and how long these automatically -// created snapshot should be retained. +// target disk. Also specifies how many and how long these scheduled +// snapshots should be retained. type ResourcePolicyBackupSchedulePolicy struct { // RetentionPolicy: Retention policy applied to snapshots created by // this resource policy. @@ -25550,7 +26804,7 @@ type ResourcePolicyBackupSchedulePolicy struct { Schedule *ResourcePolicyBackupSchedulePolicySchedule `json:"schedule,omitempty"` // SnapshotProperties: Properties with which snapshots are created such - // as lables, encryption keys. + // as labels, encryption keys. SnapshotProperties *ResourcePolicyBackupSchedulePolicySnapshotProperties `json:"snapshotProperties,omitempty"` // ForceSendFields is a list of field names (e.g. "RetentionPolicy") to @@ -25578,12 +26832,30 @@ func (s *ResourcePolicyBackupSchedulePolicy) MarshalJSON() ([]byte, error) { } // ResourcePolicyBackupSchedulePolicyRetentionPolicy: Policy for -// retention of automatically created snapshots. +// retention of scheduled snapshots. type ResourcePolicyBackupSchedulePolicyRetentionPolicy struct { // MaxRetentionDays: Maximum age of the snapshot that is allowed to be // kept. MaxRetentionDays int64 `json:"maxRetentionDays,omitempty"` + // OnPolicySwitch: Specifies the behavior to apply to existing, + // scheduled snapshots snapshots if the policy is changed. + // + // Possible values: + // "DO_NOT_RETROACTIVELY_APPLY" + // "RETROACTIVELY_APPLY" + // "UNSPECIFIED_ON_POLICY_SWITCH" + OnPolicySwitch string `json:"onPolicySwitch,omitempty"` + + // OnSourceDiskDelete: Specifies the behavior to apply to scheduled + // snapshots when the source disk is deleted. + // + // Possible values: + // "APPLY_RETENTION_POLICY" + // "KEEP_AUTO_SNAPSHOTS" + // "UNSPECIFIED_ON_SOURCE_DISK_DELETE" + OnSourceDiskDelete string `json:"onSourceDiskDelete,omitempty"` + // ForceSendFields is a list of field names (e.g. "MaxRetentionDays") to // unconditionally include in API requests. By default, fields with // empty values are omitted from API requests. However, any non-pointer, @@ -25641,15 +26913,19 @@ func (s *ResourcePolicyBackupSchedulePolicySchedule) MarshalJSON() ([]byte, erro } // ResourcePolicyBackupSchedulePolicySnapshotProperties: Specified -// snapshot properties for automatic snapshots created by this policy. +// snapshot properties for scheduled snapshots created by this policy. type ResourcePolicyBackupSchedulePolicySnapshotProperties struct { // GuestFlush: Indication to perform a ?guest aware? snapshot. GuestFlush bool `json:"guestFlush,omitempty"` - // Labels: Labels to apply to automatic snapshots. These can be later + // Labels: Labels to apply to scheduled snapshots. These can be later // modified by the setLabels method. Label values may be empty. Labels map[string]string `json:"labels,omitempty"` + // StorageLocations: GCS bucket storage location of the auto snapshot + // (regional or multi-regional). + StorageLocations []string `json:"storageLocations,omitempty"` + // ForceSendFields is a list of field names (e.g. "GuestFlush") to // unconditionally include in API requests. By default, fields with // empty values are omitted from API requests. However, any non-pointer, @@ -25684,7 +26960,7 @@ type ResourcePolicyDailyCycle struct { Duration string `json:"duration,omitempty"` // StartTime: Time within the window to start the operations. It must be - // in format "HH:MM?, where HH : [00-23] and MM : [00-59] GMT. + // in format "HH:MM", where HH : [00-23] and MM : [00-00] GMT. StartTime string `json:"startTime,omitempty"` // ForceSendFields is a list of field names (e.g. "DaysInCycle") to @@ -25721,7 +26997,7 @@ type ResourcePolicyHourlyCycle struct { HoursInCycle int64 `json:"hoursInCycle,omitempty"` // StartTime: Time within the window to start the operations. It must be - // in format "HH:MM?, where HH : [00-23] and MM : [00-59] GMT. + // in format "HH:MM", where HH : [00-23] and MM : [00-00] GMT. StartTime string `json:"startTime,omitempty"` // ForceSendFields is a list of field names (e.g. "Duration") to @@ -25747,33 +27023,180 @@ func (s *ResourcePolicyHourlyCycle) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } -type ResourcePolicyVmMaintenancePolicy struct { - // MaintenanceEnvironment: A hint about the environment this VM belongs - // to (production vs develoment) +type ResourcePolicyList struct { + Etag string `json:"etag,omitempty"` + + // Id: [Output Only] The unique identifier for the resource. This + // identifier is defined by the server. + Id string `json:"id,omitempty"` + + // Items: [Output Only] A list of ResourcePolicy resources. + Items []*ResourcePolicy `json:"items,omitempty"` + + // Kind: [Output Only] Type of resource.Always + // compute#resourcePoliciesList for listsof resourcePolicies + Kind string `json:"kind,omitempty"` + + // NextPageToken: [Output Only] This token allows you to get the next + // page of results for list requests. If the number of results is larger + // than maxResults, use the nextPageToken as a value for the query + // parameter pageToken in the next list request. Subsequent list + // requests will have their own nextPageToken to continue paging through + // the results. + NextPageToken string `json:"nextPageToken,omitempty"` + + // SelfLink: [Output Only] Server-defined URL for this resource. + SelfLink string `json:"selfLink,omitempty"` + + // Warning: [Output Only] Informational warning message. + Warning *ResourcePolicyListWarning `json:"warning,omitempty"` + + // ServerResponse contains the HTTP response code and headers from the + // server. + googleapi.ServerResponse `json:"-"` + + // ForceSendFields is a list of field names (e.g. "Etag") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Etag") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *ResourcePolicyList) MarshalJSON() ([]byte, error) { + type NoMethod ResourcePolicyList + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// ResourcePolicyListWarning: [Output Only] Informational warning +// message. +type ResourcePolicyListWarning struct { + // Code: [Output Only] A warning code, if applicable. For example, + // Compute Engine returns NO_RESULTS_ON_PAGE if there are no results in + // the response. // // Possible values: - // "DEVELOPMENT" - // "MAINTENANCE_ENVIRONMENT_UNSPECIFIED" - // "PRODUCTION" - MaintenanceEnvironment string `json:"maintenanceEnvironment,omitempty"` + // "CLEANUP_FAILED" + // "DEPRECATED_RESOURCE_USED" + // "DEPRECATED_TYPE_USED" + // "DISK_SIZE_LARGER_THAN_IMAGE_SIZE" + // "EXPERIMENTAL_TYPE_USED" + // "EXTERNAL_API_WARNING" + // "FIELD_VALUE_OVERRIDEN" + // "INJECTED_KERNELS_DEPRECATED" + // "MISSING_TYPE_DEPENDENCY" + // "NEXT_HOP_ADDRESS_NOT_ASSIGNED" + // "NEXT_HOP_CANNOT_IP_FORWARD" + // "NEXT_HOP_INSTANCE_NOT_FOUND" + // "NEXT_HOP_INSTANCE_NOT_ON_NETWORK" + // "NEXT_HOP_NOT_RUNNING" + // "NOT_CRITICAL_ERROR" + // "NO_RESULTS_ON_PAGE" + // "REQUIRED_TOS_AGREEMENT" + // "RESOURCE_IN_USE_BY_OTHER_RESOURCE_WARNING" + // "RESOURCE_NOT_DELETED" + // "SCHEMA_VALIDATION_IGNORED" + // "SINGLE_INSTANCE_PROPERTY_TEMPLATE" + // "UNDECLARED_PROPERTIES" + // "UNREACHABLE" + Code string `json:"code,omitempty"` + // Data: [Output Only] Metadata about this warning in key: value format. + // For example: + // "data": [ { "key": "scope", "value": "zones/us-east1-d" } + Data []*ResourcePolicyListWarningData `json:"data,omitempty"` + + // Message: [Output Only] A human-readable description of the warning + // code. + Message string `json:"message,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Code") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Code") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *ResourcePolicyListWarning) MarshalJSON() ([]byte, error) { + type NoMethod ResourcePolicyListWarning + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type ResourcePolicyListWarningData struct { + // Key: [Output Only] A key that provides more detail on the warning + // being returned. For example, for warnings where there are no results + // in a list request for a particular zone, this key might be scope and + // the key value might be the zone name. Other examples might be a key + // indicating a deprecated resource and a suggested replacement, or a + // warning about invalid network settings (for example, if an instance + // attempts to perform IP forwarding but is not enabled for IP + // forwarding). + Key string `json:"key,omitempty"` + + // Value: [Output Only] A warning data value corresponding to the key. + Value string `json:"value,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Key") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Key") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *ResourcePolicyListWarningData) MarshalJSON() ([]byte, error) { + type NoMethod ResourcePolicyListWarningData + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type ResourcePolicyVmMaintenancePolicy struct { // MaintenanceWindow: Maintenance windows that are applied to VMs // covered by this policy. MaintenanceWindow *ResourcePolicyVmMaintenancePolicyMaintenanceWindow `json:"maintenanceWindow,omitempty"` - // ForceSendFields is a list of field names (e.g. - // "MaintenanceEnvironment") to unconditionally include in API requests. - // By default, fields with empty values are omitted from API requests. - // However, any non-pointer, non-interface field appearing in - // ForceSendFields will be sent to the server regardless of whether the - // field is empty or not. This may be used to include empty fields in - // Patch requests. + // ForceSendFields is a list of field names (e.g. "MaintenanceWindow") + // to unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. ForceSendFields []string `json:"-"` - // NullFields is a list of field names (e.g. "MaintenanceEnvironment") - // to include in API requests with the JSON null value. By default, - // fields with empty values are omitted from API requests. However, any - // field with an empty value appearing in NullFields will be sent to the + // NullFields is a list of field names (e.g. "MaintenanceWindow") to + // include in API requests with the JSON null value. By default, fields + // with empty values are omitted from API requests. However, any field + // with an empty value appearing in NullFields will be sent to the // server as null. It is an error if a field in this list has a // non-empty value. This may be used to include null fields in Patch // requests. @@ -25792,8 +27215,6 @@ func (s *ResourcePolicyVmMaintenancePolicy) MarshalJSON() ([]byte, error) { type ResourcePolicyVmMaintenancePolicyMaintenanceWindow struct { DailyMaintenanceWindow *ResourcePolicyDailyCycle `json:"dailyMaintenanceWindow,omitempty"` - WeeklyMaintenanceWindow *ResourcePolicyWeeklyCycle `json:"weeklyMaintenanceWindow,omitempty"` - // ForceSendFields is a list of field names (e.g. // "DailyMaintenanceWindow") to unconditionally include in API requests. // By default, fields with empty values are omitted from API requests. @@ -25867,7 +27288,7 @@ type ResourcePolicyWeeklyCycleDayOfWeek struct { Duration string `json:"duration,omitempty"` // StartTime: Time within the window to start the operations. It must be - // in format "HH:MM?, where HH : [00-23] and MM : [00-59] GMT. + // in format "HH:MM", where HH : [00-23] and MM : [00-00] GMT. StartTime string `json:"startTime,omitempty"` // ForceSendFields is a list of field names (e.g. "Day") to @@ -26571,7 +27992,9 @@ type RouterBgp struct { // field blank to advertise no custom groups. // // Possible values: + // "ALL_PEER_VPC_SUBNETS" // "ALL_SUBNETS" + // "ALL_VPC_SUBNETS" AdvertisedGroups []string `json:"advertisedGroups,omitempty"` // AdvertisedIpRanges: User-specified list of individual IP ranges to @@ -26628,7 +28051,9 @@ type RouterBgpPeer struct { // groups. // // Possible values: + // "ALL_PEER_VPC_SUBNETS" // "ALL_SUBNETS" + // "ALL_VPC_SUBNETS" AdvertisedGroups []string `json:"advertisedGroups,omitempty"` // AdvertisedIpRanges: User-specified list of individual IP ranges to @@ -26651,12 +28076,13 @@ type RouterBgpPeer struct { // Only IPv4 is supported. IpAddress string `json:"ipAddress,omitempty"` - // ManagementType: [Output Only] Type of how the resource/configuration - // of the BGP peer is managed. MANAGED_BY_USER is the default value; - // MANAGED_BY_ATTACHMENT represents an BGP peer that is automatically - // created for PARTNER interconnectAttachment, Google will automatically - // create/delete this type of BGP peer when the PARTNER - // interconnectAttachment is created/deleted. + // ManagementType: [Output Only] The resource that configures and + // manages this BGP peer. MANAGED_BY_USER is the default value and can + // be managed by you or other users; MANAGED_BY_ATTACHMENT is a BGP peer + // that is configured and managed by Cloud Interconnect, specifically by + // an InterconnectAttachment of type PARTNER. Google will automatically + // create, update, and delete this type of BGP peer when the PARTNER + // InterconnectAttachment is created, updated, or deleted. // // Possible values: // "MANAGED_BY_ATTACHMENT" @@ -26718,12 +28144,14 @@ type RouterInterface struct { // attachment. LinkedVpnTunnel string `json:"linkedVpnTunnel,omitempty"` - // ManagementType: [Output Only] Type of how the resource/configuration - // of the interface is managed. MANAGED_BY_USER is the default value; - // MANAGED_BY_ATTACHMENT represents an interface that is automatically - // created for PARTNER type interconnectAttachment, Google will - // automatically create/update/delete this type of interface when the - // PARTNER interconnectAttachment is created/provisioned/deleted. + // ManagementType: [Output Only] The resource that configures and + // manages this interface. MANAGED_BY_USER is the default value and can + // be managed by you or other users; MANAGED_BY_ATTACHMENT is an + // interface that is configured and managed by Cloud Interconnect, + // specifically by an InterconnectAttachment of type PARTNER. Google + // will automatically create, update, and delete this type of interface + // when the PARTNER InterconnectAttachment is created, updated, or + // deleted. // // Possible values: // "MANAGED_BY_ATTACHMENT" @@ -26919,17 +28347,13 @@ func (s *RouterListWarningData) MarshalJSON() ([]byte, error) { // that would be used for NAT. GCP would auto-allocate ephemeral IPs if // no external IPs are provided. type RouterNat struct { - // AutoAllocatedNatIps: [Output Only] A list of IPs allocated - // automatically by GCP for this Nat service. They will be raw IP - // strings like "179.12.26.133". They are ephemeral IPs allocated from - // the IP blocks managed by the NAT manager. This list can grow and - // shrink based on the number of VMs configured to use NAT. - AutoAllocatedNatIps []string `json:"autoAllocatedNatIps,omitempty"` - // IcmpIdleTimeoutSec: Timeout (in seconds) for ICMP connections. // Defaults to 30s if not set. IcmpIdleTimeoutSec int64 `json:"icmpIdleTimeoutSec,omitempty"` + // LogConfig: Configure logging on this NAT. + LogConfig *RouterNatLogConfig `json:"logConfig,omitempty"` + // MinPortsPerVm: Minimum number of ports allocated to a VM from this // NAT config. If not set, a default number of ports is allocated to a // VM. This gets rounded up to the nearest power of 2. Eg. if the value @@ -26982,7 +28406,7 @@ type RouterNat struct { // to 30s if not set. UdpIdleTimeoutSec int64 `json:"udpIdleTimeoutSec,omitempty"` - // ForceSendFields is a list of field names (e.g. "AutoAllocatedNatIps") + // ForceSendFields is a list of field names (e.g. "IcmpIdleTimeoutSec") // to unconditionally include in API requests. By default, fields with // empty values are omitted from API requests. However, any non-pointer, // non-interface field appearing in ForceSendFields will be sent to the @@ -26990,7 +28414,7 @@ type RouterNat struct { // used to include empty fields in Patch requests. ForceSendFields []string `json:"-"` - // NullFields is a list of field names (e.g. "AutoAllocatedNatIps") to + // NullFields is a list of field names (e.g. "IcmpIdleTimeoutSec") to // include in API requests with the JSON null value. By default, fields // with empty values are omitted from API requests. However, any field // with an empty value appearing in NullFields will be sent to the @@ -27006,6 +28430,44 @@ func (s *RouterNat) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +// RouterNatLogConfig: Configuration of logging on a NAT. +type RouterNatLogConfig struct { + // Enabled: Indicates whether or not to export logs. This is false by + // default. + Enabled bool `json:"enabled,omitempty"` + + // Filter: Specifies the desired filtering of logs on this NAT. If + // unspecified, logs are exported for all connections handled by this + // NAT. + // + // Possible values: + // "ERRORS_ONLY" + // "TRANSLATIONS_ONLY" + Filter string `json:"filter,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Enabled") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Enabled") to include in + // API requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *RouterNatLogConfig) MarshalJSON() ([]byte, error) { + type NoMethod RouterNatLogConfig + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + // RouterNatSubnetworkToNat: Defines the IP ranges that want to use NAT // for a subnetwork. type RouterNatSubnetworkToNat struct { @@ -27018,7 +28480,7 @@ type RouterNatSubnetworkToNat struct { // source_ip_ranges_to_nat. SecondaryIpRangeNames []string `json:"secondaryIpRangeNames,omitempty"` - // SourceIpRangesToNats: Specify the options for NAT ranges in the + // SourceIpRangesToNat: Specify the options for NAT ranges in the // Subnetwork. All usages of single value are valid except // NAT_IP_RANGE_OPTION_UNSPECIFIED. The only valid option with multiple // values is: ["PRIMARY_IP_RANGE", "LIST_OF_SECONDARY_IP_RANGES"] @@ -27028,7 +28490,7 @@ type RouterNatSubnetworkToNat struct { // "ALL_IP_RANGES" // "LIST_OF_SECONDARY_IP_RANGES" // "PRIMARY_IP_RANGE" - SourceIpRangesToNats []string `json:"sourceIpRangesToNats,omitempty"` + SourceIpRangesToNat []string `json:"sourceIpRangesToNat,omitempty"` // ForceSendFields is a list of field names (e.g. "Name") to // unconditionally include in API requests. By default, fields with @@ -27539,6 +29001,173 @@ func (s *SSLHealthCheck) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +// SavedAttachedDisk: An instance-attached disk resource. +type SavedAttachedDisk struct { + // AutoDelete: Specifies whether the disk will be auto-deleted when the + // instance is deleted (but not when the disk is detached from the + // instance). + AutoDelete bool `json:"autoDelete,omitempty"` + + // Boot: Indicates that this is a boot disk. The virtual machine will + // use the first partition of the disk for its root filesystem. + Boot bool `json:"boot,omitempty"` + + // DeviceName: Specifies a unique device name of your choice that is + // reflected into the /dev/disk/by-id/google-* tree of a Linux operating + // system running within the instance. This name can be used to + // reference the device for mounting, resizing, and so on, from within + // the instance. + // + // If not specified, the server chooses a default device name to apply + // to this disk, in the form persistent-disks-x, where x is a number + // assigned by Google Compute Engine. This field is only applicable for + // persistent disks. + DeviceName string `json:"deviceName,omitempty"` + + // DiskEncryptionKey: Encrypts or decrypts a disk using a + // customer-supplied encryption key. + // + // If you are creating a new disk, this field encrypts the new disk + // using an encryption key that you provide. If you are attaching an + // existing disk that is already encrypted, this field decrypts the disk + // using the customer-supplied encryption key. + // + // If you encrypt a disk using a customer-supplied key, you must provide + // the same key again when you attempt to use this resource at a later + // time. For example, you must provide the key when you create a + // snapshot or an image from the disk or when you attach the disk to a + // virtual machine instance. + // + // If you do not provide an encryption key, then the disk will be + // encrypted using an automatically generated key and you do not need to + // provide a key to use the disk later. + // + // Machine Images do not store customer-supplied encryption keys, so you + // cannot use your own keys to encrypt disks in a managed instance + // group. + DiskEncryptionKey *CustomerEncryptionKey `json:"diskEncryptionKey,omitempty"` + + // DiskSizeGb: The size of the disk in base-2 GB. This supersedes + // disk_size_gb in InitializeParams. + DiskSizeGb int64 `json:"diskSizeGb,omitempty,string"` + + // GuestOsFeatures: A list of features to enable on the guest operating + // system. Applicable only for bootable images. Read Enabling guest + // operating system features to see a list of available options. + GuestOsFeatures []*GuestOsFeature `json:"guestOsFeatures,omitempty"` + + // Index: [Output Only] A zero-based index to this disk, where 0 is + // reserved for the boot disk. If you have many disks attached to an + // instance, each disk would have a unique index number. + Index int64 `json:"index,omitempty"` + + // InitializeParams: [Input Only] Specifies the parameters for a new + // disk that will be created alongside the new instance. Use + // initialization parameters to create boot disks or local SSDs attached + // to the new instance. + // + // This property is mutually exclusive with the source property; you can + // only define one or the other, but not both. + InitializeParams *AttachedDiskInitializeParams `json:"initializeParams,omitempty"` + + // Interface: Specifies the disk interface to use for attaching this + // disk, which is either SCSI or NVME. The default is SCSI. Persistent + // disks must always use SCSI and the request will fail if you attempt + // to attach a persistent disk in any other format than SCSI. Local SSDs + // can use either NVME or SCSI. For performance characteristics of SCSI + // over NVMe, see Local SSD performance. + // + // Possible values: + // "NVDIMM" + // "NVME" + // "SCSI" + Interface string `json:"interface,omitempty"` + + // Kind: [Output Only] Type of the resource. Always compute#attachedDisk + // for attached disks. + Kind string `json:"kind,omitempty"` + + // Licenses: [Output Only] Any valid publicly visible licenses. + Licenses []string `json:"licenses,omitempty"` + + // Mode: The mode in which to attach this disk, either READ_WRITE or + // READ_ONLY. If not specified, the default is to attach the disk in + // READ_WRITE mode. + // + // Possible values: + // "READ_ONLY" + // "READ_WRITE" + Mode string `json:"mode,omitempty"` + + // SavedState: For LocalSSD disks on VM Instances in STOPPED or + // SUSPENDED state, this field is set to PRESERVED if the LocalSSD data + // has been saved to a persistent location by customer request. (see the + // discard_local_ssd option on Stop/Suspend). Read-only in the api. + // + // Possible values: + // "DISK_SAVED_STATE_UNSPECIFIED" + // "PRESERVED" + SavedState string `json:"savedState,omitempty"` + + // Source: Specifies a valid partial or full URL to an existing + // Persistent Disk resource. When creating a new instance, one of + // initializeParams.sourceImage or disks.source is required except for + // local SSD. + // + // If desired, you can also attach existing non-root persistent disks + // using this property. This field is only applicable for persistent + // disks. + // + // Note that for sourceMachineImage, specify the disk name, not the URL + // for the disk. + Source string `json:"source,omitempty"` + + // StorageBytes: [Output Only] A size of the storage used by the disk's + // snapshot. + StorageBytes int64 `json:"storageBytes,omitempty,string"` + + // StorageBytesStatus: [Output Only] An indicator whether storageBytes + // is in a stable state or it is being adjusted as a result of shared + // storage reallocation. This status can either be UPDATING, meaning the + // size of the snapshot is being updated, or UP_TO_DATE, meaning the + // size of the snapshot is up-to-date. + // + // Possible values: + // "UPDATING" + // "UP_TO_DATE" + StorageBytesStatus string `json:"storageBytesStatus,omitempty"` + + // Type: Specifies the type of the disk, either SCRATCH or PERSISTENT. + // If not specified, the default is PERSISTENT. + // + // Possible values: + // "PERSISTENT" + // "SCRATCH" + Type string `json:"type,omitempty"` + + // ForceSendFields is a list of field names (e.g. "AutoDelete") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "AutoDelete") to include in + // API requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *SavedAttachedDisk) MarshalJSON() ([]byte, error) { + type NoMethod SavedAttachedDisk + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + // Scheduling: Sets the scheduling options for an Instance. type Scheduling struct { // AutomaticRestart: Specifies whether the instance should be @@ -27551,6 +29180,10 @@ type Scheduling struct { // restarted if it is terminated by Compute Engine. AutomaticRestart *bool `json:"automaticRestart,omitempty"` + // MinNodeCpus: The minimum number of virtual CPUs this instance will + // consume when running on a sole-tenant node. + MinNodeCpus int64 `json:"minNodeCpus,omitempty"` + // NodeAffinities: A set of node affinity and anti-affinity. NodeAffinities []*SchedulingNodeAffinity `json:"nodeAffinities,omitempty"` @@ -27693,9 +29326,13 @@ func (s *SecurityPoliciesWafConfig) MarshalJSON() ([]byte, error) { } // SecurityPolicy: A security policy is comprised of one or more rules. -// It can also be associated with one or more 'targets'. Next available -// tag: 11 +// It can also be associated with one or more 'targets'. (== +// resource_for v1.securityPolicies ==) (== resource_for +// beta.securityPolicies ==) type SecurityPolicy struct { + // Associations: A list of assocations that belong to this policy. + Associations []*SecurityPolicyAssociation `json:"associations,omitempty"` + // CreationTimestamp: [Output Only] Creation timestamp in RFC3339 text // format. CreationTimestamp string `json:"creationTimestamp,omitempty"` @@ -27709,7 +29346,8 @@ type SecurityPolicy struct { // locking. The fingerprint is initially generated by Compute Engine and // changes after every request to modify or update metadata. You must // always provide an up-to-date fingerprint hash in order to update or - // change metadata. + // change metadata, otherwise the request will fail with error 412 + // conditionNotMet. // // To see the latest fingerprint, make get() request to the security // policy. @@ -27757,25 +29395,33 @@ type SecurityPolicy struct { // SelfLink: [Output Only] Server-defined URL for the resource. SelfLink string `json:"selfLink,omitempty"` + // Type: The type indicates the intended use of the security policy. + // CLOUD_ARMOR policies apply to backend services. FIREWALL policies + // apply to organizations. + // + // Possible values: + // "CLOUD_ARMOR" + // "FIREWALL" + Type string `json:"type,omitempty"` + // ServerResponse contains the HTTP response code and headers from the // server. googleapi.ServerResponse `json:"-"` - // ForceSendFields is a list of field names (e.g. "CreationTimestamp") - // to unconditionally include in API requests. By default, fields with + // ForceSendFields is a list of field names (e.g. "Associations") to + // unconditionally include in API requests. By default, fields with // empty values are omitted from API requests. However, any non-pointer, // non-interface field appearing in ForceSendFields will be sent to the // server regardless of whether the field is empty or not. This may be // used to include empty fields in Patch requests. ForceSendFields []string `json:"-"` - // NullFields is a list of field names (e.g. "CreationTimestamp") to - // include in API requests with the JSON null value. By default, fields - // with empty values are omitted from API requests. However, any field - // with an empty value appearing in NullFields will be sent to the - // server as null. It is an error if a field in this list has a - // non-empty value. This may be used to include null fields in Patch - // requests. + // NullFields is a list of field names (e.g. "Associations") to include + // in API requests with the JSON null value. By default, fields with + // empty values are omitted from API requests. However, any field with + // an empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. NullFields []string `json:"-"` } @@ -27785,6 +29431,40 @@ func (s *SecurityPolicy) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +type SecurityPolicyAssociation struct { + // AttachmentId: The resource that the security policy is attached to. + AttachmentId string `json:"attachmentId,omitempty"` + + // Name: The name for an association. + Name string `json:"name,omitempty"` + + // ServerResponse contains the HTTP response code and headers from the + // server. + googleapi.ServerResponse `json:"-"` + + // ForceSendFields is a list of field names (e.g. "AttachmentId") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "AttachmentId") to include + // in API requests with the JSON null value. By default, fields with + // empty values are omitted from API requests. However, any field with + // an empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *SecurityPolicyAssociation) MarshalJSON() ([]byte, error) { + type NoMethod SecurityPolicyAssociation + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + type SecurityPolicyList struct { // Id: [Output Only] Unique identifier for the resource; defined by the // server. @@ -27977,6 +29657,24 @@ type SecurityPolicyRule struct { // property when you create the resource. Description string `json:"description,omitempty"` + // Direction: The direction in which this rule applies. This field may + // only be specified when versioned_expr is set to FIREWALL. + // + // Possible values: + // "EGRESS" + // "INGRESS" + Direction string `json:"direction,omitempty"` + + // EnableLogging: Denotes whether to enable logging for a particular + // rule. If logging is enabled, logs will be exported to the configured + // export destination in Stackdriver. Logs may be exported to BigQuery + // or Pub/Sub. Note: you cannot enable logging on "goto_next" + // rules. + // + // This field may only be specified when the versioned_expr is set to + // FIREWALL. + EnableLogging bool `json:"enableLogging,omitempty"` + // Kind: [Output only] Type of the resource. Always // compute#securityPolicyRule for security policy rules Kind string `json:"kind,omitempty"` @@ -27990,9 +29688,19 @@ type SecurityPolicyRule struct { // Priority: An integer indicating the priority of a rule in the list. // The priority must be a positive value between 0 and 2147483647. Rules - // are evaluated in the increasing order of priority. + // are evaluated from highest to lowest priority where 0 is the highest + // priority and 2147483647 is the lowest prority. Priority int64 `json:"priority,omitempty"` + // TargetResources: A list of network resource URLs to which this rule + // applies. This field allows you to control which network?s VMs get + // this rule. If this field is left blank, all VMs within the + // organization will receive the rule. + // + // This field may only be specified when versioned_expr is set to + // FIREWALL. + TargetResources []string `json:"targetResources,omitempty"` + // ServerResponse contains the HTTP response code and headers from the // server. googleapi.ServerResponse `json:"-"` @@ -28033,17 +29741,14 @@ type SecurityPolicyRuleMatcher struct { // contents in the request header. Expr *Expr `json:"expr,omitempty"` - // SrcIpRanges: CIDR IP address range. - SrcIpRanges []string `json:"srcIpRanges,omitempty"` - // VersionedExpr: Preconfigured versioned expression. If this field is // specified, config must also be specified. Available preconfigured // expressions along with their requirements are: SRC_IPS_V1 - must // specify the corresponding src_ip_range field in config. // // Possible values: + // "FIREWALL" // "SRC_IPS_V1" - // "VERSIONED_EXPR_UNSPECIFIED" VersionedExpr string `json:"versionedExpr,omitempty"` // ForceSendFields is a list of field names (e.g. "Config") to @@ -28070,10 +29775,23 @@ func (s *SecurityPolicyRuleMatcher) MarshalJSON() ([]byte, error) { } type SecurityPolicyRuleMatcherConfig struct { + // DestIpRanges: CIDR IP address range. + // + // This field may only be specified when versioned_expr is set to + // FIREWALL. + DestIpRanges []string `json:"destIpRanges,omitempty"` + + // DestPorts: Pairs of IP protocols and ports that the rule should + // match. + // + // This field may only be specified when versioned_expr is set to + // FIREWALL. + DestPorts []*SecurityPolicyRuleMatcherConfigDestinationPort `json:"destPorts,omitempty"` + // SrcIpRanges: CIDR IP address range. SrcIpRanges []string `json:"srcIpRanges,omitempty"` - // ForceSendFields is a list of field names (e.g. "SrcIpRanges") to + // ForceSendFields is a list of field names (e.g. "DestIpRanges") to // unconditionally include in API requests. By default, fields with // empty values are omitted from API requests. However, any non-pointer, // non-interface field appearing in ForceSendFields will be sent to the @@ -28081,7 +29799,7 @@ type SecurityPolicyRuleMatcherConfig struct { // used to include empty fields in Patch requests. ForceSendFields []string `json:"-"` - // NullFields is a list of field names (e.g. "SrcIpRanges") to include + // NullFields is a list of field names (e.g. "DestIpRanges") to include // in API requests with the JSON null value. By default, fields with // empty values are omitted from API requests. However, any field with // an empty value appearing in NullFields will be sent to the server as @@ -28096,6 +29814,48 @@ func (s *SecurityPolicyRuleMatcherConfig) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +type SecurityPolicyRuleMatcherConfigDestinationPort struct { + // IpProtocol: The IP protocol to which this rule applies. The protocol + // type is required when creating a firewall rule. This value can either + // be one of the following well known protocol strings (tcp, udp, icmp, + // esp, ah, ipip, sctp), or the IP protocol number. + IpProtocol string `json:"ipProtocol,omitempty"` + + // Ports: An optional list of ports to which this rule applies. This + // field is only applicable for UDP or TCP protocol. Each entry must be + // either an integer or a range. If not specified, this rule applies to + // connections through any port. + // + // Example inputs include: ["22"], ["80","443"], and + // ["12345-12349"]. + // + // This field may only be specified when versioned_expr is set to + // FIREWALL. + Ports []string `json:"ports,omitempty"` + + // ForceSendFields is a list of field names (e.g. "IpProtocol") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "IpProtocol") to include in + // API requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *SecurityPolicyRuleMatcherConfigDestinationPort) MarshalJSON() ([]byte, error) { + type NoMethod SecurityPolicyRuleMatcherConfigDestinationPort + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + // SerialPortOutput: An instance's serial console output. type SerialPortOutput struct { // Contents: [Output Only] The contents of the console output. @@ -28147,6 +29907,36 @@ func (s *SerialPortOutput) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +type ServerBinding struct { + // Possible values: + // "RESTART_NODE_ON_ANY_SERVER" + // "RESTART_NODE_ON_MINIMAL_SERVERS" + // "SERVER_BINDING_TYPE_UNSPECIFIED" + Type string `json:"type,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Type") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Type") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *ServerBinding) MarshalJSON() ([]byte, error) { + type NoMethod ServerBinding + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + // ServiceAccount: A service account. type ServiceAccount struct { // Email: Email address of the service account. @@ -28181,15 +29971,15 @@ func (s *ServiceAccount) MarshalJSON() ([]byte, error) { // ShieldedVmConfig: A set of Shielded VM options. type ShieldedVmConfig struct { - // EnableIntegrityMonitoring: Defines whether the instance should have - // integrity monitoring enabled. + // EnableIntegrityMonitoring: Defines whether the instance has integrity + // monitoring enabled. EnableIntegrityMonitoring bool `json:"enableIntegrityMonitoring,omitempty"` - // EnableSecureBoot: Defines whether the instance should have secure - // boot enabled. + // EnableSecureBoot: Defines whether the instance has Secure Boot + // enabled. EnableSecureBoot bool `json:"enableSecureBoot,omitempty"` - // EnableVtpm: Defines whether the instance should have the TPM enabled. + // EnableVtpm: Defines whether the instance has the vTPM enabled. EnableVtpm bool `json:"enableVtpm,omitempty"` // ForceSendFields is a list of field names (e.g. @@ -28217,11 +30007,82 @@ func (s *ShieldedVmConfig) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } -// ShieldedVmIntegrityPolicy: The policy describes how boot integrity -// measurements are evaluated. +// ShieldedVmIdentity: A shielded VM identity entry. +type ShieldedVmIdentity struct { + // EncryptionKey: An Endorsement Key (EK) issued to the Shielded VM's + // vTPM. + EncryptionKey *ShieldedVmIdentityEntry `json:"encryptionKey,omitempty"` + + // Kind: [Output Only] Type of the resource. Always + // compute#shieldedVmIdentity for shielded VM identity entry. + Kind string `json:"kind,omitempty"` + + // SigningKey: An Attestation Key (AK) issued to the Shielded VM's vTPM. + SigningKey *ShieldedVmIdentityEntry `json:"signingKey,omitempty"` + + // ServerResponse contains the HTTP response code and headers from the + // server. + googleapi.ServerResponse `json:"-"` + + // ForceSendFields is a list of field names (e.g. "EncryptionKey") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "EncryptionKey") to include + // in API requests with the JSON null value. By default, fields with + // empty values are omitted from API requests. However, any field with + // an empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *ShieldedVmIdentity) MarshalJSON() ([]byte, error) { + type NoMethod ShieldedVmIdentity + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// ShieldedVmIdentityEntry: A Shielded VM Identity Entry. +type ShieldedVmIdentityEntry struct { + // EkCert: A PEM-encoded X.509 certificate. This field can be empty. + EkCert string `json:"ekCert,omitempty"` + + // EkPub: A PEM-encoded public key. + EkPub string `json:"ekPub,omitempty"` + + // ForceSendFields is a list of field names (e.g. "EkCert") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "EkCert") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *ShieldedVmIdentityEntry) MarshalJSON() ([]byte, error) { + type NoMethod ShieldedVmIdentityEntry + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// ShieldedVmIntegrityPolicy: The policy describes the baseline against +// which VM instance boot integrity is measured. type ShieldedVmIntegrityPolicy struct { - // UpdateAutoLearnPolicy: Triggers an auto relearn event: the integrity - // monitoring module copies existing guest measurements to the baseline. + // UpdateAutoLearnPolicy: Updates the integrity policy baseline using + // the measurements from the VM instance's most recent boot. UpdateAutoLearnPolicy bool `json:"updateAutoLearnPolicy,omitempty"` // ForceSendFields is a list of field names (e.g. @@ -28290,7 +30151,7 @@ func (s *SignedUrlKey) MarshalJSON() ([]byte, error) { // Snapshot: A persistent disk snapshot resource. (== resource_for // beta.snapshots ==) (== resource_for v1.snapshots ==) type Snapshot struct { - // AutoCreated: [Output Only] Set to true if snapshots are autoamtically + // AutoCreated: [Output Only] Set to true if snapshots are automatically // by applying resource policy on the target disk. AutoCreated bool `json:"autoCreated,omitempty"` @@ -28324,7 +30185,8 @@ type Snapshot struct { // optimistic locking. The fingerprint is initially generated by Compute // Engine and changes after every request to modify or update labels. // You must always provide an up-to-date fingerprint hash in order to - // update or change labels. + // update or change labels, otherwise the request will fail with error + // 412 conditionNotMet. // // To see the latest fingerprint, make a get() request to retrieve a // snapshot. @@ -28631,6 +30493,97 @@ func (s *SourceInstanceParams) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +type SourceInstanceProperties struct { + // CanIpForward: Enables instances created based on this machine image + // to send packets with source IP addresses other than their own and + // receive packets with destination IP addresses other than their own. + // If these instances will be used as an IP gateway or it will be set as + // the next-hop in a Route resource, specify true. If unsure, leave this + // set to false. See the Enable IP forwarding documentation for more + // information. + CanIpForward bool `json:"canIpForward,omitempty"` + + // DeletionProtection: Whether the instance created from the machine + // image should be protected against deletion. + DeletionProtection bool `json:"deletionProtection,omitempty"` + + // Description: An optional text description for the instances that are + // created from this machine image. + Description string `json:"description,omitempty"` + + // Disks: An array of disks that are associated with the instances that + // are created from this machine image. + Disks []*SavedAttachedDisk `json:"disks,omitempty"` + + // GuestAccelerators: A list of guest accelerator cards' type and count + // to use for instances created from the machine image. + GuestAccelerators []*AcceleratorConfig `json:"guestAccelerators,omitempty"` + + // Labels: Labels to apply to instances that are created from this + // machine image. + Labels map[string]string `json:"labels,omitempty"` + + // MachineType: The machine type to use for instances that are created + // from this machine image. + MachineType string `json:"machineType,omitempty"` + + // Metadata: The metadata key/value pairs to assign to instances that + // are created from this machine image. These pairs can consist of + // custom metadata or predefined keys. See Project and instance metadata + // for more information. + Metadata *Metadata `json:"metadata,omitempty"` + + // MinCpuPlatform: Minimum cpu/platform to be used by this instance. The + // instance may be scheduled on the specified or newer cpu/platform. + // Applicable values are the friendly names of CPU platforms, such as + // minCpuPlatform: "Intel Haswell" or minCpuPlatform: "Intel Sandy + // Bridge". For more information, read Specifying a Minimum CPU + // Platform. + MinCpuPlatform string `json:"minCpuPlatform,omitempty"` + + // NetworkInterfaces: An array of network access configurations for this + // interface. + NetworkInterfaces []*NetworkInterface `json:"networkInterfaces,omitempty"` + + // Scheduling: Specifies the scheduling options for the instances that + // are created from this machine image. + Scheduling *Scheduling `json:"scheduling,omitempty"` + + // ServiceAccounts: A list of service accounts with specified scopes. + // Access tokens for these service accounts are available to the + // instances that are created from this machine image. Use metadata + // queries to obtain the access tokens for these instances. + ServiceAccounts []*ServiceAccount `json:"serviceAccounts,omitempty"` + + // Tags: A list of tags to apply to the instances that are created from + // this machine image. The tags identify valid sources or targets for + // network firewalls. The setTags method can modify this list of tags. + // Each tag within the list must comply with RFC1035. + Tags *Tags `json:"tags,omitempty"` + + // ForceSendFields is a list of field names (e.g. "CanIpForward") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "CanIpForward") to include + // in API requests with the JSON null value. By default, fields with + // empty values are omitted from API requests. However, any field with + // an empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *SourceInstanceProperties) MarshalJSON() ([]byte, error) { + type NoMethod SourceInstanceProperties + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + // SslCertificate: An SslCertificate resource. This resource provides a // mechanism to upload an SSL key and certificate to the load balancer // to serve secure connections from the user. (== resource_for @@ -28676,6 +30629,11 @@ type SslCertificate struct { // requests will include this field. PrivateKey string `json:"privateKey,omitempty"` + // Region: [Output Only] URL of the region where the regional SSL + // Certificate resides. This field is not applicable to global SSL + // Certificate. + Region string `json:"region,omitempty"` + // SelfLink: [Output only] Server-defined URL for the resource. SelfLink string `json:"selfLink,omitempty"` @@ -28724,6 +30682,161 @@ func (s *SslCertificate) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +type SslCertificateAggregatedList struct { + // Id: [Output Only] Unique identifier for the resource; defined by the + // server. + Id string `json:"id,omitempty"` + + // Items: A list of SslCertificatesScopedList resources. + Items map[string]SslCertificatesScopedList `json:"items,omitempty"` + + // Kind: [Output Only] Type of resource. Always + // compute#sslCertificateAggregatedList for lists of SSL Certificates. + Kind string `json:"kind,omitempty"` + + // NextPageToken: [Output Only] This token allows you to get the next + // page of results for list requests. If the number of results is larger + // than maxResults, use the nextPageToken as a value for the query + // parameter pageToken in the next list request. Subsequent list + // requests will have their own nextPageToken to continue paging through + // the results. + NextPageToken string `json:"nextPageToken,omitempty"` + + // SelfLink: [Output Only] Server-defined URL for this resource. + SelfLink string `json:"selfLink,omitempty"` + + // Warning: [Output Only] Informational warning message. + Warning *SslCertificateAggregatedListWarning `json:"warning,omitempty"` + + // ServerResponse contains the HTTP response code and headers from the + // server. + googleapi.ServerResponse `json:"-"` + + // ForceSendFields is a list of field names (e.g. "Id") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Id") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *SslCertificateAggregatedList) MarshalJSON() ([]byte, error) { + type NoMethod SslCertificateAggregatedList + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// SslCertificateAggregatedListWarning: [Output Only] Informational +// warning message. +type SslCertificateAggregatedListWarning struct { + // Code: [Output Only] A warning code, if applicable. For example, + // Compute Engine returns NO_RESULTS_ON_PAGE if there are no results in + // the response. + // + // Possible values: + // "CLEANUP_FAILED" + // "DEPRECATED_RESOURCE_USED" + // "DEPRECATED_TYPE_USED" + // "DISK_SIZE_LARGER_THAN_IMAGE_SIZE" + // "EXPERIMENTAL_TYPE_USED" + // "EXTERNAL_API_WARNING" + // "FIELD_VALUE_OVERRIDEN" + // "INJECTED_KERNELS_DEPRECATED" + // "MISSING_TYPE_DEPENDENCY" + // "NEXT_HOP_ADDRESS_NOT_ASSIGNED" + // "NEXT_HOP_CANNOT_IP_FORWARD" + // "NEXT_HOP_INSTANCE_NOT_FOUND" + // "NEXT_HOP_INSTANCE_NOT_ON_NETWORK" + // "NEXT_HOP_NOT_RUNNING" + // "NOT_CRITICAL_ERROR" + // "NO_RESULTS_ON_PAGE" + // "REQUIRED_TOS_AGREEMENT" + // "RESOURCE_IN_USE_BY_OTHER_RESOURCE_WARNING" + // "RESOURCE_NOT_DELETED" + // "SCHEMA_VALIDATION_IGNORED" + // "SINGLE_INSTANCE_PROPERTY_TEMPLATE" + // "UNDECLARED_PROPERTIES" + // "UNREACHABLE" + Code string `json:"code,omitempty"` + + // Data: [Output Only] Metadata about this warning in key: value format. + // For example: + // "data": [ { "key": "scope", "value": "zones/us-east1-d" } + Data []*SslCertificateAggregatedListWarningData `json:"data,omitempty"` + + // Message: [Output Only] A human-readable description of the warning + // code. + Message string `json:"message,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Code") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Code") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *SslCertificateAggregatedListWarning) MarshalJSON() ([]byte, error) { + type NoMethod SslCertificateAggregatedListWarning + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type SslCertificateAggregatedListWarningData struct { + // Key: [Output Only] A key that provides more detail on the warning + // being returned. For example, for warnings where there are no results + // in a list request for a particular zone, this key might be scope and + // the key value might be the zone name. Other examples might be a key + // indicating a deprecated resource and a suggested replacement, or a + // warning about invalid network settings (for example, if an instance + // attempts to perform IP forwarding but is not enabled for IP + // forwarding). + Key string `json:"key,omitempty"` + + // Value: [Output Only] A warning data value corresponding to the key. + Value string `json:"value,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Key") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Key") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *SslCertificateAggregatedListWarningData) MarshalJSON() ([]byte, error) { + type NoMethod SslCertificateAggregatedListWarningData + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + // SslCertificateList: Contains a list of SslCertificate resources. type SslCertificateList struct { // Id: [Output Only] Unique identifier for the resource; defined by the @@ -28959,6 +31072,140 @@ func (s *SslCertificateSelfManagedSslCertificate) MarshalJSON() ([]byte, error) return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +type SslCertificatesScopedList struct { + // SslCertificates: List of SslCertificates contained in this scope. + SslCertificates []*SslCertificate `json:"sslCertificates,omitempty"` + + // Warning: Informational warning which replaces the list of backend + // services when the list is empty. + Warning *SslCertificatesScopedListWarning `json:"warning,omitempty"` + + // ForceSendFields is a list of field names (e.g. "SslCertificates") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "SslCertificates") to + // include in API requests with the JSON null value. By default, fields + // with empty values are omitted from API requests. However, any field + // with an empty value appearing in NullFields will be sent to the + // server as null. It is an error if a field in this list has a + // non-empty value. This may be used to include null fields in Patch + // requests. + NullFields []string `json:"-"` +} + +func (s *SslCertificatesScopedList) MarshalJSON() ([]byte, error) { + type NoMethod SslCertificatesScopedList + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// SslCertificatesScopedListWarning: Informational warning which +// replaces the list of backend services when the list is empty. +type SslCertificatesScopedListWarning struct { + // Code: [Output Only] A warning code, if applicable. For example, + // Compute Engine returns NO_RESULTS_ON_PAGE if there are no results in + // the response. + // + // Possible values: + // "CLEANUP_FAILED" + // "DEPRECATED_RESOURCE_USED" + // "DEPRECATED_TYPE_USED" + // "DISK_SIZE_LARGER_THAN_IMAGE_SIZE" + // "EXPERIMENTAL_TYPE_USED" + // "EXTERNAL_API_WARNING" + // "FIELD_VALUE_OVERRIDEN" + // "INJECTED_KERNELS_DEPRECATED" + // "MISSING_TYPE_DEPENDENCY" + // "NEXT_HOP_ADDRESS_NOT_ASSIGNED" + // "NEXT_HOP_CANNOT_IP_FORWARD" + // "NEXT_HOP_INSTANCE_NOT_FOUND" + // "NEXT_HOP_INSTANCE_NOT_ON_NETWORK" + // "NEXT_HOP_NOT_RUNNING" + // "NOT_CRITICAL_ERROR" + // "NO_RESULTS_ON_PAGE" + // "REQUIRED_TOS_AGREEMENT" + // "RESOURCE_IN_USE_BY_OTHER_RESOURCE_WARNING" + // "RESOURCE_NOT_DELETED" + // "SCHEMA_VALIDATION_IGNORED" + // "SINGLE_INSTANCE_PROPERTY_TEMPLATE" + // "UNDECLARED_PROPERTIES" + // "UNREACHABLE" + Code string `json:"code,omitempty"` + + // Data: [Output Only] Metadata about this warning in key: value format. + // For example: + // "data": [ { "key": "scope", "value": "zones/us-east1-d" } + Data []*SslCertificatesScopedListWarningData `json:"data,omitempty"` + + // Message: [Output Only] A human-readable description of the warning + // code. + Message string `json:"message,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Code") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Code") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *SslCertificatesScopedListWarning) MarshalJSON() ([]byte, error) { + type NoMethod SslCertificatesScopedListWarning + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type SslCertificatesScopedListWarningData struct { + // Key: [Output Only] A key that provides more detail on the warning + // being returned. For example, for warnings where there are no results + // in a list request for a particular zone, this key might be scope and + // the key value might be the zone name. Other examples might be a key + // indicating a deprecated resource and a suggested replacement, or a + // warning about invalid network settings (for example, if an instance + // attempts to perform IP forwarding but is not enabled for IP + // forwarding). + Key string `json:"key,omitempty"` + + // Value: [Output Only] A warning data value corresponding to the key. + Value string `json:"value,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Key") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Key") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *SslCertificatesScopedListWarningData) MarshalJSON() ([]byte, error) { + type NoMethod SslCertificatesScopedListWarningData + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + type SslPoliciesList struct { // Id: [Output Only] Unique identifier for the resource; defined by the // server. @@ -29170,7 +31417,11 @@ type SslPolicy struct { // Fingerprint: Fingerprint of this resource. A hash of the contents // stored in this object. This field is used in optimistic locking. This // field will be ignored when inserting a SslPolicy. An up-to-date - // fingerprint must be provided in order to update the SslPolicy. + // fingerprint must be provided in order to update the SslPolicy, + // otherwise the request will fail with error 412 conditionNotMet. + // + // To see the latest fingerprint, make a get() request to retrieve an + // SslPolicy. Fingerprint string `json:"fingerprint,omitempty"` // Id: [Output Only] The unique identifier for the resource. This @@ -29381,6 +31632,8 @@ func (s *SslPolicyReference) MarshalJSON() ([]byte, error) { type StatefulPolicy struct { PreservedResources *StatefulPolicyPreservedResources `json:"preservedResources,omitempty"` + PreservedState *StatefulPolicyPreservedState `json:"preservedState,omitempty"` + // ForceSendFields is a list of field names (e.g. "PreservedResources") // to unconditionally include in API requests. By default, fields with // empty values are omitted from API requests. However, any non-pointer, @@ -29462,9 +31715,90 @@ func (s *StatefulPolicyPreservedResources) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +// StatefulPolicyPreservedState: Configuration of preserved resources. +type StatefulPolicyPreservedState struct { + // Disks: Disks created on the instances that will be preserved on + // instance delete, resize down, etc. This map is keyed with the device + // names of the disks. + Disks map[string]StatefulPolicyPreservedStateDiskDevice `json:"disks,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Disks") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Disks") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *StatefulPolicyPreservedState) MarshalJSON() ([]byte, error) { + type NoMethod StatefulPolicyPreservedState + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type StatefulPolicyPreservedStateDiskDevice struct { + // AutoDelete: These stateful disks will never be deleted during + // autohealing, update or VM instance recreate operations. This flag is + // used to configure if the disk should be deleted after it is no longer + // used by the group, e.g. when the given instance or the whole group is + // deleted. Note: disks attached in READ_ONLY mode cannot be + // auto-deleted. + // + // Possible values: + // "NEVER" + // "WHEN_NOT_IN_USE" + AutoDelete string `json:"autoDelete,omitempty"` + + // ForceSendFields is a list of field names (e.g. "AutoDelete") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "AutoDelete") to include in + // API requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *StatefulPolicyPreservedStateDiskDevice) MarshalJSON() ([]byte, error) { + type NoMethod StatefulPolicyPreservedStateDiskDevice + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + // Subnetwork: A Subnetwork resource. (== resource_for beta.subnetworks // ==) (== resource_for v1.subnetworks ==) type Subnetwork struct { + // AggregationInterval: Can only be specified if VPC flow logging for + // this subnetwork is enabled. Toggles the aggregation interval for + // collecting flow logs. Increasing the interval time will reduce the + // amount of generated flow logs for long lasting connections. Default + // is an interval of 5 seconds per connection. + // + // Possible values: + // "INTERVAL_10_MIN" + // "INTERVAL_15_MIN" + // "INTERVAL_1_MIN" + // "INTERVAL_30_SEC" + // "INTERVAL_5_MIN" + // "INTERVAL_5_SEC" + AggregationInterval string `json:"aggregationInterval,omitempty"` + // AllowSubnetCidrRoutesOverlap: Whether this subnetwork can conflict // with static routes. Setting this to true allows this subnetwork's // primary and secondary ranges to conflict with routes that have @@ -29492,6 +31826,8 @@ type Subnetwork struct { Description string `json:"description,omitempty"` // EnableFlowLogs: Whether to enable flow logging for this subnetwork. + // If this field is not explicitly set, it will not appear in get + // listings. If not set the default behavior is to disable flow logging. EnableFlowLogs bool `json:"enableFlowLogs,omitempty"` // EnablePrivateV6Access: Whether the VMs in this subnet can directly @@ -29502,9 +31838,21 @@ type Subnetwork struct { // Fingerprint: Fingerprint of this resource. A hash of the contents // stored in this object. This field is used in optimistic locking. This // field will be ignored when inserting a Subnetwork. An up-to-date - // fingerprint must be provided in order to update the Subnetwork. + // fingerprint must be provided in order to update the Subnetwork, + // otherwise the request will fail with error 412 conditionNotMet. + // + // To see the latest fingerprint, make a get() request to retrieve a + // Subnetwork. Fingerprint string `json:"fingerprint,omitempty"` + // FlowSampling: Can only be specified if VPC flow logging for this + // subnetwork is enabled. The value of the field must be in [0, 1]. Set + // the sampling rate of VPC flow logs within the subnetwork where 1.0 + // means all collected logs are reported and 0.0 means no logs are + // reported. Default is 0.5 which means half of all collected logs are + // reported. + FlowSampling float64 `json:"flowSampling,omitempty"` + // GatewayAddress: [Output Only] The gateway address for default routes // to reach destination addresses outside this subnetwork. GatewayAddress string `json:"gatewayAddress,omitempty"` @@ -29528,6 +31876,20 @@ type Subnetwork struct { // for Subnetwork resources. Kind string `json:"kind,omitempty"` + // LogConfig: This field denotes the logging options for the load + // balancer traffic served by this backend service. If logging is + // enabled, logs will be exported to Stackdriver. + LogConfig *SubnetworkLogConfig `json:"logConfig,omitempty"` + + // Metadata: Can only be specified if VPC flow logging for this + // subnetwork is enabled. Configures whether metadata fields should be + // added to the reported VPC flow logs. Default is INCLUDE_ALL_METADATA. + // + // Possible values: + // "EXCLUDE_ALL_METADATA" + // "INCLUDE_ALL_METADATA" + Metadata string `json:"metadata,omitempty"` + // Name: The name of the resource, provided by the client when initially // creating the resource. The name must be 1-63 characters long, and // comply with RFC1035. Specifically, the name must be 1-63 characters @@ -29557,6 +31919,7 @@ type Subnetwork struct { // // Possible values: // "INTERNAL_HTTPS_LOAD_BALANCER" + // "PRIVATE" // "PRIVATE_RFC_1918" Purpose string `json:"purpose,omitempty"` @@ -29568,7 +31931,8 @@ type Subnetwork struct { // purpose = INTERNAL_HTTPS_LOAD_BALANCER. The value can be set to // ACTIVE or BACKUP. An ACTIVE subnetwork is one that is currently being // used for Internal HTTP(S) Load Balancing. A BACKUP subnetwork is one - // that is ready to be promoted to ACTIVE or is currently draining. + // that is ready to be promoted to ACTIVE or is currently draining. This + // field can be updated with a patch request. // // Possible values: // "ACTIVE" @@ -29578,32 +31942,45 @@ type Subnetwork struct { // SecondaryIpRanges: An array of configurations for secondary IP ranges // for VM instances contained in this subnetwork. The primary IP of such // VM must belong to the primary ipCidrRange of the subnetwork. The - // alias IPs may belong to either primary or secondary ranges. + // alias IPs may belong to either primary or secondary ranges. This + // field can be updated with a patch request. SecondaryIpRanges []*SubnetworkSecondaryRange `json:"secondaryIpRanges,omitempty"` // SelfLink: [Output Only] Server-defined URL for the resource. SelfLink string `json:"selfLink,omitempty"` + // State: [Output Only] The state of the subnetwork, which can be one of + // READY or DRAINING. A subnetwork that is READY is ready to be used. + // The state of DRAINING is only applicable to subnetworks that have the + // purpose set to INTERNAL_HTTPS_LOAD_BALANCER and indicates that + // connections to the load balancer are being drained. A subnetwork that + // is draining cannot be used or modified until it reaches a status of + // READY. + // + // Possible values: + // "DRAINING" + // "READY" + State string `json:"state,omitempty"` + // ServerResponse contains the HTTP response code and headers from the // server. googleapi.ServerResponse `json:"-"` - // ForceSendFields is a list of field names (e.g. - // "AllowSubnetCidrRoutesOverlap") to unconditionally include in API - // requests. By default, fields with empty values are omitted from API - // requests. However, any non-pointer, non-interface field appearing in - // ForceSendFields will be sent to the server regardless of whether the - // field is empty or not. This may be used to include empty fields in - // Patch requests. + // ForceSendFields is a list of field names (e.g. "AggregationInterval") + // to unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. ForceSendFields []string `json:"-"` - // NullFields is a list of field names (e.g. - // "AllowSubnetCidrRoutesOverlap") to include in API requests with the - // JSON null value. By default, fields with empty values are omitted - // from API requests. However, any field with an empty value appearing - // in NullFields will be sent to the server as null. It is an error if a - // field in this list has a non-empty value. This may be used to include - // null fields in Patch requests. + // NullFields is a list of field names (e.g. "AggregationInterval") to + // include in API requests with the JSON null value. By default, fields + // with empty values are omitted from API requests. However, any field + // with an empty value appearing in NullFields will be sent to the + // server as null. It is an error if a field in this list has a + // non-empty value. This may be used to include null fields in Patch + // requests. NullFields []string `json:"-"` } @@ -29613,6 +31990,20 @@ func (s *Subnetwork) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +func (s *Subnetwork) UnmarshalJSON(data []byte) error { + type NoMethod Subnetwork + var s1 struct { + FlowSampling gensupport.JSONFloat64 `json:"flowSampling"` + *NoMethod + } + s1.NoMethod = (*NoMethod)(s) + if err := json.Unmarshal(data, &s1); err != nil { + return err + } + s.FlowSampling = float64(s1.FlowSampling) + return nil +} + type SubnetworkAggregatedList struct { // Id: [Output Only] Unique identifier for the resource; defined by the // server. @@ -29923,6 +32314,84 @@ func (s *SubnetworkListWarningData) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +// SubnetworkLogConfig: The available logging options for this +// subnetwork. +type SubnetworkLogConfig struct { + // AggregationInterval: Can only be specified if VPC flow logging for + // this subnetwork is enabled. Toggles the aggregation interval for + // collecting flow logs. Increasing the interval time will reduce the + // amount of generated flow logs for long lasting connections. Default + // is an interval of 5 seconds per connection. + // + // Possible values: + // "INTERVAL_10_MIN" + // "INTERVAL_15_MIN" + // "INTERVAL_1_MIN" + // "INTERVAL_30_SEC" + // "INTERVAL_5_MIN" + // "INTERVAL_5_SEC" + AggregationInterval string `json:"aggregationInterval,omitempty"` + + // Enable: Whether to enable flow logging for this subnetwork. If this + // field is not explicitly set, it will not appear in get listings. If + // not set the default behavior is to disable flow logging. + Enable bool `json:"enable,omitempty"` + + // FlowSampling: Can only be specified if VPC flow logging for this + // subnetwork is enabled. The value of the field must be in [0, 1]. Set + // the sampling rate of VPC flow logs within the subnetwork where 1.0 + // means all collected logs are reported and 0.0 means no logs are + // reported. Default is 0.5 which means half of all collected logs are + // reported. + FlowSampling float64 `json:"flowSampling,omitempty"` + + // Metadata: Can only be specified if VPC flow logging for this + // subnetwork is enabled. Configures whether metadata fields should be + // added to the reported VPC flow logs. Default is INCLUDE_ALL_METADATA. + // + // Possible values: + // "EXCLUDE_ALL_METADATA" + // "INCLUDE_ALL_METADATA" + Metadata string `json:"metadata,omitempty"` + + // ForceSendFields is a list of field names (e.g. "AggregationInterval") + // to unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "AggregationInterval") to + // include in API requests with the JSON null value. By default, fields + // with empty values are omitted from API requests. However, any field + // with an empty value appearing in NullFields will be sent to the + // server as null. It is an error if a field in this list has a + // non-empty value. This may be used to include null fields in Patch + // requests. + NullFields []string `json:"-"` +} + +func (s *SubnetworkLogConfig) MarshalJSON() ([]byte, error) { + type NoMethod SubnetworkLogConfig + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +func (s *SubnetworkLogConfig) UnmarshalJSON(data []byte) error { + type NoMethod SubnetworkLogConfig + var s1 struct { + FlowSampling gensupport.JSONFloat64 `json:"flowSampling"` + *NoMethod + } + s1.NoMethod = (*NoMethod)(s) + if err := json.Unmarshal(data, &s1); err != nil { + return err + } + s.FlowSampling = float64(s1.FlowSampling) + return nil +} + // SubnetworkSecondaryRange: Represents a secondary IP range of a // subnetwork. type SubnetworkSecondaryRange struct { @@ -30788,6 +33257,141 @@ func (s *TargetHttpProxyListWarningData) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +type TargetHttpsProxiesScopedList struct { + // TargetHttpsProxies: A list of TargetHttpsProxies contained in this + // scope. + TargetHttpsProxies []*TargetHttpsProxy `json:"targetHttpsProxies,omitempty"` + + // Warning: Informational warning which replaces the list of backend + // services when the list is empty. + Warning *TargetHttpsProxiesScopedListWarning `json:"warning,omitempty"` + + // ForceSendFields is a list of field names (e.g. "TargetHttpsProxies") + // to unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "TargetHttpsProxies") to + // include in API requests with the JSON null value. By default, fields + // with empty values are omitted from API requests. However, any field + // with an empty value appearing in NullFields will be sent to the + // server as null. It is an error if a field in this list has a + // non-empty value. This may be used to include null fields in Patch + // requests. + NullFields []string `json:"-"` +} + +func (s *TargetHttpsProxiesScopedList) MarshalJSON() ([]byte, error) { + type NoMethod TargetHttpsProxiesScopedList + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// TargetHttpsProxiesScopedListWarning: Informational warning which +// replaces the list of backend services when the list is empty. +type TargetHttpsProxiesScopedListWarning struct { + // Code: [Output Only] A warning code, if applicable. For example, + // Compute Engine returns NO_RESULTS_ON_PAGE if there are no results in + // the response. + // + // Possible values: + // "CLEANUP_FAILED" + // "DEPRECATED_RESOURCE_USED" + // "DEPRECATED_TYPE_USED" + // "DISK_SIZE_LARGER_THAN_IMAGE_SIZE" + // "EXPERIMENTAL_TYPE_USED" + // "EXTERNAL_API_WARNING" + // "FIELD_VALUE_OVERRIDEN" + // "INJECTED_KERNELS_DEPRECATED" + // "MISSING_TYPE_DEPENDENCY" + // "NEXT_HOP_ADDRESS_NOT_ASSIGNED" + // "NEXT_HOP_CANNOT_IP_FORWARD" + // "NEXT_HOP_INSTANCE_NOT_FOUND" + // "NEXT_HOP_INSTANCE_NOT_ON_NETWORK" + // "NEXT_HOP_NOT_RUNNING" + // "NOT_CRITICAL_ERROR" + // "NO_RESULTS_ON_PAGE" + // "REQUIRED_TOS_AGREEMENT" + // "RESOURCE_IN_USE_BY_OTHER_RESOURCE_WARNING" + // "RESOURCE_NOT_DELETED" + // "SCHEMA_VALIDATION_IGNORED" + // "SINGLE_INSTANCE_PROPERTY_TEMPLATE" + // "UNDECLARED_PROPERTIES" + // "UNREACHABLE" + Code string `json:"code,omitempty"` + + // Data: [Output Only] Metadata about this warning in key: value format. + // For example: + // "data": [ { "key": "scope", "value": "zones/us-east1-d" } + Data []*TargetHttpsProxiesScopedListWarningData `json:"data,omitempty"` + + // Message: [Output Only] A human-readable description of the warning + // code. + Message string `json:"message,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Code") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Code") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *TargetHttpsProxiesScopedListWarning) MarshalJSON() ([]byte, error) { + type NoMethod TargetHttpsProxiesScopedListWarning + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type TargetHttpsProxiesScopedListWarningData struct { + // Key: [Output Only] A key that provides more detail on the warning + // being returned. For example, for warnings where there are no results + // in a list request for a particular zone, this key might be scope and + // the key value might be the zone name. Other examples might be a key + // indicating a deprecated resource and a suggested replacement, or a + // warning about invalid network settings (for example, if an instance + // attempts to perform IP forwarding but is not enabled for IP + // forwarding). + Key string `json:"key,omitempty"` + + // Value: [Output Only] A warning data value corresponding to the key. + Value string `json:"value,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Key") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Key") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *TargetHttpsProxiesScopedListWarningData) MarshalJSON() ([]byte, error) { + type NoMethod TargetHttpsProxiesScopedListWarningData + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + type TargetHttpsProxiesSetQuicOverrideRequest struct { // QuicOverride: QUIC policy for the TargetHttpsProxy resource. // @@ -30894,12 +33498,18 @@ type TargetHttpsProxy struct { // "NONE" QuicOverride string `json:"quicOverride,omitempty"` + // Region: [Output Only] URL of the region where the regional + // TargetHttpsProxy resides. This field is not applicable to global + // TargetHttpsProxies. + Region string `json:"region,omitempty"` + // SelfLink: [Output Only] Server-defined URL for the resource. SelfLink string `json:"selfLink,omitempty"` // SslCertificates: URLs to SslCertificate resources that are used to - // authenticate connections between users and the load balancer. - // Currently, exactly one SSL certificate must be specified. + // authenticate connections between users and the load balancer. At + // least one SSL certificate must be specified. Currently, you may + // specify up to 15 SSL certificates. SslCertificates []string `json:"sslCertificates,omitempty"` // SslPolicy: URL of SslPolicy resource that will be associated with the @@ -30944,6 +33554,162 @@ func (s *TargetHttpsProxy) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +type TargetHttpsProxyAggregatedList struct { + // Id: [Output Only] Unique identifier for the resource; defined by the + // server. + Id string `json:"id,omitempty"` + + // Items: A list of TargetHttpsProxiesScopedList resources. + Items map[string]TargetHttpsProxiesScopedList `json:"items,omitempty"` + + // Kind: [Output Only] Type of resource. Always + // compute#targetHttpsProxyAggregatedList for lists of Target HTTP + // Proxies. + Kind string `json:"kind,omitempty"` + + // NextPageToken: [Output Only] This token allows you to get the next + // page of results for list requests. If the number of results is larger + // than maxResults, use the nextPageToken as a value for the query + // parameter pageToken in the next list request. Subsequent list + // requests will have their own nextPageToken to continue paging through + // the results. + NextPageToken string `json:"nextPageToken,omitempty"` + + // SelfLink: [Output Only] Server-defined URL for this resource. + SelfLink string `json:"selfLink,omitempty"` + + // Warning: [Output Only] Informational warning message. + Warning *TargetHttpsProxyAggregatedListWarning `json:"warning,omitempty"` + + // ServerResponse contains the HTTP response code and headers from the + // server. + googleapi.ServerResponse `json:"-"` + + // ForceSendFields is a list of field names (e.g. "Id") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Id") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *TargetHttpsProxyAggregatedList) MarshalJSON() ([]byte, error) { + type NoMethod TargetHttpsProxyAggregatedList + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// TargetHttpsProxyAggregatedListWarning: [Output Only] Informational +// warning message. +type TargetHttpsProxyAggregatedListWarning struct { + // Code: [Output Only] A warning code, if applicable. For example, + // Compute Engine returns NO_RESULTS_ON_PAGE if there are no results in + // the response. + // + // Possible values: + // "CLEANUP_FAILED" + // "DEPRECATED_RESOURCE_USED" + // "DEPRECATED_TYPE_USED" + // "DISK_SIZE_LARGER_THAN_IMAGE_SIZE" + // "EXPERIMENTAL_TYPE_USED" + // "EXTERNAL_API_WARNING" + // "FIELD_VALUE_OVERRIDEN" + // "INJECTED_KERNELS_DEPRECATED" + // "MISSING_TYPE_DEPENDENCY" + // "NEXT_HOP_ADDRESS_NOT_ASSIGNED" + // "NEXT_HOP_CANNOT_IP_FORWARD" + // "NEXT_HOP_INSTANCE_NOT_FOUND" + // "NEXT_HOP_INSTANCE_NOT_ON_NETWORK" + // "NEXT_HOP_NOT_RUNNING" + // "NOT_CRITICAL_ERROR" + // "NO_RESULTS_ON_PAGE" + // "REQUIRED_TOS_AGREEMENT" + // "RESOURCE_IN_USE_BY_OTHER_RESOURCE_WARNING" + // "RESOURCE_NOT_DELETED" + // "SCHEMA_VALIDATION_IGNORED" + // "SINGLE_INSTANCE_PROPERTY_TEMPLATE" + // "UNDECLARED_PROPERTIES" + // "UNREACHABLE" + Code string `json:"code,omitempty"` + + // Data: [Output Only] Metadata about this warning in key: value format. + // For example: + // "data": [ { "key": "scope", "value": "zones/us-east1-d" } + Data []*TargetHttpsProxyAggregatedListWarningData `json:"data,omitempty"` + + // Message: [Output Only] A human-readable description of the warning + // code. + Message string `json:"message,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Code") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Code") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *TargetHttpsProxyAggregatedListWarning) MarshalJSON() ([]byte, error) { + type NoMethod TargetHttpsProxyAggregatedListWarning + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type TargetHttpsProxyAggregatedListWarningData struct { + // Key: [Output Only] A key that provides more detail on the warning + // being returned. For example, for warnings where there are no results + // in a list request for a particular zone, this key might be scope and + // the key value might be the zone name. Other examples might be a key + // indicating a deprecated resource and a suggested replacement, or a + // warning about invalid network settings (for example, if an instance + // attempts to perform IP forwarding but is not enabled for IP + // forwarding). + Key string `json:"key,omitempty"` + + // Value: [Output Only] A warning data value corresponding to the key. + Value string `json:"value,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Key") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Key") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *TargetHttpsProxyAggregatedListWarningData) MarshalJSON() ([]byte, error) { + type NoMethod TargetHttpsProxyAggregatedListWarningData + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + // TargetHttpsProxyList: Contains a list of TargetHttpsProxy resources. type TargetHttpsProxyList struct { // Id: [Output Only] Unique identifier for the resource; defined by the @@ -31710,7 +34476,7 @@ type TargetPool struct { // SelfLink: [Output Only] Server-defined URL for the resource. SelfLink string `json:"selfLink,omitempty"` - // SessionAffinity: Sesssion affinity option, must be one of the + // SessionAffinity: Session affinity option, must be one of the // following values: // NONE: Connections from the same client IP may go to any instance in // the pool. @@ -32529,8 +35295,9 @@ type TargetSslProxy struct { Service string `json:"service,omitempty"` // SslCertificates: URLs to SslCertificate resources that are used to - // authenticate connections to Backends. Currently exactly one SSL - // certificate must be specified. + // authenticate connections to Backends. At least one SSL certificate + // must be specified. Currently, you may specify up to 15 SSL + // certificates. SslCertificates []string `json:"sslCertificates,omitempty"` // SslPolicy: URL of SslPolicy resource that will be associated with the @@ -33038,9 +35805,10 @@ type TargetVpnGateway struct { // for optimistic locking. The fingerprint is initially generated by // Compute Engine and changes after every request to modify or update // labels. You must always provide an up-to-date fingerprint hash in - // order to update or change labels. + // order to update or change labels, otherwise the request will fail + // with error 412 conditionNotMet. // - // To see the latest fingerprint, make a get() request to retrieve an + // To see the latest fingerprint, make a get() request to retrieve a // TargetVpnGateway. LabelFingerprint string `json:"labelFingerprint,omitempty"` @@ -33700,8 +36468,13 @@ type UrlMap struct { // format. CreationTimestamp string `json:"creationTimestamp,omitempty"` - // DefaultService: The URL of the BackendService resource if none of the + // DefaultService: The URL of the backendService resource if none of the // hostRules match. + // Use defaultService instead of defaultRouteAction when simple routing + // to a backendService is desired and other advanced capabilities like + // traffic splitting and rewrites are not required. + // Only one of defaultService, defaultRouteAction or defaultUrlRedirect + // should must be set. DefaultService string `json:"defaultService,omitempty"` // Description: An optional description of this resource. Provide this @@ -33711,7 +36484,11 @@ type UrlMap struct { // Fingerprint: Fingerprint of this resource. A hash of the contents // stored in this object. This field is used in optimistic locking. This // field will be ignored when inserting a UrlMap. An up-to-date - // fingerprint must be provided in order to update the UrlMap. + // fingerprint must be provided in order to update the UrlMap, otherwise + // the request will fail with error 412 conditionNotMet. + // + // To see the latest fingerprint, make a get() request to retrieve a + // UrlMap. Fingerprint string `json:"fingerprint,omitempty"` // HostRules: The list of HostRules to use against the URL. @@ -34036,6 +36813,293 @@ func (s *UrlMapValidationResult) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +type UrlMapsAggregatedList struct { + // Id: [Output Only] Unique identifier for the resource; defined by the + // server. + Id string `json:"id,omitempty"` + + // Items: A list of UrlMapsScopedList resources. + Items map[string]UrlMapsScopedList `json:"items,omitempty"` + + // Kind: Type of resource. + Kind string `json:"kind,omitempty"` + + // NextPageToken: [Output Only] This token allows you to get the next + // page of results for list requests. If the number of results is larger + // than maxResults, use the nextPageToken as a value for the query + // parameter pageToken in the next list request. Subsequent list + // requests will have their own nextPageToken to continue paging through + // the results. + NextPageToken string `json:"nextPageToken,omitempty"` + + // SelfLink: [Output Only] Server-defined URL for this resource. + SelfLink string `json:"selfLink,omitempty"` + + // Warning: [Output Only] Informational warning message. + Warning *UrlMapsAggregatedListWarning `json:"warning,omitempty"` + + // ServerResponse contains the HTTP response code and headers from the + // server. + googleapi.ServerResponse `json:"-"` + + // ForceSendFields is a list of field names (e.g. "Id") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Id") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *UrlMapsAggregatedList) MarshalJSON() ([]byte, error) { + type NoMethod UrlMapsAggregatedList + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// UrlMapsAggregatedListWarning: [Output Only] Informational warning +// message. +type UrlMapsAggregatedListWarning struct { + // Code: [Output Only] A warning code, if applicable. For example, + // Compute Engine returns NO_RESULTS_ON_PAGE if there are no results in + // the response. + // + // Possible values: + // "CLEANUP_FAILED" + // "DEPRECATED_RESOURCE_USED" + // "DEPRECATED_TYPE_USED" + // "DISK_SIZE_LARGER_THAN_IMAGE_SIZE" + // "EXPERIMENTAL_TYPE_USED" + // "EXTERNAL_API_WARNING" + // "FIELD_VALUE_OVERRIDEN" + // "INJECTED_KERNELS_DEPRECATED" + // "MISSING_TYPE_DEPENDENCY" + // "NEXT_HOP_ADDRESS_NOT_ASSIGNED" + // "NEXT_HOP_CANNOT_IP_FORWARD" + // "NEXT_HOP_INSTANCE_NOT_FOUND" + // "NEXT_HOP_INSTANCE_NOT_ON_NETWORK" + // "NEXT_HOP_NOT_RUNNING" + // "NOT_CRITICAL_ERROR" + // "NO_RESULTS_ON_PAGE" + // "REQUIRED_TOS_AGREEMENT" + // "RESOURCE_IN_USE_BY_OTHER_RESOURCE_WARNING" + // "RESOURCE_NOT_DELETED" + // "SCHEMA_VALIDATION_IGNORED" + // "SINGLE_INSTANCE_PROPERTY_TEMPLATE" + // "UNDECLARED_PROPERTIES" + // "UNREACHABLE" + Code string `json:"code,omitempty"` + + // Data: [Output Only] Metadata about this warning in key: value format. + // For example: + // "data": [ { "key": "scope", "value": "zones/us-east1-d" } + Data []*UrlMapsAggregatedListWarningData `json:"data,omitempty"` + + // Message: [Output Only] A human-readable description of the warning + // code. + Message string `json:"message,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Code") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Code") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *UrlMapsAggregatedListWarning) MarshalJSON() ([]byte, error) { + type NoMethod UrlMapsAggregatedListWarning + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type UrlMapsAggregatedListWarningData struct { + // Key: [Output Only] A key that provides more detail on the warning + // being returned. For example, for warnings where there are no results + // in a list request for a particular zone, this key might be scope and + // the key value might be the zone name. Other examples might be a key + // indicating a deprecated resource and a suggested replacement, or a + // warning about invalid network settings (for example, if an instance + // attempts to perform IP forwarding but is not enabled for IP + // forwarding). + Key string `json:"key,omitempty"` + + // Value: [Output Only] A warning data value corresponding to the key. + Value string `json:"value,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Key") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Key") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *UrlMapsAggregatedListWarningData) MarshalJSON() ([]byte, error) { + type NoMethod UrlMapsAggregatedListWarningData + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type UrlMapsScopedList struct { + // UrlMaps: A list of UrlMaps contained in this scope. + UrlMaps []*UrlMap `json:"urlMaps,omitempty"` + + // Warning: Informational warning which replaces the list of backend + // services when the list is empty. + Warning *UrlMapsScopedListWarning `json:"warning,omitempty"` + + // ForceSendFields is a list of field names (e.g. "UrlMaps") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "UrlMaps") to include in + // API requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *UrlMapsScopedList) MarshalJSON() ([]byte, error) { + type NoMethod UrlMapsScopedList + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// UrlMapsScopedListWarning: Informational warning which replaces the +// list of backend services when the list is empty. +type UrlMapsScopedListWarning struct { + // Code: [Output Only] A warning code, if applicable. For example, + // Compute Engine returns NO_RESULTS_ON_PAGE if there are no results in + // the response. + // + // Possible values: + // "CLEANUP_FAILED" + // "DEPRECATED_RESOURCE_USED" + // "DEPRECATED_TYPE_USED" + // "DISK_SIZE_LARGER_THAN_IMAGE_SIZE" + // "EXPERIMENTAL_TYPE_USED" + // "EXTERNAL_API_WARNING" + // "FIELD_VALUE_OVERRIDEN" + // "INJECTED_KERNELS_DEPRECATED" + // "MISSING_TYPE_DEPENDENCY" + // "NEXT_HOP_ADDRESS_NOT_ASSIGNED" + // "NEXT_HOP_CANNOT_IP_FORWARD" + // "NEXT_HOP_INSTANCE_NOT_FOUND" + // "NEXT_HOP_INSTANCE_NOT_ON_NETWORK" + // "NEXT_HOP_NOT_RUNNING" + // "NOT_CRITICAL_ERROR" + // "NO_RESULTS_ON_PAGE" + // "REQUIRED_TOS_AGREEMENT" + // "RESOURCE_IN_USE_BY_OTHER_RESOURCE_WARNING" + // "RESOURCE_NOT_DELETED" + // "SCHEMA_VALIDATION_IGNORED" + // "SINGLE_INSTANCE_PROPERTY_TEMPLATE" + // "UNDECLARED_PROPERTIES" + // "UNREACHABLE" + Code string `json:"code,omitempty"` + + // Data: [Output Only] Metadata about this warning in key: value format. + // For example: + // "data": [ { "key": "scope", "value": "zones/us-east1-d" } + Data []*UrlMapsScopedListWarningData `json:"data,omitempty"` + + // Message: [Output Only] A human-readable description of the warning + // code. + Message string `json:"message,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Code") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Code") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *UrlMapsScopedListWarning) MarshalJSON() ([]byte, error) { + type NoMethod UrlMapsScopedListWarning + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type UrlMapsScopedListWarningData struct { + // Key: [Output Only] A key that provides more detail on the warning + // being returned. For example, for warnings where there are no results + // in a list request for a particular zone, this key might be scope and + // the key value might be the zone name. Other examples might be a key + // indicating a deprecated resource and a suggested replacement, or a + // warning about invalid network settings (for example, if an instance + // attempts to perform IP forwarding but is not enabled for IP + // forwarding). + Key string `json:"key,omitempty"` + + // Value: [Output Only] A warning data value corresponding to the key. + Value string `json:"value,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Key") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Key") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *UrlMapsScopedListWarningData) MarshalJSON() ([]byte, error) { + type NoMethod UrlMapsScopedListWarningData + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + type UrlMapsValidateRequest struct { // Resource: Content of the UrlMap to be validated. Resource *UrlMap `json:"resource,omitempty"` @@ -34625,7 +37689,8 @@ type VpnGateway struct { // optimistic locking. The fingerprint is initially generated by Compute // Engine and changes after every request to modify or update labels. // You must always provide an up-to-date fingerprint hash in order to - // update or change labels. + // update or change labels, otherwise the request will fail with error + // 412 conditionNotMet. // // To see the latest fingerprint, make a get() request to retrieve an // VpnGateway. @@ -35196,7 +38261,8 @@ type VpnTunnel struct { // optimistic locking. The fingerprint is initially generated by Compute // Engine and changes after every request to modify or update labels. // You must always provide an up-to-date fingerprint hash in order to - // update or change labels. + // update or change labels, otherwise the request will fail with error + // 412 conditionNotMet. // // To see the latest fingerprint, make a get() request to retrieve a // VpnTunnel. @@ -35979,8 +39045,8 @@ func (s *XpnHostListWarningData) MarshalJSON() ([]byte, error) { // XpnResourceId: Service resource (a.k.a service project) ID. type XpnResourceId struct { // Id: The ID of the service resource. In the case of projects, this - // field matches the project ID (e.g., my-project), not the project - // number (e.g., 12345678). + // field supports project id (e.g., my-project-123) and project number + // (e.g. 12345678). Id string `json:"id,omitempty"` // Type: The type of the service resource. @@ -36440,9 +39506,13 @@ func (c *AcceleratorTypesAggregatedListCall) doRequest(alt string) (*http.Respon } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/aggregated/acceleratorTypes") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -36628,9 +39698,13 @@ func (c *AcceleratorTypesGetCall) doRequest(alt string) (*http.Response, error) } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/acceleratorTypes/{acceleratorType}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -36852,9 +39926,13 @@ func (c *AcceleratorTypesListCall) doRequest(alt string) (*http.Response, error) } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/acceleratorTypes") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -37109,9 +40187,13 @@ func (c *AddressesAggregatedListCall) doRequest(alt string) (*http.Response, err } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/aggregated/addresses") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -37303,9 +40385,13 @@ func (c *AddressesDeleteCall) doRequest(alt string) (*http.Response, error) { reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/addresses/{address}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -37470,9 +40556,13 @@ func (c *AddressesGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/addresses/{address}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -37644,9 +40734,13 @@ func (c *AddressesInsertCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/addresses") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -37867,9 +40961,13 @@ func (c *AddressesListCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/addresses") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -38077,9 +41175,13 @@ func (c *AddressesSetLabelsCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/addresses/{resource}/setLabels") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -38156,9 +41258,9 @@ func (c *AddressesSetLabelsCall) Do(opts ...googleapi.CallOption) (*Operation, e // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -38240,9 +41342,13 @@ func (c *AddressesTestIamPermissionsCall) doRequest(alt string) (*http.Response, } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/addresses/{resource}/testIamPermissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -38314,9 +41420,9 @@ func (c *AddressesTestIamPermissionsCall) Do(opts ...googleapi.CallOption) (*Tes // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -38337,6 +41443,1712 @@ func (c *AddressesTestIamPermissionsCall) Do(opts ...googleapi.CallOption) (*Tes } +// method id "compute.allocations.aggregatedList": + +type AllocationsAggregatedListCall struct { + s *Service + project string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// AggregatedList: Retrieves an aggregated list of allocations. +func (r *AllocationsService) AggregatedList(project string) *AllocationsAggregatedListCall { + c := &AllocationsAggregatedListCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + return c +} + +// Filter sets the optional parameter "filter": A filter expression that +// filters resources listed in the response. The expression must specify +// the field name, a comparison operator, and the value that you want to +// use for filtering. The value must be a string, a number, or a +// boolean. The comparison operator must be either =, !=, >, or <. +// +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. +// +// You can also filter nested fields. For example, you could specify +// scheduling.automaticRestart = false to include instances only if they +// are not scheduled for automatic restarts. You can use filtering on +// nested fields to filter based on resource labels. +// +// To filter on multiple expressions, provide each separate expression +// within parentheses. For example, (scheduling.automaticRestart = true) +// (cpuPlatform = "Intel Skylake"). By default, each expression is an +// AND expression. However, you can include AND and OR expressions +// explicitly. For example, (cpuPlatform = "Intel Skylake") OR +// (cpuPlatform = "Intel Broadwell") AND (scheduling.automaticRestart = +// true). +func (c *AllocationsAggregatedListCall) Filter(filter string) *AllocationsAggregatedListCall { + c.urlParams_.Set("filter", filter) + return c +} + +// MaxResults sets the optional parameter "maxResults": The maximum +// number of results per page that should be returned. If the number of +// available results is larger than maxResults, Compute Engine returns a +// nextPageToken that can be used to get the next page of results in +// subsequent list requests. Acceptable values are 0 to 500, inclusive. +// (Default: 500) +func (c *AllocationsAggregatedListCall) MaxResults(maxResults int64) *AllocationsAggregatedListCall { + c.urlParams_.Set("maxResults", fmt.Sprint(maxResults)) + return c +} + +// OrderBy sets the optional parameter "orderBy": Sorts list results by +// a certain order. By default, results are returned in alphanumerical +// order based on the resource name. +// +// You can also sort results in descending order based on the creation +// timestamp using orderBy="creationTimestamp desc". This sorts results +// based on the creationTimestamp field in reverse chronological order +// (newest result first). Use this to sort resources like operations so +// that the newest operation is returned first. +// +// Currently, only sorting by name or creationTimestamp desc is +// supported. +func (c *AllocationsAggregatedListCall) OrderBy(orderBy string) *AllocationsAggregatedListCall { + c.urlParams_.Set("orderBy", orderBy) + return c +} + +// PageToken sets the optional parameter "pageToken": Specifies a page +// token to use. Set pageToken to the nextPageToken returned by a +// previous list request to get the next page of results. +func (c *AllocationsAggregatedListCall) PageToken(pageToken string) *AllocationsAggregatedListCall { + c.urlParams_.Set("pageToken", pageToken) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *AllocationsAggregatedListCall) Fields(s ...googleapi.Field) *AllocationsAggregatedListCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// IfNoneMatch sets the optional parameter which makes the operation +// fail if the object's ETag matches the given value. This is useful for +// getting updates only after the object has changed since the last +// request. Use googleapi.IsNotModified to check whether the response +// error from Do is the result of In-None-Match. +func (c *AllocationsAggregatedListCall) IfNoneMatch(entityTag string) *AllocationsAggregatedListCall { + c.ifNoneMatch_ = entityTag + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *AllocationsAggregatedListCall) Context(ctx context.Context) *AllocationsAggregatedListCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *AllocationsAggregatedListCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *AllocationsAggregatedListCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + if c.ifNoneMatch_ != "" { + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) + } + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/aggregated/allocations") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.allocations.aggregatedList" call. +// Exactly one of *AllocationAggregatedList or error will be non-nil. +// Any non-2xx status code is an error. Response headers are in either +// *AllocationAggregatedList.ServerResponse.Header or (if a response was +// returned at all) in error.(*googleapi.Error).Header. Use +// googleapi.IsNotModified to check whether the returned error was +// because http.StatusNotModified was returned. +func (c *AllocationsAggregatedListCall) Do(opts ...googleapi.CallOption) (*AllocationAggregatedList, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &AllocationAggregatedList{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Retrieves an aggregated list of allocations.", + // "httpMethod": "GET", + // "id": "compute.allocations.aggregatedList", + // "parameterOrder": [ + // "project" + // ], + // "parameters": { + // "filter": { + // "description": "A filter expression that filters resources listed in the response. The expression must specify the field name, a comparison operator, and the value that you want to use for filtering. The value must be a string, a number, or a boolean. The comparison operator must be either =, !=, \u003e, or \u003c.\n\nFor example, if you are filtering Compute Engine instances, you can exclude instances named example-instance by specifying name != example-instance.\n\nYou can also filter nested fields. For example, you could specify scheduling.automaticRestart = false to include instances only if they are not scheduled for automatic restarts. You can use filtering on nested fields to filter based on resource labels.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart = true) (cpuPlatform = \"Intel Skylake\"). By default, each expression is an AND expression. However, you can include AND and OR expressions explicitly. For example, (cpuPlatform = \"Intel Skylake\") OR (cpuPlatform = \"Intel Broadwell\") AND (scheduling.automaticRestart = true).", + // "location": "query", + // "type": "string" + // }, + // "maxResults": { + // "default": "500", + // "description": "The maximum number of results per page that should be returned. If the number of available results is larger than maxResults, Compute Engine returns a nextPageToken that can be used to get the next page of results in subsequent list requests. Acceptable values are 0 to 500, inclusive. (Default: 500)", + // "format": "uint32", + // "location": "query", + // "minimum": "0", + // "type": "integer" + // }, + // "orderBy": { + // "description": "Sorts list results by a certain order. By default, results are returned in alphanumerical order based on the resource name.\n\nYou can also sort results in descending order based on the creation timestamp using orderBy=\"creationTimestamp desc\". This sorts results based on the creationTimestamp field in reverse chronological order (newest result first). Use this to sort resources like operations so that the newest operation is returned first.\n\nCurrently, only sorting by name or creationTimestamp desc is supported.", + // "location": "query", + // "type": "string" + // }, + // "pageToken": { + // "description": "Specifies a page token to use. Set pageToken to the nextPageToken returned by a previous list request to get the next page of results.", + // "location": "query", + // "type": "string" + // }, + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/aggregated/allocations", + // "response": { + // "$ref": "AllocationAggregatedList" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute", + // "https://www.googleapis.com/auth/compute.readonly" + // ] + // } + +} + +// Pages invokes f for each page of results. +// A non-nil error returned from f will halt the iteration. +// The provided context supersedes any context provided to the Context method. +func (c *AllocationsAggregatedListCall) Pages(ctx context.Context, f func(*AllocationAggregatedList) error) error { + c.ctx_ = ctx + defer c.PageToken(c.urlParams_.Get("pageToken")) // reset paging to original point + for { + x, err := c.Do() + if err != nil { + return err + } + if err := f(x); err != nil { + return err + } + if x.NextPageToken == "" { + return nil + } + c.PageToken(x.NextPageToken) + } +} + +// method id "compute.allocations.delete": + +type AllocationsDeleteCall struct { + s *Service + project string + zone string + allocation string + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// Delete: Deletes the specified allocation. +func (r *AllocationsService) Delete(project string, zone string, allocation string) *AllocationsDeleteCall { + c := &AllocationsDeleteCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.zone = zone + c.allocation = allocation + return c +} + +// RequestId sets the optional parameter "requestId": An optional +// request ID to identify requests. Specify a unique request ID so that +// if you must retry your request, the server will know to ignore the +// request if it has already been completed. +// +// For example, consider a situation where you make an initial request +// and the request times out. If you make the request again with the +// same request ID, the server can check if original operation with the +// same request ID was received, and if so, will ignore the second +// request. This prevents clients from accidentally creating duplicate +// commitments. +// +// The request ID must be a valid UUID with the exception that zero UUID +// is not supported (00000000-0000-0000-0000-000000000000). +func (c *AllocationsDeleteCall) RequestId(requestId string) *AllocationsDeleteCall { + c.urlParams_.Set("requestId", requestId) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *AllocationsDeleteCall) Fields(s ...googleapi.Field) *AllocationsDeleteCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *AllocationsDeleteCall) Context(ctx context.Context) *AllocationsDeleteCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *AllocationsDeleteCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *AllocationsDeleteCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/allocations/{allocation}") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "zone": c.zone, + "allocation": c.allocation, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.allocations.delete" call. +// Exactly one of *Operation or error will be non-nil. Any non-2xx +// status code is an error. Response headers are in either +// *Operation.ServerResponse.Header or (if a response was returned at +// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified +// to check whether the returned error was because +// http.StatusNotModified was returned. +func (c *AllocationsDeleteCall) Do(opts ...googleapi.CallOption) (*Operation, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Operation{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Deletes the specified allocation.", + // "httpMethod": "DELETE", + // "id": "compute.allocations.delete", + // "parameterOrder": [ + // "project", + // "zone", + // "allocation" + // ], + // "parameters": { + // "allocation": { + // "description": "Name of the allocation to delete.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // }, + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "requestId": { + // "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", + // "location": "query", + // "type": "string" + // }, + // "zone": { + // "description": "Name of the zone for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/zones/{zone}/allocations/{allocation}", + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + +// method id "compute.allocations.get": + +type AllocationsGetCall struct { + s *Service + project string + zone string + allocation string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// Get: Retrieves all information of the specified allocation. +func (r *AllocationsService) Get(project string, zone string, allocation string) *AllocationsGetCall { + c := &AllocationsGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.zone = zone + c.allocation = allocation + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *AllocationsGetCall) Fields(s ...googleapi.Field) *AllocationsGetCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// IfNoneMatch sets the optional parameter which makes the operation +// fail if the object's ETag matches the given value. This is useful for +// getting updates only after the object has changed since the last +// request. Use googleapi.IsNotModified to check whether the response +// error from Do is the result of In-None-Match. +func (c *AllocationsGetCall) IfNoneMatch(entityTag string) *AllocationsGetCall { + c.ifNoneMatch_ = entityTag + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *AllocationsGetCall) Context(ctx context.Context) *AllocationsGetCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *AllocationsGetCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *AllocationsGetCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + if c.ifNoneMatch_ != "" { + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) + } + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/allocations/{allocation}") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "zone": c.zone, + "allocation": c.allocation, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.allocations.get" call. +// Exactly one of *Allocation or error will be non-nil. Any non-2xx +// status code is an error. Response headers are in either +// *Allocation.ServerResponse.Header or (if a response was returned at +// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified +// to check whether the returned error was because +// http.StatusNotModified was returned. +func (c *AllocationsGetCall) Do(opts ...googleapi.CallOption) (*Allocation, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Allocation{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Retrieves all information of the specified allocation.", + // "httpMethod": "GET", + // "id": "compute.allocations.get", + // "parameterOrder": [ + // "project", + // "zone", + // "allocation" + // ], + // "parameters": { + // "allocation": { + // "description": "Name of the allocation to retrieve.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // }, + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "zone": { + // "description": "Name of the zone for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/zones/{zone}/allocations/{allocation}", + // "response": { + // "$ref": "Allocation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute", + // "https://www.googleapis.com/auth/compute.readonly" + // ] + // } + +} + +// method id "compute.allocations.getIamPolicy": + +type AllocationsGetIamPolicyCall struct { + s *Service + project string + zone string + resource string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// GetIamPolicy: Gets the access control policy for a resource. May be +// empty if no such policy or resource exists. +func (r *AllocationsService) GetIamPolicy(project string, zone string, resource string) *AllocationsGetIamPolicyCall { + c := &AllocationsGetIamPolicyCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.zone = zone + c.resource = resource + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *AllocationsGetIamPolicyCall) Fields(s ...googleapi.Field) *AllocationsGetIamPolicyCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// IfNoneMatch sets the optional parameter which makes the operation +// fail if the object's ETag matches the given value. This is useful for +// getting updates only after the object has changed since the last +// request. Use googleapi.IsNotModified to check whether the response +// error from Do is the result of In-None-Match. +func (c *AllocationsGetIamPolicyCall) IfNoneMatch(entityTag string) *AllocationsGetIamPolicyCall { + c.ifNoneMatch_ = entityTag + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *AllocationsGetIamPolicyCall) Context(ctx context.Context) *AllocationsGetIamPolicyCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *AllocationsGetIamPolicyCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *AllocationsGetIamPolicyCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + if c.ifNoneMatch_ != "" { + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) + } + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/allocations/{resource}/getIamPolicy") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "zone": c.zone, + "resource": c.resource, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.allocations.getIamPolicy" call. +// Exactly one of *Policy or error will be non-nil. Any non-2xx status +// code is an error. Response headers are in either +// *Policy.ServerResponse.Header or (if a response was returned at all) +// in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to +// check whether the returned error was because http.StatusNotModified +// was returned. +func (c *AllocationsGetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Policy, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Policy{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Gets the access control policy for a resource. May be empty if no such policy or resource exists.", + // "httpMethod": "GET", + // "id": "compute.allocations.getIamPolicy", + // "parameterOrder": [ + // "project", + // "zone", + // "resource" + // ], + // "parameters": { + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "resource": { + // "description": "Name or id of the resource for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + // "required": true, + // "type": "string" + // }, + // "zone": { + // "description": "The name of the zone for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/zones/{zone}/allocations/{resource}/getIamPolicy", + // "response": { + // "$ref": "Policy" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute", + // "https://www.googleapis.com/auth/compute.readonly" + // ] + // } + +} + +// method id "compute.allocations.insert": + +type AllocationsInsertCall struct { + s *Service + project string + zone string + allocation *Allocation + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// Insert: Creates a new allocation. +func (r *AllocationsService) Insert(project string, zone string, allocation *Allocation) *AllocationsInsertCall { + c := &AllocationsInsertCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.zone = zone + c.allocation = allocation + return c +} + +// RequestId sets the optional parameter "requestId": An optional +// request ID to identify requests. Specify a unique request ID so that +// if you must retry your request, the server will know to ignore the +// request if it has already been completed. +// +// For example, consider a situation where you make an initial request +// and the request times out. If you make the request again with the +// same request ID, the server can check if original operation with the +// same request ID was received, and if so, will ignore the second +// request. This prevents clients from accidentally creating duplicate +// commitments. +// +// The request ID must be a valid UUID with the exception that zero UUID +// is not supported (00000000-0000-0000-0000-000000000000). +func (c *AllocationsInsertCall) RequestId(requestId string) *AllocationsInsertCall { + c.urlParams_.Set("requestId", requestId) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *AllocationsInsertCall) Fields(s ...googleapi.Field) *AllocationsInsertCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *AllocationsInsertCall) Context(ctx context.Context) *AllocationsInsertCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *AllocationsInsertCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *AllocationsInsertCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.allocation) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/allocations") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "zone": c.zone, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.allocations.insert" call. +// Exactly one of *Operation or error will be non-nil. Any non-2xx +// status code is an error. Response headers are in either +// *Operation.ServerResponse.Header or (if a response was returned at +// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified +// to check whether the returned error was because +// http.StatusNotModified was returned. +func (c *AllocationsInsertCall) Do(opts ...googleapi.CallOption) (*Operation, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Operation{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Creates a new allocation.", + // "httpMethod": "POST", + // "id": "compute.allocations.insert", + // "parameterOrder": [ + // "project", + // "zone" + // ], + // "parameters": { + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "requestId": { + // "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", + // "location": "query", + // "type": "string" + // }, + // "zone": { + // "description": "Name of the zone for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/zones/{zone}/allocations", + // "request": { + // "$ref": "Allocation" + // }, + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + +// method id "compute.allocations.list": + +type AllocationsListCall struct { + s *Service + project string + zone string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// List: A list all the allocations that have been configured for the +// specified project in specified zone. +func (r *AllocationsService) List(project string, zone string) *AllocationsListCall { + c := &AllocationsListCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.zone = zone + return c +} + +// Filter sets the optional parameter "filter": A filter expression that +// filters resources listed in the response. The expression must specify +// the field name, a comparison operator, and the value that you want to +// use for filtering. The value must be a string, a number, or a +// boolean. The comparison operator must be either =, !=, >, or <. +// +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. +// +// You can also filter nested fields. For example, you could specify +// scheduling.automaticRestart = false to include instances only if they +// are not scheduled for automatic restarts. You can use filtering on +// nested fields to filter based on resource labels. +// +// To filter on multiple expressions, provide each separate expression +// within parentheses. For example, (scheduling.automaticRestart = true) +// (cpuPlatform = "Intel Skylake"). By default, each expression is an +// AND expression. However, you can include AND and OR expressions +// explicitly. For example, (cpuPlatform = "Intel Skylake") OR +// (cpuPlatform = "Intel Broadwell") AND (scheduling.automaticRestart = +// true). +func (c *AllocationsListCall) Filter(filter string) *AllocationsListCall { + c.urlParams_.Set("filter", filter) + return c +} + +// MaxResults sets the optional parameter "maxResults": The maximum +// number of results per page that should be returned. If the number of +// available results is larger than maxResults, Compute Engine returns a +// nextPageToken that can be used to get the next page of results in +// subsequent list requests. Acceptable values are 0 to 500, inclusive. +// (Default: 500) +func (c *AllocationsListCall) MaxResults(maxResults int64) *AllocationsListCall { + c.urlParams_.Set("maxResults", fmt.Sprint(maxResults)) + return c +} + +// OrderBy sets the optional parameter "orderBy": Sorts list results by +// a certain order. By default, results are returned in alphanumerical +// order based on the resource name. +// +// You can also sort results in descending order based on the creation +// timestamp using orderBy="creationTimestamp desc". This sorts results +// based on the creationTimestamp field in reverse chronological order +// (newest result first). Use this to sort resources like operations so +// that the newest operation is returned first. +// +// Currently, only sorting by name or creationTimestamp desc is +// supported. +func (c *AllocationsListCall) OrderBy(orderBy string) *AllocationsListCall { + c.urlParams_.Set("orderBy", orderBy) + return c +} + +// PageToken sets the optional parameter "pageToken": Specifies a page +// token to use. Set pageToken to the nextPageToken returned by a +// previous list request to get the next page of results. +func (c *AllocationsListCall) PageToken(pageToken string) *AllocationsListCall { + c.urlParams_.Set("pageToken", pageToken) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *AllocationsListCall) Fields(s ...googleapi.Field) *AllocationsListCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// IfNoneMatch sets the optional parameter which makes the operation +// fail if the object's ETag matches the given value. This is useful for +// getting updates only after the object has changed since the last +// request. Use googleapi.IsNotModified to check whether the response +// error from Do is the result of In-None-Match. +func (c *AllocationsListCall) IfNoneMatch(entityTag string) *AllocationsListCall { + c.ifNoneMatch_ = entityTag + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *AllocationsListCall) Context(ctx context.Context) *AllocationsListCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *AllocationsListCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *AllocationsListCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + if c.ifNoneMatch_ != "" { + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) + } + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/allocations") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "zone": c.zone, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.allocations.list" call. +// Exactly one of *AllocationList or error will be non-nil. Any non-2xx +// status code is an error. Response headers are in either +// *AllocationList.ServerResponse.Header or (if a response was returned +// at all) in error.(*googleapi.Error).Header. Use +// googleapi.IsNotModified to check whether the returned error was +// because http.StatusNotModified was returned. +func (c *AllocationsListCall) Do(opts ...googleapi.CallOption) (*AllocationList, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &AllocationList{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "A list all the allocations that have been configured for the specified project in specified zone.", + // "httpMethod": "GET", + // "id": "compute.allocations.list", + // "parameterOrder": [ + // "project", + // "zone" + // ], + // "parameters": { + // "filter": { + // "description": "A filter expression that filters resources listed in the response. The expression must specify the field name, a comparison operator, and the value that you want to use for filtering. The value must be a string, a number, or a boolean. The comparison operator must be either =, !=, \u003e, or \u003c.\n\nFor example, if you are filtering Compute Engine instances, you can exclude instances named example-instance by specifying name != example-instance.\n\nYou can also filter nested fields. For example, you could specify scheduling.automaticRestart = false to include instances only if they are not scheduled for automatic restarts. You can use filtering on nested fields to filter based on resource labels.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart = true) (cpuPlatform = \"Intel Skylake\"). By default, each expression is an AND expression. However, you can include AND and OR expressions explicitly. For example, (cpuPlatform = \"Intel Skylake\") OR (cpuPlatform = \"Intel Broadwell\") AND (scheduling.automaticRestart = true).", + // "location": "query", + // "type": "string" + // }, + // "maxResults": { + // "default": "500", + // "description": "The maximum number of results per page that should be returned. If the number of available results is larger than maxResults, Compute Engine returns a nextPageToken that can be used to get the next page of results in subsequent list requests. Acceptable values are 0 to 500, inclusive. (Default: 500)", + // "format": "uint32", + // "location": "query", + // "minimum": "0", + // "type": "integer" + // }, + // "orderBy": { + // "description": "Sorts list results by a certain order. By default, results are returned in alphanumerical order based on the resource name.\n\nYou can also sort results in descending order based on the creation timestamp using orderBy=\"creationTimestamp desc\". This sorts results based on the creationTimestamp field in reverse chronological order (newest result first). Use this to sort resources like operations so that the newest operation is returned first.\n\nCurrently, only sorting by name or creationTimestamp desc is supported.", + // "location": "query", + // "type": "string" + // }, + // "pageToken": { + // "description": "Specifies a page token to use. Set pageToken to the nextPageToken returned by a previous list request to get the next page of results.", + // "location": "query", + // "type": "string" + // }, + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "zone": { + // "description": "Name of the zone for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/zones/{zone}/allocations", + // "response": { + // "$ref": "AllocationList" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute", + // "https://www.googleapis.com/auth/compute.readonly" + // ] + // } + +} + +// Pages invokes f for each page of results. +// A non-nil error returned from f will halt the iteration. +// The provided context supersedes any context provided to the Context method. +func (c *AllocationsListCall) Pages(ctx context.Context, f func(*AllocationList) error) error { + c.ctx_ = ctx + defer c.PageToken(c.urlParams_.Get("pageToken")) // reset paging to original point + for { + x, err := c.Do() + if err != nil { + return err + } + if err := f(x); err != nil { + return err + } + if x.NextPageToken == "" { + return nil + } + c.PageToken(x.NextPageToken) + } +} + +// method id "compute.allocations.setIamPolicy": + +type AllocationsSetIamPolicyCall struct { + s *Service + project string + zone string + resource string + zonesetpolicyrequest *ZoneSetPolicyRequest + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// SetIamPolicy: Sets the access control policy on the specified +// resource. Replaces any existing policy. +func (r *AllocationsService) SetIamPolicy(project string, zone string, resource string, zonesetpolicyrequest *ZoneSetPolicyRequest) *AllocationsSetIamPolicyCall { + c := &AllocationsSetIamPolicyCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.zone = zone + c.resource = resource + c.zonesetpolicyrequest = zonesetpolicyrequest + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *AllocationsSetIamPolicyCall) Fields(s ...googleapi.Field) *AllocationsSetIamPolicyCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *AllocationsSetIamPolicyCall) Context(ctx context.Context) *AllocationsSetIamPolicyCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *AllocationsSetIamPolicyCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *AllocationsSetIamPolicyCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.zonesetpolicyrequest) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/allocations/{resource}/setIamPolicy") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "zone": c.zone, + "resource": c.resource, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.allocations.setIamPolicy" call. +// Exactly one of *Policy or error will be non-nil. Any non-2xx status +// code is an error. Response headers are in either +// *Policy.ServerResponse.Header or (if a response was returned at all) +// in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to +// check whether the returned error was because http.StatusNotModified +// was returned. +func (c *AllocationsSetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Policy, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Policy{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Sets the access control policy on the specified resource. Replaces any existing policy.", + // "httpMethod": "POST", + // "id": "compute.allocations.setIamPolicy", + // "parameterOrder": [ + // "project", + // "zone", + // "resource" + // ], + // "parameters": { + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "resource": { + // "description": "Name or id of the resource for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + // "required": true, + // "type": "string" + // }, + // "zone": { + // "description": "The name of the zone for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/zones/{zone}/allocations/{resource}/setIamPolicy", + // "request": { + // "$ref": "ZoneSetPolicyRequest" + // }, + // "response": { + // "$ref": "Policy" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + +// method id "compute.allocations.testIamPermissions": + +type AllocationsTestIamPermissionsCall struct { + s *Service + project string + zone string + resource string + testpermissionsrequest *TestPermissionsRequest + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// TestIamPermissions: Returns permissions that a caller has on the +// specified resource. +func (r *AllocationsService) TestIamPermissions(project string, zone string, resource string, testpermissionsrequest *TestPermissionsRequest) *AllocationsTestIamPermissionsCall { + c := &AllocationsTestIamPermissionsCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.zone = zone + c.resource = resource + c.testpermissionsrequest = testpermissionsrequest + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *AllocationsTestIamPermissionsCall) Fields(s ...googleapi.Field) *AllocationsTestIamPermissionsCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *AllocationsTestIamPermissionsCall) Context(ctx context.Context) *AllocationsTestIamPermissionsCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *AllocationsTestIamPermissionsCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *AllocationsTestIamPermissionsCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.testpermissionsrequest) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/allocations/{resource}/testIamPermissions") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "zone": c.zone, + "resource": c.resource, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.allocations.testIamPermissions" call. +// Exactly one of *TestPermissionsResponse or error will be non-nil. Any +// non-2xx status code is an error. Response headers are in either +// *TestPermissionsResponse.ServerResponse.Header or (if a response was +// returned at all) in error.(*googleapi.Error).Header. Use +// googleapi.IsNotModified to check whether the returned error was +// because http.StatusNotModified was returned. +func (c *AllocationsTestIamPermissionsCall) Do(opts ...googleapi.CallOption) (*TestPermissionsResponse, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &TestPermissionsResponse{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Returns permissions that a caller has on the specified resource.", + // "httpMethod": "POST", + // "id": "compute.allocations.testIamPermissions", + // "parameterOrder": [ + // "project", + // "zone", + // "resource" + // ], + // "parameters": { + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "resource": { + // "description": "Name or id of the resource for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + // "required": true, + // "type": "string" + // }, + // "zone": { + // "description": "The name of the zone for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/zones/{zone}/allocations/{resource}/testIamPermissions", + // "request": { + // "$ref": "TestPermissionsRequest" + // }, + // "response": { + // "$ref": "TestPermissionsResponse" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute", + // "https://www.googleapis.com/auth/compute.readonly" + // ] + // } + +} + +// method id "compute.allocations.updateResourceShape": + +type AllocationsUpdateResourceShapeCall struct { + s *Service + project string + zone string + allocation string + allocationsupdateresourceshaperequest *AllocationsUpdateResourceShapeRequest + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// UpdateResourceShape: Updates the shape of an allocation. +func (r *AllocationsService) UpdateResourceShape(project string, zone string, allocation string, allocationsupdateresourceshaperequest *AllocationsUpdateResourceShapeRequest) *AllocationsUpdateResourceShapeCall { + c := &AllocationsUpdateResourceShapeCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.zone = zone + c.allocation = allocation + c.allocationsupdateresourceshaperequest = allocationsupdateresourceshaperequest + return c +} + +// RequestId sets the optional parameter "requestId": An optional +// request ID to identify requests. Specify a unique request ID so that +// if you must retry your request, the server will know to ignore the +// request if it has already been completed. +// +// For example, consider a situation where you make an initial request +// and the request times out. If you make the request again with the +// same request ID, the server can check if original operation with the +// same request ID was received, and if so, will ignore the second +// request. This prevents clients from accidentally creating duplicate +// commitments. +// +// The request ID must be a valid UUID with the exception that zero UUID +// is not supported (00000000-0000-0000-0000-000000000000). +func (c *AllocationsUpdateResourceShapeCall) RequestId(requestId string) *AllocationsUpdateResourceShapeCall { + c.urlParams_.Set("requestId", requestId) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *AllocationsUpdateResourceShapeCall) Fields(s ...googleapi.Field) *AllocationsUpdateResourceShapeCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *AllocationsUpdateResourceShapeCall) Context(ctx context.Context) *AllocationsUpdateResourceShapeCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *AllocationsUpdateResourceShapeCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *AllocationsUpdateResourceShapeCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.allocationsupdateresourceshaperequest) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/allocations/{allocation}/updateResourceShape") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "zone": c.zone, + "allocation": c.allocation, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.allocations.updateResourceShape" call. +// Exactly one of *Operation or error will be non-nil. Any non-2xx +// status code is an error. Response headers are in either +// *Operation.ServerResponse.Header or (if a response was returned at +// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified +// to check whether the returned error was because +// http.StatusNotModified was returned. +func (c *AllocationsUpdateResourceShapeCall) Do(opts ...googleapi.CallOption) (*Operation, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Operation{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Updates the shape of an allocation.", + // "httpMethod": "POST", + // "id": "compute.allocations.updateResourceShape", + // "parameterOrder": [ + // "project", + // "zone", + // "allocation" + // ], + // "parameters": { + // "allocation": { + // "description": "Name of the allocation to update.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // }, + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "requestId": { + // "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", + // "location": "query", + // "type": "string" + // }, + // "zone": { + // "description": "Name of the zone for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/zones/{zone}/allocations/{allocation}/updateResourceShape", + // "request": { + // "$ref": "AllocationsUpdateResourceShapeRequest" + // }, + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + // method id "compute.autoscalers.aggregatedList": type AutoscalersAggregatedListCall struct { @@ -38464,9 +43276,13 @@ func (c *AutoscalersAggregatedListCall) doRequest(alt string) (*http.Response, e } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/aggregated/autoscalers") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -38657,9 +43473,13 @@ func (c *AutoscalersDeleteCall) doRequest(alt string) (*http.Response, error) { reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/autoscalers/{autoscaler}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -38824,9 +43644,13 @@ func (c *AutoscalersGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/autoscalers/{autoscaler}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -38997,9 +43821,13 @@ func (c *AutoscalersInsertCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/autoscalers") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -39219,9 +44047,13 @@ func (c *AutoscalersListCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/autoscalers") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -39435,9 +44267,13 @@ func (c *AutoscalersPatchCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/autoscalers") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PATCH", urls, body) + req, err := http.NewRequest("PATCH", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -39595,9 +44431,13 @@ func (c *AutoscalersTestIamPermissionsCall) doRequest(alt string) (*http.Respons } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/autoscalers/{resource}/testIamPermissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -39662,9 +44502,9 @@ func (c *AutoscalersTestIamPermissionsCall) Do(opts ...googleapi.CallOption) (*T // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -39778,9 +44618,13 @@ func (c *AutoscalersUpdateCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/autoscalers") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PUT", urls, body) + req, err := http.NewRequest("PUT", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -39888,7 +44732,8 @@ type BackendBucketsAddSignedUrlKeyCall struct { header_ http.Header } -// AddSignedUrlKey: Adds the given Signed URL Key to the backend bucket. +// AddSignedUrlKey: Adds a key for validating requests with signed URLs +// for this backend bucket. func (r *BackendBucketsService) AddSignedUrlKey(project string, backendBucket string, signedurlkey *SignedUrlKey) *BackendBucketsAddSignedUrlKeyCall { c := &BackendBucketsAddSignedUrlKeyCall{s: r.s, urlParams_: make(gensupport.URLParams)} c.project = project @@ -39954,9 +44799,13 @@ func (c *BackendBucketsAddSignedUrlKeyCall) doRequest(alt string) (*http.Respons } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/backendBuckets/{backendBucket}/addSignedUrlKey") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -40003,7 +44852,7 @@ func (c *BackendBucketsAddSignedUrlKeyCall) Do(opts ...googleapi.CallOption) (*O } return ret, nil // { - // "description": "Adds the given Signed URL Key to the backend bucket.", + // "description": "Adds a key for validating requests with signed URLs for this backend bucket.", // "httpMethod": "POST", // "id": "compute.backendBuckets.addSignedUrlKey", // "parameterOrder": [ @@ -40116,9 +44965,13 @@ func (c *BackendBucketsDeleteCall) doRequest(alt string) (*http.Response, error) reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/backendBuckets/{backendBucket}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -40216,8 +45069,8 @@ type BackendBucketsDeleteSignedUrlKeyCall struct { header_ http.Header } -// DeleteSignedUrlKey: Deletes the given Signed URL Key from the backend -// bucket. +// DeleteSignedUrlKey: Deletes a key for validating requests with signed +// URLs for this backend bucket. func (r *BackendBucketsService) DeleteSignedUrlKey(project string, backendBucket string, keyName string) *BackendBucketsDeleteSignedUrlKeyCall { c := &BackendBucketsDeleteSignedUrlKeyCall{s: r.s, urlParams_: make(gensupport.URLParams)} c.project = project @@ -40278,9 +45131,13 @@ func (c *BackendBucketsDeleteSignedUrlKeyCall) doRequest(alt string) (*http.Resp reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/backendBuckets/{backendBucket}/deleteSignedUrlKey") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -40327,7 +45184,7 @@ func (c *BackendBucketsDeleteSignedUrlKeyCall) Do(opts ...googleapi.CallOption) } return ret, nil // { - // "description": "Deletes the given Signed URL Key from the backend bucket.", + // "description": "Deletes a key for validating requests with signed URLs for this backend bucket.", // "httpMethod": "POST", // "id": "compute.backendBuckets.deleteSignedUrlKey", // "parameterOrder": [ @@ -40440,9 +45297,13 @@ func (c *BackendBucketsGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/backendBuckets/{backendBucket}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -40592,9 +45453,13 @@ func (c *BackendBucketsGetIamPolicyCall) doRequest(alt string) (*http.Response, } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/backendBuckets/{resource}/getIamPolicy") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -40657,9 +45522,9 @@ func (c *BackendBucketsGetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Poli // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z0-9](?:[-a-z0-9_]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -40754,9 +45619,13 @@ func (c *BackendBucketsInsertCall) doRequest(alt string) (*http.Response, error) } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/backendBuckets") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -40965,9 +45834,13 @@ func (c *BackendBucketsListCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/backendBuckets") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -41165,9 +46038,13 @@ func (c *BackendBucketsPatchCall) doRequest(alt string) (*http.Response, error) } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/backendBuckets/{backendBucket}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PATCH", urls, body) + req, err := http.NewRequest("PATCH", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -41317,9 +46194,13 @@ func (c *BackendBucketsSetIamPolicyCall) doRequest(alt string) (*http.Response, } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/backendBuckets/{resource}/setIamPolicy") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -41382,9 +46263,9 @@ func (c *BackendBucketsSetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Poli // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z0-9](?:[-a-z0-9_]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -41464,9 +46345,13 @@ func (c *BackendBucketsTestIamPermissionsCall) doRequest(alt string) (*http.Resp } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/backendBuckets/{resource}/testIamPermissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -41529,9 +46414,9 @@ func (c *BackendBucketsTestIamPermissionsCall) Do(opts ...googleapi.CallOption) // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "(?:[-a-z0-9_]{0,62}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -41631,9 +46516,13 @@ func (c *BackendBucketsUpdateCall) doRequest(alt string) (*http.Response, error) } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/backendBuckets/{backendBucket}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PUT", urls, body) + req, err := http.NewRequest("PUT", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -41735,8 +46624,8 @@ type BackendServicesAddSignedUrlKeyCall struct { header_ http.Header } -// AddSignedUrlKey: Adds the given Signed URL Key to the specified -// backend service. +// AddSignedUrlKey: Adds a key for validating requests with signed URLs +// for this backend service. func (r *BackendServicesService) AddSignedUrlKey(project string, backendService string, signedurlkey *SignedUrlKey) *BackendServicesAddSignedUrlKeyCall { c := &BackendServicesAddSignedUrlKeyCall{s: r.s, urlParams_: make(gensupport.URLParams)} c.project = project @@ -41802,9 +46691,13 @@ func (c *BackendServicesAddSignedUrlKeyCall) doRequest(alt string) (*http.Respon } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/backendServices/{backendService}/addSignedUrlKey") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -41851,7 +46744,7 @@ func (c *BackendServicesAddSignedUrlKeyCall) Do(opts ...googleapi.CallOption) (* } return ret, nil // { - // "description": "Adds the given Signed URL Key to the specified backend service.", + // "description": "Adds a key for validating requests with signed URLs for this backend service.", // "httpMethod": "POST", // "id": "compute.backendServices.addSignedUrlKey", // "parameterOrder": [ @@ -42021,9 +46914,13 @@ func (c *BackendServicesAggregatedListCall) doRequest(alt string) (*http.Respons } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/aggregated/backendServices") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -42213,9 +47110,13 @@ func (c *BackendServicesDeleteCall) doRequest(alt string) (*http.Response, error reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/backendServices/{backendService}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -42313,8 +47214,8 @@ type BackendServicesDeleteSignedUrlKeyCall struct { header_ http.Header } -// DeleteSignedUrlKey: Deletes the given Signed URL Key from the -// specified backend service. +// DeleteSignedUrlKey: Deletes a key for validating requests with signed +// URLs for this backend service. func (r *BackendServicesService) DeleteSignedUrlKey(project string, backendService string, keyName string) *BackendServicesDeleteSignedUrlKeyCall { c := &BackendServicesDeleteSignedUrlKeyCall{s: r.s, urlParams_: make(gensupport.URLParams)} c.project = project @@ -42375,9 +47276,13 @@ func (c *BackendServicesDeleteSignedUrlKeyCall) doRequest(alt string) (*http.Res reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/backendServices/{backendService}/deleteSignedUrlKey") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -42424,7 +47329,7 @@ func (c *BackendServicesDeleteSignedUrlKeyCall) Do(opts ...googleapi.CallOption) } return ret, nil // { - // "description": "Deletes the given Signed URL Key from the specified backend service.", + // "description": "Deletes a key for validating requests with signed URLs for this backend service.", // "httpMethod": "POST", // "id": "compute.backendServices.deleteSignedUrlKey", // "parameterOrder": [ @@ -42483,7 +47388,7 @@ type BackendServicesGetCall struct { } // Get: Returns the specified BackendService resource. Gets a list of -// available backend services by making a list() request. +// available backend services. // For details, see https://cloud.google.com/compute/docs/reference/latest/backendServices/get func (r *BackendServicesService) Get(project string, backendService string) *BackendServicesGetCall { c := &BackendServicesGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} @@ -42538,9 +47443,13 @@ func (c *BackendServicesGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/backendServices/{backendService}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -42587,7 +47496,7 @@ func (c *BackendServicesGetCall) Do(opts ...googleapi.CallOption) (*BackendServi } return ret, nil // { - // "description": "Returns the specified BackendService resource. Gets a list of available backend services by making a list() request.", + // "description": "Returns the specified BackendService resource. Gets a list of available backend services.", // "httpMethod": "GET", // "id": "compute.backendServices.get", // "parameterOrder": [ @@ -42684,9 +47593,13 @@ func (c *BackendServicesGetHealthCall) doRequest(alt string) (*http.Response, er } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/backendServices/{backendService}/getHealth") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -42851,9 +47764,13 @@ func (c *BackendServicesInsertCall) doRequest(alt string) (*http.Response, error } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/backendServices") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -43063,9 +47980,13 @@ func (c *BackendServicesListCall) doRequest(alt string) (*http.Response, error) } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/backendServices") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -43267,9 +48188,13 @@ func (c *BackendServicesPatchCall) doRequest(alt string) (*http.Response, error) } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/backendServices/{backendService}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PATCH", urls, body) + req, err := http.NewRequest("PATCH", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -43327,7 +48252,7 @@ func (c *BackendServicesPatchCall) Do(opts ...googleapi.CallOption) (*Operation, // "backendService": { // "description": "Name of the BackendService resource to patch.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -43438,9 +48363,13 @@ func (c *BackendServicesSetSecurityPolicyCall) doRequest(alt string) (*http.Resp } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/backendServices/{backendService}/setSecurityPolicy") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -43589,9 +48518,13 @@ func (c *BackendServicesTestIamPermissionsCall) doRequest(alt string) (*http.Res } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/backendServices/{resource}/testIamPermissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -43654,9 +48587,9 @@ func (c *BackendServicesTestIamPermissionsCall) Do(opts ...googleapi.CallOption) // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "(?:[-a-z0-9_]{0,62}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -43759,9 +48692,13 @@ func (c *BackendServicesUpdateCall) doRequest(alt string) (*http.Response, error } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/backendServices/{backendService}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PUT", urls, body) + req, err := http.NewRequest("PUT", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -43979,9 +48916,13 @@ func (c *DiskTypesAggregatedListCall) doRequest(alt string) (*http.Response, err } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/aggregated/diskTypes") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -44169,9 +49110,13 @@ func (c *DiskTypesGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/diskTypes/{diskType}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -44394,9 +49339,13 @@ func (c *DiskTypesListCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/diskTypes") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -44605,9 +49554,13 @@ func (c *DisksAddResourcePoliciesCall) doRequest(alt string) (*http.Response, er } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/disks/{disk}/addResourcePolicies") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -44667,7 +49620,7 @@ func (c *DisksAddResourcePoliciesCall) Do(opts ...googleapi.CallOption) (*Operat // "disk": { // "description": "The disk name for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -44834,9 +49787,13 @@ func (c *DisksAggregatedListCall) doRequest(alt string) (*http.Response, error) } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/aggregated/disks") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -45041,9 +49998,13 @@ func (c *DisksCreateSnapshotCall) doRequest(alt string) (*http.Response, error) } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/disks/{disk}/createSnapshot") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -45103,7 +50064,7 @@ func (c *DisksCreateSnapshotCall) Do(opts ...googleapi.CallOption) (*Operation, // "disk": { // "description": "Name of the persistent disk to snapshot.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -45223,9 +50184,13 @@ func (c *DisksDeleteCall) doRequest(alt string) (*http.Response, error) { reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/disks/{disk}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -45390,9 +50355,13 @@ func (c *DisksGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/disks/{disk}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -45452,7 +50421,7 @@ func (c *DisksGetCall) Do(opts ...googleapi.CallOption) (*Disk, error) { // "disk": { // "description": "Name of the persistent disk to return.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -45553,9 +50522,13 @@ func (c *DisksGetIamPolicyCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/disks/{resource}/getIamPolicy") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -45620,9 +50593,9 @@ func (c *DisksGetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Policy, error // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -45737,9 +50710,13 @@ func (c *DisksInsertCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/disks") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -45965,9 +50942,13 @@ func (c *DisksListCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/disks") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -46174,9 +51155,13 @@ func (c *DisksRemoveResourcePoliciesCall) doRequest(alt string) (*http.Response, } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/disks/{disk}/removeResourcePolicies") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -46236,7 +51221,7 @@ func (c *DisksRemoveResourcePoliciesCall) Do(opts ...googleapi.CallOption) (*Ope // "disk": { // "description": "The disk name for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -46356,9 +51341,13 @@ func (c *DisksResizeCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/disks/{disk}/resize") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -46418,7 +51407,7 @@ func (c *DisksResizeCall) Do(opts ...googleapi.CallOption) (*Operation, error) { // "disk": { // "description": "The name of the persistent disk.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -46519,9 +51508,13 @@ func (c *DisksSetIamPolicyCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/disks/{resource}/setIamPolicy") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -46586,9 +51579,9 @@ func (c *DisksSetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Policy, error // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -46696,9 +51689,13 @@ func (c *DisksSetLabelsCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/disks/{resource}/setLabels") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -46768,9 +51765,9 @@ func (c *DisksSetLabelsCall) Do(opts ...googleapi.CallOption) (*Operation, error // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -46859,9 +51856,13 @@ func (c *DisksTestIamPermissionsCall) doRequest(alt string) (*http.Response, err } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/disks/{resource}/testIamPermissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -46926,9 +51927,9 @@ func (c *DisksTestIamPermissionsCall) Do(opts ...googleapi.CallOption) (*TestPer // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -47028,9 +52029,13 @@ func (c *FirewallsDeleteCall) doRequest(alt string) (*http.Response, error) { reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/firewalls/{firewall}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -47088,7 +52093,7 @@ func (c *FirewallsDeleteCall) Do(opts ...googleapi.CallOption) (*Operation, erro // "firewall": { // "description": "Name of the firewall rule to delete.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -47184,9 +52189,13 @@ func (c *FirewallsGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/firewalls/{firewall}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -47244,7 +52253,7 @@ func (c *FirewallsGetCall) Do(opts ...googleapi.CallOption) (*Firewall, error) { // "firewall": { // "description": "Name of the firewall rule to return.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -47347,9 +52356,13 @@ func (c *FirewallsInsertCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/firewalls") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -47559,9 +52572,13 @@ func (c *FirewallsListCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/firewalls") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -47760,9 +52777,13 @@ func (c *FirewallsPatchCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/firewalls/{firewall}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PATCH", urls, body) + req, err := http.NewRequest("PATCH", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -47820,7 +52841,7 @@ func (c *FirewallsPatchCall) Do(opts ...googleapi.CallOption) (*Operation, error // "firewall": { // "description": "Name of the firewall rule to patch.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -47912,9 +52933,13 @@ func (c *FirewallsTestIamPermissionsCall) doRequest(alt string) (*http.Response, } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/firewalls/{resource}/testIamPermissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -47977,9 +53002,9 @@ func (c *FirewallsTestIamPermissionsCall) Do(opts ...googleapi.CallOption) (*Tes // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "(?:[-a-z0-9_]{0,62}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -48082,9 +53107,13 @@ func (c *FirewallsUpdateCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/firewalls/{firewall}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PUT", urls, body) + req, err := http.NewRequest("PUT", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -48142,7 +53171,7 @@ func (c *FirewallsUpdateCall) Do(opts ...googleapi.CallOption) (*Operation, erro // "firewall": { // "description": "Name of the firewall rule to update.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -48302,9 +53331,13 @@ func (c *ForwardingRulesAggregatedListCall) doRequest(alt string) (*http.Respons } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/aggregated/forwardingRules") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -48496,9 +53529,13 @@ func (c *ForwardingRulesDeleteCall) doRequest(alt string) (*http.Response, error reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/forwardingRules/{forwardingRule}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -48663,9 +53700,13 @@ func (c *ForwardingRulesGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/forwardingRules/{forwardingRule}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -48837,9 +53878,13 @@ func (c *ForwardingRulesInsertCall) doRequest(alt string) (*http.Response, error } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/forwardingRules") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -49060,9 +54105,13 @@ func (c *ForwardingRulesListCall) doRequest(alt string) (*http.Response, error) } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/forwardingRules") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -49272,9 +54321,13 @@ func (c *ForwardingRulesPatchCall) doRequest(alt string) (*http.Response, error) } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/forwardingRules/{forwardingRule}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PATCH", urls, body) + req, err := http.NewRequest("PATCH", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -49454,9 +54507,13 @@ func (c *ForwardingRulesSetLabelsCall) doRequest(alt string) (*http.Response, er } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/forwardingRules/{resource}/setLabels") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -49533,9 +54590,9 @@ func (c *ForwardingRulesSetLabelsCall) Do(opts ...googleapi.CallOption) (*Operat // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -49637,9 +54694,13 @@ func (c *ForwardingRulesSetTargetCall) doRequest(alt string) (*http.Response, er } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/forwardingRules/{forwardingRule}/setTarget") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -49800,9 +54861,13 @@ func (c *ForwardingRulesTestIamPermissionsCall) doRequest(alt string) (*http.Res } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/forwardingRules/{resource}/testIamPermissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -49874,9 +54939,9 @@ func (c *ForwardingRulesTestIamPermissionsCall) Do(opts ...googleapi.CallOption) // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -49969,9 +55034,13 @@ func (c *GlobalAddressesDeleteCall) doRequest(alt string) (*http.Response, error reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/addresses/{address}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -50126,9 +55195,13 @@ func (c *GlobalAddressesGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/addresses/{address}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -50289,9 +55362,13 @@ func (c *GlobalAddressesInsertCall) doRequest(alt string) (*http.Response, error } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/addresses") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -50500,9 +55577,13 @@ func (c *GlobalAddressesListCall) doRequest(alt string) (*http.Response, error) } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/addresses") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -50680,9 +55761,13 @@ func (c *GlobalAddressesSetLabelsCall) doRequest(alt string) (*http.Response, er } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/addresses/{resource}/setLabels") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -50745,9 +55830,9 @@ func (c *GlobalAddressesSetLabelsCall) Do(opts ...googleapi.CallOption) (*Operat // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -50827,9 +55912,13 @@ func (c *GlobalAddressesTestIamPermissionsCall) doRequest(alt string) (*http.Res } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/addresses/{resource}/testIamPermissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -50892,9 +55981,9 @@ func (c *GlobalAddressesTestIamPermissionsCall) Do(opts ...googleapi.CallOption) // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "(?:[-a-z0-9_]{0,62}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -50987,9 +56076,13 @@ func (c *GlobalForwardingRulesDeleteCall) doRequest(alt string) (*http.Response, reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/forwardingRules/{forwardingRule}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -51144,9 +56237,13 @@ func (c *GlobalForwardingRulesGetCall) doRequest(alt string) (*http.Response, er } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/forwardingRules/{forwardingRule}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -51307,9 +56404,13 @@ func (c *GlobalForwardingRulesInsertCall) doRequest(alt string) (*http.Response, } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/forwardingRules") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -51519,9 +56620,13 @@ func (c *GlobalForwardingRulesListCall) doRequest(alt string) (*http.Response, e } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/forwardingRules") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -51720,9 +56825,13 @@ func (c *GlobalForwardingRulesPatchCall) doRequest(alt string) (*http.Response, } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/forwardingRules/{forwardingRule}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PATCH", urls, body) + req, err := http.NewRequest("PATCH", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -51872,9 +56981,13 @@ func (c *GlobalForwardingRulesSetLabelsCall) doRequest(alt string) (*http.Respon } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/forwardingRules/{resource}/setLabels") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -51937,9 +57050,9 @@ func (c *GlobalForwardingRulesSetLabelsCall) Do(opts ...googleapi.CallOption) (* // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -52039,9 +57152,13 @@ func (c *GlobalForwardingRulesSetTargetCall) doRequest(alt string) (*http.Respon } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/forwardingRules/{forwardingRule}/setTarget") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -52191,9 +57308,13 @@ func (c *GlobalForwardingRulesTestIamPermissionsCall) doRequest(alt string) (*ht } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/forwardingRules/{resource}/testIamPermissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -52256,9 +57377,9 @@ func (c *GlobalForwardingRulesTestIamPermissionsCall) Do(opts ...googleapi.CallO // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "(?:[-a-z0-9_]{0,62}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -52407,9 +57528,13 @@ func (c *GlobalOperationsAggregatedListCall) doRequest(alt string) (*http.Respon } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/aggregated/operations") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -52580,9 +57705,13 @@ func (c *GlobalOperationsDeleteCall) doRequest(alt string) (*http.Response, erro reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/operations/{operation}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -52704,9 +57833,13 @@ func (c *GlobalOperationsGetCall) doRequest(alt string) (*http.Response, error) } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/operations/{operation}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -52918,9 +58051,13 @@ func (c *GlobalOperationsListCall) doRequest(alt string) (*http.Response, error) } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/operations") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -53099,9 +58236,13 @@ func (c *GlobalOperationsWaitCall) doRequest(alt string) (*http.Response, error) reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/operations/{operation}/wait") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -53184,6 +58325,676 @@ func (c *GlobalOperationsWaitCall) Do(opts ...googleapi.CallOption) (*Operation, } +// method id "compute.globalOrganizationOperations.delete": + +type GlobalOrganizationOperationsDeleteCall struct { + s *Service + operation string + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// Delete: Deletes the specified Operations resource. +func (r *GlobalOrganizationOperationsService) Delete(operation string) *GlobalOrganizationOperationsDeleteCall { + c := &GlobalOrganizationOperationsDeleteCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.operation = operation + return c +} + +// ParentId sets the optional parameter "parentId": Parent ID for this +// request. +func (c *GlobalOrganizationOperationsDeleteCall) ParentId(parentId string) *GlobalOrganizationOperationsDeleteCall { + c.urlParams_.Set("parentId", parentId) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *GlobalOrganizationOperationsDeleteCall) Fields(s ...googleapi.Field) *GlobalOrganizationOperationsDeleteCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *GlobalOrganizationOperationsDeleteCall) Context(ctx context.Context) *GlobalOrganizationOperationsDeleteCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *GlobalOrganizationOperationsDeleteCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *GlobalOrganizationOperationsDeleteCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "locations/global/operations/{operation}") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "operation": c.operation, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.globalOrganizationOperations.delete" call. +func (c *GlobalOrganizationOperationsDeleteCall) Do(opts ...googleapi.CallOption) error { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if err != nil { + return err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return err + } + return nil + // { + // "description": "Deletes the specified Operations resource.", + // "httpMethod": "DELETE", + // "id": "compute.globalOrganizationOperations.delete", + // "parameterOrder": [ + // "operation" + // ], + // "parameters": { + // "operation": { + // "description": "Name of the Operations resource to delete.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // }, + // "parentId": { + // "description": "Parent ID for this request.", + // "location": "query", + // "type": "string" + // } + // }, + // "path": "locations/global/operations/{operation}", + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + +// method id "compute.globalOrganizationOperations.get": + +type GlobalOrganizationOperationsGetCall struct { + s *Service + operation string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// Get: Retrieves the specified Operations resource. Gets a list of +// operations by making a list() request. +func (r *GlobalOrganizationOperationsService) Get(operation string) *GlobalOrganizationOperationsGetCall { + c := &GlobalOrganizationOperationsGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.operation = operation + return c +} + +// ParentId sets the optional parameter "parentId": Parent ID for this +// request. +func (c *GlobalOrganizationOperationsGetCall) ParentId(parentId string) *GlobalOrganizationOperationsGetCall { + c.urlParams_.Set("parentId", parentId) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *GlobalOrganizationOperationsGetCall) Fields(s ...googleapi.Field) *GlobalOrganizationOperationsGetCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// IfNoneMatch sets the optional parameter which makes the operation +// fail if the object's ETag matches the given value. This is useful for +// getting updates only after the object has changed since the last +// request. Use googleapi.IsNotModified to check whether the response +// error from Do is the result of In-None-Match. +func (c *GlobalOrganizationOperationsGetCall) IfNoneMatch(entityTag string) *GlobalOrganizationOperationsGetCall { + c.ifNoneMatch_ = entityTag + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *GlobalOrganizationOperationsGetCall) Context(ctx context.Context) *GlobalOrganizationOperationsGetCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *GlobalOrganizationOperationsGetCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *GlobalOrganizationOperationsGetCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + if c.ifNoneMatch_ != "" { + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) + } + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "locations/global/operations/{operation}") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "operation": c.operation, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.globalOrganizationOperations.get" call. +// Exactly one of *Operation or error will be non-nil. Any non-2xx +// status code is an error. Response headers are in either +// *Operation.ServerResponse.Header or (if a response was returned at +// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified +// to check whether the returned error was because +// http.StatusNotModified was returned. +func (c *GlobalOrganizationOperationsGetCall) Do(opts ...googleapi.CallOption) (*Operation, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Operation{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Retrieves the specified Operations resource. Gets a list of operations by making a list() request.", + // "httpMethod": "GET", + // "id": "compute.globalOrganizationOperations.get", + // "parameterOrder": [ + // "operation" + // ], + // "parameters": { + // "operation": { + // "description": "Name of the Operations resource to return.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // }, + // "parentId": { + // "description": "Parent ID for this request.", + // "location": "query", + // "type": "string" + // } + // }, + // "path": "locations/global/operations/{operation}", + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute", + // "https://www.googleapis.com/auth/compute.readonly" + // ] + // } + +} + +// method id "compute.globalOrganizationOperations.list": + +type GlobalOrganizationOperationsListCall struct { + s *Service + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// List: Retrieves a list of Operation resources contained within the +// specified organization. +func (r *GlobalOrganizationOperationsService) List() *GlobalOrganizationOperationsListCall { + c := &GlobalOrganizationOperationsListCall{s: r.s, urlParams_: make(gensupport.URLParams)} + return c +} + +// Filter sets the optional parameter "filter": A filter expression that +// filters resources listed in the response. The expression must specify +// the field name, a comparison operator, and the value that you want to +// use for filtering. The value must be a string, a number, or a +// boolean. The comparison operator must be either =, !=, >, or <. +// +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. +// +// You can also filter nested fields. For example, you could specify +// scheduling.automaticRestart = false to include instances only if they +// are not scheduled for automatic restarts. You can use filtering on +// nested fields to filter based on resource labels. +// +// To filter on multiple expressions, provide each separate expression +// within parentheses. For example, (scheduling.automaticRestart = true) +// (cpuPlatform = "Intel Skylake"). By default, each expression is an +// AND expression. However, you can include AND and OR expressions +// explicitly. For example, (cpuPlatform = "Intel Skylake") OR +// (cpuPlatform = "Intel Broadwell") AND (scheduling.automaticRestart = +// true). +func (c *GlobalOrganizationOperationsListCall) Filter(filter string) *GlobalOrganizationOperationsListCall { + c.urlParams_.Set("filter", filter) + return c +} + +// MaxResults sets the optional parameter "maxResults": The maximum +// number of results per page that should be returned. If the number of +// available results is larger than maxResults, Compute Engine returns a +// nextPageToken that can be used to get the next page of results in +// subsequent list requests. Acceptable values are 0 to 500, inclusive. +// (Default: 500) +func (c *GlobalOrganizationOperationsListCall) MaxResults(maxResults int64) *GlobalOrganizationOperationsListCall { + c.urlParams_.Set("maxResults", fmt.Sprint(maxResults)) + return c +} + +// OrderBy sets the optional parameter "orderBy": Sorts list results by +// a certain order. By default, results are returned in alphanumerical +// order based on the resource name. +// +// You can also sort results in descending order based on the creation +// timestamp using orderBy="creationTimestamp desc". This sorts results +// based on the creationTimestamp field in reverse chronological order +// (newest result first). Use this to sort resources like operations so +// that the newest operation is returned first. +// +// Currently, only sorting by name or creationTimestamp desc is +// supported. +func (c *GlobalOrganizationOperationsListCall) OrderBy(orderBy string) *GlobalOrganizationOperationsListCall { + c.urlParams_.Set("orderBy", orderBy) + return c +} + +// PageToken sets the optional parameter "pageToken": Specifies a page +// token to use. Set pageToken to the nextPageToken returned by a +// previous list request to get the next page of results. +func (c *GlobalOrganizationOperationsListCall) PageToken(pageToken string) *GlobalOrganizationOperationsListCall { + c.urlParams_.Set("pageToken", pageToken) + return c +} + +// ParentId sets the optional parameter "parentId": Parent ID for this +// request. +func (c *GlobalOrganizationOperationsListCall) ParentId(parentId string) *GlobalOrganizationOperationsListCall { + c.urlParams_.Set("parentId", parentId) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *GlobalOrganizationOperationsListCall) Fields(s ...googleapi.Field) *GlobalOrganizationOperationsListCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// IfNoneMatch sets the optional parameter which makes the operation +// fail if the object's ETag matches the given value. This is useful for +// getting updates only after the object has changed since the last +// request. Use googleapi.IsNotModified to check whether the response +// error from Do is the result of In-None-Match. +func (c *GlobalOrganizationOperationsListCall) IfNoneMatch(entityTag string) *GlobalOrganizationOperationsListCall { + c.ifNoneMatch_ = entityTag + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *GlobalOrganizationOperationsListCall) Context(ctx context.Context) *GlobalOrganizationOperationsListCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *GlobalOrganizationOperationsListCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *GlobalOrganizationOperationsListCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + if c.ifNoneMatch_ != "" { + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) + } + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "locations/global/operations") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.globalOrganizationOperations.list" call. +// Exactly one of *OperationList or error will be non-nil. Any non-2xx +// status code is an error. Response headers are in either +// *OperationList.ServerResponse.Header or (if a response was returned +// at all) in error.(*googleapi.Error).Header. Use +// googleapi.IsNotModified to check whether the returned error was +// because http.StatusNotModified was returned. +func (c *GlobalOrganizationOperationsListCall) Do(opts ...googleapi.CallOption) (*OperationList, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &OperationList{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Retrieves a list of Operation resources contained within the specified organization.", + // "httpMethod": "GET", + // "id": "compute.globalOrganizationOperations.list", + // "parameters": { + // "filter": { + // "description": "A filter expression that filters resources listed in the response. The expression must specify the field name, a comparison operator, and the value that you want to use for filtering. The value must be a string, a number, or a boolean. The comparison operator must be either =, !=, \u003e, or \u003c.\n\nFor example, if you are filtering Compute Engine instances, you can exclude instances named example-instance by specifying name != example-instance.\n\nYou can also filter nested fields. For example, you could specify scheduling.automaticRestart = false to include instances only if they are not scheduled for automatic restarts. You can use filtering on nested fields to filter based on resource labels.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart = true) (cpuPlatform = \"Intel Skylake\"). By default, each expression is an AND expression. However, you can include AND and OR expressions explicitly. For example, (cpuPlatform = \"Intel Skylake\") OR (cpuPlatform = \"Intel Broadwell\") AND (scheduling.automaticRestart = true).", + // "location": "query", + // "type": "string" + // }, + // "maxResults": { + // "default": "500", + // "description": "The maximum number of results per page that should be returned. If the number of available results is larger than maxResults, Compute Engine returns a nextPageToken that can be used to get the next page of results in subsequent list requests. Acceptable values are 0 to 500, inclusive. (Default: 500)", + // "format": "uint32", + // "location": "query", + // "minimum": "0", + // "type": "integer" + // }, + // "orderBy": { + // "description": "Sorts list results by a certain order. By default, results are returned in alphanumerical order based on the resource name.\n\nYou can also sort results in descending order based on the creation timestamp using orderBy=\"creationTimestamp desc\". This sorts results based on the creationTimestamp field in reverse chronological order (newest result first). Use this to sort resources like operations so that the newest operation is returned first.\n\nCurrently, only sorting by name or creationTimestamp desc is supported.", + // "location": "query", + // "type": "string" + // }, + // "pageToken": { + // "description": "Specifies a page token to use. Set pageToken to the nextPageToken returned by a previous list request to get the next page of results.", + // "location": "query", + // "type": "string" + // }, + // "parentId": { + // "description": "Parent ID for this request.", + // "location": "query", + // "type": "string" + // } + // }, + // "path": "locations/global/operations", + // "response": { + // "$ref": "OperationList" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute", + // "https://www.googleapis.com/auth/compute.readonly" + // ] + // } + +} + +// Pages invokes f for each page of results. +// A non-nil error returned from f will halt the iteration. +// The provided context supersedes any context provided to the Context method. +func (c *GlobalOrganizationOperationsListCall) Pages(ctx context.Context, f func(*OperationList) error) error { + c.ctx_ = ctx + defer c.PageToken(c.urlParams_.Get("pageToken")) // reset paging to original point + for { + x, err := c.Do() + if err != nil { + return err + } + if err := f(x); err != nil { + return err + } + if x.NextPageToken == "" { + return nil + } + c.PageToken(x.NextPageToken) + } +} + +// method id "compute.globalOrganizationOperations.wait": + +type GlobalOrganizationOperationsWaitCall struct { + s *Service + operation string + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// Wait: Waits for the specified Operations resource until it is done or +// timeout, and retrieves the specified Operations resource. 1. +// Immediately returns when the operation is already done. 2. Waits for +// no more than the default deadline (2 minutes, subject to change) and +// then returns the current state of the operation, which may be DONE or +// still in progress. 3. Is best-effort: a. The server can wait less +// than the default deadline or zero seconds, in overload situations. b. +// There is no guarantee that the operation is actually done when +// returns. 4. User should be prepared to retry if the operation is not +// DONE. +func (r *GlobalOrganizationOperationsService) Wait(operation string) *GlobalOrganizationOperationsWaitCall { + c := &GlobalOrganizationOperationsWaitCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.operation = operation + return c +} + +// ParentId sets the optional parameter "parentId": Parent ID for this +// request. +func (c *GlobalOrganizationOperationsWaitCall) ParentId(parentId string) *GlobalOrganizationOperationsWaitCall { + c.urlParams_.Set("parentId", parentId) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *GlobalOrganizationOperationsWaitCall) Fields(s ...googleapi.Field) *GlobalOrganizationOperationsWaitCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *GlobalOrganizationOperationsWaitCall) Context(ctx context.Context) *GlobalOrganizationOperationsWaitCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *GlobalOrganizationOperationsWaitCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *GlobalOrganizationOperationsWaitCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "locations/global/operations/{operation}/wait") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "operation": c.operation, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.globalOrganizationOperations.wait" call. +// Exactly one of *Operation or error will be non-nil. Any non-2xx +// status code is an error. Response headers are in either +// *Operation.ServerResponse.Header or (if a response was returned at +// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified +// to check whether the returned error was because +// http.StatusNotModified was returned. +func (c *GlobalOrganizationOperationsWaitCall) Do(opts ...googleapi.CallOption) (*Operation, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Operation{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Waits for the specified Operations resource until it is done or timeout, and retrieves the specified Operations resource. 1. Immediately returns when the operation is already done. 2. Waits for no more than the default deadline (2 minutes, subject to change) and then returns the current state of the operation, which may be DONE or still in progress. 3. Is best-effort: a. The server can wait less than the default deadline or zero seconds, in overload situations. b. There is no guarantee that the operation is actually done when returns. 4. User should be prepared to retry if the operation is not DONE.", + // "httpMethod": "POST", + // "id": "compute.globalOrganizationOperations.wait", + // "parameterOrder": [ + // "operation" + // ], + // "parameters": { + // "operation": { + // "description": "Name of the Operations resource to return.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // }, + // "parentId": { + // "description": "Parent ID for this request.", + // "location": "query", + // "type": "string" + // } + // }, + // "path": "locations/global/operations/{operation}/wait", + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute", + // "https://www.googleapis.com/auth/compute.readonly" + // ] + // } + +} + // method id "compute.healthChecks.aggregatedList": type HealthChecksAggregatedListCall struct { @@ -53312,9 +59123,13 @@ func (c *HealthChecksAggregatedListCall) doRequest(alt string) (*http.Response, } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/aggregated/healthChecks") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -53503,9 +59318,13 @@ func (c *HealthChecksDeleteCall) doRequest(alt string) (*http.Response, error) { reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/healthChecks/{healthCheck}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -53659,9 +59478,13 @@ func (c *HealthChecksGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/healthChecks/{healthCheck}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -53821,9 +59644,13 @@ func (c *HealthChecksInsertCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/healthChecks") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -54032,9 +59859,13 @@ func (c *HealthChecksListCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/healthChecks") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -54232,9 +60063,13 @@ func (c *HealthChecksPatchCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/healthChecks/{healthCheck}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PATCH", urls, body) + req, err := http.NewRequest("PATCH", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -54384,9 +60219,13 @@ func (c *HealthChecksTestIamPermissionsCall) doRequest(alt string) (*http.Respon } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/healthChecks/{resource}/testIamPermissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -54449,9 +60288,9 @@ func (c *HealthChecksTestIamPermissionsCall) Do(opts ...googleapi.CallOption) (* // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "(?:[-a-z0-9_]{0,62}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -54551,9 +60390,13 @@ func (c *HealthChecksUpdateCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/healthChecks/{healthCheck}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PUT", urls, body) + req, err := http.NewRequest("PUT", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -54643,2165 +60486,6 @@ func (c *HealthChecksUpdateCall) Do(opts ...googleapi.CallOption) (*Operation, e } -// method id "compute.hostTypes.aggregatedList": - -type HostTypesAggregatedListCall struct { - s *Service - project string - urlParams_ gensupport.URLParams - ifNoneMatch_ string - ctx_ context.Context - header_ http.Header -} - -// AggregatedList: Retrieves an aggregated list of host types. -func (r *HostTypesService) AggregatedList(project string) *HostTypesAggregatedListCall { - c := &HostTypesAggregatedListCall{s: r.s, urlParams_: make(gensupport.URLParams)} - c.project = project - return c -} - -// Filter sets the optional parameter "filter": A filter expression that -// filters resources listed in the response. The expression must specify -// the field name, a comparison operator, and the value that you want to -// use for filtering. The value must be a string, a number, or a -// boolean. The comparison operator must be either =, !=, >, or <. -// -// For example, if you are filtering Compute Engine instances, you can -// exclude instances named example-instance by specifying name != -// example-instance. -// -// You can also filter nested fields. For example, you could specify -// scheduling.automaticRestart = false to include instances only if they -// are not scheduled for automatic restarts. You can use filtering on -// nested fields to filter based on resource labels. -// -// To filter on multiple expressions, provide each separate expression -// within parentheses. For example, (scheduling.automaticRestart = true) -// (cpuPlatform = "Intel Skylake"). By default, each expression is an -// AND expression. However, you can include AND and OR expressions -// explicitly. For example, (cpuPlatform = "Intel Skylake") OR -// (cpuPlatform = "Intel Broadwell") AND (scheduling.automaticRestart = -// true). -func (c *HostTypesAggregatedListCall) Filter(filter string) *HostTypesAggregatedListCall { - c.urlParams_.Set("filter", filter) - return c -} - -// MaxResults sets the optional parameter "maxResults": The maximum -// number of results per page that should be returned. If the number of -// available results is larger than maxResults, Compute Engine returns a -// nextPageToken that can be used to get the next page of results in -// subsequent list requests. Acceptable values are 0 to 500, inclusive. -// (Default: 500) -func (c *HostTypesAggregatedListCall) MaxResults(maxResults int64) *HostTypesAggregatedListCall { - c.urlParams_.Set("maxResults", fmt.Sprint(maxResults)) - return c -} - -// OrderBy sets the optional parameter "orderBy": Sorts list results by -// a certain order. By default, results are returned in alphanumerical -// order based on the resource name. -// -// You can also sort results in descending order based on the creation -// timestamp using orderBy="creationTimestamp desc". This sorts results -// based on the creationTimestamp field in reverse chronological order -// (newest result first). Use this to sort resources like operations so -// that the newest operation is returned first. -// -// Currently, only sorting by name or creationTimestamp desc is -// supported. -func (c *HostTypesAggregatedListCall) OrderBy(orderBy string) *HostTypesAggregatedListCall { - c.urlParams_.Set("orderBy", orderBy) - return c -} - -// PageToken sets the optional parameter "pageToken": Specifies a page -// token to use. Set pageToken to the nextPageToken returned by a -// previous list request to get the next page of results. -func (c *HostTypesAggregatedListCall) PageToken(pageToken string) *HostTypesAggregatedListCall { - c.urlParams_.Set("pageToken", pageToken) - return c -} - -// Fields allows partial responses to be retrieved. See -// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse -// for more information. -func (c *HostTypesAggregatedListCall) Fields(s ...googleapi.Field) *HostTypesAggregatedListCall { - c.urlParams_.Set("fields", googleapi.CombineFields(s)) - return c -} - -// IfNoneMatch sets the optional parameter which makes the operation -// fail if the object's ETag matches the given value. This is useful for -// getting updates only after the object has changed since the last -// request. Use googleapi.IsNotModified to check whether the response -// error from Do is the result of In-None-Match. -func (c *HostTypesAggregatedListCall) IfNoneMatch(entityTag string) *HostTypesAggregatedListCall { - c.ifNoneMatch_ = entityTag - return c -} - -// Context sets the context to be used in this call's Do method. Any -// pending HTTP request will be aborted if the provided context is -// canceled. -func (c *HostTypesAggregatedListCall) Context(ctx context.Context) *HostTypesAggregatedListCall { - c.ctx_ = ctx - return c -} - -// Header returns an http.Header that can be modified by the caller to -// add HTTP headers to the request. -func (c *HostTypesAggregatedListCall) Header() http.Header { - if c.header_ == nil { - c.header_ = make(http.Header) - } - return c.header_ -} - -func (c *HostTypesAggregatedListCall) doRequest(alt string) (*http.Response, error) { - reqHeaders := make(http.Header) - for k, v := range c.header_ { - reqHeaders[k] = v - } - reqHeaders.Set("User-Agent", c.s.userAgent()) - if c.ifNoneMatch_ != "" { - reqHeaders.Set("If-None-Match", c.ifNoneMatch_) - } - var body io.Reader = nil - c.urlParams_.Set("alt", alt) - urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/aggregated/hostTypes") - urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) - req.Header = reqHeaders - googleapi.Expand(req.URL, map[string]string{ - "project": c.project, - }) - return gensupport.SendRequest(c.ctx_, c.s.client, req) -} - -// Do executes the "compute.hostTypes.aggregatedList" call. -// Exactly one of *HostTypeAggregatedList or error will be non-nil. Any -// non-2xx status code is an error. Response headers are in either -// *HostTypeAggregatedList.ServerResponse.Header or (if a response was -// returned at all) in error.(*googleapi.Error).Header. Use -// googleapi.IsNotModified to check whether the returned error was -// because http.StatusNotModified was returned. -func (c *HostTypesAggregatedListCall) Do(opts ...googleapi.CallOption) (*HostTypeAggregatedList, error) { - gensupport.SetOptions(c.urlParams_, opts...) - res, err := c.doRequest("json") - if res != nil && res.StatusCode == http.StatusNotModified { - if res.Body != nil { - res.Body.Close() - } - return nil, &googleapi.Error{ - Code: res.StatusCode, - Header: res.Header, - } - } - if err != nil { - return nil, err - } - defer googleapi.CloseBody(res) - if err := googleapi.CheckResponse(res); err != nil { - return nil, err - } - ret := &HostTypeAggregatedList{ - ServerResponse: googleapi.ServerResponse{ - Header: res.Header, - HTTPStatusCode: res.StatusCode, - }, - } - target := &ret - if err := gensupport.DecodeResponse(target, res); err != nil { - return nil, err - } - return ret, nil - // { - // "description": "Retrieves an aggregated list of host types.", - // "httpMethod": "GET", - // "id": "compute.hostTypes.aggregatedList", - // "parameterOrder": [ - // "project" - // ], - // "parameters": { - // "filter": { - // "description": "A filter expression that filters resources listed in the response. The expression must specify the field name, a comparison operator, and the value that you want to use for filtering. The value must be a string, a number, or a boolean. The comparison operator must be either =, !=, \u003e, or \u003c.\n\nFor example, if you are filtering Compute Engine instances, you can exclude instances named example-instance by specifying name != example-instance.\n\nYou can also filter nested fields. For example, you could specify scheduling.automaticRestart = false to include instances only if they are not scheduled for automatic restarts. You can use filtering on nested fields to filter based on resource labels.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart = true) (cpuPlatform = \"Intel Skylake\"). By default, each expression is an AND expression. However, you can include AND and OR expressions explicitly. For example, (cpuPlatform = \"Intel Skylake\") OR (cpuPlatform = \"Intel Broadwell\") AND (scheduling.automaticRestart = true).", - // "location": "query", - // "type": "string" - // }, - // "maxResults": { - // "default": "500", - // "description": "The maximum number of results per page that should be returned. If the number of available results is larger than maxResults, Compute Engine returns a nextPageToken that can be used to get the next page of results in subsequent list requests. Acceptable values are 0 to 500, inclusive. (Default: 500)", - // "format": "uint32", - // "location": "query", - // "minimum": "0", - // "type": "integer" - // }, - // "orderBy": { - // "description": "Sorts list results by a certain order. By default, results are returned in alphanumerical order based on the resource name.\n\nYou can also sort results in descending order based on the creation timestamp using orderBy=\"creationTimestamp desc\". This sorts results based on the creationTimestamp field in reverse chronological order (newest result first). Use this to sort resources like operations so that the newest operation is returned first.\n\nCurrently, only sorting by name or creationTimestamp desc is supported.", - // "location": "query", - // "type": "string" - // }, - // "pageToken": { - // "description": "Specifies a page token to use. Set pageToken to the nextPageToken returned by a previous list request to get the next page of results.", - // "location": "query", - // "type": "string" - // }, - // "project": { - // "description": "Project ID for this request.", - // "location": "path", - // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", - // "required": true, - // "type": "string" - // } - // }, - // "path": "{project}/aggregated/hostTypes", - // "response": { - // "$ref": "HostTypeAggregatedList" - // }, - // "scopes": [ - // "https://www.googleapis.com/auth/cloud-platform", - // "https://www.googleapis.com/auth/compute", - // "https://www.googleapis.com/auth/compute.readonly" - // ] - // } - -} - -// Pages invokes f for each page of results. -// A non-nil error returned from f will halt the iteration. -// The provided context supersedes any context provided to the Context method. -func (c *HostTypesAggregatedListCall) Pages(ctx context.Context, f func(*HostTypeAggregatedList) error) error { - c.ctx_ = ctx - defer c.PageToken(c.urlParams_.Get("pageToken")) // reset paging to original point - for { - x, err := c.Do() - if err != nil { - return err - } - if err := f(x); err != nil { - return err - } - if x.NextPageToken == "" { - return nil - } - c.PageToken(x.NextPageToken) - } -} - -// method id "compute.hostTypes.get": - -type HostTypesGetCall struct { - s *Service - project string - zone string - hostType string - urlParams_ gensupport.URLParams - ifNoneMatch_ string - ctx_ context.Context - header_ http.Header -} - -// Get: Returns the specified host type. Gets a list of available host -// types by making a list() request. -func (r *HostTypesService) Get(project string, zone string, hostType string) *HostTypesGetCall { - c := &HostTypesGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} - c.project = project - c.zone = zone - c.hostType = hostType - return c -} - -// Fields allows partial responses to be retrieved. See -// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse -// for more information. -func (c *HostTypesGetCall) Fields(s ...googleapi.Field) *HostTypesGetCall { - c.urlParams_.Set("fields", googleapi.CombineFields(s)) - return c -} - -// IfNoneMatch sets the optional parameter which makes the operation -// fail if the object's ETag matches the given value. This is useful for -// getting updates only after the object has changed since the last -// request. Use googleapi.IsNotModified to check whether the response -// error from Do is the result of In-None-Match. -func (c *HostTypesGetCall) IfNoneMatch(entityTag string) *HostTypesGetCall { - c.ifNoneMatch_ = entityTag - return c -} - -// Context sets the context to be used in this call's Do method. Any -// pending HTTP request will be aborted if the provided context is -// canceled. -func (c *HostTypesGetCall) Context(ctx context.Context) *HostTypesGetCall { - c.ctx_ = ctx - return c -} - -// Header returns an http.Header that can be modified by the caller to -// add HTTP headers to the request. -func (c *HostTypesGetCall) Header() http.Header { - if c.header_ == nil { - c.header_ = make(http.Header) - } - return c.header_ -} - -func (c *HostTypesGetCall) doRequest(alt string) (*http.Response, error) { - reqHeaders := make(http.Header) - for k, v := range c.header_ { - reqHeaders[k] = v - } - reqHeaders.Set("User-Agent", c.s.userAgent()) - if c.ifNoneMatch_ != "" { - reqHeaders.Set("If-None-Match", c.ifNoneMatch_) - } - var body io.Reader = nil - c.urlParams_.Set("alt", alt) - urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/hostTypes/{hostType}") - urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) - req.Header = reqHeaders - googleapi.Expand(req.URL, map[string]string{ - "project": c.project, - "zone": c.zone, - "hostType": c.hostType, - }) - return gensupport.SendRequest(c.ctx_, c.s.client, req) -} - -// Do executes the "compute.hostTypes.get" call. -// Exactly one of *HostType or error will be non-nil. Any non-2xx status -// code is an error. Response headers are in either -// *HostType.ServerResponse.Header or (if a response was returned at -// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified -// to check whether the returned error was because -// http.StatusNotModified was returned. -func (c *HostTypesGetCall) Do(opts ...googleapi.CallOption) (*HostType, error) { - gensupport.SetOptions(c.urlParams_, opts...) - res, err := c.doRequest("json") - if res != nil && res.StatusCode == http.StatusNotModified { - if res.Body != nil { - res.Body.Close() - } - return nil, &googleapi.Error{ - Code: res.StatusCode, - Header: res.Header, - } - } - if err != nil { - return nil, err - } - defer googleapi.CloseBody(res) - if err := googleapi.CheckResponse(res); err != nil { - return nil, err - } - ret := &HostType{ - ServerResponse: googleapi.ServerResponse{ - Header: res.Header, - HTTPStatusCode: res.StatusCode, - }, - } - target := &ret - if err := gensupport.DecodeResponse(target, res); err != nil { - return nil, err - } - return ret, nil - // { - // "description": "Returns the specified host type. Gets a list of available host types by making a list() request.", - // "httpMethod": "GET", - // "id": "compute.hostTypes.get", - // "parameterOrder": [ - // "project", - // "zone", - // "hostType" - // ], - // "parameters": { - // "hostType": { - // "description": "Name of the host type to return.", - // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", - // "required": true, - // "type": "string" - // }, - // "project": { - // "description": "Project ID for this request.", - // "location": "path", - // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", - // "required": true, - // "type": "string" - // }, - // "zone": { - // "description": "The name of the zone for this request.", - // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", - // "required": true, - // "type": "string" - // } - // }, - // "path": "{project}/zones/{zone}/hostTypes/{hostType}", - // "response": { - // "$ref": "HostType" - // }, - // "scopes": [ - // "https://www.googleapis.com/auth/cloud-platform", - // "https://www.googleapis.com/auth/compute", - // "https://www.googleapis.com/auth/compute.readonly" - // ] - // } - -} - -// method id "compute.hostTypes.list": - -type HostTypesListCall struct { - s *Service - project string - zone string - urlParams_ gensupport.URLParams - ifNoneMatch_ string - ctx_ context.Context - header_ http.Header -} - -// List: Retrieves a list of host types available to the specified -// project. -func (r *HostTypesService) List(project string, zone string) *HostTypesListCall { - c := &HostTypesListCall{s: r.s, urlParams_: make(gensupport.URLParams)} - c.project = project - c.zone = zone - return c -} - -// Filter sets the optional parameter "filter": A filter expression that -// filters resources listed in the response. The expression must specify -// the field name, a comparison operator, and the value that you want to -// use for filtering. The value must be a string, a number, or a -// boolean. The comparison operator must be either =, !=, >, or <. -// -// For example, if you are filtering Compute Engine instances, you can -// exclude instances named example-instance by specifying name != -// example-instance. -// -// You can also filter nested fields. For example, you could specify -// scheduling.automaticRestart = false to include instances only if they -// are not scheduled for automatic restarts. You can use filtering on -// nested fields to filter based on resource labels. -// -// To filter on multiple expressions, provide each separate expression -// within parentheses. For example, (scheduling.automaticRestart = true) -// (cpuPlatform = "Intel Skylake"). By default, each expression is an -// AND expression. However, you can include AND and OR expressions -// explicitly. For example, (cpuPlatform = "Intel Skylake") OR -// (cpuPlatform = "Intel Broadwell") AND (scheduling.automaticRestart = -// true). -func (c *HostTypesListCall) Filter(filter string) *HostTypesListCall { - c.urlParams_.Set("filter", filter) - return c -} - -// MaxResults sets the optional parameter "maxResults": The maximum -// number of results per page that should be returned. If the number of -// available results is larger than maxResults, Compute Engine returns a -// nextPageToken that can be used to get the next page of results in -// subsequent list requests. Acceptable values are 0 to 500, inclusive. -// (Default: 500) -func (c *HostTypesListCall) MaxResults(maxResults int64) *HostTypesListCall { - c.urlParams_.Set("maxResults", fmt.Sprint(maxResults)) - return c -} - -// OrderBy sets the optional parameter "orderBy": Sorts list results by -// a certain order. By default, results are returned in alphanumerical -// order based on the resource name. -// -// You can also sort results in descending order based on the creation -// timestamp using orderBy="creationTimestamp desc". This sorts results -// based on the creationTimestamp field in reverse chronological order -// (newest result first). Use this to sort resources like operations so -// that the newest operation is returned first. -// -// Currently, only sorting by name or creationTimestamp desc is -// supported. -func (c *HostTypesListCall) OrderBy(orderBy string) *HostTypesListCall { - c.urlParams_.Set("orderBy", orderBy) - return c -} - -// PageToken sets the optional parameter "pageToken": Specifies a page -// token to use. Set pageToken to the nextPageToken returned by a -// previous list request to get the next page of results. -func (c *HostTypesListCall) PageToken(pageToken string) *HostTypesListCall { - c.urlParams_.Set("pageToken", pageToken) - return c -} - -// Fields allows partial responses to be retrieved. See -// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse -// for more information. -func (c *HostTypesListCall) Fields(s ...googleapi.Field) *HostTypesListCall { - c.urlParams_.Set("fields", googleapi.CombineFields(s)) - return c -} - -// IfNoneMatch sets the optional parameter which makes the operation -// fail if the object's ETag matches the given value. This is useful for -// getting updates only after the object has changed since the last -// request. Use googleapi.IsNotModified to check whether the response -// error from Do is the result of In-None-Match. -func (c *HostTypesListCall) IfNoneMatch(entityTag string) *HostTypesListCall { - c.ifNoneMatch_ = entityTag - return c -} - -// Context sets the context to be used in this call's Do method. Any -// pending HTTP request will be aborted if the provided context is -// canceled. -func (c *HostTypesListCall) Context(ctx context.Context) *HostTypesListCall { - c.ctx_ = ctx - return c -} - -// Header returns an http.Header that can be modified by the caller to -// add HTTP headers to the request. -func (c *HostTypesListCall) Header() http.Header { - if c.header_ == nil { - c.header_ = make(http.Header) - } - return c.header_ -} - -func (c *HostTypesListCall) doRequest(alt string) (*http.Response, error) { - reqHeaders := make(http.Header) - for k, v := range c.header_ { - reqHeaders[k] = v - } - reqHeaders.Set("User-Agent", c.s.userAgent()) - if c.ifNoneMatch_ != "" { - reqHeaders.Set("If-None-Match", c.ifNoneMatch_) - } - var body io.Reader = nil - c.urlParams_.Set("alt", alt) - urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/hostTypes") - urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) - req.Header = reqHeaders - googleapi.Expand(req.URL, map[string]string{ - "project": c.project, - "zone": c.zone, - }) - return gensupport.SendRequest(c.ctx_, c.s.client, req) -} - -// Do executes the "compute.hostTypes.list" call. -// Exactly one of *HostTypeList or error will be non-nil. Any non-2xx -// status code is an error. Response headers are in either -// *HostTypeList.ServerResponse.Header or (if a response was returned at -// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified -// to check whether the returned error was because -// http.StatusNotModified was returned. -func (c *HostTypesListCall) Do(opts ...googleapi.CallOption) (*HostTypeList, error) { - gensupport.SetOptions(c.urlParams_, opts...) - res, err := c.doRequest("json") - if res != nil && res.StatusCode == http.StatusNotModified { - if res.Body != nil { - res.Body.Close() - } - return nil, &googleapi.Error{ - Code: res.StatusCode, - Header: res.Header, - } - } - if err != nil { - return nil, err - } - defer googleapi.CloseBody(res) - if err := googleapi.CheckResponse(res); err != nil { - return nil, err - } - ret := &HostTypeList{ - ServerResponse: googleapi.ServerResponse{ - Header: res.Header, - HTTPStatusCode: res.StatusCode, - }, - } - target := &ret - if err := gensupport.DecodeResponse(target, res); err != nil { - return nil, err - } - return ret, nil - // { - // "description": "Retrieves a list of host types available to the specified project.", - // "httpMethod": "GET", - // "id": "compute.hostTypes.list", - // "parameterOrder": [ - // "project", - // "zone" - // ], - // "parameters": { - // "filter": { - // "description": "A filter expression that filters resources listed in the response. The expression must specify the field name, a comparison operator, and the value that you want to use for filtering. The value must be a string, a number, or a boolean. The comparison operator must be either =, !=, \u003e, or \u003c.\n\nFor example, if you are filtering Compute Engine instances, you can exclude instances named example-instance by specifying name != example-instance.\n\nYou can also filter nested fields. For example, you could specify scheduling.automaticRestart = false to include instances only if they are not scheduled for automatic restarts. You can use filtering on nested fields to filter based on resource labels.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart = true) (cpuPlatform = \"Intel Skylake\"). By default, each expression is an AND expression. However, you can include AND and OR expressions explicitly. For example, (cpuPlatform = \"Intel Skylake\") OR (cpuPlatform = \"Intel Broadwell\") AND (scheduling.automaticRestart = true).", - // "location": "query", - // "type": "string" - // }, - // "maxResults": { - // "default": "500", - // "description": "The maximum number of results per page that should be returned. If the number of available results is larger than maxResults, Compute Engine returns a nextPageToken that can be used to get the next page of results in subsequent list requests. Acceptable values are 0 to 500, inclusive. (Default: 500)", - // "format": "uint32", - // "location": "query", - // "minimum": "0", - // "type": "integer" - // }, - // "orderBy": { - // "description": "Sorts list results by a certain order. By default, results are returned in alphanumerical order based on the resource name.\n\nYou can also sort results in descending order based on the creation timestamp using orderBy=\"creationTimestamp desc\". This sorts results based on the creationTimestamp field in reverse chronological order (newest result first). Use this to sort resources like operations so that the newest operation is returned first.\n\nCurrently, only sorting by name or creationTimestamp desc is supported.", - // "location": "query", - // "type": "string" - // }, - // "pageToken": { - // "description": "Specifies a page token to use. Set pageToken to the nextPageToken returned by a previous list request to get the next page of results.", - // "location": "query", - // "type": "string" - // }, - // "project": { - // "description": "Project ID for this request.", - // "location": "path", - // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", - // "required": true, - // "type": "string" - // }, - // "zone": { - // "description": "The name of the zone for this request.", - // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", - // "required": true, - // "type": "string" - // } - // }, - // "path": "{project}/zones/{zone}/hostTypes", - // "response": { - // "$ref": "HostTypeList" - // }, - // "scopes": [ - // "https://www.googleapis.com/auth/cloud-platform", - // "https://www.googleapis.com/auth/compute", - // "https://www.googleapis.com/auth/compute.readonly" - // ] - // } - -} - -// Pages invokes f for each page of results. -// A non-nil error returned from f will halt the iteration. -// The provided context supersedes any context provided to the Context method. -func (c *HostTypesListCall) Pages(ctx context.Context, f func(*HostTypeList) error) error { - c.ctx_ = ctx - defer c.PageToken(c.urlParams_.Get("pageToken")) // reset paging to original point - for { - x, err := c.Do() - if err != nil { - return err - } - if err := f(x); err != nil { - return err - } - if x.NextPageToken == "" { - return nil - } - c.PageToken(x.NextPageToken) - } -} - -// method id "compute.hosts.aggregatedList": - -type HostsAggregatedListCall struct { - s *Service - project string - urlParams_ gensupport.URLParams - ifNoneMatch_ string - ctx_ context.Context - header_ http.Header -} - -// AggregatedList: Retrieves an aggregated list of hosts. -func (r *HostsService) AggregatedList(project string) *HostsAggregatedListCall { - c := &HostsAggregatedListCall{s: r.s, urlParams_: make(gensupport.URLParams)} - c.project = project - return c -} - -// Filter sets the optional parameter "filter": A filter expression that -// filters resources listed in the response. The expression must specify -// the field name, a comparison operator, and the value that you want to -// use for filtering. The value must be a string, a number, or a -// boolean. The comparison operator must be either =, !=, >, or <. -// -// For example, if you are filtering Compute Engine instances, you can -// exclude instances named example-instance by specifying name != -// example-instance. -// -// You can also filter nested fields. For example, you could specify -// scheduling.automaticRestart = false to include instances only if they -// are not scheduled for automatic restarts. You can use filtering on -// nested fields to filter based on resource labels. -// -// To filter on multiple expressions, provide each separate expression -// within parentheses. For example, (scheduling.automaticRestart = true) -// (cpuPlatform = "Intel Skylake"). By default, each expression is an -// AND expression. However, you can include AND and OR expressions -// explicitly. For example, (cpuPlatform = "Intel Skylake") OR -// (cpuPlatform = "Intel Broadwell") AND (scheduling.automaticRestart = -// true). -func (c *HostsAggregatedListCall) Filter(filter string) *HostsAggregatedListCall { - c.urlParams_.Set("filter", filter) - return c -} - -// MaxResults sets the optional parameter "maxResults": The maximum -// number of results per page that should be returned. If the number of -// available results is larger than maxResults, Compute Engine returns a -// nextPageToken that can be used to get the next page of results in -// subsequent list requests. Acceptable values are 0 to 500, inclusive. -// (Default: 500) -func (c *HostsAggregatedListCall) MaxResults(maxResults int64) *HostsAggregatedListCall { - c.urlParams_.Set("maxResults", fmt.Sprint(maxResults)) - return c -} - -// OrderBy sets the optional parameter "orderBy": Sorts list results by -// a certain order. By default, results are returned in alphanumerical -// order based on the resource name. -// -// You can also sort results in descending order based on the creation -// timestamp using orderBy="creationTimestamp desc". This sorts results -// based on the creationTimestamp field in reverse chronological order -// (newest result first). Use this to sort resources like operations so -// that the newest operation is returned first. -// -// Currently, only sorting by name or creationTimestamp desc is -// supported. -func (c *HostsAggregatedListCall) OrderBy(orderBy string) *HostsAggregatedListCall { - c.urlParams_.Set("orderBy", orderBy) - return c -} - -// PageToken sets the optional parameter "pageToken": Specifies a page -// token to use. Set pageToken to the nextPageToken returned by a -// previous list request to get the next page of results. -func (c *HostsAggregatedListCall) PageToken(pageToken string) *HostsAggregatedListCall { - c.urlParams_.Set("pageToken", pageToken) - return c -} - -// Fields allows partial responses to be retrieved. See -// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse -// for more information. -func (c *HostsAggregatedListCall) Fields(s ...googleapi.Field) *HostsAggregatedListCall { - c.urlParams_.Set("fields", googleapi.CombineFields(s)) - return c -} - -// IfNoneMatch sets the optional parameter which makes the operation -// fail if the object's ETag matches the given value. This is useful for -// getting updates only after the object has changed since the last -// request. Use googleapi.IsNotModified to check whether the response -// error from Do is the result of In-None-Match. -func (c *HostsAggregatedListCall) IfNoneMatch(entityTag string) *HostsAggregatedListCall { - c.ifNoneMatch_ = entityTag - return c -} - -// Context sets the context to be used in this call's Do method. Any -// pending HTTP request will be aborted if the provided context is -// canceled. -func (c *HostsAggregatedListCall) Context(ctx context.Context) *HostsAggregatedListCall { - c.ctx_ = ctx - return c -} - -// Header returns an http.Header that can be modified by the caller to -// add HTTP headers to the request. -func (c *HostsAggregatedListCall) Header() http.Header { - if c.header_ == nil { - c.header_ = make(http.Header) - } - return c.header_ -} - -func (c *HostsAggregatedListCall) doRequest(alt string) (*http.Response, error) { - reqHeaders := make(http.Header) - for k, v := range c.header_ { - reqHeaders[k] = v - } - reqHeaders.Set("User-Agent", c.s.userAgent()) - if c.ifNoneMatch_ != "" { - reqHeaders.Set("If-None-Match", c.ifNoneMatch_) - } - var body io.Reader = nil - c.urlParams_.Set("alt", alt) - urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/aggregated/hosts") - urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) - req.Header = reqHeaders - googleapi.Expand(req.URL, map[string]string{ - "project": c.project, - }) - return gensupport.SendRequest(c.ctx_, c.s.client, req) -} - -// Do executes the "compute.hosts.aggregatedList" call. -// Exactly one of *HostAggregatedList or error will be non-nil. Any -// non-2xx status code is an error. Response headers are in either -// *HostAggregatedList.ServerResponse.Header or (if a response was -// returned at all) in error.(*googleapi.Error).Header. Use -// googleapi.IsNotModified to check whether the returned error was -// because http.StatusNotModified was returned. -func (c *HostsAggregatedListCall) Do(opts ...googleapi.CallOption) (*HostAggregatedList, error) { - gensupport.SetOptions(c.urlParams_, opts...) - res, err := c.doRequest("json") - if res != nil && res.StatusCode == http.StatusNotModified { - if res.Body != nil { - res.Body.Close() - } - return nil, &googleapi.Error{ - Code: res.StatusCode, - Header: res.Header, - } - } - if err != nil { - return nil, err - } - defer googleapi.CloseBody(res) - if err := googleapi.CheckResponse(res); err != nil { - return nil, err - } - ret := &HostAggregatedList{ - ServerResponse: googleapi.ServerResponse{ - Header: res.Header, - HTTPStatusCode: res.StatusCode, - }, - } - target := &ret - if err := gensupport.DecodeResponse(target, res); err != nil { - return nil, err - } - return ret, nil - // { - // "description": "Retrieves an aggregated list of hosts.", - // "httpMethod": "GET", - // "id": "compute.hosts.aggregatedList", - // "parameterOrder": [ - // "project" - // ], - // "parameters": { - // "filter": { - // "description": "A filter expression that filters resources listed in the response. The expression must specify the field name, a comparison operator, and the value that you want to use for filtering. The value must be a string, a number, or a boolean. The comparison operator must be either =, !=, \u003e, or \u003c.\n\nFor example, if you are filtering Compute Engine instances, you can exclude instances named example-instance by specifying name != example-instance.\n\nYou can also filter nested fields. For example, you could specify scheduling.automaticRestart = false to include instances only if they are not scheduled for automatic restarts. You can use filtering on nested fields to filter based on resource labels.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart = true) (cpuPlatform = \"Intel Skylake\"). By default, each expression is an AND expression. However, you can include AND and OR expressions explicitly. For example, (cpuPlatform = \"Intel Skylake\") OR (cpuPlatform = \"Intel Broadwell\") AND (scheduling.automaticRestart = true).", - // "location": "query", - // "type": "string" - // }, - // "maxResults": { - // "default": "500", - // "description": "The maximum number of results per page that should be returned. If the number of available results is larger than maxResults, Compute Engine returns a nextPageToken that can be used to get the next page of results in subsequent list requests. Acceptable values are 0 to 500, inclusive. (Default: 500)", - // "format": "uint32", - // "location": "query", - // "minimum": "0", - // "type": "integer" - // }, - // "orderBy": { - // "description": "Sorts list results by a certain order. By default, results are returned in alphanumerical order based on the resource name.\n\nYou can also sort results in descending order based on the creation timestamp using orderBy=\"creationTimestamp desc\". This sorts results based on the creationTimestamp field in reverse chronological order (newest result first). Use this to sort resources like operations so that the newest operation is returned first.\n\nCurrently, only sorting by name or creationTimestamp desc is supported.", - // "location": "query", - // "type": "string" - // }, - // "pageToken": { - // "description": "Specifies a page token to use. Set pageToken to the nextPageToken returned by a previous list request to get the next page of results.", - // "location": "query", - // "type": "string" - // }, - // "project": { - // "description": "Project ID for this request.", - // "location": "path", - // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", - // "required": true, - // "type": "string" - // } - // }, - // "path": "{project}/aggregated/hosts", - // "response": { - // "$ref": "HostAggregatedList" - // }, - // "scopes": [ - // "https://www.googleapis.com/auth/cloud-platform", - // "https://www.googleapis.com/auth/compute", - // "https://www.googleapis.com/auth/compute.readonly" - // ] - // } - -} - -// Pages invokes f for each page of results. -// A non-nil error returned from f will halt the iteration. -// The provided context supersedes any context provided to the Context method. -func (c *HostsAggregatedListCall) Pages(ctx context.Context, f func(*HostAggregatedList) error) error { - c.ctx_ = ctx - defer c.PageToken(c.urlParams_.Get("pageToken")) // reset paging to original point - for { - x, err := c.Do() - if err != nil { - return err - } - if err := f(x); err != nil { - return err - } - if x.NextPageToken == "" { - return nil - } - c.PageToken(x.NextPageToken) - } -} - -// method id "compute.hosts.delete": - -type HostsDeleteCall struct { - s *Service - project string - zone string - host string - urlParams_ gensupport.URLParams - ctx_ context.Context - header_ http.Header -} - -// Delete: Deletes the specified Host resource. -func (r *HostsService) Delete(project string, zone string, host string) *HostsDeleteCall { - c := &HostsDeleteCall{s: r.s, urlParams_: make(gensupport.URLParams)} - c.project = project - c.zone = zone - c.host = host - return c -} - -// RequestId sets the optional parameter "requestId": An optional -// request ID to identify requests. Specify a unique request ID so that -// if you must retry your request, the server will know to ignore the -// request if it has already been completed. -// -// For example, consider a situation where you make an initial request -// and the request times out. If you make the request again with the -// same request ID, the server can check if original operation with the -// same request ID was received, and if so, will ignore the second -// request. This prevents clients from accidentally creating duplicate -// commitments. -// -// The request ID must be a valid UUID with the exception that zero UUID -// is not supported (00000000-0000-0000-0000-000000000000). -func (c *HostsDeleteCall) RequestId(requestId string) *HostsDeleteCall { - c.urlParams_.Set("requestId", requestId) - return c -} - -// Fields allows partial responses to be retrieved. See -// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse -// for more information. -func (c *HostsDeleteCall) Fields(s ...googleapi.Field) *HostsDeleteCall { - c.urlParams_.Set("fields", googleapi.CombineFields(s)) - return c -} - -// Context sets the context to be used in this call's Do method. Any -// pending HTTP request will be aborted if the provided context is -// canceled. -func (c *HostsDeleteCall) Context(ctx context.Context) *HostsDeleteCall { - c.ctx_ = ctx - return c -} - -// Header returns an http.Header that can be modified by the caller to -// add HTTP headers to the request. -func (c *HostsDeleteCall) Header() http.Header { - if c.header_ == nil { - c.header_ = make(http.Header) - } - return c.header_ -} - -func (c *HostsDeleteCall) doRequest(alt string) (*http.Response, error) { - reqHeaders := make(http.Header) - for k, v := range c.header_ { - reqHeaders[k] = v - } - reqHeaders.Set("User-Agent", c.s.userAgent()) - var body io.Reader = nil - c.urlParams_.Set("alt", alt) - urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/hosts/{host}") - urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) - req.Header = reqHeaders - googleapi.Expand(req.URL, map[string]string{ - "project": c.project, - "zone": c.zone, - "host": c.host, - }) - return gensupport.SendRequest(c.ctx_, c.s.client, req) -} - -// Do executes the "compute.hosts.delete" call. -// Exactly one of *Operation or error will be non-nil. Any non-2xx -// status code is an error. Response headers are in either -// *Operation.ServerResponse.Header or (if a response was returned at -// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified -// to check whether the returned error was because -// http.StatusNotModified was returned. -func (c *HostsDeleteCall) Do(opts ...googleapi.CallOption) (*Operation, error) { - gensupport.SetOptions(c.urlParams_, opts...) - res, err := c.doRequest("json") - if res != nil && res.StatusCode == http.StatusNotModified { - if res.Body != nil { - res.Body.Close() - } - return nil, &googleapi.Error{ - Code: res.StatusCode, - Header: res.Header, - } - } - if err != nil { - return nil, err - } - defer googleapi.CloseBody(res) - if err := googleapi.CheckResponse(res); err != nil { - return nil, err - } - ret := &Operation{ - ServerResponse: googleapi.ServerResponse{ - Header: res.Header, - HTTPStatusCode: res.StatusCode, - }, - } - target := &ret - if err := gensupport.DecodeResponse(target, res); err != nil { - return nil, err - } - return ret, nil - // { - // "description": "Deletes the specified Host resource.", - // "httpMethod": "DELETE", - // "id": "compute.hosts.delete", - // "parameterOrder": [ - // "project", - // "zone", - // "host" - // ], - // "parameters": { - // "host": { - // "description": "Name of the Host resource to delete.", - // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", - // "required": true, - // "type": "string" - // }, - // "project": { - // "description": "Project ID for this request.", - // "location": "path", - // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", - // "required": true, - // "type": "string" - // }, - // "requestId": { - // "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", - // "location": "query", - // "type": "string" - // }, - // "zone": { - // "description": "The name of the zone for this request.", - // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", - // "required": true, - // "type": "string" - // } - // }, - // "path": "{project}/zones/{zone}/hosts/{host}", - // "response": { - // "$ref": "Operation" - // }, - // "scopes": [ - // "https://www.googleapis.com/auth/cloud-platform", - // "https://www.googleapis.com/auth/compute" - // ] - // } - -} - -// method id "compute.hosts.get": - -type HostsGetCall struct { - s *Service - project string - zone string - host string - urlParams_ gensupport.URLParams - ifNoneMatch_ string - ctx_ context.Context - header_ http.Header -} - -// Get: Returns the specified host. Gets a list of available hosts by -// making a list() request. -func (r *HostsService) Get(project string, zone string, host string) *HostsGetCall { - c := &HostsGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} - c.project = project - c.zone = zone - c.host = host - return c -} - -// Fields allows partial responses to be retrieved. See -// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse -// for more information. -func (c *HostsGetCall) Fields(s ...googleapi.Field) *HostsGetCall { - c.urlParams_.Set("fields", googleapi.CombineFields(s)) - return c -} - -// IfNoneMatch sets the optional parameter which makes the operation -// fail if the object's ETag matches the given value. This is useful for -// getting updates only after the object has changed since the last -// request. Use googleapi.IsNotModified to check whether the response -// error from Do is the result of In-None-Match. -func (c *HostsGetCall) IfNoneMatch(entityTag string) *HostsGetCall { - c.ifNoneMatch_ = entityTag - return c -} - -// Context sets the context to be used in this call's Do method. Any -// pending HTTP request will be aborted if the provided context is -// canceled. -func (c *HostsGetCall) Context(ctx context.Context) *HostsGetCall { - c.ctx_ = ctx - return c -} - -// Header returns an http.Header that can be modified by the caller to -// add HTTP headers to the request. -func (c *HostsGetCall) Header() http.Header { - if c.header_ == nil { - c.header_ = make(http.Header) - } - return c.header_ -} - -func (c *HostsGetCall) doRequest(alt string) (*http.Response, error) { - reqHeaders := make(http.Header) - for k, v := range c.header_ { - reqHeaders[k] = v - } - reqHeaders.Set("User-Agent", c.s.userAgent()) - if c.ifNoneMatch_ != "" { - reqHeaders.Set("If-None-Match", c.ifNoneMatch_) - } - var body io.Reader = nil - c.urlParams_.Set("alt", alt) - urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/hosts/{host}") - urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) - req.Header = reqHeaders - googleapi.Expand(req.URL, map[string]string{ - "project": c.project, - "zone": c.zone, - "host": c.host, - }) - return gensupport.SendRequest(c.ctx_, c.s.client, req) -} - -// Do executes the "compute.hosts.get" call. -// Exactly one of *Host or error will be non-nil. Any non-2xx status -// code is an error. Response headers are in either -// *Host.ServerResponse.Header or (if a response was returned at all) in -// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check -// whether the returned error was because http.StatusNotModified was -// returned. -func (c *HostsGetCall) Do(opts ...googleapi.CallOption) (*Host, error) { - gensupport.SetOptions(c.urlParams_, opts...) - res, err := c.doRequest("json") - if res != nil && res.StatusCode == http.StatusNotModified { - if res.Body != nil { - res.Body.Close() - } - return nil, &googleapi.Error{ - Code: res.StatusCode, - Header: res.Header, - } - } - if err != nil { - return nil, err - } - defer googleapi.CloseBody(res) - if err := googleapi.CheckResponse(res); err != nil { - return nil, err - } - ret := &Host{ - ServerResponse: googleapi.ServerResponse{ - Header: res.Header, - HTTPStatusCode: res.StatusCode, - }, - } - target := &ret - if err := gensupport.DecodeResponse(target, res); err != nil { - return nil, err - } - return ret, nil - // { - // "description": "Returns the specified host. Gets a list of available hosts by making a list() request.", - // "httpMethod": "GET", - // "id": "compute.hosts.get", - // "parameterOrder": [ - // "project", - // "zone", - // "host" - // ], - // "parameters": { - // "host": { - // "description": "Name of the host to return.", - // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", - // "required": true, - // "type": "string" - // }, - // "project": { - // "description": "Project ID for this request.", - // "location": "path", - // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", - // "required": true, - // "type": "string" - // }, - // "zone": { - // "description": "The name of the zone for this request.", - // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", - // "required": true, - // "type": "string" - // } - // }, - // "path": "{project}/zones/{zone}/hosts/{host}", - // "response": { - // "$ref": "Host" - // }, - // "scopes": [ - // "https://www.googleapis.com/auth/cloud-platform", - // "https://www.googleapis.com/auth/compute", - // "https://www.googleapis.com/auth/compute.readonly" - // ] - // } - -} - -// method id "compute.hosts.getIamPolicy": - -type HostsGetIamPolicyCall struct { - s *Service - project string - zone string - resource string - urlParams_ gensupport.URLParams - ifNoneMatch_ string - ctx_ context.Context - header_ http.Header -} - -// GetIamPolicy: Gets the access control policy for a resource. May be -// empty if no such policy or resource exists. -func (r *HostsService) GetIamPolicy(project string, zone string, resource string) *HostsGetIamPolicyCall { - c := &HostsGetIamPolicyCall{s: r.s, urlParams_: make(gensupport.URLParams)} - c.project = project - c.zone = zone - c.resource = resource - return c -} - -// Fields allows partial responses to be retrieved. See -// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse -// for more information. -func (c *HostsGetIamPolicyCall) Fields(s ...googleapi.Field) *HostsGetIamPolicyCall { - c.urlParams_.Set("fields", googleapi.CombineFields(s)) - return c -} - -// IfNoneMatch sets the optional parameter which makes the operation -// fail if the object's ETag matches the given value. This is useful for -// getting updates only after the object has changed since the last -// request. Use googleapi.IsNotModified to check whether the response -// error from Do is the result of In-None-Match. -func (c *HostsGetIamPolicyCall) IfNoneMatch(entityTag string) *HostsGetIamPolicyCall { - c.ifNoneMatch_ = entityTag - return c -} - -// Context sets the context to be used in this call's Do method. Any -// pending HTTP request will be aborted if the provided context is -// canceled. -func (c *HostsGetIamPolicyCall) Context(ctx context.Context) *HostsGetIamPolicyCall { - c.ctx_ = ctx - return c -} - -// Header returns an http.Header that can be modified by the caller to -// add HTTP headers to the request. -func (c *HostsGetIamPolicyCall) Header() http.Header { - if c.header_ == nil { - c.header_ = make(http.Header) - } - return c.header_ -} - -func (c *HostsGetIamPolicyCall) doRequest(alt string) (*http.Response, error) { - reqHeaders := make(http.Header) - for k, v := range c.header_ { - reqHeaders[k] = v - } - reqHeaders.Set("User-Agent", c.s.userAgent()) - if c.ifNoneMatch_ != "" { - reqHeaders.Set("If-None-Match", c.ifNoneMatch_) - } - var body io.Reader = nil - c.urlParams_.Set("alt", alt) - urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/hosts/{resource}/getIamPolicy") - urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) - req.Header = reqHeaders - googleapi.Expand(req.URL, map[string]string{ - "project": c.project, - "zone": c.zone, - "resource": c.resource, - }) - return gensupport.SendRequest(c.ctx_, c.s.client, req) -} - -// Do executes the "compute.hosts.getIamPolicy" call. -// Exactly one of *Policy or error will be non-nil. Any non-2xx status -// code is an error. Response headers are in either -// *Policy.ServerResponse.Header or (if a response was returned at all) -// in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to -// check whether the returned error was because http.StatusNotModified -// was returned. -func (c *HostsGetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Policy, error) { - gensupport.SetOptions(c.urlParams_, opts...) - res, err := c.doRequest("json") - if res != nil && res.StatusCode == http.StatusNotModified { - if res.Body != nil { - res.Body.Close() - } - return nil, &googleapi.Error{ - Code: res.StatusCode, - Header: res.Header, - } - } - if err != nil { - return nil, err - } - defer googleapi.CloseBody(res) - if err := googleapi.CheckResponse(res); err != nil { - return nil, err - } - ret := &Policy{ - ServerResponse: googleapi.ServerResponse{ - Header: res.Header, - HTTPStatusCode: res.StatusCode, - }, - } - target := &ret - if err := gensupport.DecodeResponse(target, res); err != nil { - return nil, err - } - return ret, nil - // { - // "description": "Gets the access control policy for a resource. May be empty if no such policy or resource exists.", - // "httpMethod": "GET", - // "id": "compute.hosts.getIamPolicy", - // "parameterOrder": [ - // "project", - // "zone", - // "resource" - // ], - // "parameters": { - // "project": { - // "description": "Project ID for this request.", - // "location": "path", - // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", - // "required": true, - // "type": "string" - // }, - // "resource": { - // "description": "Name of the resource for this request.", - // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", - // "required": true, - // "type": "string" - // }, - // "zone": { - // "description": "The name of the zone for this request.", - // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", - // "required": true, - // "type": "string" - // } - // }, - // "path": "{project}/zones/{zone}/hosts/{resource}/getIamPolicy", - // "response": { - // "$ref": "Policy" - // }, - // "scopes": [ - // "https://www.googleapis.com/auth/cloud-platform", - // "https://www.googleapis.com/auth/compute", - // "https://www.googleapis.com/auth/compute.readonly" - // ] - // } - -} - -// method id "compute.hosts.insert": - -type HostsInsertCall struct { - s *Service - project string - zone string - host *Host - urlParams_ gensupport.URLParams - ctx_ context.Context - header_ http.Header -} - -// Insert: Creates a host resource in the specified project using the -// data included in the request. -func (r *HostsService) Insert(project string, zone string, host *Host) *HostsInsertCall { - c := &HostsInsertCall{s: r.s, urlParams_: make(gensupport.URLParams)} - c.project = project - c.zone = zone - c.host = host - return c -} - -// RequestId sets the optional parameter "requestId": An optional -// request ID to identify requests. Specify a unique request ID so that -// if you must retry your request, the server will know to ignore the -// request if it has already been completed. -// -// For example, consider a situation where you make an initial request -// and the request times out. If you make the request again with the -// same request ID, the server can check if original operation with the -// same request ID was received, and if so, will ignore the second -// request. This prevents clients from accidentally creating duplicate -// commitments. -// -// The request ID must be a valid UUID with the exception that zero UUID -// is not supported (00000000-0000-0000-0000-000000000000). -func (c *HostsInsertCall) RequestId(requestId string) *HostsInsertCall { - c.urlParams_.Set("requestId", requestId) - return c -} - -// Fields allows partial responses to be retrieved. See -// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse -// for more information. -func (c *HostsInsertCall) Fields(s ...googleapi.Field) *HostsInsertCall { - c.urlParams_.Set("fields", googleapi.CombineFields(s)) - return c -} - -// Context sets the context to be used in this call's Do method. Any -// pending HTTP request will be aborted if the provided context is -// canceled. -func (c *HostsInsertCall) Context(ctx context.Context) *HostsInsertCall { - c.ctx_ = ctx - return c -} - -// Header returns an http.Header that can be modified by the caller to -// add HTTP headers to the request. -func (c *HostsInsertCall) Header() http.Header { - if c.header_ == nil { - c.header_ = make(http.Header) - } - return c.header_ -} - -func (c *HostsInsertCall) doRequest(alt string) (*http.Response, error) { - reqHeaders := make(http.Header) - for k, v := range c.header_ { - reqHeaders[k] = v - } - reqHeaders.Set("User-Agent", c.s.userAgent()) - var body io.Reader = nil - body, err := googleapi.WithoutDataWrapper.JSONReader(c.host) - if err != nil { - return nil, err - } - reqHeaders.Set("Content-Type", "application/json") - c.urlParams_.Set("alt", alt) - urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/hosts") - urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) - req.Header = reqHeaders - googleapi.Expand(req.URL, map[string]string{ - "project": c.project, - "zone": c.zone, - }) - return gensupport.SendRequest(c.ctx_, c.s.client, req) -} - -// Do executes the "compute.hosts.insert" call. -// Exactly one of *Operation or error will be non-nil. Any non-2xx -// status code is an error. Response headers are in either -// *Operation.ServerResponse.Header or (if a response was returned at -// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified -// to check whether the returned error was because -// http.StatusNotModified was returned. -func (c *HostsInsertCall) Do(opts ...googleapi.CallOption) (*Operation, error) { - gensupport.SetOptions(c.urlParams_, opts...) - res, err := c.doRequest("json") - if res != nil && res.StatusCode == http.StatusNotModified { - if res.Body != nil { - res.Body.Close() - } - return nil, &googleapi.Error{ - Code: res.StatusCode, - Header: res.Header, - } - } - if err != nil { - return nil, err - } - defer googleapi.CloseBody(res) - if err := googleapi.CheckResponse(res); err != nil { - return nil, err - } - ret := &Operation{ - ServerResponse: googleapi.ServerResponse{ - Header: res.Header, - HTTPStatusCode: res.StatusCode, - }, - } - target := &ret - if err := gensupport.DecodeResponse(target, res); err != nil { - return nil, err - } - return ret, nil - // { - // "description": "Creates a host resource in the specified project using the data included in the request.", - // "httpMethod": "POST", - // "id": "compute.hosts.insert", - // "parameterOrder": [ - // "project", - // "zone" - // ], - // "parameters": { - // "project": { - // "description": "Project ID for this request.", - // "location": "path", - // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", - // "required": true, - // "type": "string" - // }, - // "requestId": { - // "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", - // "location": "query", - // "type": "string" - // }, - // "zone": { - // "description": "The name of the zone for this request.", - // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", - // "required": true, - // "type": "string" - // } - // }, - // "path": "{project}/zones/{zone}/hosts", - // "request": { - // "$ref": "Host" - // }, - // "response": { - // "$ref": "Operation" - // }, - // "scopes": [ - // "https://www.googleapis.com/auth/cloud-platform", - // "https://www.googleapis.com/auth/compute" - // ] - // } - -} - -// method id "compute.hosts.list": - -type HostsListCall struct { - s *Service - project string - zone string - urlParams_ gensupport.URLParams - ifNoneMatch_ string - ctx_ context.Context - header_ http.Header -} - -// List: Retrieves a list of hosts available to the specified project. -func (r *HostsService) List(project string, zone string) *HostsListCall { - c := &HostsListCall{s: r.s, urlParams_: make(gensupport.URLParams)} - c.project = project - c.zone = zone - return c -} - -// Filter sets the optional parameter "filter": A filter expression that -// filters resources listed in the response. The expression must specify -// the field name, a comparison operator, and the value that you want to -// use for filtering. The value must be a string, a number, or a -// boolean. The comparison operator must be either =, !=, >, or <. -// -// For example, if you are filtering Compute Engine instances, you can -// exclude instances named example-instance by specifying name != -// example-instance. -// -// You can also filter nested fields. For example, you could specify -// scheduling.automaticRestart = false to include instances only if they -// are not scheduled for automatic restarts. You can use filtering on -// nested fields to filter based on resource labels. -// -// To filter on multiple expressions, provide each separate expression -// within parentheses. For example, (scheduling.automaticRestart = true) -// (cpuPlatform = "Intel Skylake"). By default, each expression is an -// AND expression. However, you can include AND and OR expressions -// explicitly. For example, (cpuPlatform = "Intel Skylake") OR -// (cpuPlatform = "Intel Broadwell") AND (scheduling.automaticRestart = -// true). -func (c *HostsListCall) Filter(filter string) *HostsListCall { - c.urlParams_.Set("filter", filter) - return c -} - -// MaxResults sets the optional parameter "maxResults": The maximum -// number of results per page that should be returned. If the number of -// available results is larger than maxResults, Compute Engine returns a -// nextPageToken that can be used to get the next page of results in -// subsequent list requests. Acceptable values are 0 to 500, inclusive. -// (Default: 500) -func (c *HostsListCall) MaxResults(maxResults int64) *HostsListCall { - c.urlParams_.Set("maxResults", fmt.Sprint(maxResults)) - return c -} - -// OrderBy sets the optional parameter "orderBy": Sorts list results by -// a certain order. By default, results are returned in alphanumerical -// order based on the resource name. -// -// You can also sort results in descending order based on the creation -// timestamp using orderBy="creationTimestamp desc". This sorts results -// based on the creationTimestamp field in reverse chronological order -// (newest result first). Use this to sort resources like operations so -// that the newest operation is returned first. -// -// Currently, only sorting by name or creationTimestamp desc is -// supported. -func (c *HostsListCall) OrderBy(orderBy string) *HostsListCall { - c.urlParams_.Set("orderBy", orderBy) - return c -} - -// PageToken sets the optional parameter "pageToken": Specifies a page -// token to use. Set pageToken to the nextPageToken returned by a -// previous list request to get the next page of results. -func (c *HostsListCall) PageToken(pageToken string) *HostsListCall { - c.urlParams_.Set("pageToken", pageToken) - return c -} - -// Fields allows partial responses to be retrieved. See -// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse -// for more information. -func (c *HostsListCall) Fields(s ...googleapi.Field) *HostsListCall { - c.urlParams_.Set("fields", googleapi.CombineFields(s)) - return c -} - -// IfNoneMatch sets the optional parameter which makes the operation -// fail if the object's ETag matches the given value. This is useful for -// getting updates only after the object has changed since the last -// request. Use googleapi.IsNotModified to check whether the response -// error from Do is the result of In-None-Match. -func (c *HostsListCall) IfNoneMatch(entityTag string) *HostsListCall { - c.ifNoneMatch_ = entityTag - return c -} - -// Context sets the context to be used in this call's Do method. Any -// pending HTTP request will be aborted if the provided context is -// canceled. -func (c *HostsListCall) Context(ctx context.Context) *HostsListCall { - c.ctx_ = ctx - return c -} - -// Header returns an http.Header that can be modified by the caller to -// add HTTP headers to the request. -func (c *HostsListCall) Header() http.Header { - if c.header_ == nil { - c.header_ = make(http.Header) - } - return c.header_ -} - -func (c *HostsListCall) doRequest(alt string) (*http.Response, error) { - reqHeaders := make(http.Header) - for k, v := range c.header_ { - reqHeaders[k] = v - } - reqHeaders.Set("User-Agent", c.s.userAgent()) - if c.ifNoneMatch_ != "" { - reqHeaders.Set("If-None-Match", c.ifNoneMatch_) - } - var body io.Reader = nil - c.urlParams_.Set("alt", alt) - urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/hosts") - urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) - req.Header = reqHeaders - googleapi.Expand(req.URL, map[string]string{ - "project": c.project, - "zone": c.zone, - }) - return gensupport.SendRequest(c.ctx_, c.s.client, req) -} - -// Do executes the "compute.hosts.list" call. -// Exactly one of *HostList or error will be non-nil. Any non-2xx status -// code is an error. Response headers are in either -// *HostList.ServerResponse.Header or (if a response was returned at -// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified -// to check whether the returned error was because -// http.StatusNotModified was returned. -func (c *HostsListCall) Do(opts ...googleapi.CallOption) (*HostList, error) { - gensupport.SetOptions(c.urlParams_, opts...) - res, err := c.doRequest("json") - if res != nil && res.StatusCode == http.StatusNotModified { - if res.Body != nil { - res.Body.Close() - } - return nil, &googleapi.Error{ - Code: res.StatusCode, - Header: res.Header, - } - } - if err != nil { - return nil, err - } - defer googleapi.CloseBody(res) - if err := googleapi.CheckResponse(res); err != nil { - return nil, err - } - ret := &HostList{ - ServerResponse: googleapi.ServerResponse{ - Header: res.Header, - HTTPStatusCode: res.StatusCode, - }, - } - target := &ret - if err := gensupport.DecodeResponse(target, res); err != nil { - return nil, err - } - return ret, nil - // { - // "description": "Retrieves a list of hosts available to the specified project.", - // "httpMethod": "GET", - // "id": "compute.hosts.list", - // "parameterOrder": [ - // "project", - // "zone" - // ], - // "parameters": { - // "filter": { - // "description": "A filter expression that filters resources listed in the response. The expression must specify the field name, a comparison operator, and the value that you want to use for filtering. The value must be a string, a number, or a boolean. The comparison operator must be either =, !=, \u003e, or \u003c.\n\nFor example, if you are filtering Compute Engine instances, you can exclude instances named example-instance by specifying name != example-instance.\n\nYou can also filter nested fields. For example, you could specify scheduling.automaticRestart = false to include instances only if they are not scheduled for automatic restarts. You can use filtering on nested fields to filter based on resource labels.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart = true) (cpuPlatform = \"Intel Skylake\"). By default, each expression is an AND expression. However, you can include AND and OR expressions explicitly. For example, (cpuPlatform = \"Intel Skylake\") OR (cpuPlatform = \"Intel Broadwell\") AND (scheduling.automaticRestart = true).", - // "location": "query", - // "type": "string" - // }, - // "maxResults": { - // "default": "500", - // "description": "The maximum number of results per page that should be returned. If the number of available results is larger than maxResults, Compute Engine returns a nextPageToken that can be used to get the next page of results in subsequent list requests. Acceptable values are 0 to 500, inclusive. (Default: 500)", - // "format": "uint32", - // "location": "query", - // "minimum": "0", - // "type": "integer" - // }, - // "orderBy": { - // "description": "Sorts list results by a certain order. By default, results are returned in alphanumerical order based on the resource name.\n\nYou can also sort results in descending order based on the creation timestamp using orderBy=\"creationTimestamp desc\". This sorts results based on the creationTimestamp field in reverse chronological order (newest result first). Use this to sort resources like operations so that the newest operation is returned first.\n\nCurrently, only sorting by name or creationTimestamp desc is supported.", - // "location": "query", - // "type": "string" - // }, - // "pageToken": { - // "description": "Specifies a page token to use. Set pageToken to the nextPageToken returned by a previous list request to get the next page of results.", - // "location": "query", - // "type": "string" - // }, - // "project": { - // "description": "Project ID for this request.", - // "location": "path", - // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", - // "required": true, - // "type": "string" - // }, - // "zone": { - // "description": "The name of the zone for this request.", - // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", - // "required": true, - // "type": "string" - // } - // }, - // "path": "{project}/zones/{zone}/hosts", - // "response": { - // "$ref": "HostList" - // }, - // "scopes": [ - // "https://www.googleapis.com/auth/cloud-platform", - // "https://www.googleapis.com/auth/compute", - // "https://www.googleapis.com/auth/compute.readonly" - // ] - // } - -} - -// Pages invokes f for each page of results. -// A non-nil error returned from f will halt the iteration. -// The provided context supersedes any context provided to the Context method. -func (c *HostsListCall) Pages(ctx context.Context, f func(*HostList) error) error { - c.ctx_ = ctx - defer c.PageToken(c.urlParams_.Get("pageToken")) // reset paging to original point - for { - x, err := c.Do() - if err != nil { - return err - } - if err := f(x); err != nil { - return err - } - if x.NextPageToken == "" { - return nil - } - c.PageToken(x.NextPageToken) - } -} - -// method id "compute.hosts.setIamPolicy": - -type HostsSetIamPolicyCall struct { - s *Service - project string - zone string - resource string - zonesetpolicyrequest *ZoneSetPolicyRequest - urlParams_ gensupport.URLParams - ctx_ context.Context - header_ http.Header -} - -// SetIamPolicy: Sets the access control policy on the specified -// resource. Replaces any existing policy. -func (r *HostsService) SetIamPolicy(project string, zone string, resource string, zonesetpolicyrequest *ZoneSetPolicyRequest) *HostsSetIamPolicyCall { - c := &HostsSetIamPolicyCall{s: r.s, urlParams_: make(gensupport.URLParams)} - c.project = project - c.zone = zone - c.resource = resource - c.zonesetpolicyrequest = zonesetpolicyrequest - return c -} - -// Fields allows partial responses to be retrieved. See -// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse -// for more information. -func (c *HostsSetIamPolicyCall) Fields(s ...googleapi.Field) *HostsSetIamPolicyCall { - c.urlParams_.Set("fields", googleapi.CombineFields(s)) - return c -} - -// Context sets the context to be used in this call's Do method. Any -// pending HTTP request will be aborted if the provided context is -// canceled. -func (c *HostsSetIamPolicyCall) Context(ctx context.Context) *HostsSetIamPolicyCall { - c.ctx_ = ctx - return c -} - -// Header returns an http.Header that can be modified by the caller to -// add HTTP headers to the request. -func (c *HostsSetIamPolicyCall) Header() http.Header { - if c.header_ == nil { - c.header_ = make(http.Header) - } - return c.header_ -} - -func (c *HostsSetIamPolicyCall) doRequest(alt string) (*http.Response, error) { - reqHeaders := make(http.Header) - for k, v := range c.header_ { - reqHeaders[k] = v - } - reqHeaders.Set("User-Agent", c.s.userAgent()) - var body io.Reader = nil - body, err := googleapi.WithoutDataWrapper.JSONReader(c.zonesetpolicyrequest) - if err != nil { - return nil, err - } - reqHeaders.Set("Content-Type", "application/json") - c.urlParams_.Set("alt", alt) - urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/hosts/{resource}/setIamPolicy") - urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) - req.Header = reqHeaders - googleapi.Expand(req.URL, map[string]string{ - "project": c.project, - "zone": c.zone, - "resource": c.resource, - }) - return gensupport.SendRequest(c.ctx_, c.s.client, req) -} - -// Do executes the "compute.hosts.setIamPolicy" call. -// Exactly one of *Policy or error will be non-nil. Any non-2xx status -// code is an error. Response headers are in either -// *Policy.ServerResponse.Header or (if a response was returned at all) -// in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to -// check whether the returned error was because http.StatusNotModified -// was returned. -func (c *HostsSetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Policy, error) { - gensupport.SetOptions(c.urlParams_, opts...) - res, err := c.doRequest("json") - if res != nil && res.StatusCode == http.StatusNotModified { - if res.Body != nil { - res.Body.Close() - } - return nil, &googleapi.Error{ - Code: res.StatusCode, - Header: res.Header, - } - } - if err != nil { - return nil, err - } - defer googleapi.CloseBody(res) - if err := googleapi.CheckResponse(res); err != nil { - return nil, err - } - ret := &Policy{ - ServerResponse: googleapi.ServerResponse{ - Header: res.Header, - HTTPStatusCode: res.StatusCode, - }, - } - target := &ret - if err := gensupport.DecodeResponse(target, res); err != nil { - return nil, err - } - return ret, nil - // { - // "description": "Sets the access control policy on the specified resource. Replaces any existing policy.", - // "httpMethod": "POST", - // "id": "compute.hosts.setIamPolicy", - // "parameterOrder": [ - // "project", - // "zone", - // "resource" - // ], - // "parameters": { - // "project": { - // "description": "Project ID for this request.", - // "location": "path", - // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", - // "required": true, - // "type": "string" - // }, - // "resource": { - // "description": "Name of the resource for this request.", - // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", - // "required": true, - // "type": "string" - // }, - // "zone": { - // "description": "The name of the zone for this request.", - // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", - // "required": true, - // "type": "string" - // } - // }, - // "path": "{project}/zones/{zone}/hosts/{resource}/setIamPolicy", - // "request": { - // "$ref": "ZoneSetPolicyRequest" - // }, - // "response": { - // "$ref": "Policy" - // }, - // "scopes": [ - // "https://www.googleapis.com/auth/cloud-platform", - // "https://www.googleapis.com/auth/compute" - // ] - // } - -} - -// method id "compute.hosts.testIamPermissions": - -type HostsTestIamPermissionsCall struct { - s *Service - project string - zone string - resource string - testpermissionsrequest *TestPermissionsRequest - urlParams_ gensupport.URLParams - ctx_ context.Context - header_ http.Header -} - -// TestIamPermissions: Returns permissions that a caller has on the -// specified resource. -func (r *HostsService) TestIamPermissions(project string, zone string, resource string, testpermissionsrequest *TestPermissionsRequest) *HostsTestIamPermissionsCall { - c := &HostsTestIamPermissionsCall{s: r.s, urlParams_: make(gensupport.URLParams)} - c.project = project - c.zone = zone - c.resource = resource - c.testpermissionsrequest = testpermissionsrequest - return c -} - -// Fields allows partial responses to be retrieved. See -// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse -// for more information. -func (c *HostsTestIamPermissionsCall) Fields(s ...googleapi.Field) *HostsTestIamPermissionsCall { - c.urlParams_.Set("fields", googleapi.CombineFields(s)) - return c -} - -// Context sets the context to be used in this call's Do method. Any -// pending HTTP request will be aborted if the provided context is -// canceled. -func (c *HostsTestIamPermissionsCall) Context(ctx context.Context) *HostsTestIamPermissionsCall { - c.ctx_ = ctx - return c -} - -// Header returns an http.Header that can be modified by the caller to -// add HTTP headers to the request. -func (c *HostsTestIamPermissionsCall) Header() http.Header { - if c.header_ == nil { - c.header_ = make(http.Header) - } - return c.header_ -} - -func (c *HostsTestIamPermissionsCall) doRequest(alt string) (*http.Response, error) { - reqHeaders := make(http.Header) - for k, v := range c.header_ { - reqHeaders[k] = v - } - reqHeaders.Set("User-Agent", c.s.userAgent()) - var body io.Reader = nil - body, err := googleapi.WithoutDataWrapper.JSONReader(c.testpermissionsrequest) - if err != nil { - return nil, err - } - reqHeaders.Set("Content-Type", "application/json") - c.urlParams_.Set("alt", alt) - urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/hosts/{resource}/testIamPermissions") - urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) - req.Header = reqHeaders - googleapi.Expand(req.URL, map[string]string{ - "project": c.project, - "zone": c.zone, - "resource": c.resource, - }) - return gensupport.SendRequest(c.ctx_, c.s.client, req) -} - -// Do executes the "compute.hosts.testIamPermissions" call. -// Exactly one of *TestPermissionsResponse or error will be non-nil. Any -// non-2xx status code is an error. Response headers are in either -// *TestPermissionsResponse.ServerResponse.Header or (if a response was -// returned at all) in error.(*googleapi.Error).Header. Use -// googleapi.IsNotModified to check whether the returned error was -// because http.StatusNotModified was returned. -func (c *HostsTestIamPermissionsCall) Do(opts ...googleapi.CallOption) (*TestPermissionsResponse, error) { - gensupport.SetOptions(c.urlParams_, opts...) - res, err := c.doRequest("json") - if res != nil && res.StatusCode == http.StatusNotModified { - if res.Body != nil { - res.Body.Close() - } - return nil, &googleapi.Error{ - Code: res.StatusCode, - Header: res.Header, - } - } - if err != nil { - return nil, err - } - defer googleapi.CloseBody(res) - if err := googleapi.CheckResponse(res); err != nil { - return nil, err - } - ret := &TestPermissionsResponse{ - ServerResponse: googleapi.ServerResponse{ - Header: res.Header, - HTTPStatusCode: res.StatusCode, - }, - } - target := &ret - if err := gensupport.DecodeResponse(target, res); err != nil { - return nil, err - } - return ret, nil - // { - // "description": "Returns permissions that a caller has on the specified resource.", - // "httpMethod": "POST", - // "id": "compute.hosts.testIamPermissions", - // "parameterOrder": [ - // "project", - // "zone", - // "resource" - // ], - // "parameters": { - // "project": { - // "description": "Project ID for this request.", - // "location": "path", - // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", - // "required": true, - // "type": "string" - // }, - // "resource": { - // "description": "Name of the resource for this request.", - // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", - // "required": true, - // "type": "string" - // }, - // "zone": { - // "description": "The name of the zone for this request.", - // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", - // "required": true, - // "type": "string" - // } - // }, - // "path": "{project}/zones/{zone}/hosts/{resource}/testIamPermissions", - // "request": { - // "$ref": "TestPermissionsRequest" - // }, - // "response": { - // "$ref": "TestPermissionsResponse" - // }, - // "scopes": [ - // "https://www.googleapis.com/auth/cloud-platform", - // "https://www.googleapis.com/auth/compute", - // "https://www.googleapis.com/auth/compute.readonly" - // ] - // } - -} - // method id "compute.httpHealthChecks.delete": type HttpHealthChecksDeleteCall struct { @@ -56874,9 +60558,13 @@ func (c *HttpHealthChecksDeleteCall) doRequest(alt string) (*http.Response, erro reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/httpHealthChecks/{httpHealthCheck}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -57031,9 +60719,13 @@ func (c *HttpHealthChecksGetCall) doRequest(alt string) (*http.Response, error) } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/httpHealthChecks/{httpHealthCheck}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -57194,9 +60886,13 @@ func (c *HttpHealthChecksInsertCall) doRequest(alt string) (*http.Response, erro } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/httpHealthChecks") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -57406,9 +61102,13 @@ func (c *HttpHealthChecksListCall) doRequest(alt string) (*http.Response, error) } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/httpHealthChecks") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -57607,9 +61307,13 @@ func (c *HttpHealthChecksPatchCall) doRequest(alt string) (*http.Response, error } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/httpHealthChecks/{httpHealthCheck}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PATCH", urls, body) + req, err := http.NewRequest("PATCH", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -57759,9 +61463,13 @@ func (c *HttpHealthChecksTestIamPermissionsCall) doRequest(alt string) (*http.Re } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/httpHealthChecks/{resource}/testIamPermissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -57824,9 +61532,9 @@ func (c *HttpHealthChecksTestIamPermissionsCall) Do(opts ...googleapi.CallOption // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "(?:[-a-z0-9_]{0,62}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -57927,9 +61635,13 @@ func (c *HttpHealthChecksUpdateCall) doRequest(alt string) (*http.Response, erro } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/httpHealthChecks/{httpHealthCheck}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PUT", urls, body) + req, err := http.NewRequest("PUT", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -58090,9 +61802,13 @@ func (c *HttpsHealthChecksDeleteCall) doRequest(alt string) (*http.Response, err reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/httpsHealthChecks/{httpsHealthCheck}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -58246,9 +61962,13 @@ func (c *HttpsHealthChecksGetCall) doRequest(alt string) (*http.Response, error) } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/httpsHealthChecks/{httpsHealthCheck}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -58408,9 +62128,13 @@ func (c *HttpsHealthChecksInsertCall) doRequest(alt string) (*http.Response, err } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/httpsHealthChecks") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -58619,9 +62343,13 @@ func (c *HttpsHealthChecksListCall) doRequest(alt string) (*http.Response, error } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/httpsHealthChecks") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -58819,9 +62547,13 @@ func (c *HttpsHealthChecksPatchCall) doRequest(alt string) (*http.Response, erro } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/httpsHealthChecks/{httpsHealthCheck}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PATCH", urls, body) + req, err := http.NewRequest("PATCH", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -58971,9 +62703,13 @@ func (c *HttpsHealthChecksTestIamPermissionsCall) doRequest(alt string) (*http.R } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/httpsHealthChecks/{resource}/testIamPermissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -59036,9 +62772,9 @@ func (c *HttpsHealthChecksTestIamPermissionsCall) Do(opts ...googleapi.CallOptio // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "(?:[-a-z0-9_]{0,62}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -59138,9 +62874,13 @@ func (c *HttpsHealthChecksUpdateCall) doRequest(alt string) (*http.Response, err } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/httpsHealthChecks/{httpsHealthCheck}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PUT", urls, body) + req, err := http.NewRequest("PUT", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -59302,9 +63042,13 @@ func (c *ImagesDeleteCall) doRequest(alt string) (*http.Response, error) { reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/images/{image}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -59362,7 +63106,7 @@ func (c *ImagesDeleteCall) Do(opts ...googleapi.CallOption) (*Operation, error) // "image": { // "description": "Name of the image resource to delete.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -59473,9 +63217,13 @@ func (c *ImagesDeprecateCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/images/{image}/deprecate") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -59533,7 +63281,7 @@ func (c *ImagesDeprecateCall) Do(opts ...googleapi.CallOption) (*Operation, erro // "image": { // "description": "Image name.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -59633,9 +63381,13 @@ func (c *ImagesGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/images/{image}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -59693,7 +63445,7 @@ func (c *ImagesGetCall) Do(opts ...googleapi.CallOption) (*Image, error) { // "image": { // "description": "Name of the image resource to return.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -59785,9 +63537,13 @@ func (c *ImagesGetFromFamilyCall) doRequest(alt string) (*http.Response, error) } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/images/family/{family}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -59845,7 +63601,7 @@ func (c *ImagesGetFromFamilyCall) Do(opts ...googleapi.CallOption) (*Image, erro // "family": { // "description": "Name of the image family to search for.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -59937,9 +63693,13 @@ func (c *ImagesGetIamPolicyCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/images/{resource}/getIamPolicy") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -60002,9 +63762,9 @@ func (c *ImagesGetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Policy, erro // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z0-9](?:[-a-z0-9_]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -60107,9 +63867,13 @@ func (c *ImagesInsertCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/images") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -60332,9 +64096,13 @@ func (c *ImagesListCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/images") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -60512,9 +64280,13 @@ func (c *ImagesSetIamPolicyCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/images/{resource}/setIamPolicy") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -60577,9 +64349,9 @@ func (c *ImagesSetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Policy, erro // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z0-9](?:[-a-z0-9_]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -60659,9 +64431,13 @@ func (c *ImagesSetLabelsCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/images/{resource}/setLabels") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -60724,9 +64500,9 @@ func (c *ImagesSetLabelsCall) Do(opts ...googleapi.CallOption) (*Operation, erro // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -60806,9 +64582,13 @@ func (c *ImagesTestIamPermissionsCall) doRequest(alt string) (*http.Response, er } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/images/{resource}/testIamPermissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -60871,9 +64651,9 @@ func (c *ImagesTestIamPermissionsCall) Do(opts ...googleapi.CallOption) (*TestPe // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "(?:[-a-z0-9_]{0,62}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -60907,15 +64687,15 @@ type InstanceGroupManagersAbandonInstancesCall struct { header_ http.Header } -// AbandonInstances: Schedules a group action to remove the specified -// instances from the managed instance group. Abandoning an instance -// does not delete the instance, but it does remove the instance from -// any target pools that are applied by the managed instance group. This -// method reduces the targetSize of the managed instance group by the -// number of instances that you abandon. This operation is marked as -// DONE when the action is scheduled even if the instances have not yet -// been removed from the group. You must separately verify the status of -// the abandoning action with the listmanagedinstances method. +// AbandonInstances: Flags the specified instances to be removed from +// the managed instance group. Abandoning an instance does not delete +// the instance, but it does remove the instance from any target pools +// that are applied by the managed instance group. This method reduces +// the targetSize of the managed instance group by the number of +// instances that you abandon. This operation is marked as DONE when the +// action is scheduled even if the instances have not yet been removed +// from the group. You must separately verify the status of the +// abandoning action with the listmanagedinstances method. // // If the group is part of a backend service that has enabled connection // draining, it can take up to 60 seconds after the connection draining @@ -60990,9 +64770,13 @@ func (c *InstanceGroupManagersAbandonInstancesCall) doRequest(alt string) (*http } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instanceGroupManagers/{instanceGroupManager}/abandonInstances") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -61040,7 +64824,7 @@ func (c *InstanceGroupManagersAbandonInstancesCall) Do(opts ...googleapi.CallOpt } return ret, nil // { - // "description": "Schedules a group action to remove the specified instances from the managed instance group. Abandoning an instance does not delete the instance, but it does remove the instance from any target pools that are applied by the managed instance group. This method reduces the targetSize of the managed instance group by the number of instances that you abandon. This operation is marked as DONE when the action is scheduled even if the instances have not yet been removed from the group. You must separately verify the status of the abandoning action with the listmanagedinstances method.\n\nIf the group is part of a backend service that has enabled connection draining, it can take up to 60 seconds after the connection draining duration has elapsed before the VM instance is removed or deleted.\n\nYou can specify a maximum of 1000 instances with this method per request.", + // "description": "Flags the specified instances to be removed from the managed instance group. Abandoning an instance does not delete the instance, but it does remove the instance from any target pools that are applied by the managed instance group. This method reduces the targetSize of the managed instance group by the number of instances that you abandon. This operation is marked as DONE when the action is scheduled even if the instances have not yet been removed from the group. You must separately verify the status of the abandoning action with the listmanagedinstances method.\n\nIf the group is part of a backend service that has enabled connection draining, it can take up to 60 seconds after the connection draining duration has elapsed before the VM instance is removed or deleted.\n\nYou can specify a maximum of 1000 instances with this method per request.", // "httpMethod": "POST", // "id": "compute.instanceGroupManagers.abandonInstances", // "parameterOrder": [ @@ -61217,9 +65001,13 @@ func (c *InstanceGroupManagersAggregatedListCall) doRequest(alt string) (*http.R } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/aggregated/instanceGroupManagers") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -61401,9 +65189,13 @@ func (c *InstanceGroupManagersApplyUpdatesToInstancesCall) doRequest(alt string) } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instanceGroupManagers/{instanceGroupManager}/applyUpdatesToInstances") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -61495,6 +65287,193 @@ func (c *InstanceGroupManagersApplyUpdatesToInstancesCall) Do(opts ...googleapi. } +// method id "compute.instanceGroupManagers.createInstances": + +type InstanceGroupManagersCreateInstancesCall struct { + s *Service + project string + zone string + instanceGroupManager string + instancegroupmanagerscreateinstancesrequest *InstanceGroupManagersCreateInstancesRequest + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// CreateInstances: Creates instances with per-instance configs in this +// managed instance group. Instances are created using the current +// instance template. The create instances operation is marked DONE if +// the createInstances request is successful. The underlying actions +// take additional time. You must separately verify the status of the +// creating or actions with the listmanagedinstances method. +func (r *InstanceGroupManagersService) CreateInstances(project string, zone string, instanceGroupManager string, instancegroupmanagerscreateinstancesrequest *InstanceGroupManagersCreateInstancesRequest) *InstanceGroupManagersCreateInstancesCall { + c := &InstanceGroupManagersCreateInstancesCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.zone = zone + c.instanceGroupManager = instanceGroupManager + c.instancegroupmanagerscreateinstancesrequest = instancegroupmanagerscreateinstancesrequest + return c +} + +// RequestId sets the optional parameter "requestId": An optional +// request ID to identify requests. Specify a unique request ID so that +// if you must retry your request, the server will know to ignore the +// request if it has already been completed. +// +// For example, consider a situation where you make an initial request +// and the request times out. If you make the request again with the +// same request ID, the server can check if original operation with the +// same request ID was received, and if so, will ignore the second +// request. +// +// The request ID must be a valid UUID with the exception that zero UUID +// is not supported (00000000-0000-0000-0000-000000000000). +func (c *InstanceGroupManagersCreateInstancesCall) RequestId(requestId string) *InstanceGroupManagersCreateInstancesCall { + c.urlParams_.Set("requestId", requestId) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *InstanceGroupManagersCreateInstancesCall) Fields(s ...googleapi.Field) *InstanceGroupManagersCreateInstancesCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *InstanceGroupManagersCreateInstancesCall) Context(ctx context.Context) *InstanceGroupManagersCreateInstancesCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *InstanceGroupManagersCreateInstancesCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *InstanceGroupManagersCreateInstancesCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.instancegroupmanagerscreateinstancesrequest) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instanceGroupManagers/{instanceGroupManager}/createInstances") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "zone": c.zone, + "instanceGroupManager": c.instanceGroupManager, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.instanceGroupManagers.createInstances" call. +// Exactly one of *Operation or error will be non-nil. Any non-2xx +// status code is an error. Response headers are in either +// *Operation.ServerResponse.Header or (if a response was returned at +// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified +// to check whether the returned error was because +// http.StatusNotModified was returned. +func (c *InstanceGroupManagersCreateInstancesCall) Do(opts ...googleapi.CallOption) (*Operation, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Operation{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Creates instances with per-instance configs in this managed instance group. Instances are created using the current instance template. The create instances operation is marked DONE if the createInstances request is successful. The underlying actions take additional time. You must separately verify the status of the creating or actions with the listmanagedinstances method.", + // "httpMethod": "POST", + // "id": "compute.instanceGroupManagers.createInstances", + // "parameterOrder": [ + // "project", + // "zone", + // "instanceGroupManager" + // ], + // "parameters": { + // "instanceGroupManager": { + // "description": "The name of the managed instance group. It should conform to RFC1035.", + // "location": "path", + // "required": true, + // "type": "string" + // }, + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "requestId": { + // "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", + // "location": "query", + // "type": "string" + // }, + // "zone": { + // "description": "The name of the zone where the managed instance group is located. It should conform to RFC1035.", + // "location": "path", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/zones/{zone}/instanceGroupManagers/{instanceGroupManager}/createInstances", + // "request": { + // "$ref": "InstanceGroupManagersCreateInstancesRequest" + // }, + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + // method id "compute.instanceGroupManagers.delete": type InstanceGroupManagersDeleteCall struct { @@ -61571,9 +65550,13 @@ func (c *InstanceGroupManagersDeleteCall) doRequest(alt string) (*http.Response, reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instanceGroupManagers/{instanceGroupManager}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -61680,14 +65663,14 @@ type InstanceGroupManagersDeleteInstancesCall struct { header_ http.Header } -// DeleteInstances: Schedules a group action to delete the specified -// instances in the managed instance group. The instances are also -// removed from any target pools of which they were a member. This -// method reduces the targetSize of the managed instance group by the -// number of instances that you delete. This operation is marked as DONE -// when the action is scheduled even if the instances are still being -// deleted. You must separately verify the status of the deleting action -// with the listmanagedinstances method. +// DeleteInstances: Flags the specified instances in the managed +// instance group for immediate deletion. The instances are also removed +// from any target pools of which they were a member. This method +// reduces the targetSize of the managed instance group by the number of +// instances that you delete. This operation is marked as DONE when the +// action is scheduled even if the instances are still being deleted. +// You must separately verify the status of the deleting action with the +// listmanagedinstances method. // // If the group is part of a backend service that has enabled connection // draining, it can take up to 60 seconds after the connection draining @@ -61762,9 +65745,13 @@ func (c *InstanceGroupManagersDeleteInstancesCall) doRequest(alt string) (*http. } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instanceGroupManagers/{instanceGroupManager}/deleteInstances") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -61812,7 +65799,7 @@ func (c *InstanceGroupManagersDeleteInstancesCall) Do(opts ...googleapi.CallOpti } return ret, nil // { - // "description": "Schedules a group action to delete the specified instances in the managed instance group. The instances are also removed from any target pools of which they were a member. This method reduces the targetSize of the managed instance group by the number of instances that you delete. This operation is marked as DONE when the action is scheduled even if the instances are still being deleted. You must separately verify the status of the deleting action with the listmanagedinstances method.\n\nIf the group is part of a backend service that has enabled connection draining, it can take up to 60 seconds after the connection draining duration has elapsed before the VM instance is removed or deleted.\n\nYou can specify a maximum of 1000 instances with this method per request.", + // "description": "Flags the specified instances in the managed instance group for immediate deletion. The instances are also removed from any target pools of which they were a member. This method reduces the targetSize of the managed instance group by the number of instances that you delete. This operation is marked as DONE when the action is scheduled even if the instances are still being deleted. You must separately verify the status of the deleting action with the listmanagedinstances method.\n\nIf the group is part of a backend service that has enabled connection draining, it can take up to 60 seconds after the connection draining duration has elapsed before the VM instance is removed or deleted.\n\nYou can specify a maximum of 1000 instances with this method per request.", // "httpMethod": "POST", // "id": "compute.instanceGroupManagers.deleteInstances", // "parameterOrder": [ @@ -61923,9 +65910,13 @@ func (c *InstanceGroupManagersDeletePerInstanceConfigsCall) doRequest(alt string } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instanceGroupManagers/{instanceGroupManager}/deletePerInstanceConfigs") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -62087,9 +66078,13 @@ func (c *InstanceGroupManagersGetCall) doRequest(alt string) (*http.Response, er } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instanceGroupManagers/{instanceGroupManager}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -62192,12 +66187,12 @@ type InstanceGroupManagersInsertCall struct { } // Insert: Creates a managed instance group using the information that -// you specify in the request. After the group is created, it schedules -// an action to create instances in the group using the specified -// instance template. This operation is marked as DONE when the group is -// created even if the instances in the group have not yet been created. -// You must separately verify the status of the individual instances -// with the listmanagedinstances method. +// you specify in the request. After the group is created, instances in +// the group are created using the specified instance template. This +// operation is marked as DONE when the group is created even if the +// instances in the group have not yet been created. You must separately +// verify the status of the individual instances with the +// listmanagedinstances method. // // A managed instance group can have up to 1000 VM instances per group. // Please contact Cloud Support if you need an increase in this limit. @@ -62266,9 +66261,13 @@ func (c *InstanceGroupManagersInsertCall) doRequest(alt string) (*http.Response, } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instanceGroupManagers") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -62315,7 +66314,7 @@ func (c *InstanceGroupManagersInsertCall) Do(opts ...googleapi.CallOption) (*Ope } return ret, nil // { - // "description": "Creates a managed instance group using the information that you specify in the request. After the group is created, it schedules an action to create instances in the group using the specified instance template. This operation is marked as DONE when the group is created even if the instances in the group have not yet been created. You must separately verify the status of the individual instances with the listmanagedinstances method.\n\nA managed instance group can have up to 1000 VM instances per group. Please contact Cloud Support if you need an increase in this limit.", + // "description": "Creates a managed instance group using the information that you specify in the request. After the group is created, instances in the group are created using the specified instance template. This operation is marked as DONE when the group is created even if the instances in the group have not yet been created. You must separately verify the status of the individual instances with the listmanagedinstances method.\n\nA managed instance group can have up to 1000 VM instances per group. Please contact Cloud Support if you need an increase in this limit.", // "httpMethod": "POST", // "id": "compute.instanceGroupManagers.insert", // "parameterOrder": [ @@ -62487,9 +66486,13 @@ func (c *InstanceGroupManagersListCall) doRequest(alt string) (*http.Response, e } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instanceGroupManagers") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -62641,25 +66644,64 @@ func (r *InstanceGroupManagersService) ListManagedInstances(project string, zone return c } -// Filter sets the optional parameter "filter": +// Filter sets the optional parameter "filter": A filter expression that +// filters resources listed in the response. The expression must specify +// the field name, a comparison operator, and the value that you want to +// use for filtering. The value must be a string, a number, or a +// boolean. The comparison operator must be either =, !=, >, or <. +// +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. +// +// You can also filter nested fields. For example, you could specify +// scheduling.automaticRestart = false to include instances only if they +// are not scheduled for automatic restarts. You can use filtering on +// nested fields to filter based on resource labels. +// +// To filter on multiple expressions, provide each separate expression +// within parentheses. For example, (scheduling.automaticRestart = true) +// (cpuPlatform = "Intel Skylake"). By default, each expression is an +// AND expression. However, you can include AND and OR expressions +// explicitly. For example, (cpuPlatform = "Intel Skylake") OR +// (cpuPlatform = "Intel Broadwell") AND (scheduling.automaticRestart = +// true). func (c *InstanceGroupManagersListManagedInstancesCall) Filter(filter string) *InstanceGroupManagersListManagedInstancesCall { c.urlParams_.Set("filter", filter) return c } -// MaxResults sets the optional parameter "maxResults": +// MaxResults sets the optional parameter "maxResults": The maximum +// number of results per page that should be returned. If the number of +// available results is larger than maxResults, Compute Engine returns a +// nextPageToken that can be used to get the next page of results in +// subsequent list requests. Acceptable values are 0 to 500, inclusive. +// (Default: 500) func (c *InstanceGroupManagersListManagedInstancesCall) MaxResults(maxResults int64) *InstanceGroupManagersListManagedInstancesCall { c.urlParams_.Set("maxResults", fmt.Sprint(maxResults)) return c } -// OrderBy sets the optional parameter "order_by": +// OrderBy sets the optional parameter "order_by": Sorts list results by +// a certain order. By default, results are returned in alphanumerical +// order based on the resource name. +// +// You can also sort results in descending order based on the creation +// timestamp using orderBy="creationTimestamp desc". This sorts results +// based on the creationTimestamp field in reverse chronological order +// (newest result first). Use this to sort resources like operations so +// that the newest operation is returned first. +// +// Currently, only sorting by name or creationTimestamp desc is +// supported. func (c *InstanceGroupManagersListManagedInstancesCall) OrderBy(orderBy string) *InstanceGroupManagersListManagedInstancesCall { c.urlParams_.Set("order_by", orderBy) return c } -// PageToken sets the optional parameter "pageToken": +// PageToken sets the optional parameter "pageToken": Specifies a page +// token to use. Set pageToken to the nextPageToken returned by a +// previous list request to get the next page of results. func (c *InstanceGroupManagersListManagedInstancesCall) PageToken(pageToken string) *InstanceGroupManagersListManagedInstancesCall { c.urlParams_.Set("pageToken", pageToken) return c @@ -62698,9 +66740,13 @@ func (c *InstanceGroupManagersListManagedInstancesCall) doRequest(alt string) (* reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instanceGroupManagers/{instanceGroupManager}/listManagedInstances") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -62760,6 +66806,7 @@ func (c *InstanceGroupManagersListManagedInstancesCall) Do(opts ...googleapi.Cal // ], // "parameters": { // "filter": { + // "description": "A filter expression that filters resources listed in the response. The expression must specify the field name, a comparison operator, and the value that you want to use for filtering. The value must be a string, a number, or a boolean. The comparison operator must be either =, !=, \u003e, or \u003c.\n\nFor example, if you are filtering Compute Engine instances, you can exclude instances named example-instance by specifying name != example-instance.\n\nYou can also filter nested fields. For example, you could specify scheduling.automaticRestart = false to include instances only if they are not scheduled for automatic restarts. You can use filtering on nested fields to filter based on resource labels.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart = true) (cpuPlatform = \"Intel Skylake\"). By default, each expression is an AND expression. However, you can include AND and OR expressions explicitly. For example, (cpuPlatform = \"Intel Skylake\") OR (cpuPlatform = \"Intel Broadwell\") AND (scheduling.automaticRestart = true).", // "location": "query", // "type": "string" // }, @@ -62771,16 +66818,19 @@ func (c *InstanceGroupManagersListManagedInstancesCall) Do(opts ...googleapi.Cal // }, // "maxResults": { // "default": "500", + // "description": "The maximum number of results per page that should be returned. If the number of available results is larger than maxResults, Compute Engine returns a nextPageToken that can be used to get the next page of results in subsequent list requests. Acceptable values are 0 to 500, inclusive. (Default: 500)", // "format": "uint32", // "location": "query", // "minimum": "0", // "type": "integer" // }, // "order_by": { + // "description": "Sorts list results by a certain order. By default, results are returned in alphanumerical order based on the resource name.\n\nYou can also sort results in descending order based on the creation timestamp using orderBy=\"creationTimestamp desc\". This sorts results based on the creationTimestamp field in reverse chronological order (newest result first). Use this to sort resources like operations so that the newest operation is returned first.\n\nCurrently, only sorting by name or creationTimestamp desc is supported.", // "location": "query", // "type": "string" // }, // "pageToken": { + // "description": "Specifies a page token to use. Set pageToken to the nextPageToken returned by a previous list request to get the next page of results.", // "location": "query", // "type": "string" // }, @@ -62950,9 +67000,13 @@ func (c *InstanceGroupManagersListPerInstanceConfigsCall) doRequest(alt string) reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instanceGroupManagers/{instanceGroupManager}/listPerInstanceConfigs") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -63174,9 +67228,13 @@ func (c *InstanceGroupManagersPatchCall) doRequest(alt string) (*http.Response, } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instanceGroupManagers/{instanceGroupManager}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PATCH", urls, body) + req, err := http.NewRequest("PATCH", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -63286,11 +67344,11 @@ type InstanceGroupManagersRecreateInstancesCall struct { header_ http.Header } -// RecreateInstances: Schedules a group action to recreate the specified -// instances in the managed instance group. The instances are deleted +// RecreateInstances: Flags the specified instances in the managed +// instance group to be immediately recreated. The instances are deleted // and recreated using the current instance template for the managed -// instance group. This operation is marked as DONE when the action is -// scheduled even if the instances have not yet been recreated. You must +// instance group. This operation is marked as DONE when the flag is set +// even if the instances have not yet been recreated. You must // separately verify the status of the recreating action with the // listmanagedinstances method. // @@ -63367,9 +67425,13 @@ func (c *InstanceGroupManagersRecreateInstancesCall) doRequest(alt string) (*htt } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instanceGroupManagers/{instanceGroupManager}/recreateInstances") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -63417,7 +67479,7 @@ func (c *InstanceGroupManagersRecreateInstancesCall) Do(opts ...googleapi.CallOp } return ret, nil // { - // "description": "Schedules a group action to recreate the specified instances in the managed instance group. The instances are deleted and recreated using the current instance template for the managed instance group. This operation is marked as DONE when the action is scheduled even if the instances have not yet been recreated. You must separately verify the status of the recreating action with the listmanagedinstances method.\n\nIf the group is part of a backend service that has enabled connection draining, it can take up to 60 seconds after the connection draining duration has elapsed before the VM instance is removed or deleted.\n\nYou can specify a maximum of 1000 instances with this method per request.", + // "description": "Flags the specified instances in the managed instance group to be immediately recreated. The instances are deleted and recreated using the current instance template for the managed instance group. This operation is marked as DONE when the flag is set even if the instances have not yet been recreated. You must separately verify the status of the recreating action with the listmanagedinstances method.\n\nIf the group is part of a backend service that has enabled connection draining, it can take up to 60 seconds after the connection draining duration has elapsed before the VM instance is removed or deleted.\n\nYou can specify a maximum of 1000 instances with this method per request.", // "httpMethod": "POST", // "id": "compute.instanceGroupManagers.recreateInstances", // "parameterOrder": [ @@ -63486,6 +67548,16 @@ type InstanceGroupManagersResizeCall struct { // separately verify the status of the creating or deleting actions with // the listmanagedinstances method. // +// When resizing down, the instance group arbitrarily chooses the order +// in which VMs are deleted. The group takes into account some VM +// attributes when making the selection including: +// +// + The status of the VM instance. + The health of the VM instance. + +// The instance template version the VM is based on. + For regional +// managed instance groups, the location of the VM instance. +// +// This list is subject to change. +// // If the group is part of a backend service that has enabled connection // draining, it can take up to 60 seconds after the connection draining // duration has elapsed before the VM instance is removed or deleted. @@ -63550,9 +67622,13 @@ func (c *InstanceGroupManagersResizeCall) doRequest(alt string) (*http.Response, reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instanceGroupManagers/{instanceGroupManager}/resize") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -63600,7 +67676,7 @@ func (c *InstanceGroupManagersResizeCall) Do(opts ...googleapi.CallOption) (*Ope } return ret, nil // { - // "description": "Resizes the managed instance group. If you increase the size, the group creates new instances using the current instance template. If you decrease the size, the group deletes instances. The resize operation is marked DONE when the resize actions are scheduled even if the group has not yet added or deleted any instances. You must separately verify the status of the creating or deleting actions with the listmanagedinstances method.\n\nIf the group is part of a backend service that has enabled connection draining, it can take up to 60 seconds after the connection draining duration has elapsed before the VM instance is removed or deleted.", + // "description": "Resizes the managed instance group. If you increase the size, the group creates new instances using the current instance template. If you decrease the size, the group deletes instances. The resize operation is marked DONE when the resize actions are scheduled even if the group has not yet added or deleted any instances. You must separately verify the status of the creating or deleting actions with the listmanagedinstances method.\n\nWhen resizing down, the instance group arbitrarily chooses the order in which VMs are deleted. The group takes into account some VM attributes when making the selection including:\n\n+ The status of the VM instance. + The health of the VM instance. + The instance template version the VM is based on. + For regional managed instance groups, the location of the VM instance.\n\nThis list is subject to change.\n\nIf the group is part of a backend service that has enabled connection draining, it can take up to 60 seconds after the connection draining duration has elapsed before the VM instance is removed or deleted.", // "httpMethod": "POST", // "id": "compute.instanceGroupManagers.resize", // "parameterOrder": [ @@ -63748,9 +67824,13 @@ func (c *InstanceGroupManagersResizeAdvancedCall) doRequest(alt string) (*http.R } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instanceGroupManagers/{instanceGroupManager}/resizeAdvanced") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -63861,6 +67941,7 @@ type InstanceGroupManagersSetAutoHealingPoliciesCall struct { } // SetAutoHealingPolicies: Modifies the autohealing policies. +// [Deprecated] This method is deprecated. Please use Patch instead. func (r *InstanceGroupManagersService) SetAutoHealingPolicies(project string, zone string, instanceGroupManager string, instancegroupmanagerssetautohealingrequest *InstanceGroupManagersSetAutoHealingRequest) *InstanceGroupManagersSetAutoHealingPoliciesCall { c := &InstanceGroupManagersSetAutoHealingPoliciesCall{s: r.s, urlParams_: make(gensupport.URLParams)} c.project = project @@ -63927,9 +68008,13 @@ func (c *InstanceGroupManagersSetAutoHealingPoliciesCall) doRequest(alt string) } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instanceGroupManagers/{instanceGroupManager}/setAutoHealingPolicies") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -63977,7 +68062,7 @@ func (c *InstanceGroupManagersSetAutoHealingPoliciesCall) Do(opts ...googleapi.C } return ret, nil // { - // "description": "Modifies the autohealing policies.", + // "description": "Modifies the autohealing policies. [Deprecated] This method is deprecated. Please use Patch instead.", // "httpMethod": "POST", // "id": "compute.instanceGroupManagers.setAutoHealingPolicies", // "parameterOrder": [ @@ -64108,9 +68193,13 @@ func (c *InstanceGroupManagersSetInstanceTemplateCall) doRequest(alt string) (*h } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instanceGroupManagers/{instanceGroupManager}/setInstanceTemplate") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -64293,9 +68382,13 @@ func (c *InstanceGroupManagersSetTargetPoolsCall) doRequest(alt string) (*http.R } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instanceGroupManagers/{instanceGroupManager}/setTargetPools") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -64454,9 +68547,13 @@ func (c *InstanceGroupManagersTestIamPermissionsCall) doRequest(alt string) (*ht } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instanceGroupManagers/{resource}/testIamPermissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -64521,9 +68618,9 @@ func (c *InstanceGroupManagersTestIamPermissionsCall) Do(opts ...googleapi.CallO // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -64635,9 +68732,13 @@ func (c *InstanceGroupManagersUpdateCall) doRequest(alt string) (*http.Response, } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instanceGroupManagers/{instanceGroupManager}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PUT", urls, body) + req, err := http.NewRequest("PUT", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -64817,9 +68918,13 @@ func (c *InstanceGroupManagersUpdatePerInstanceConfigsCall) doRequest(alt string } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instanceGroupManagers/{instanceGroupManager}/updatePerInstanceConfigs") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -64998,9 +69103,13 @@ func (c *InstanceGroupsAddInstancesCall) doRequest(alt string) (*http.Response, } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instanceGroups/{instanceGroup}/addInstances") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -65225,9 +69334,13 @@ func (c *InstanceGroupsAggregatedListCall) doRequest(alt string) (*http.Response } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/aggregated/instanceGroups") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -65421,9 +69534,13 @@ func (c *InstanceGroupsDeleteCall) doRequest(alt string) (*http.Response, error) reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instanceGroups/{instanceGroup}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -65586,9 +69703,13 @@ func (c *InstanceGroupsGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instanceGroups/{instanceGroup}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -65757,9 +69878,13 @@ func (c *InstanceGroupsInsertCall) doRequest(alt string) (*http.Response, error) } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instanceGroups") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -65978,9 +70103,13 @@ func (c *InstanceGroupsListCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instanceGroups") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -66230,9 +70359,13 @@ func (c *InstanceGroupsListInstancesCall) doRequest(alt string) (*http.Response, } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instanceGroups/{instanceGroup}/listInstances") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -66454,9 +70587,13 @@ func (c *InstanceGroupsRemoveInstancesCall) doRequest(alt string) (*http.Respons } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instanceGroups/{instanceGroup}/removeInstances") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -66633,9 +70770,13 @@ func (c *InstanceGroupsSetNamedPortsCall) doRequest(alt string) (*http.Response, } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instanceGroups/{instanceGroup}/setNamedPorts") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -66794,9 +70935,13 @@ func (c *InstanceGroupsTestIamPermissionsCall) doRequest(alt string) (*http.Resp } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instanceGroups/{resource}/testIamPermissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -66861,9 +71006,9 @@ func (c *InstanceGroupsTestIamPermissionsCall) Do(opts ...googleapi.CallOption) // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -66965,9 +71110,13 @@ func (c *InstanceTemplatesDeleteCall) doRequest(alt string) (*http.Response, err reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/instanceTemplates/{instanceTemplate}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -67122,9 +71271,13 @@ func (c *InstanceTemplatesGetCall) doRequest(alt string) (*http.Response, error) } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/instanceTemplates/{instanceTemplate}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -67207,6 +71360,162 @@ func (c *InstanceTemplatesGetCall) Do(opts ...googleapi.CallOption) (*InstanceTe } +// method id "compute.instanceTemplates.getIamPolicy": + +type InstanceTemplatesGetIamPolicyCall struct { + s *Service + project string + resource string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// GetIamPolicy: Gets the access control policy for a resource. May be +// empty if no such policy or resource exists. +func (r *InstanceTemplatesService) GetIamPolicy(project string, resource string) *InstanceTemplatesGetIamPolicyCall { + c := &InstanceTemplatesGetIamPolicyCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.resource = resource + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *InstanceTemplatesGetIamPolicyCall) Fields(s ...googleapi.Field) *InstanceTemplatesGetIamPolicyCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// IfNoneMatch sets the optional parameter which makes the operation +// fail if the object's ETag matches the given value. This is useful for +// getting updates only after the object has changed since the last +// request. Use googleapi.IsNotModified to check whether the response +// error from Do is the result of In-None-Match. +func (c *InstanceTemplatesGetIamPolicyCall) IfNoneMatch(entityTag string) *InstanceTemplatesGetIamPolicyCall { + c.ifNoneMatch_ = entityTag + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *InstanceTemplatesGetIamPolicyCall) Context(ctx context.Context) *InstanceTemplatesGetIamPolicyCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *InstanceTemplatesGetIamPolicyCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *InstanceTemplatesGetIamPolicyCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + if c.ifNoneMatch_ != "" { + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) + } + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/instanceTemplates/{resource}/getIamPolicy") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "resource": c.resource, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.instanceTemplates.getIamPolicy" call. +// Exactly one of *Policy or error will be non-nil. Any non-2xx status +// code is an error. Response headers are in either +// *Policy.ServerResponse.Header or (if a response was returned at all) +// in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to +// check whether the returned error was because http.StatusNotModified +// was returned. +func (c *InstanceTemplatesGetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Policy, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Policy{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Gets the access control policy for a resource. May be empty if no such policy or resource exists.", + // "httpMethod": "GET", + // "id": "compute.instanceTemplates.getIamPolicy", + // "parameterOrder": [ + // "project", + // "resource" + // ], + // "parameters": { + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "resource": { + // "description": "Name or id of the resource for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/global/instanceTemplates/{resource}/getIamPolicy", + // "response": { + // "$ref": "Policy" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute", + // "https://www.googleapis.com/auth/compute.readonly" + // ] + // } + +} + // method id "compute.instanceTemplates.insert": type InstanceTemplatesInsertCall struct { @@ -67288,9 +71597,13 @@ func (c *InstanceTemplatesInsertCall) doRequest(alt string) (*http.Response, err } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/instanceTemplates") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -67500,9 +71813,13 @@ func (c *InstanceTemplatesListCall) doRequest(alt string) (*http.Response, error } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/instanceTemplates") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -67620,6 +71937,157 @@ func (c *InstanceTemplatesListCall) Pages(ctx context.Context, f func(*InstanceT } } +// method id "compute.instanceTemplates.setIamPolicy": + +type InstanceTemplatesSetIamPolicyCall struct { + s *Service + project string + resource string + globalsetpolicyrequest *GlobalSetPolicyRequest + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// SetIamPolicy: Sets the access control policy on the specified +// resource. Replaces any existing policy. +func (r *InstanceTemplatesService) SetIamPolicy(project string, resource string, globalsetpolicyrequest *GlobalSetPolicyRequest) *InstanceTemplatesSetIamPolicyCall { + c := &InstanceTemplatesSetIamPolicyCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.resource = resource + c.globalsetpolicyrequest = globalsetpolicyrequest + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *InstanceTemplatesSetIamPolicyCall) Fields(s ...googleapi.Field) *InstanceTemplatesSetIamPolicyCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *InstanceTemplatesSetIamPolicyCall) Context(ctx context.Context) *InstanceTemplatesSetIamPolicyCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *InstanceTemplatesSetIamPolicyCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *InstanceTemplatesSetIamPolicyCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.globalsetpolicyrequest) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/instanceTemplates/{resource}/setIamPolicy") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "resource": c.resource, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.instanceTemplates.setIamPolicy" call. +// Exactly one of *Policy or error will be non-nil. Any non-2xx status +// code is an error. Response headers are in either +// *Policy.ServerResponse.Header or (if a response was returned at all) +// in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to +// check whether the returned error was because http.StatusNotModified +// was returned. +func (c *InstanceTemplatesSetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Policy, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Policy{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Sets the access control policy on the specified resource. Replaces any existing policy.", + // "httpMethod": "POST", + // "id": "compute.instanceTemplates.setIamPolicy", + // "parameterOrder": [ + // "project", + // "resource" + // ], + // "parameters": { + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "resource": { + // "description": "Name or id of the resource for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/global/instanceTemplates/{resource}/setIamPolicy", + // "request": { + // "$ref": "GlobalSetPolicyRequest" + // }, + // "response": { + // "$ref": "Policy" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + // method id "compute.instanceTemplates.testIamPermissions": type InstanceTemplatesTestIamPermissionsCall struct { @@ -67680,9 +72148,13 @@ func (c *InstanceTemplatesTestIamPermissionsCall) doRequest(alt string) (*http.R } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/instanceTemplates/{resource}/testIamPermissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -67745,9 +72217,9 @@ func (c *InstanceTemplatesTestIamPermissionsCall) Do(opts ...googleapi.CallOptio // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "(?:[-a-z0-9_]{0,62}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -67851,9 +72323,13 @@ func (c *InstancesAddAccessConfigCall) doRequest(alt string) (*http.Response, er } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{instance}/addAccessConfig") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -67914,7 +72390,7 @@ func (c *InstancesAddAccessConfigCall) Do(opts ...googleapi.CallOption) (*Operat // "instance": { // "description": "The instance name for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -68041,9 +72517,13 @@ func (c *InstancesAddResourcePoliciesCall) doRequest(alt string) (*http.Response } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{instance}/addResourcePolicies") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -68103,7 +72583,7 @@ func (c *InstancesAddResourcePoliciesCall) Do(opts ...googleapi.CallOption) (*Op // "instance": { // "description": "The instance name for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -68153,7 +72633,8 @@ type InstancesAggregatedListCall struct { header_ http.Header } -// AggregatedList: Retrieves aggregated list of instances. +// AggregatedList: Retrieves aggregated list of all of the instances in +// your project across all regions and zones. // For details, see https://cloud.google.com/compute/docs/reference/latest/instances/aggregatedList func (r *InstancesService) AggregatedList(project string) *InstancesAggregatedListCall { c := &InstancesAggregatedListCall{s: r.s, urlParams_: make(gensupport.URLParams)} @@ -68270,9 +72751,13 @@ func (c *InstancesAggregatedListCall) doRequest(alt string) (*http.Response, err } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/aggregated/instances") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -68318,7 +72803,7 @@ func (c *InstancesAggregatedListCall) Do(opts ...googleapi.CallOption) (*Instanc } return ret, nil // { - // "description": "Retrieves aggregated list of instances.", + // "description": "Retrieves aggregated list of all of the instances in your project across all regions and zones.", // "httpMethod": "GET", // "id": "compute.instances.aggregatedList", // "parameterOrder": [ @@ -68482,9 +72967,13 @@ func (c *InstancesAttachDiskCall) doRequest(alt string) (*http.Response, error) } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{instance}/attachDisk") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -68549,7 +73038,7 @@ func (c *InstancesAttachDiskCall) Do(opts ...googleapi.CallOption) (*Operation, // "instance": { // "description": "The instance name for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -68663,9 +73152,13 @@ func (c *InstancesDeleteCall) doRequest(alt string) (*http.Response, error) { reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{instance}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -68725,7 +73218,7 @@ func (c *InstancesDeleteCall) Do(opts ...googleapi.CallOption) (*Operation, erro // "instance": { // "description": "Name of the instance resource to delete.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -68838,9 +73331,13 @@ func (c *InstancesDeleteAccessConfigCall) doRequest(alt string) (*http.Response, reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{instance}/deleteAccessConfig") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -68908,7 +73405,7 @@ func (c *InstancesDeleteAccessConfigCall) Do(opts ...googleapi.CallOption) (*Ope // "instance": { // "description": "The instance name for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -69025,9 +73522,13 @@ func (c *InstancesDetachDiskCall) doRequest(alt string) (*http.Response, error) reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{instance}/detachDisk") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -69086,15 +73587,15 @@ func (c *InstancesDetachDiskCall) Do(opts ...googleapi.CallOption) (*Operation, // ], // "parameters": { // "deviceName": { - // "description": "Disk device name to detach.", + // "description": "The device name of the disk to detach. Make a get() request on the instance to view currently attached disks and device names.", // "location": "query", // "required": true, // "type": "string" // }, // "instance": { - // "description": "Instance name.", + // "description": "Instance name for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -69200,9 +73701,13 @@ func (c *InstancesGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{instance}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -69262,7 +73767,7 @@ func (c *InstancesGetCall) Do(opts ...googleapi.CallOption) (*Instance, error) { // "instance": { // "description": "Name of the instance resource to return.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -69316,6 +73821,13 @@ func (r *InstancesService) GetGuestAttributes(project string, zone string, insta return c } +// QueryPath sets the optional parameter "queryPath": Specifies the +// guest attributes path to be queried. +func (c *InstancesGetGuestAttributesCall) QueryPath(queryPath string) *InstancesGetGuestAttributesCall { + c.urlParams_.Set("queryPath", queryPath) + return c +} + // VariableKey sets the optional parameter "variableKey": Specifies the // key for the guest attributes entry. func (c *InstancesGetGuestAttributesCall) VariableKey(variableKey string) *InstancesGetGuestAttributesCall { @@ -69369,9 +73881,13 @@ func (c *InstancesGetGuestAttributesCall) doRequest(alt string) (*http.Response, } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{instance}/getGuestAttributes") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -69431,7 +73947,7 @@ func (c *InstancesGetGuestAttributesCall) Do(opts ...googleapi.CallOption) (*Gue // "instance": { // "description": "Name of the instance scoping this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -69442,6 +73958,11 @@ func (c *InstancesGetGuestAttributesCall) Do(opts ...googleapi.CallOption) (*Gue // "required": true, // "type": "string" // }, + // "queryPath": { + // "description": "Specifies the guest attributes path to be queried.", + // "location": "query", + // "type": "string" + // }, // "variableKey": { // "description": "Specifies the key for the guest attributes entry.", // "location": "query", @@ -69537,9 +74058,13 @@ func (c *InstancesGetIamPolicyCall) doRequest(alt string) (*http.Response, error } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{resource}/getIamPolicy") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -69604,9 +74129,9 @@ func (c *InstancesGetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Policy, e // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -69644,8 +74169,8 @@ type InstancesGetSerialPortOutputCall struct { header_ http.Header } -// GetSerialPortOutput: Returns the specified instance's serial port -// output. +// GetSerialPortOutput: Returns the last 1 MB of serial port output from +// the specified instance. // For details, see https://cloud.google.com/compute/docs/reference/latest/instances/getSerialPortOutput func (r *InstancesService) GetSerialPortOutput(project string, zone string, instance string) *InstancesGetSerialPortOutputCall { c := &InstancesGetSerialPortOutputCall{s: r.s, urlParams_: make(gensupport.URLParams)} @@ -69719,9 +74244,13 @@ func (c *InstancesGetSerialPortOutputCall) doRequest(alt string) (*http.Response } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{instance}/serialPort") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -69769,7 +74298,7 @@ func (c *InstancesGetSerialPortOutputCall) Do(opts ...googleapi.CallOption) (*Se } return ret, nil // { - // "description": "Returns the specified instance's serial port output.", + // "description": "Returns the last 1 MB of serial port output from the specified instance.", // "httpMethod": "GET", // "id": "compute.instances.getSerialPortOutput", // "parameterOrder": [ @@ -69781,7 +74310,7 @@ func (c *InstancesGetSerialPortOutputCall) Do(opts ...googleapi.CallOption) (*Se // "instance": { // "description": "Name of the instance scoping this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -69828,6 +74357,173 @@ func (c *InstancesGetSerialPortOutputCall) Do(opts ...googleapi.CallOption) (*Se } +// method id "compute.instances.getShieldedVmIdentity": + +type InstancesGetShieldedVmIdentityCall struct { + s *Service + project string + zone string + instance string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// GetShieldedVmIdentity: Returns the Shielded VM Identity of an +// instance +func (r *InstancesService) GetShieldedVmIdentity(project string, zone string, instance string) *InstancesGetShieldedVmIdentityCall { + c := &InstancesGetShieldedVmIdentityCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.zone = zone + c.instance = instance + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *InstancesGetShieldedVmIdentityCall) Fields(s ...googleapi.Field) *InstancesGetShieldedVmIdentityCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// IfNoneMatch sets the optional parameter which makes the operation +// fail if the object's ETag matches the given value. This is useful for +// getting updates only after the object has changed since the last +// request. Use googleapi.IsNotModified to check whether the response +// error from Do is the result of In-None-Match. +func (c *InstancesGetShieldedVmIdentityCall) IfNoneMatch(entityTag string) *InstancesGetShieldedVmIdentityCall { + c.ifNoneMatch_ = entityTag + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *InstancesGetShieldedVmIdentityCall) Context(ctx context.Context) *InstancesGetShieldedVmIdentityCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *InstancesGetShieldedVmIdentityCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *InstancesGetShieldedVmIdentityCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + if c.ifNoneMatch_ != "" { + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) + } + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{instance}/getShieldedVmIdentity") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "zone": c.zone, + "instance": c.instance, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.instances.getShieldedVmIdentity" call. +// Exactly one of *ShieldedVmIdentity or error will be non-nil. Any +// non-2xx status code is an error. Response headers are in either +// *ShieldedVmIdentity.ServerResponse.Header or (if a response was +// returned at all) in error.(*googleapi.Error).Header. Use +// googleapi.IsNotModified to check whether the returned error was +// because http.StatusNotModified was returned. +func (c *InstancesGetShieldedVmIdentityCall) Do(opts ...googleapi.CallOption) (*ShieldedVmIdentity, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &ShieldedVmIdentity{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Returns the Shielded VM Identity of an instance", + // "httpMethod": "GET", + // "id": "compute.instances.getShieldedVmIdentity", + // "parameterOrder": [ + // "project", + // "zone", + // "instance" + // ], + // "parameters": { + // "instance": { + // "description": "Name of the instance scoping this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + // "required": true, + // "type": "string" + // }, + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "zone": { + // "description": "The name of the zone for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/zones/{zone}/instances/{instance}/getShieldedVmIdentity", + // "response": { + // "$ref": "ShieldedVmIdentity" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute", + // "https://www.googleapis.com/auth/compute.readonly" + // ] + // } + +} + // method id "compute.instances.insert": type InstancesInsertCall struct { @@ -69877,15 +74573,28 @@ func (c *InstancesInsertCall) RequestId(requestId string) *InstancesInsertCall { // This field is optional. It can be a full or partial URL. For example, // the following are all valid URLs to an instance template: // - -// https://www.googleapis.com/compute/v1/projects/project/global/global/instanceTemplates/instanceTemplate -// - projects/project/global/global/instanceTemplates/instanceTemplate -// -// - global/instancesTemplates/instanceTemplate +// https://www.googleapis.com/compute/v1/projects/project/global/instanceTemplates/instanceTemplate +// - projects/project/global/instanceTemplates/instanceTemplate +// - global/instanceTemplates/instanceTemplate func (c *InstancesInsertCall) SourceInstanceTemplate(sourceInstanceTemplate string) *InstancesInsertCall { c.urlParams_.Set("sourceInstanceTemplate", sourceInstanceTemplate) return c } +// SourceMachineImage sets the optional parameter "sourceMachineImage": +// Specifies instance machine to create the instance. +// +// This field is optional. It can be a full or partial URL. For example, +// the following are all valid URLs to an instance template: +// - +// https://www.googleapis.com/compute/v1/projects/project/global/global/machineImages/machineImage +// - projects/project/global/global/machineImages/machineImage +// - global/machineImages/machineImage +func (c *InstancesInsertCall) SourceMachineImage(sourceMachineImage string) *InstancesInsertCall { + c.urlParams_.Set("sourceMachineImage", sourceMachineImage) + return c +} + // Fields allows partial responses to be retrieved. See // https://developers.google.com/gdata/docs/2.0/basics#PartialResponse // for more information. @@ -69924,9 +74633,13 @@ func (c *InstancesInsertCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -69994,7 +74707,12 @@ func (c *InstancesInsertCall) Do(opts ...googleapi.CallOption) (*Operation, erro // "type": "string" // }, // "sourceInstanceTemplate": { - // "description": "Specifies instance template to create the instance.\n\nThis field is optional. It can be a full or partial URL. For example, the following are all valid URLs to an instance template: \n- https://www.googleapis.com/compute/v1/projects/project/global/global/instanceTemplates/instanceTemplate \n- projects/project/global/global/instanceTemplates/instanceTemplate \n- global/instancesTemplates/instanceTemplate", + // "description": "Specifies instance template to create the instance.\n\nThis field is optional. It can be a full or partial URL. For example, the following are all valid URLs to an instance template: \n- https://www.googleapis.com/compute/v1/projects/project/global/instanceTemplates/instanceTemplate \n- projects/project/global/instanceTemplates/instanceTemplate \n- global/instanceTemplates/instanceTemplate", + // "location": "query", + // "type": "string" + // }, + // "sourceMachineImage": { + // "description": "Specifies instance machine to create the instance.\n\nThis field is optional. It can be a full or partial URL. For example, the following are all valid URLs to an instance template: \n- https://www.googleapis.com/compute/v1/projects/project/global/global/machineImages/machineImage \n- projects/project/global/global/machineImages/machineImage \n- global/machineImages/machineImage", // "location": "query", // "type": "string" // }, @@ -70152,9 +74870,13 @@ func (c *InstancesListCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -70295,7 +75017,8 @@ type InstancesListReferrersCall struct { } // ListReferrers: Retrieves the list of referrers to instances contained -// within the specified zone. +// within the specified zone. For more information, read Viewing +// Referrers to VM Instances. func (r *InstancesService) ListReferrers(project string, zone string, instance string) *InstancesListReferrersCall { c := &InstancesListReferrersCall{s: r.s, urlParams_: make(gensupport.URLParams)} c.project = project @@ -70413,9 +75136,13 @@ func (c *InstancesListReferrersCall) doRequest(alt string) (*http.Response, erro } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{instance}/referrers") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -70463,7 +75190,7 @@ func (c *InstancesListReferrersCall) Do(opts ...googleapi.CallOption) (*Instance } return ret, nil // { - // "description": "Retrieves the list of referrers to instances contained within the specified zone.", + // "description": "Retrieves the list of referrers to instances contained within the specified zone. For more information, read Viewing Referrers to VM Instances.", // "httpMethod": "GET", // "id": "compute.instances.listReferrers", // "parameterOrder": [ @@ -70480,7 +75207,7 @@ func (c *InstancesListReferrersCall) Do(opts ...googleapi.CallOption) (*Instance // "instance": { // "description": "Name of the target instance scoping this request, or '-' if the request should span over all instances in the container.", // "location": "path", - // "pattern": "-|[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "-|[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -70631,9 +75358,13 @@ func (c *InstancesRemoveResourcePoliciesCall) doRequest(alt string) (*http.Respo } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{instance}/removeResourcePolicies") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -70693,7 +75424,7 @@ func (c *InstancesRemoveResourcePoliciesCall) Do(opts ...googleapi.CallOption) ( // "instance": { // "description": "The instance name for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -70807,9 +75538,13 @@ func (c *InstancesResetCall) doRequest(alt string) (*http.Response, error) { reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{instance}/reset") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -70869,7 +75604,7 @@ func (c *InstancesResetCall) Do(opts ...googleapi.CallOption) (*Operation, error // "instance": { // "description": "Name of the instance scoping this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -70986,9 +75721,13 @@ func (c *InstancesResumeCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{instance}/resume") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -71048,7 +75787,7 @@ func (c *InstancesResumeCall) Do(opts ...googleapi.CallOption) (*Operation, erro // "instance": { // "description": "Name of the instance resource to resume.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -71167,9 +75906,13 @@ func (c *InstancesSetDeletionProtectionCall) doRequest(alt string) (*http.Respon reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{resource}/setDeletionProtection") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -71245,9 +75988,9 @@ func (c *InstancesSetDeletionProtectionCall) Do(opts ...googleapi.CallOption) (* // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -71348,9 +76091,13 @@ func (c *InstancesSetDiskAutoDeleteCall) doRequest(alt string) (*http.Response, reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{instance}/setDiskAutoDelete") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -71416,16 +76163,16 @@ func (c *InstancesSetDiskAutoDeleteCall) Do(opts ...googleapi.CallOption) (*Oper // "type": "boolean" // }, // "deviceName": { - // "description": "The device name of the disk to modify.", + // "description": "The device name of the disk to modify. Make a get() request on the instance to view currently attached disks and device names.", // "location": "query", // "pattern": "\\w[\\w.-]{0,254}", // "required": true, // "type": "string" // }, // "instance": { - // "description": "The instance name.", + // "description": "The instance name for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -71523,9 +76270,13 @@ func (c *InstancesSetIamPolicyCall) doRequest(alt string) (*http.Response, error } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{resource}/setIamPolicy") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -71590,9 +76341,9 @@ func (c *InstancesSetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Policy, e // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -71700,9 +76451,13 @@ func (c *InstancesSetLabelsCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{instance}/setLabels") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -71762,7 +76517,7 @@ func (c *InstancesSetLabelsCall) Do(opts ...googleapi.CallOption) (*Operation, e // "instance": { // "description": "Name of the instance scoping this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -71882,9 +76637,13 @@ func (c *InstancesSetMachineResourcesCall) doRequest(alt string) (*http.Response } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{instance}/setMachineResources") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -71944,7 +76703,7 @@ func (c *InstancesSetMachineResourcesCall) Do(opts ...googleapi.CallOption) (*Op // "instance": { // "description": "Name of the instance scoping this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -72064,9 +76823,13 @@ func (c *InstancesSetMachineTypeCall) doRequest(alt string) (*http.Response, err } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{instance}/setMachineType") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -72126,7 +76889,7 @@ func (c *InstancesSetMachineTypeCall) Do(opts ...googleapi.CallOption) (*Operati // "instance": { // "description": "Name of the instance scoping this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -72247,9 +77010,13 @@ func (c *InstancesSetMetadataCall) doRequest(alt string) (*http.Response, error) } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{instance}/setMetadata") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -72309,7 +77076,7 @@ func (c *InstancesSetMetadataCall) Do(opts ...googleapi.CallOption) (*Operation, // "instance": { // "description": "Name of the instance scoping this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -72431,9 +77198,13 @@ func (c *InstancesSetMinCpuPlatformCall) doRequest(alt string) (*http.Response, } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{instance}/setMinCpuPlatform") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -72493,7 +77264,7 @@ func (c *InstancesSetMinCpuPlatformCall) Do(opts ...googleapi.CallOption) (*Oper // "instance": { // "description": "Name of the instance scoping this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -72613,9 +77384,13 @@ func (c *InstancesSetSchedulingCall) doRequest(alt string) (*http.Response, erro } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{instance}/setScheduling") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -72673,9 +77448,9 @@ func (c *InstancesSetSchedulingCall) Do(opts ...googleapi.CallOption) (*Operatio // ], // "parameters": { // "instance": { - // "description": "Instance name.", + // "description": "Instance name for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -72796,9 +77571,13 @@ func (c *InstancesSetServiceAccountCall) doRequest(alt string) (*http.Response, } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{instance}/setServiceAccount") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -72858,7 +77637,7 @@ func (c *InstancesSetServiceAccountCall) Do(opts ...googleapi.CallOption) (*Oper // "instance": { // "description": "Name of the instance resource to start.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -72911,8 +77690,9 @@ type InstancesSetShieldedVmIntegrityPolicyCall struct { } // SetShieldedVmIntegrityPolicy: Sets the Shielded VM integrity policy -// for an instance. This method supports PATCH semantics and uses the -// JSON merge patch format and processing rules. +// for a VM instance. You can only use this method on a running VM +// instance. This method supports PATCH semantics and uses the JSON +// merge patch format and processing rules. func (r *InstancesService) SetShieldedVmIntegrityPolicy(project string, zone string, instance string, shieldedvmintegritypolicy *ShieldedVmIntegrityPolicy) *InstancesSetShieldedVmIntegrityPolicyCall { c := &InstancesSetShieldedVmIntegrityPolicyCall{s: r.s, urlParams_: make(gensupport.URLParams)} c.project = project @@ -72979,9 +77759,13 @@ func (c *InstancesSetShieldedVmIntegrityPolicyCall) doRequest(alt string) (*http } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{instance}/setShieldedVmIntegrityPolicy") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PATCH", urls, body) + req, err := http.NewRequest("PATCH", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -73029,7 +77813,7 @@ func (c *InstancesSetShieldedVmIntegrityPolicyCall) Do(opts ...googleapi.CallOpt } return ret, nil // { - // "description": "Sets the Shielded VM integrity policy for an instance. This method supports PATCH semantics and uses the JSON merge patch format and processing rules.", + // "description": "Sets the Shielded VM integrity policy for a VM instance. You can only use this method on a running VM instance. This method supports PATCH semantics and uses the JSON merge patch format and processing rules.", // "httpMethod": "PATCH", // "id": "compute.instances.setShieldedVmIntegrityPolicy", // "parameterOrder": [ @@ -73041,7 +77825,7 @@ func (c *InstancesSetShieldedVmIntegrityPolicyCall) Do(opts ...googleapi.CallOpt // "instance": { // "description": "Name of the instance scoping this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -73093,8 +77877,8 @@ type InstancesSetTagsCall struct { header_ http.Header } -// SetTags: Sets tags for the specified instance to the data included in -// the request. +// SetTags: Sets network tags for the specified instance to the data +// included in the request. // For details, see https://cloud.google.com/compute/docs/reference/latest/instances/setTags func (r *InstancesService) SetTags(project string, zone string, instance string, tags *Tags) *InstancesSetTagsCall { c := &InstancesSetTagsCall{s: r.s, urlParams_: make(gensupport.URLParams)} @@ -73162,9 +77946,13 @@ func (c *InstancesSetTagsCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{instance}/setTags") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -73212,7 +78000,7 @@ func (c *InstancesSetTagsCall) Do(opts ...googleapi.CallOption) (*Operation, err } return ret, nil // { - // "description": "Sets tags for the specified instance to the data included in the request.", + // "description": "Sets network tags for the specified instance to the data included in the request.", // "httpMethod": "POST", // "id": "compute.instances.setTags", // "parameterOrder": [ @@ -73224,7 +78012,7 @@ func (c *InstancesSetTagsCall) Do(opts ...googleapi.CallOption) (*Operation, err // "instance": { // "description": "Name of the instance scoping this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -73318,9 +78106,13 @@ func (c *InstancesSimulateMaintenanceEventCall) doRequest(alt string) (*http.Res reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{instance}/simulateMaintenanceEvent") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -73380,7 +78172,7 @@ func (c *InstancesSimulateMaintenanceEventCall) Do(opts ...googleapi.CallOption) // "instance": { // "description": "Name of the instance scoping this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -73486,9 +78278,13 @@ func (c *InstancesStartCall) doRequest(alt string) (*http.Response, error) { reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{instance}/start") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -73548,7 +78344,7 @@ func (c *InstancesStartCall) Do(opts ...googleapi.CallOption) (*Operation, error // "instance": { // "description": "Name of the instance resource to start.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -73666,9 +78462,13 @@ func (c *InstancesStartWithEncryptionKeyCall) doRequest(alt string) (*http.Respo } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{instance}/startWithEncryptionKey") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -73728,7 +78528,7 @@ func (c *InstancesStartWithEncryptionKeyCall) Do(opts ...googleapi.CallOption) ( // "instance": { // "description": "Name of the instance resource to start.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -73854,9 +78654,13 @@ func (c *InstancesStopCall) doRequest(alt string) (*http.Response, error) { reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{instance}/stop") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -73921,7 +78725,7 @@ func (c *InstancesStopCall) Do(opts ...googleapi.CallOption) (*Operation, error) // "instance": { // "description": "Name of the instance resource to stop.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -74043,9 +78847,13 @@ func (c *InstancesSuspendCall) doRequest(alt string) (*http.Response, error) { reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{instance}/suspend") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -74110,7 +78918,7 @@ func (c *InstancesSuspendCall) Do(opts ...googleapi.CallOption) (*Operation, err // "instance": { // "description": "Name of the instance resource to suspend.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -74208,9 +79016,13 @@ func (c *InstancesTestIamPermissionsCall) doRequest(alt string) (*http.Response, } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{resource}/testIamPermissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -74275,9 +79087,9 @@ func (c *InstancesTestIamPermissionsCall) Do(opts ...googleapi.CallOption) (*Tes // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -74389,9 +79201,13 @@ func (c *InstancesUpdateAccessConfigCall) doRequest(alt string) (*http.Response, } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{instance}/updateAccessConfig") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -74452,7 +79268,7 @@ func (c *InstancesUpdateAccessConfigCall) Do(opts ...googleapi.CallOption) (*Ope // "instance": { // "description": "The instance name for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -74497,6 +79313,194 @@ func (c *InstancesUpdateAccessConfigCall) Do(opts ...googleapi.CallOption) (*Ope } +// method id "compute.instances.updateDisplayDevice": + +type InstancesUpdateDisplayDeviceCall struct { + s *Service + project string + zone string + instance string + displaydevice *DisplayDevice + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// UpdateDisplayDevice: Updates the Display config for a VM instance. +// You can only use this method on a stopped VM instance. This method +// supports PATCH semantics and uses the JSON merge patch format and +// processing rules. +func (r *InstancesService) UpdateDisplayDevice(project string, zone string, instance string, displaydevice *DisplayDevice) *InstancesUpdateDisplayDeviceCall { + c := &InstancesUpdateDisplayDeviceCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.zone = zone + c.instance = instance + c.displaydevice = displaydevice + return c +} + +// RequestId sets the optional parameter "requestId": An optional +// request ID to identify requests. Specify a unique request ID so that +// if you must retry your request, the server will know to ignore the +// request if it has already been completed. +// +// For example, consider a situation where you make an initial request +// and the request times out. If you make the request again with the +// same request ID, the server can check if original operation with the +// same request ID was received, and if so, will ignore the second +// request. This prevents clients from accidentally creating duplicate +// commitments. +// +// The request ID must be a valid UUID with the exception that zero UUID +// is not supported (00000000-0000-0000-0000-000000000000). +func (c *InstancesUpdateDisplayDeviceCall) RequestId(requestId string) *InstancesUpdateDisplayDeviceCall { + c.urlParams_.Set("requestId", requestId) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *InstancesUpdateDisplayDeviceCall) Fields(s ...googleapi.Field) *InstancesUpdateDisplayDeviceCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *InstancesUpdateDisplayDeviceCall) Context(ctx context.Context) *InstancesUpdateDisplayDeviceCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *InstancesUpdateDisplayDeviceCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *InstancesUpdateDisplayDeviceCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.displaydevice) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{instance}/updateDisplayDevice") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("PATCH", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "zone": c.zone, + "instance": c.instance, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.instances.updateDisplayDevice" call. +// Exactly one of *Operation or error will be non-nil. Any non-2xx +// status code is an error. Response headers are in either +// *Operation.ServerResponse.Header or (if a response was returned at +// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified +// to check whether the returned error was because +// http.StatusNotModified was returned. +func (c *InstancesUpdateDisplayDeviceCall) Do(opts ...googleapi.CallOption) (*Operation, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Operation{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Updates the Display config for a VM instance. You can only use this method on a stopped VM instance. This method supports PATCH semantics and uses the JSON merge patch format and processing rules.", + // "httpMethod": "PATCH", + // "id": "compute.instances.updateDisplayDevice", + // "parameterOrder": [ + // "project", + // "zone", + // "instance" + // ], + // "parameters": { + // "instance": { + // "description": "Name of the instance scoping this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // }, + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "requestId": { + // "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", + // "location": "query", + // "type": "string" + // }, + // "zone": { + // "description": "The name of the zone for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/zones/{zone}/instances/{instance}/updateDisplayDevice", + // "request": { + // "$ref": "DisplayDevice" + // }, + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + // method id "compute.instances.updateNetworkInterface": type InstancesUpdateNetworkInterfaceCall struct { @@ -74579,9 +79583,13 @@ func (c *InstancesUpdateNetworkInterfaceCall) doRequest(alt string) (*http.Respo } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{instance}/updateNetworkInterface") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PATCH", urls, body) + req, err := http.NewRequest("PATCH", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -74642,7 +79650,7 @@ func (c *InstancesUpdateNetworkInterfaceCall) Do(opts ...googleapi.CallOption) ( // "instance": { // "description": "The instance name for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -74700,9 +79708,10 @@ type InstancesUpdateShieldedVmConfigCall struct { header_ http.Header } -// UpdateShieldedVmConfig: Updates the Shielded VM config for an -// instance. This method supports PATCH semantics and uses the JSON -// merge patch format and processing rules. +// UpdateShieldedVmConfig: Updates the Shielded VM config for a VM +// instance. You can only use this method on a stopped VM instance. This +// method supports PATCH semantics and uses the JSON merge patch format +// and processing rules. func (r *InstancesService) UpdateShieldedVmConfig(project string, zone string, instance string, shieldedvmconfig *ShieldedVmConfig) *InstancesUpdateShieldedVmConfigCall { c := &InstancesUpdateShieldedVmConfigCall{s: r.s, urlParams_: make(gensupport.URLParams)} c.project = project @@ -74769,9 +79778,13 @@ func (c *InstancesUpdateShieldedVmConfigCall) doRequest(alt string) (*http.Respo } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{instance}/updateShieldedVmConfig") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PATCH", urls, body) + req, err := http.NewRequest("PATCH", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -74819,7 +79832,7 @@ func (c *InstancesUpdateShieldedVmConfigCall) Do(opts ...googleapi.CallOption) ( } return ret, nil // { - // "description": "Updates the Shielded VM config for an instance. This method supports PATCH semantics and uses the JSON merge patch format and processing rules.", + // "description": "Updates the Shielded VM config for a VM instance. You can only use this method on a stopped VM instance. This method supports PATCH semantics and uses the JSON merge patch format and processing rules.", // "httpMethod": "PATCH", // "id": "compute.instances.updateShieldedVmConfig", // "parameterOrder": [ @@ -74831,7 +79844,7 @@ func (c *InstancesUpdateShieldedVmConfigCall) Do(opts ...googleapi.CallOption) ( // "instance": { // "description": "Name of the instance scoping this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -74998,9 +80011,13 @@ func (c *InterconnectAttachmentsAggregatedListCall) doRequest(alt string) (*http } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/aggregated/interconnectAttachments") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -75192,9 +80209,13 @@ func (c *InterconnectAttachmentsDeleteCall) doRequest(alt string) (*http.Respons reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/interconnectAttachments/{interconnectAttachment}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -75358,9 +80379,13 @@ func (c *InterconnectAttachmentsGetCall) doRequest(alt string) (*http.Response, } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/interconnectAttachments/{interconnectAttachment}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -75521,9 +80546,13 @@ func (c *InterconnectAttachmentsGetIamPolicyCall) doRequest(alt string) (*http.R } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/interconnectAttachments/{resource}/getIamPolicy") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -75595,9 +80624,9 @@ func (c *InterconnectAttachmentsGetIamPolicyCall) Do(opts ...googleapi.CallOptio // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -75694,9 +80723,13 @@ func (c *InterconnectAttachmentsInsertCall) doRequest(alt string) (*http.Respons } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/interconnectAttachments") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -75916,9 +80949,13 @@ func (c *InterconnectAttachmentsListCall) doRequest(alt string) (*http.Response, } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/interconnectAttachments") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -76127,9 +81164,13 @@ func (c *InterconnectAttachmentsPatchCall) doRequest(alt string) (*http.Response } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/interconnectAttachments/{interconnectAttachment}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PATCH", urls, body) + req, err := http.NewRequest("PATCH", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -76290,9 +81331,13 @@ func (c *InterconnectAttachmentsSetIamPolicyCall) doRequest(alt string) (*http.R } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/interconnectAttachments/{resource}/setIamPolicy") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -76364,9 +81409,9 @@ func (c *InterconnectAttachmentsSetIamPolicyCall) Do(opts ...googleapi.CallOptio // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -76467,9 +81512,13 @@ func (c *InterconnectAttachmentsSetLabelsCall) doRequest(alt string) (*http.Resp } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/interconnectAttachments/{resource}/setLabels") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -76546,9 +81595,9 @@ func (c *InterconnectAttachmentsSetLabelsCall) Do(opts ...googleapi.CallOption) // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -76630,9 +81679,13 @@ func (c *InterconnectAttachmentsTestIamPermissionsCall) doRequest(alt string) (* } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/interconnectAttachments/{resource}/testIamPermissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -76704,9 +81757,9 @@ func (c *InterconnectAttachmentsTestIamPermissionsCall) Do(opts ...googleapi.Cal // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -76795,9 +81848,13 @@ func (c *InterconnectLocationsGetCall) doRequest(alt string) (*http.Response, er } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/interconnectLocations/{interconnectLocation}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -77008,9 +82065,13 @@ func (c *InterconnectLocationsListCall) doRequest(alt string) (*http.Response, e } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/interconnectLocations") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -77188,9 +82249,13 @@ func (c *InterconnectLocationsTestIamPermissionsCall) doRequest(alt string) (*ht } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/interconnectLocations/{resource}/testIamPermissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -77253,9 +82318,9 @@ func (c *InterconnectLocationsTestIamPermissionsCall) Do(opts ...googleapi.CallO // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "(?:[-a-z0-9_]{0,62}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -77347,9 +82412,13 @@ func (c *InterconnectsDeleteCall) doRequest(alt string) (*http.Response, error) reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/interconnects/{interconnect}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -77503,9 +82572,13 @@ func (c *InterconnectsGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/interconnects/{interconnect}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -77588,6 +82661,163 @@ func (c *InterconnectsGetCall) Do(opts ...googleapi.CallOption) (*Interconnect, } +// method id "compute.interconnects.getDiagnostics": + +type InterconnectsGetDiagnosticsCall struct { + s *Service + project string + interconnect string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// GetDiagnostics: Returns the interconnectDiagnostics for the specified +// interconnect. +func (r *InterconnectsService) GetDiagnostics(project string, interconnect string) *InterconnectsGetDiagnosticsCall { + c := &InterconnectsGetDiagnosticsCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.interconnect = interconnect + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *InterconnectsGetDiagnosticsCall) Fields(s ...googleapi.Field) *InterconnectsGetDiagnosticsCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// IfNoneMatch sets the optional parameter which makes the operation +// fail if the object's ETag matches the given value. This is useful for +// getting updates only after the object has changed since the last +// request. Use googleapi.IsNotModified to check whether the response +// error from Do is the result of In-None-Match. +func (c *InterconnectsGetDiagnosticsCall) IfNoneMatch(entityTag string) *InterconnectsGetDiagnosticsCall { + c.ifNoneMatch_ = entityTag + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *InterconnectsGetDiagnosticsCall) Context(ctx context.Context) *InterconnectsGetDiagnosticsCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *InterconnectsGetDiagnosticsCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *InterconnectsGetDiagnosticsCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + if c.ifNoneMatch_ != "" { + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) + } + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/interconnects/{interconnect}/getDiagnostics") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "interconnect": c.interconnect, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.interconnects.getDiagnostics" call. +// Exactly one of *InterconnectsGetDiagnosticsResponse or error will be +// non-nil. Any non-2xx status code is an error. Response headers are in +// either *InterconnectsGetDiagnosticsResponse.ServerResponse.Header or +// (if a response was returned at all) in +// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check +// whether the returned error was because http.StatusNotModified was +// returned. +func (c *InterconnectsGetDiagnosticsCall) Do(opts ...googleapi.CallOption) (*InterconnectsGetDiagnosticsResponse, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &InterconnectsGetDiagnosticsResponse{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Returns the interconnectDiagnostics for the specified interconnect.", + // "httpMethod": "GET", + // "id": "compute.interconnects.getDiagnostics", + // "parameterOrder": [ + // "project", + // "interconnect" + // ], + // "parameters": { + // "interconnect": { + // "description": "Name of the interconnect resource to query.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // }, + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/global/interconnects/{interconnect}/getDiagnostics", + // "response": { + // "$ref": "InterconnectsGetDiagnosticsResponse" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute", + // "https://www.googleapis.com/auth/compute.readonly" + // ] + // } + +} + // method id "compute.interconnects.getIamPolicy": type InterconnectsGetIamPolicyCall struct { @@ -77655,9 +82885,13 @@ func (c *InterconnectsGetIamPolicyCall) doRequest(alt string) (*http.Response, e } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/interconnects/{resource}/getIamPolicy") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -77720,9 +82954,9 @@ func (c *InterconnectsGetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Polic // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z0-9](?:[-a-z0-9_]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -77817,9 +83051,13 @@ func (c *InterconnectsInsertCall) doRequest(alt string) (*http.Response, error) } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/interconnects") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -78028,9 +83266,13 @@ func (c *InterconnectsListCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/interconnects") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -78228,9 +83470,13 @@ func (c *InterconnectsPatchCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/interconnects/{interconnect}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PATCH", urls, body) + req, err := http.NewRequest("PATCH", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -78380,9 +83626,13 @@ func (c *InterconnectsSetIamPolicyCall) doRequest(alt string) (*http.Response, e } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/interconnects/{resource}/setIamPolicy") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -78445,9 +83695,9 @@ func (c *InterconnectsSetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Polic // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z0-9](?:[-a-z0-9_]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -78527,9 +83777,13 @@ func (c *InterconnectsSetLabelsCall) doRequest(alt string) (*http.Response, erro } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/interconnects/{resource}/setLabels") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -78592,9 +83846,9 @@ func (c *InterconnectsSetLabelsCall) Do(opts ...googleapi.CallOption) (*Operatio // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -78674,9 +83928,13 @@ func (c *InterconnectsTestIamPermissionsCall) doRequest(alt string) (*http.Respo } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/interconnects/{resource}/testIamPermissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -78739,9 +83997,9 @@ func (c *InterconnectsTestIamPermissionsCall) Do(opts ...googleapi.CallOption) ( // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "(?:[-a-z0-9_]{0,62}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -78829,9 +84087,13 @@ func (c *LicenseCodesGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/licenseCodes/{licenseCode}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -78981,9 +84243,13 @@ func (c *LicenseCodesGetIamPolicyCall) doRequest(alt string) (*http.Response, er } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/licenseCodes/{resource}/getIamPolicy") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -79046,9 +84312,9 @@ func (c *LicenseCodesGetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Policy // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z0-9](?:[-a-z0-9_]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -79126,9 +84392,13 @@ func (c *LicenseCodesSetIamPolicyCall) doRequest(alt string) (*http.Response, er } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/licenseCodes/{resource}/setIamPolicy") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -79191,9 +84461,9 @@ func (c *LicenseCodesSetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Policy // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z0-9](?:[-a-z0-9_]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -79273,9 +84543,13 @@ func (c *LicenseCodesTestIamPermissionsCall) doRequest(alt string) (*http.Respon } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/licenseCodes/{resource}/testIamPermissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -79338,9 +84612,9 @@ func (c *LicenseCodesTestIamPermissionsCall) Do(opts ...googleapi.CallOption) (* // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "(?:[-a-z0-9_]{0,62}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -79432,9 +84706,13 @@ func (c *LicensesDeleteCall) doRequest(alt string) (*http.Response, error) { reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/licenses/{license}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -79588,9 +84866,13 @@ func (c *LicensesGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/licenses/{license}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -79740,9 +85022,13 @@ func (c *LicensesGetIamPolicyCall) doRequest(alt string) (*http.Response, error) } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/licenses/{resource}/getIamPolicy") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -79805,9 +85091,9 @@ func (c *LicensesGetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Policy, er // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z0-9](?:[-a-z0-9_]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -79901,9 +85187,13 @@ func (c *LicensesInsertCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/licenses") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -80119,9 +85409,13 @@ func (c *LicensesListCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/licenses") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -80299,9 +85593,13 @@ func (c *LicensesSetIamPolicyCall) doRequest(alt string) (*http.Response, error) } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/licenses/{resource}/setIamPolicy") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -80364,9 +85662,9 @@ func (c *LicensesSetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Policy, er // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z0-9](?:[-a-z0-9_]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -80446,9 +85744,13 @@ func (c *LicensesTestIamPermissionsCall) doRequest(alt string) (*http.Response, } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/licenses/{resource}/testIamPermissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -80511,9 +85813,9 @@ func (c *LicensesTestIamPermissionsCall) Do(opts ...googleapi.CallOption) (*Test // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "(?:[-a-z0-9_]{0,62}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -80534,6 +85836,1218 @@ func (c *LicensesTestIamPermissionsCall) Do(opts ...googleapi.CallOption) (*Test } +// method id "compute.machineImages.delete": + +type MachineImagesDeleteCall struct { + s *Service + project string + machineImage string + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// Delete: Deletes the specified machine image. Deleting a machine image +// is permanent and cannot be undone. +func (r *MachineImagesService) Delete(project string, machineImage string) *MachineImagesDeleteCall { + c := &MachineImagesDeleteCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.machineImage = machineImage + return c +} + +// RequestId sets the optional parameter "requestId": An optional +// request ID to identify requests. Specify a unique request ID so that +// if you must retry your request, the server will know to ignore the +// request if it has already been completed. +// +// For example, consider a situation where you make an initial request +// and the request times out. If you make the request again with the +// same request ID, the server can check if original operation with the +// same request ID was received, and if so, will ignore the second +// request. This prevents clients from accidentally creating duplicate +// commitments. +// +// The request ID must be a valid UUID with the exception that zero UUID +// is not supported (00000000-0000-0000-0000-000000000000). +func (c *MachineImagesDeleteCall) RequestId(requestId string) *MachineImagesDeleteCall { + c.urlParams_.Set("requestId", requestId) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *MachineImagesDeleteCall) Fields(s ...googleapi.Field) *MachineImagesDeleteCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *MachineImagesDeleteCall) Context(ctx context.Context) *MachineImagesDeleteCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *MachineImagesDeleteCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *MachineImagesDeleteCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/machineImages/{machineImage}") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "machineImage": c.machineImage, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.machineImages.delete" call. +// Exactly one of *Operation or error will be non-nil. Any non-2xx +// status code is an error. Response headers are in either +// *Operation.ServerResponse.Header or (if a response was returned at +// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified +// to check whether the returned error was because +// http.StatusNotModified was returned. +func (c *MachineImagesDeleteCall) Do(opts ...googleapi.CallOption) (*Operation, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Operation{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Deletes the specified machine image. Deleting a machine image is permanent and cannot be undone.", + // "httpMethod": "DELETE", + // "id": "compute.machineImages.delete", + // "parameterOrder": [ + // "project", + // "machineImage" + // ], + // "parameters": { + // "machineImage": { + // "description": "The name of the machine image to delete.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // }, + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "requestId": { + // "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", + // "location": "query", + // "type": "string" + // } + // }, + // "path": "{project}/global/machineImages/{machineImage}", + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + +// method id "compute.machineImages.get": + +type MachineImagesGetCall struct { + s *Service + project string + machineImage string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// Get: Returns the specified machine image. Gets a list of available +// machine images by making a list() request. +func (r *MachineImagesService) Get(project string, machineImage string) *MachineImagesGetCall { + c := &MachineImagesGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.machineImage = machineImage + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *MachineImagesGetCall) Fields(s ...googleapi.Field) *MachineImagesGetCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// IfNoneMatch sets the optional parameter which makes the operation +// fail if the object's ETag matches the given value. This is useful for +// getting updates only after the object has changed since the last +// request. Use googleapi.IsNotModified to check whether the response +// error from Do is the result of In-None-Match. +func (c *MachineImagesGetCall) IfNoneMatch(entityTag string) *MachineImagesGetCall { + c.ifNoneMatch_ = entityTag + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *MachineImagesGetCall) Context(ctx context.Context) *MachineImagesGetCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *MachineImagesGetCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *MachineImagesGetCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + if c.ifNoneMatch_ != "" { + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) + } + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/machineImages/{machineImage}") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "machineImage": c.machineImage, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.machineImages.get" call. +// Exactly one of *MachineImage or error will be non-nil. Any non-2xx +// status code is an error. Response headers are in either +// *MachineImage.ServerResponse.Header or (if a response was returned at +// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified +// to check whether the returned error was because +// http.StatusNotModified was returned. +func (c *MachineImagesGetCall) Do(opts ...googleapi.CallOption) (*MachineImage, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &MachineImage{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Returns the specified machine image. Gets a list of available machine images by making a list() request.", + // "httpMethod": "GET", + // "id": "compute.machineImages.get", + // "parameterOrder": [ + // "project", + // "machineImage" + // ], + // "parameters": { + // "machineImage": { + // "description": "The name of the machine image.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // }, + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/global/machineImages/{machineImage}", + // "response": { + // "$ref": "MachineImage" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute", + // "https://www.googleapis.com/auth/compute.readonly" + // ] + // } + +} + +// method id "compute.machineImages.getIamPolicy": + +type MachineImagesGetIamPolicyCall struct { + s *Service + project string + resource string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// GetIamPolicy: Gets the access control policy for a resource. May be +// empty if no such policy or resource exists. +func (r *MachineImagesService) GetIamPolicy(project string, resource string) *MachineImagesGetIamPolicyCall { + c := &MachineImagesGetIamPolicyCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.resource = resource + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *MachineImagesGetIamPolicyCall) Fields(s ...googleapi.Field) *MachineImagesGetIamPolicyCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// IfNoneMatch sets the optional parameter which makes the operation +// fail if the object's ETag matches the given value. This is useful for +// getting updates only after the object has changed since the last +// request. Use googleapi.IsNotModified to check whether the response +// error from Do is the result of In-None-Match. +func (c *MachineImagesGetIamPolicyCall) IfNoneMatch(entityTag string) *MachineImagesGetIamPolicyCall { + c.ifNoneMatch_ = entityTag + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *MachineImagesGetIamPolicyCall) Context(ctx context.Context) *MachineImagesGetIamPolicyCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *MachineImagesGetIamPolicyCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *MachineImagesGetIamPolicyCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + if c.ifNoneMatch_ != "" { + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) + } + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/machineImages/{resource}/getIamPolicy") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "resource": c.resource, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.machineImages.getIamPolicy" call. +// Exactly one of *Policy or error will be non-nil. Any non-2xx status +// code is an error. Response headers are in either +// *Policy.ServerResponse.Header or (if a response was returned at all) +// in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to +// check whether the returned error was because http.StatusNotModified +// was returned. +func (c *MachineImagesGetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Policy, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Policy{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Gets the access control policy for a resource. May be empty if no such policy or resource exists.", + // "httpMethod": "GET", + // "id": "compute.machineImages.getIamPolicy", + // "parameterOrder": [ + // "project", + // "resource" + // ], + // "parameters": { + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "resource": { + // "description": "Name or id of the resource for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/global/machineImages/{resource}/getIamPolicy", + // "response": { + // "$ref": "Policy" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute", + // "https://www.googleapis.com/auth/compute.readonly" + // ] + // } + +} + +// method id "compute.machineImages.insert": + +type MachineImagesInsertCall struct { + s *Service + project string + machineimage *MachineImage + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// Insert: Creates a machine image in the specified project using the +// data that is included in the request. If you are creating a new +// machine image to update an existing instance, your new machine image +// should use the same network or, if applicable, the same subnetwork as +// the original instance. +func (r *MachineImagesService) Insert(project string, machineimage *MachineImage) *MachineImagesInsertCall { + c := &MachineImagesInsertCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.machineimage = machineimage + return c +} + +// RequestId sets the optional parameter "requestId": An optional +// request ID to identify requests. Specify a unique request ID so that +// if you must retry your request, the server will know to ignore the +// request if it has already been completed. +// +// For example, consider a situation where you make an initial request +// and the request times out. If you make the request again with the +// same request ID, the server can check if original operation with the +// same request ID was received, and if so, will ignore the second +// request. This prevents clients from accidentally creating duplicate +// commitments. +// +// The request ID must be a valid UUID with the exception that zero UUID +// is not supported (00000000-0000-0000-0000-000000000000). +func (c *MachineImagesInsertCall) RequestId(requestId string) *MachineImagesInsertCall { + c.urlParams_.Set("requestId", requestId) + return c +} + +// SourceInstance sets the optional parameter "sourceInstance": +// Required. Source instance that is used to create the machine image +// from. +func (c *MachineImagesInsertCall) SourceInstance(sourceInstance string) *MachineImagesInsertCall { + c.urlParams_.Set("sourceInstance", sourceInstance) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *MachineImagesInsertCall) Fields(s ...googleapi.Field) *MachineImagesInsertCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *MachineImagesInsertCall) Context(ctx context.Context) *MachineImagesInsertCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *MachineImagesInsertCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *MachineImagesInsertCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.machineimage) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/machineImages") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.machineImages.insert" call. +// Exactly one of *Operation or error will be non-nil. Any non-2xx +// status code is an error. Response headers are in either +// *Operation.ServerResponse.Header or (if a response was returned at +// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified +// to check whether the returned error was because +// http.StatusNotModified was returned. +func (c *MachineImagesInsertCall) Do(opts ...googleapi.CallOption) (*Operation, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Operation{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Creates a machine image in the specified project using the data that is included in the request. If you are creating a new machine image to update an existing instance, your new machine image should use the same network or, if applicable, the same subnetwork as the original instance.", + // "httpMethod": "POST", + // "id": "compute.machineImages.insert", + // "parameterOrder": [ + // "project" + // ], + // "parameters": { + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "requestId": { + // "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", + // "location": "query", + // "type": "string" + // }, + // "sourceInstance": { + // "description": "Required. Source instance that is used to create the machine image from.", + // "location": "query", + // "type": "string" + // } + // }, + // "path": "{project}/global/machineImages", + // "request": { + // "$ref": "MachineImage" + // }, + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + +// method id "compute.machineImages.list": + +type MachineImagesListCall struct { + s *Service + project string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// List: Retrieves a list of machine images that are contained within +// the specified project. +func (r *MachineImagesService) List(project string) *MachineImagesListCall { + c := &MachineImagesListCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + return c +} + +// Filter sets the optional parameter "filter": A filter expression that +// filters resources listed in the response. The expression must specify +// the field name, a comparison operator, and the value that you want to +// use for filtering. The value must be a string, a number, or a +// boolean. The comparison operator must be either =, !=, >, or <. +// +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. +// +// You can also filter nested fields. For example, you could specify +// scheduling.automaticRestart = false to include instances only if they +// are not scheduled for automatic restarts. You can use filtering on +// nested fields to filter based on resource labels. +// +// To filter on multiple expressions, provide each separate expression +// within parentheses. For example, (scheduling.automaticRestart = true) +// (cpuPlatform = "Intel Skylake"). By default, each expression is an +// AND expression. However, you can include AND and OR expressions +// explicitly. For example, (cpuPlatform = "Intel Skylake") OR +// (cpuPlatform = "Intel Broadwell") AND (scheduling.automaticRestart = +// true). +func (c *MachineImagesListCall) Filter(filter string) *MachineImagesListCall { + c.urlParams_.Set("filter", filter) + return c +} + +// MaxResults sets the optional parameter "maxResults": The maximum +// number of results per page that should be returned. If the number of +// available results is larger than maxResults, Compute Engine returns a +// nextPageToken that can be used to get the next page of results in +// subsequent list requests. Acceptable values are 0 to 500, inclusive. +// (Default: 500) +func (c *MachineImagesListCall) MaxResults(maxResults int64) *MachineImagesListCall { + c.urlParams_.Set("maxResults", fmt.Sprint(maxResults)) + return c +} + +// OrderBy sets the optional parameter "orderBy": Sorts list results by +// a certain order. By default, results are returned in alphanumerical +// order based on the resource name. +// +// You can also sort results in descending order based on the creation +// timestamp using orderBy="creationTimestamp desc". This sorts results +// based on the creationTimestamp field in reverse chronological order +// (newest result first). Use this to sort resources like operations so +// that the newest operation is returned first. +// +// Currently, only sorting by name or creationTimestamp desc is +// supported. +func (c *MachineImagesListCall) OrderBy(orderBy string) *MachineImagesListCall { + c.urlParams_.Set("orderBy", orderBy) + return c +} + +// PageToken sets the optional parameter "pageToken": Specifies a page +// token to use. Set pageToken to the nextPageToken returned by a +// previous list request to get the next page of results. +func (c *MachineImagesListCall) PageToken(pageToken string) *MachineImagesListCall { + c.urlParams_.Set("pageToken", pageToken) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *MachineImagesListCall) Fields(s ...googleapi.Field) *MachineImagesListCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// IfNoneMatch sets the optional parameter which makes the operation +// fail if the object's ETag matches the given value. This is useful for +// getting updates only after the object has changed since the last +// request. Use googleapi.IsNotModified to check whether the response +// error from Do is the result of In-None-Match. +func (c *MachineImagesListCall) IfNoneMatch(entityTag string) *MachineImagesListCall { + c.ifNoneMatch_ = entityTag + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *MachineImagesListCall) Context(ctx context.Context) *MachineImagesListCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *MachineImagesListCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *MachineImagesListCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + if c.ifNoneMatch_ != "" { + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) + } + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/machineImages") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.machineImages.list" call. +// Exactly one of *MachineImageList or error will be non-nil. Any +// non-2xx status code is an error. Response headers are in either +// *MachineImageList.ServerResponse.Header or (if a response was +// returned at all) in error.(*googleapi.Error).Header. Use +// googleapi.IsNotModified to check whether the returned error was +// because http.StatusNotModified was returned. +func (c *MachineImagesListCall) Do(opts ...googleapi.CallOption) (*MachineImageList, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &MachineImageList{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Retrieves a list of machine images that are contained within the specified project.", + // "httpMethod": "GET", + // "id": "compute.machineImages.list", + // "parameterOrder": [ + // "project" + // ], + // "parameters": { + // "filter": { + // "description": "A filter expression that filters resources listed in the response. The expression must specify the field name, a comparison operator, and the value that you want to use for filtering. The value must be a string, a number, or a boolean. The comparison operator must be either =, !=, \u003e, or \u003c.\n\nFor example, if you are filtering Compute Engine instances, you can exclude instances named example-instance by specifying name != example-instance.\n\nYou can also filter nested fields. For example, you could specify scheduling.automaticRestart = false to include instances only if they are not scheduled for automatic restarts. You can use filtering on nested fields to filter based on resource labels.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart = true) (cpuPlatform = \"Intel Skylake\"). By default, each expression is an AND expression. However, you can include AND and OR expressions explicitly. For example, (cpuPlatform = \"Intel Skylake\") OR (cpuPlatform = \"Intel Broadwell\") AND (scheduling.automaticRestart = true).", + // "location": "query", + // "type": "string" + // }, + // "maxResults": { + // "default": "500", + // "description": "The maximum number of results per page that should be returned. If the number of available results is larger than maxResults, Compute Engine returns a nextPageToken that can be used to get the next page of results in subsequent list requests. Acceptable values are 0 to 500, inclusive. (Default: 500)", + // "format": "uint32", + // "location": "query", + // "minimum": "0", + // "type": "integer" + // }, + // "orderBy": { + // "description": "Sorts list results by a certain order. By default, results are returned in alphanumerical order based on the resource name.\n\nYou can also sort results in descending order based on the creation timestamp using orderBy=\"creationTimestamp desc\". This sorts results based on the creationTimestamp field in reverse chronological order (newest result first). Use this to sort resources like operations so that the newest operation is returned first.\n\nCurrently, only sorting by name or creationTimestamp desc is supported.", + // "location": "query", + // "type": "string" + // }, + // "pageToken": { + // "description": "Specifies a page token to use. Set pageToken to the nextPageToken returned by a previous list request to get the next page of results.", + // "location": "query", + // "type": "string" + // }, + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/global/machineImages", + // "response": { + // "$ref": "MachineImageList" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute", + // "https://www.googleapis.com/auth/compute.readonly" + // ] + // } + +} + +// Pages invokes f for each page of results. +// A non-nil error returned from f will halt the iteration. +// The provided context supersedes any context provided to the Context method. +func (c *MachineImagesListCall) Pages(ctx context.Context, f func(*MachineImageList) error) error { + c.ctx_ = ctx + defer c.PageToken(c.urlParams_.Get("pageToken")) // reset paging to original point + for { + x, err := c.Do() + if err != nil { + return err + } + if err := f(x); err != nil { + return err + } + if x.NextPageToken == "" { + return nil + } + c.PageToken(x.NextPageToken) + } +} + +// method id "compute.machineImages.setIamPolicy": + +type MachineImagesSetIamPolicyCall struct { + s *Service + project string + resource string + globalsetpolicyrequest *GlobalSetPolicyRequest + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// SetIamPolicy: Sets the access control policy on the specified +// resource. Replaces any existing policy. +func (r *MachineImagesService) SetIamPolicy(project string, resource string, globalsetpolicyrequest *GlobalSetPolicyRequest) *MachineImagesSetIamPolicyCall { + c := &MachineImagesSetIamPolicyCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.resource = resource + c.globalsetpolicyrequest = globalsetpolicyrequest + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *MachineImagesSetIamPolicyCall) Fields(s ...googleapi.Field) *MachineImagesSetIamPolicyCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *MachineImagesSetIamPolicyCall) Context(ctx context.Context) *MachineImagesSetIamPolicyCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *MachineImagesSetIamPolicyCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *MachineImagesSetIamPolicyCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.globalsetpolicyrequest) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/machineImages/{resource}/setIamPolicy") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "resource": c.resource, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.machineImages.setIamPolicy" call. +// Exactly one of *Policy or error will be non-nil. Any non-2xx status +// code is an error. Response headers are in either +// *Policy.ServerResponse.Header or (if a response was returned at all) +// in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to +// check whether the returned error was because http.StatusNotModified +// was returned. +func (c *MachineImagesSetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Policy, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Policy{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Sets the access control policy on the specified resource. Replaces any existing policy.", + // "httpMethod": "POST", + // "id": "compute.machineImages.setIamPolicy", + // "parameterOrder": [ + // "project", + // "resource" + // ], + // "parameters": { + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "resource": { + // "description": "Name or id of the resource for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/global/machineImages/{resource}/setIamPolicy", + // "request": { + // "$ref": "GlobalSetPolicyRequest" + // }, + // "response": { + // "$ref": "Policy" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + +// method id "compute.machineImages.testIamPermissions": + +type MachineImagesTestIamPermissionsCall struct { + s *Service + project string + resource string + testpermissionsrequest *TestPermissionsRequest + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// TestIamPermissions: Returns permissions that a caller has on the +// specified resource. +func (r *MachineImagesService) TestIamPermissions(project string, resource string, testpermissionsrequest *TestPermissionsRequest) *MachineImagesTestIamPermissionsCall { + c := &MachineImagesTestIamPermissionsCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.resource = resource + c.testpermissionsrequest = testpermissionsrequest + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *MachineImagesTestIamPermissionsCall) Fields(s ...googleapi.Field) *MachineImagesTestIamPermissionsCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *MachineImagesTestIamPermissionsCall) Context(ctx context.Context) *MachineImagesTestIamPermissionsCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *MachineImagesTestIamPermissionsCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *MachineImagesTestIamPermissionsCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.testpermissionsrequest) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/machineImages/{resource}/testIamPermissions") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "resource": c.resource, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.machineImages.testIamPermissions" call. +// Exactly one of *TestPermissionsResponse or error will be non-nil. Any +// non-2xx status code is an error. Response headers are in either +// *TestPermissionsResponse.ServerResponse.Header or (if a response was +// returned at all) in error.(*googleapi.Error).Header. Use +// googleapi.IsNotModified to check whether the returned error was +// because http.StatusNotModified was returned. +func (c *MachineImagesTestIamPermissionsCall) Do(opts ...googleapi.CallOption) (*TestPermissionsResponse, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &TestPermissionsResponse{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Returns permissions that a caller has on the specified resource.", + // "httpMethod": "POST", + // "id": "compute.machineImages.testIamPermissions", + // "parameterOrder": [ + // "project", + // "resource" + // ], + // "parameters": { + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "resource": { + // "description": "Name or id of the resource for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/global/machineImages/{resource}/testIamPermissions", + // "request": { + // "$ref": "TestPermissionsRequest" + // }, + // "response": { + // "$ref": "TestPermissionsResponse" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute", + // "https://www.googleapis.com/auth/compute.readonly" + // ] + // } + +} + // method id "compute.machineTypes.aggregatedList": type MachineTypesAggregatedListCall struct { @@ -80662,9 +87176,13 @@ func (c *MachineTypesAggregatedListCall) doRequest(alt string) (*http.Response, } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/aggregated/machineTypes") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -80852,9 +87370,13 @@ func (c *MachineTypesGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/machineTypes/{machineType}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -81077,9 +87599,13 @@ func (c *MachineTypesListCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/machineTypes") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -81334,9 +87860,13 @@ func (c *NetworkEndpointGroupsAggregatedListCall) doRequest(alt string) (*http.R } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/aggregated/networkEndpointGroups") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -81536,9 +88066,13 @@ func (c *NetworkEndpointGroupsAttachNetworkEndpointsCall) doRequest(alt string) } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/networkEndpointGroups/{networkEndpointGroup}/attachNetworkEndpoints") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -81711,9 +88245,13 @@ func (c *NetworkEndpointGroupsDeleteCall) doRequest(alt string) (*http.Response, reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/networkEndpointGroups/{networkEndpointGroup}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -81888,9 +88426,13 @@ func (c *NetworkEndpointGroupsDetachNetworkEndpointsCall) doRequest(alt string) } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/networkEndpointGroups/{networkEndpointGroup}/detachNetworkEndpoints") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -82056,9 +88598,13 @@ func (c *NetworkEndpointGroupsGetCall) doRequest(alt string) (*http.Response, er } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/networkEndpointGroups/{networkEndpointGroup}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -82227,9 +88773,13 @@ func (c *NetworkEndpointGroupsInsertCall) doRequest(alt string) (*http.Response, } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/networkEndpointGroups") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -82448,9 +88998,13 @@ func (c *NetworkEndpointGroupsListCall) doRequest(alt string) (*http.Response, e } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/networkEndpointGroups") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -82701,9 +89255,13 @@ func (c *NetworkEndpointGroupsListNetworkEndpointsCall) doRequest(alt string) (* } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/networkEndpointGroups/{networkEndpointGroup}/listNetworkEndpoints") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -82904,9 +89462,13 @@ func (c *NetworkEndpointGroupsTestIamPermissionsCall) doRequest(alt string) (*ht } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/networkEndpointGroups/{resource}/testIamPermissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -82971,9 +89533,9 @@ func (c *NetworkEndpointGroupsTestIamPermissionsCall) Do(opts ...googleapi.CallO // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -83079,9 +89641,13 @@ func (c *NetworksAddPeeringCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/networks/{network}/addPeering") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -83139,7 +89705,7 @@ func (c *NetworksAddPeeringCall) Do(opts ...googleapi.CallOption) (*Operation, e // "network": { // "description": "Name of the network resource to add peering to.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -83243,9 +89809,13 @@ func (c *NetworksDeleteCall) doRequest(alt string) (*http.Response, error) { reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/networks/{network}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -83303,7 +89873,7 @@ func (c *NetworksDeleteCall) Do(opts ...googleapi.CallOption) (*Operation, error // "network": { // "description": "Name of the network to delete.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -83400,9 +89970,13 @@ func (c *NetworksGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/networks/{network}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -83460,7 +90034,7 @@ func (c *NetworksGetCall) Do(opts ...googleapi.CallOption) (*Network, error) { // "network": { // "description": "Name of the network to return.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -83563,9 +90137,13 @@ func (c *NetworksInsertCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/networks") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -83775,9 +90353,13 @@ func (c *NetworksListCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/networks") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -83895,6 +90477,282 @@ func (c *NetworksListCall) Pages(ctx context.Context, f func(*NetworkList) error } } +// method id "compute.networks.listIpAddresses": + +type NetworksListIpAddressesCall struct { + s *Service + project string + network string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// ListIpAddresses: Lists the internal IP addresses in the specified +// network. +func (r *NetworksService) ListIpAddresses(project string, network string) *NetworksListIpAddressesCall { + c := &NetworksListIpAddressesCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.network = network + return c +} + +// Filter sets the optional parameter "filter": A filter expression that +// filters resources listed in the response. The expression must specify +// the field name, a comparison operator, and the value that you want to +// use for filtering. The value must be a string, a number, or a +// boolean. The comparison operator must be either =, !=, >, or <. +// +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. +// +// You can also filter nested fields. For example, you could specify +// scheduling.automaticRestart = false to include instances only if they +// are not scheduled for automatic restarts. You can use filtering on +// nested fields to filter based on resource labels. +// +// To filter on multiple expressions, provide each separate expression +// within parentheses. For example, (scheduling.automaticRestart = true) +// (cpuPlatform = "Intel Skylake"). By default, each expression is an +// AND expression. However, you can include AND and OR expressions +// explicitly. For example, (cpuPlatform = "Intel Skylake") OR +// (cpuPlatform = "Intel Broadwell") AND (scheduling.automaticRestart = +// true). +func (c *NetworksListIpAddressesCall) Filter(filter string) *NetworksListIpAddressesCall { + c.urlParams_.Set("filter", filter) + return c +} + +// MaxResults sets the optional parameter "maxResults": The maximum +// number of results per page that should be returned. If the number of +// available results is larger than maxResults, Compute Engine returns a +// nextPageToken that can be used to get the next page of results in +// subsequent list requests. Acceptable values are 0 to 500, inclusive. +// (Default: 500) +func (c *NetworksListIpAddressesCall) MaxResults(maxResults int64) *NetworksListIpAddressesCall { + c.urlParams_.Set("maxResults", fmt.Sprint(maxResults)) + return c +} + +// OrderBy sets the optional parameter "orderBy": Sorts list results by +// a certain order. By default, results are returned in alphanumerical +// order based on the resource name. +// +// You can also sort results in descending order based on the creation +// timestamp using orderBy="creationTimestamp desc". This sorts results +// based on the creationTimestamp field in reverse chronological order +// (newest result first). Use this to sort resources like operations so +// that the newest operation is returned first. +// +// Currently, only sorting by name or creationTimestamp desc is +// supported. +func (c *NetworksListIpAddressesCall) OrderBy(orderBy string) *NetworksListIpAddressesCall { + c.urlParams_.Set("orderBy", orderBy) + return c +} + +// PageToken sets the optional parameter "pageToken": Specifies a page +// token to use. Set pageToken to the nextPageToken returned by a +// previous list request to get the next page of results. +func (c *NetworksListIpAddressesCall) PageToken(pageToken string) *NetworksListIpAddressesCall { + c.urlParams_.Set("pageToken", pageToken) + return c +} + +// Types sets the optional parameter "types": (Optional) types filter +// separate by comma, valid values are: SUBNETWORK, RESERVED, PEER_USED, +// PEER_RESERVED, REMOTE_USED, REMOTE_RESERVED. +func (c *NetworksListIpAddressesCall) Types(types string) *NetworksListIpAddressesCall { + c.urlParams_.Set("types", types) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *NetworksListIpAddressesCall) Fields(s ...googleapi.Field) *NetworksListIpAddressesCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// IfNoneMatch sets the optional parameter which makes the operation +// fail if the object's ETag matches the given value. This is useful for +// getting updates only after the object has changed since the last +// request. Use googleapi.IsNotModified to check whether the response +// error from Do is the result of In-None-Match. +func (c *NetworksListIpAddressesCall) IfNoneMatch(entityTag string) *NetworksListIpAddressesCall { + c.ifNoneMatch_ = entityTag + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *NetworksListIpAddressesCall) Context(ctx context.Context) *NetworksListIpAddressesCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *NetworksListIpAddressesCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *NetworksListIpAddressesCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + if c.ifNoneMatch_ != "" { + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) + } + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/networks/{network}/listIpAddresses") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "network": c.network, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.networks.listIpAddresses" call. +// Exactly one of *IpAddressesList or error will be non-nil. Any non-2xx +// status code is an error. Response headers are in either +// *IpAddressesList.ServerResponse.Header or (if a response was returned +// at all) in error.(*googleapi.Error).Header. Use +// googleapi.IsNotModified to check whether the returned error was +// because http.StatusNotModified was returned. +func (c *NetworksListIpAddressesCall) Do(opts ...googleapi.CallOption) (*IpAddressesList, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &IpAddressesList{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Lists the internal IP addresses in the specified network.", + // "httpMethod": "GET", + // "id": "compute.networks.listIpAddresses", + // "parameterOrder": [ + // "project", + // "network" + // ], + // "parameters": { + // "filter": { + // "description": "A filter expression that filters resources listed in the response. The expression must specify the field name, a comparison operator, and the value that you want to use for filtering. The value must be a string, a number, or a boolean. The comparison operator must be either =, !=, \u003e, or \u003c.\n\nFor example, if you are filtering Compute Engine instances, you can exclude instances named example-instance by specifying name != example-instance.\n\nYou can also filter nested fields. For example, you could specify scheduling.automaticRestart = false to include instances only if they are not scheduled for automatic restarts. You can use filtering on nested fields to filter based on resource labels.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart = true) (cpuPlatform = \"Intel Skylake\"). By default, each expression is an AND expression. However, you can include AND and OR expressions explicitly. For example, (cpuPlatform = \"Intel Skylake\") OR (cpuPlatform = \"Intel Broadwell\") AND (scheduling.automaticRestart = true).", + // "location": "query", + // "type": "string" + // }, + // "maxResults": { + // "default": "500", + // "description": "The maximum number of results per page that should be returned. If the number of available results is larger than maxResults, Compute Engine returns a nextPageToken that can be used to get the next page of results in subsequent list requests. Acceptable values are 0 to 500, inclusive. (Default: 500)", + // "format": "uint32", + // "location": "query", + // "minimum": "0", + // "type": "integer" + // }, + // "network": { + // "description": "Name of the network for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + // "required": true, + // "type": "string" + // }, + // "orderBy": { + // "description": "Sorts list results by a certain order. By default, results are returned in alphanumerical order based on the resource name.\n\nYou can also sort results in descending order based on the creation timestamp using orderBy=\"creationTimestamp desc\". This sorts results based on the creationTimestamp field in reverse chronological order (newest result first). Use this to sort resources like operations so that the newest operation is returned first.\n\nCurrently, only sorting by name or creationTimestamp desc is supported.", + // "location": "query", + // "type": "string" + // }, + // "pageToken": { + // "description": "Specifies a page token to use. Set pageToken to the nextPageToken returned by a previous list request to get the next page of results.", + // "location": "query", + // "type": "string" + // }, + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "types": { + // "description": "(Optional) types filter separate by comma, valid values are: SUBNETWORK, RESERVED, PEER_USED, PEER_RESERVED, REMOTE_USED, REMOTE_RESERVED.", + // "location": "query", + // "type": "string" + // } + // }, + // "path": "{project}/global/networks/{network}/listIpAddresses", + // "response": { + // "$ref": "IpAddressesList" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute", + // "https://www.googleapis.com/auth/compute.readonly" + // ] + // } + +} + +// Pages invokes f for each page of results. +// A non-nil error returned from f will halt the iteration. +// The provided context supersedes any context provided to the Context method. +func (c *NetworksListIpAddressesCall) Pages(ctx context.Context, f func(*IpAddressesList) error) error { + c.ctx_ = ctx + defer c.PageToken(c.urlParams_.Get("pageToken")) // reset paging to original point + for { + x, err := c.Do() + if err != nil { + return err + } + if err := f(x); err != nil { + return err + } + if x.NextPageToken == "" { + return nil + } + c.PageToken(x.NextPageToken) + } +} + // method id "compute.networks.listIpOwners": type NetworksListIpOwnersCall struct { @@ -84059,9 +90917,13 @@ func (c *NetworksListIpOwnersCall) doRequest(alt string) (*http.Response, error) } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/networks/{network}/listIpOwners") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -84137,7 +90999,7 @@ func (c *NetworksListIpOwnersCall) Do(opts ...googleapi.CallOption) (*IpOwnerLis // "network": { // "description": "Name of the network to return.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -84215,6 +91077,318 @@ func (c *NetworksListIpOwnersCall) Pages(ctx context.Context, f func(*IpOwnerLis } } +// method id "compute.networks.listPeeringRoutes": + +type NetworksListPeeringRoutesCall struct { + s *Service + project string + network string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// ListPeeringRoutes: Lists the peering routes exchanged over peering +// connection. +func (r *NetworksService) ListPeeringRoutes(project string, network string) *NetworksListPeeringRoutesCall { + c := &NetworksListPeeringRoutesCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.network = network + return c +} + +// Direction sets the optional parameter "direction": The direction of +// the exchanged routes. +// +// Possible values: +// "INCOMING" +// "OUTGOING" +func (c *NetworksListPeeringRoutesCall) Direction(direction string) *NetworksListPeeringRoutesCall { + c.urlParams_.Set("direction", direction) + return c +} + +// Filter sets the optional parameter "filter": A filter expression that +// filters resources listed in the response. The expression must specify +// the field name, a comparison operator, and the value that you want to +// use for filtering. The value must be a string, a number, or a +// boolean. The comparison operator must be either =, !=, >, or <. +// +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. +// +// You can also filter nested fields. For example, you could specify +// scheduling.automaticRestart = false to include instances only if they +// are not scheduled for automatic restarts. You can use filtering on +// nested fields to filter based on resource labels. +// +// To filter on multiple expressions, provide each separate expression +// within parentheses. For example, (scheduling.automaticRestart = true) +// (cpuPlatform = "Intel Skylake"). By default, each expression is an +// AND expression. However, you can include AND and OR expressions +// explicitly. For example, (cpuPlatform = "Intel Skylake") OR +// (cpuPlatform = "Intel Broadwell") AND (scheduling.automaticRestart = +// true). +func (c *NetworksListPeeringRoutesCall) Filter(filter string) *NetworksListPeeringRoutesCall { + c.urlParams_.Set("filter", filter) + return c +} + +// MaxResults sets the optional parameter "maxResults": The maximum +// number of results per page that should be returned. If the number of +// available results is larger than maxResults, Compute Engine returns a +// nextPageToken that can be used to get the next page of results in +// subsequent list requests. Acceptable values are 0 to 500, inclusive. +// (Default: 500) +func (c *NetworksListPeeringRoutesCall) MaxResults(maxResults int64) *NetworksListPeeringRoutesCall { + c.urlParams_.Set("maxResults", fmt.Sprint(maxResults)) + return c +} + +// OrderBy sets the optional parameter "orderBy": Sorts list results by +// a certain order. By default, results are returned in alphanumerical +// order based on the resource name. +// +// You can also sort results in descending order based on the creation +// timestamp using orderBy="creationTimestamp desc". This sorts results +// based on the creationTimestamp field in reverse chronological order +// (newest result first). Use this to sort resources like operations so +// that the newest operation is returned first. +// +// Currently, only sorting by name or creationTimestamp desc is +// supported. +func (c *NetworksListPeeringRoutesCall) OrderBy(orderBy string) *NetworksListPeeringRoutesCall { + c.urlParams_.Set("orderBy", orderBy) + return c +} + +// PageToken sets the optional parameter "pageToken": Specifies a page +// token to use. Set pageToken to the nextPageToken returned by a +// previous list request to get the next page of results. +func (c *NetworksListPeeringRoutesCall) PageToken(pageToken string) *NetworksListPeeringRoutesCall { + c.urlParams_.Set("pageToken", pageToken) + return c +} + +// PeeringName sets the optional parameter "peeringName": The response +// will show routes exchanged over the given peering connection. +func (c *NetworksListPeeringRoutesCall) PeeringName(peeringName string) *NetworksListPeeringRoutesCall { + c.urlParams_.Set("peeringName", peeringName) + return c +} + +// Region sets the optional parameter "region": The region of the +// request. The response will include all subnet routes, static routes +// and dynamic routes in the region. +func (c *NetworksListPeeringRoutesCall) Region(region string) *NetworksListPeeringRoutesCall { + c.urlParams_.Set("region", region) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *NetworksListPeeringRoutesCall) Fields(s ...googleapi.Field) *NetworksListPeeringRoutesCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// IfNoneMatch sets the optional parameter which makes the operation +// fail if the object's ETag matches the given value. This is useful for +// getting updates only after the object has changed since the last +// request. Use googleapi.IsNotModified to check whether the response +// error from Do is the result of In-None-Match. +func (c *NetworksListPeeringRoutesCall) IfNoneMatch(entityTag string) *NetworksListPeeringRoutesCall { + c.ifNoneMatch_ = entityTag + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *NetworksListPeeringRoutesCall) Context(ctx context.Context) *NetworksListPeeringRoutesCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *NetworksListPeeringRoutesCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *NetworksListPeeringRoutesCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + if c.ifNoneMatch_ != "" { + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) + } + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/networks/{network}/listPeeringRoutes") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "network": c.network, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.networks.listPeeringRoutes" call. +// Exactly one of *ExchangedPeeringRoutesList or error will be non-nil. +// Any non-2xx status code is an error. Response headers are in either +// *ExchangedPeeringRoutesList.ServerResponse.Header or (if a response +// was returned at all) in error.(*googleapi.Error).Header. Use +// googleapi.IsNotModified to check whether the returned error was +// because http.StatusNotModified was returned. +func (c *NetworksListPeeringRoutesCall) Do(opts ...googleapi.CallOption) (*ExchangedPeeringRoutesList, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &ExchangedPeeringRoutesList{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Lists the peering routes exchanged over peering connection.", + // "httpMethod": "GET", + // "id": "compute.networks.listPeeringRoutes", + // "parameterOrder": [ + // "project", + // "network" + // ], + // "parameters": { + // "direction": { + // "description": "The direction of the exchanged routes.", + // "enum": [ + // "INCOMING", + // "OUTGOING" + // ], + // "enumDescriptions": [ + // "", + // "" + // ], + // "location": "query", + // "type": "string" + // }, + // "filter": { + // "description": "A filter expression that filters resources listed in the response. The expression must specify the field name, a comparison operator, and the value that you want to use for filtering. The value must be a string, a number, or a boolean. The comparison operator must be either =, !=, \u003e, or \u003c.\n\nFor example, if you are filtering Compute Engine instances, you can exclude instances named example-instance by specifying name != example-instance.\n\nYou can also filter nested fields. For example, you could specify scheduling.automaticRestart = false to include instances only if they are not scheduled for automatic restarts. You can use filtering on nested fields to filter based on resource labels.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart = true) (cpuPlatform = \"Intel Skylake\"). By default, each expression is an AND expression. However, you can include AND and OR expressions explicitly. For example, (cpuPlatform = \"Intel Skylake\") OR (cpuPlatform = \"Intel Broadwell\") AND (scheduling.automaticRestart = true).", + // "location": "query", + // "type": "string" + // }, + // "maxResults": { + // "default": "500", + // "description": "The maximum number of results per page that should be returned. If the number of available results is larger than maxResults, Compute Engine returns a nextPageToken that can be used to get the next page of results in subsequent list requests. Acceptable values are 0 to 500, inclusive. (Default: 500)", + // "format": "uint32", + // "location": "query", + // "minimum": "0", + // "type": "integer" + // }, + // "network": { + // "description": "Name of the network for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + // "required": true, + // "type": "string" + // }, + // "orderBy": { + // "description": "Sorts list results by a certain order. By default, results are returned in alphanumerical order based on the resource name.\n\nYou can also sort results in descending order based on the creation timestamp using orderBy=\"creationTimestamp desc\". This sorts results based on the creationTimestamp field in reverse chronological order (newest result first). Use this to sort resources like operations so that the newest operation is returned first.\n\nCurrently, only sorting by name or creationTimestamp desc is supported.", + // "location": "query", + // "type": "string" + // }, + // "pageToken": { + // "description": "Specifies a page token to use. Set pageToken to the nextPageToken returned by a previous list request to get the next page of results.", + // "location": "query", + // "type": "string" + // }, + // "peeringName": { + // "description": "The response will show routes exchanged over the given peering connection.", + // "location": "query", + // "type": "string" + // }, + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "region": { + // "description": "The region of the request. The response will include all subnet routes, static routes and dynamic routes in the region.", + // "location": "query", + // "type": "string" + // } + // }, + // "path": "{project}/global/networks/{network}/listPeeringRoutes", + // "response": { + // "$ref": "ExchangedPeeringRoutesList" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute", + // "https://www.googleapis.com/auth/compute.readonly" + // ] + // } + +} + +// Pages invokes f for each page of results. +// A non-nil error returned from f will halt the iteration. +// The provided context supersedes any context provided to the Context method. +func (c *NetworksListPeeringRoutesCall) Pages(ctx context.Context, f func(*ExchangedPeeringRoutesList) error) error { + c.ctx_ = ctx + defer c.PageToken(c.urlParams_.Get("pageToken")) // reset paging to original point + for { + x, err := c.Do() + if err != nil { + return err + } + if err := f(x); err != nil { + return err + } + if x.NextPageToken == "" { + return nil + } + c.PageToken(x.NextPageToken) + } +} + // method id "compute.networks.patch": type NetworksPatchCall struct { @@ -84295,9 +91469,13 @@ func (c *NetworksPatchCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/networks/{network}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PATCH", urls, body) + req, err := http.NewRequest("PATCH", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -84355,7 +91533,7 @@ func (c *NetworksPatchCall) Do(opts ...googleapi.CallOption) (*Operation, error) // "network": { // "description": "Name of the network to update.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -84465,9 +91643,13 @@ func (c *NetworksRemovePeeringCall) doRequest(alt string) (*http.Response, error } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/networks/{network}/removePeering") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -84525,7 +91707,7 @@ func (c *NetworksRemovePeeringCall) Do(opts ...googleapi.CallOption) (*Operation // "network": { // "description": "Name of the network resource to remove peering from.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -84629,9 +91811,13 @@ func (c *NetworksSwitchToCustomModeCall) doRequest(alt string) (*http.Response, reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/networks/{network}/switchToCustomMode") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -84689,7 +91875,7 @@ func (c *NetworksSwitchToCustomModeCall) Do(opts ...googleapi.CallOption) (*Oper // "network": { // "description": "Name of the network to be updated.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -84778,9 +91964,13 @@ func (c *NetworksTestIamPermissionsCall) doRequest(alt string) (*http.Response, } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/networks/{resource}/testIamPermissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -84843,9 +92033,9 @@ func (c *NetworksTestIamPermissionsCall) Do(opts ...googleapi.CallOption) (*Test // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "(?:[-a-z0-9_]{0,62}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -84866,6 +92056,183 @@ func (c *NetworksTestIamPermissionsCall) Do(opts ...googleapi.CallOption) (*Test } +// method id "compute.networks.updatePeering": + +type NetworksUpdatePeeringCall struct { + s *Service + project string + network string + networksupdatepeeringrequest *NetworksUpdatePeeringRequest + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// UpdatePeering: Updates the specified network peering with the data +// included in the request Only the following fields can be modified: +// NetworkPeering.export_custom_routes, and +// NetworkPeering.import_custom_routes +func (r *NetworksService) UpdatePeering(project string, network string, networksupdatepeeringrequest *NetworksUpdatePeeringRequest) *NetworksUpdatePeeringCall { + c := &NetworksUpdatePeeringCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.network = network + c.networksupdatepeeringrequest = networksupdatepeeringrequest + return c +} + +// RequestId sets the optional parameter "requestId": An optional +// request ID to identify requests. Specify a unique request ID so that +// if you must retry your request, the server will know to ignore the +// request if it has already been completed. +// +// For example, consider a situation where you make an initial request +// and the request times out. If you make the request again with the +// same request ID, the server can check if original operation with the +// same request ID was received, and if so, will ignore the second +// request. This prevents clients from accidentally creating duplicate +// commitments. +// +// The request ID must be a valid UUID with the exception that zero UUID +// is not supported (00000000-0000-0000-0000-000000000000). +func (c *NetworksUpdatePeeringCall) RequestId(requestId string) *NetworksUpdatePeeringCall { + c.urlParams_.Set("requestId", requestId) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *NetworksUpdatePeeringCall) Fields(s ...googleapi.Field) *NetworksUpdatePeeringCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *NetworksUpdatePeeringCall) Context(ctx context.Context) *NetworksUpdatePeeringCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *NetworksUpdatePeeringCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *NetworksUpdatePeeringCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.networksupdatepeeringrequest) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/networks/{network}/updatePeering") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("PATCH", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "network": c.network, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.networks.updatePeering" call. +// Exactly one of *Operation or error will be non-nil. Any non-2xx +// status code is an error. Response headers are in either +// *Operation.ServerResponse.Header or (if a response was returned at +// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified +// to check whether the returned error was because +// http.StatusNotModified was returned. +func (c *NetworksUpdatePeeringCall) Do(opts ...googleapi.CallOption) (*Operation, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Operation{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Updates the specified network peering with the data included in the request Only the following fields can be modified: NetworkPeering.export_custom_routes, and NetworkPeering.import_custom_routes", + // "httpMethod": "PATCH", + // "id": "compute.networks.updatePeering", + // "parameterOrder": [ + // "project", + // "network" + // ], + // "parameters": { + // "network": { + // "description": "Name of the network resource which the updated peering is belonging to.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + // "required": true, + // "type": "string" + // }, + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "requestId": { + // "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", + // "location": "query", + // "type": "string" + // } + // }, + // "path": "{project}/global/networks/{network}/updatePeering", + // "request": { + // "$ref": "NetworksUpdatePeeringRequest" + // }, + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + // method id "compute.nodeGroups.addNodes": type NodeGroupsAddNodesCall struct { @@ -84946,9 +92313,13 @@ func (c *NodeGroupsAddNodesCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/nodeGroups/{nodeGroup}/addNodes") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -85006,7 +92377,7 @@ func (c *NodeGroupsAddNodesCall) Do(opts ...googleapi.CallOption) (*Operation, e // ], // "parameters": { // "nodeGroup": { - // "description": "Name of the NodeGroup resource to delete.", + // "description": "Name of the NodeGroup resource.", // "location": "path", // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", // "required": true, @@ -85058,7 +92429,8 @@ type NodeGroupsAggregatedListCall struct { header_ http.Header } -// AggregatedList: Retrieves an aggregated list of node groups. +// AggregatedList: Retrieves an aggregated list of node groups. Note: +// use nodeGroups.listNodes for more details about each group. func (r *NodeGroupsService) AggregatedList(project string) *NodeGroupsAggregatedListCall { c := &NodeGroupsAggregatedListCall{s: r.s, urlParams_: make(gensupport.URLParams)} c.project = project @@ -85174,9 +92546,13 @@ func (c *NodeGroupsAggregatedListCall) doRequest(alt string) (*http.Response, er } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/aggregated/nodeGroups") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -85222,7 +92598,7 @@ func (c *NodeGroupsAggregatedListCall) Do(opts ...googleapi.CallOption) (*NodeGr } return ret, nil // { - // "description": "Retrieves an aggregated list of node groups.", + // "description": "Retrieves an aggregated list of node groups. Note: use nodeGroups.listNodes for more details about each group.", // "httpMethod": "GET", // "id": "compute.nodeGroups.aggregatedList", // "parameterOrder": [ @@ -85367,9 +92743,13 @@ func (c *NodeGroupsDeleteCall) doRequest(alt string) (*http.Response, error) { reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/nodeGroups/{nodeGroup}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -85545,9 +92925,13 @@ func (c *NodeGroupsDeleteNodesCall) doRequest(alt string) (*http.Response, error } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/nodeGroups/{nodeGroup}/deleteNodes") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -85660,7 +93044,8 @@ type NodeGroupsGetCall struct { } // Get: Returns the specified NodeGroup. Get a list of available -// NodeGroups by making a list() request. +// NodeGroups by making a list() request. Note: the "nodes" field should +// not be used. Use nodeGroups.listNodes instead. func (r *NodeGroupsService) Get(project string, zone string, nodeGroup string) *NodeGroupsGetCall { c := &NodeGroupsGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} c.project = project @@ -85715,9 +93100,13 @@ func (c *NodeGroupsGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/nodeGroups/{nodeGroup}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -85765,7 +93154,7 @@ func (c *NodeGroupsGetCall) Do(opts ...googleapi.CallOption) (*NodeGroup, error) } return ret, nil // { - // "description": "Returns the specified NodeGroup. Get a list of available NodeGroups by making a list() request.", + // "description": "Returns the specified NodeGroup. Get a list of available NodeGroups by making a list() request. Note: the \"nodes\" field should not be used. Use nodeGroups.listNodes instead.", // "httpMethod": "GET", // "id": "compute.nodeGroups.get", // "parameterOrder": [ @@ -85878,9 +93267,13 @@ func (c *NodeGroupsGetIamPolicyCall) doRequest(alt string) (*http.Response, erro } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/nodeGroups/{resource}/getIamPolicy") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -85945,9 +93338,9 @@ func (c *NodeGroupsGetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Policy, // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -86052,9 +93445,13 @@ func (c *NodeGroupsInsertCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/nodeGroups") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -86165,7 +93562,8 @@ type NodeGroupsListCall struct { } // List: Retrieves a list of node groups available to the specified -// project. +// project. Note: use nodeGroups.listNodes for more details about each +// group. func (r *NodeGroupsService) List(project string, zone string) *NodeGroupsListCall { c := &NodeGroupsListCall{s: r.s, urlParams_: make(gensupport.URLParams)} c.project = project @@ -86282,9 +93680,13 @@ func (c *NodeGroupsListCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/nodeGroups") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -86331,7 +93733,7 @@ func (c *NodeGroupsListCall) Do(opts ...googleapi.CallOption) (*NodeGroupList, e } return ret, nil // { - // "description": "Retrieves a list of node groups available to the specified project.", + // "description": "Retrieves a list of node groups available to the specified project. Note: use nodeGroups.listNodes for more details about each group.", // "httpMethod": "GET", // "id": "compute.nodeGroups.list", // "parameterOrder": [ @@ -86411,6 +93813,265 @@ func (c *NodeGroupsListCall) Pages(ctx context.Context, f func(*NodeGroupList) e } } +// method id "compute.nodeGroups.listNodes": + +type NodeGroupsListNodesCall struct { + s *Service + project string + zone string + nodeGroup string + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// ListNodes: Lists nodes in the node group. +func (r *NodeGroupsService) ListNodes(project string, zone string, nodeGroup string) *NodeGroupsListNodesCall { + c := &NodeGroupsListNodesCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.zone = zone + c.nodeGroup = nodeGroup + return c +} + +// Filter sets the optional parameter "filter": A filter expression that +// filters resources listed in the response. The expression must specify +// the field name, a comparison operator, and the value that you want to +// use for filtering. The value must be a string, a number, or a +// boolean. The comparison operator must be either =, !=, >, or <. +// +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. +// +// You can also filter nested fields. For example, you could specify +// scheduling.automaticRestart = false to include instances only if they +// are not scheduled for automatic restarts. You can use filtering on +// nested fields to filter based on resource labels. +// +// To filter on multiple expressions, provide each separate expression +// within parentheses. For example, (scheduling.automaticRestart = true) +// (cpuPlatform = "Intel Skylake"). By default, each expression is an +// AND expression. However, you can include AND and OR expressions +// explicitly. For example, (cpuPlatform = "Intel Skylake") OR +// (cpuPlatform = "Intel Broadwell") AND (scheduling.automaticRestart = +// true). +func (c *NodeGroupsListNodesCall) Filter(filter string) *NodeGroupsListNodesCall { + c.urlParams_.Set("filter", filter) + return c +} + +// MaxResults sets the optional parameter "maxResults": The maximum +// number of results per page that should be returned. If the number of +// available results is larger than maxResults, Compute Engine returns a +// nextPageToken that can be used to get the next page of results in +// subsequent list requests. Acceptable values are 0 to 500, inclusive. +// (Default: 500) +func (c *NodeGroupsListNodesCall) MaxResults(maxResults int64) *NodeGroupsListNodesCall { + c.urlParams_.Set("maxResults", fmt.Sprint(maxResults)) + return c +} + +// OrderBy sets the optional parameter "orderBy": Sorts list results by +// a certain order. By default, results are returned in alphanumerical +// order based on the resource name. +// +// You can also sort results in descending order based on the creation +// timestamp using orderBy="creationTimestamp desc". This sorts results +// based on the creationTimestamp field in reverse chronological order +// (newest result first). Use this to sort resources like operations so +// that the newest operation is returned first. +// +// Currently, only sorting by name or creationTimestamp desc is +// supported. +func (c *NodeGroupsListNodesCall) OrderBy(orderBy string) *NodeGroupsListNodesCall { + c.urlParams_.Set("orderBy", orderBy) + return c +} + +// PageToken sets the optional parameter "pageToken": Specifies a page +// token to use. Set pageToken to the nextPageToken returned by a +// previous list request to get the next page of results. +func (c *NodeGroupsListNodesCall) PageToken(pageToken string) *NodeGroupsListNodesCall { + c.urlParams_.Set("pageToken", pageToken) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *NodeGroupsListNodesCall) Fields(s ...googleapi.Field) *NodeGroupsListNodesCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *NodeGroupsListNodesCall) Context(ctx context.Context) *NodeGroupsListNodesCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *NodeGroupsListNodesCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *NodeGroupsListNodesCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/nodeGroups/{nodeGroup}/listNodes") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "zone": c.zone, + "nodeGroup": c.nodeGroup, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.nodeGroups.listNodes" call. +// Exactly one of *NodeGroupsListNodes or error will be non-nil. Any +// non-2xx status code is an error. Response headers are in either +// *NodeGroupsListNodes.ServerResponse.Header or (if a response was +// returned at all) in error.(*googleapi.Error).Header. Use +// googleapi.IsNotModified to check whether the returned error was +// because http.StatusNotModified was returned. +func (c *NodeGroupsListNodesCall) Do(opts ...googleapi.CallOption) (*NodeGroupsListNodes, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &NodeGroupsListNodes{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Lists nodes in the node group.", + // "httpMethod": "POST", + // "id": "compute.nodeGroups.listNodes", + // "parameterOrder": [ + // "project", + // "zone", + // "nodeGroup" + // ], + // "parameters": { + // "filter": { + // "description": "A filter expression that filters resources listed in the response. The expression must specify the field name, a comparison operator, and the value that you want to use for filtering. The value must be a string, a number, or a boolean. The comparison operator must be either =, !=, \u003e, or \u003c.\n\nFor example, if you are filtering Compute Engine instances, you can exclude instances named example-instance by specifying name != example-instance.\n\nYou can also filter nested fields. For example, you could specify scheduling.automaticRestart = false to include instances only if they are not scheduled for automatic restarts. You can use filtering on nested fields to filter based on resource labels.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart = true) (cpuPlatform = \"Intel Skylake\"). By default, each expression is an AND expression. However, you can include AND and OR expressions explicitly. For example, (cpuPlatform = \"Intel Skylake\") OR (cpuPlatform = \"Intel Broadwell\") AND (scheduling.automaticRestart = true).", + // "location": "query", + // "type": "string" + // }, + // "maxResults": { + // "default": "500", + // "description": "The maximum number of results per page that should be returned. If the number of available results is larger than maxResults, Compute Engine returns a nextPageToken that can be used to get the next page of results in subsequent list requests. Acceptable values are 0 to 500, inclusive. (Default: 500)", + // "format": "uint32", + // "location": "query", + // "minimum": "0", + // "type": "integer" + // }, + // "nodeGroup": { + // "description": "Name of the NodeGroup resource whose nodes you want to list.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // }, + // "orderBy": { + // "description": "Sorts list results by a certain order. By default, results are returned in alphanumerical order based on the resource name.\n\nYou can also sort results in descending order based on the creation timestamp using orderBy=\"creationTimestamp desc\". This sorts results based on the creationTimestamp field in reverse chronological order (newest result first). Use this to sort resources like operations so that the newest operation is returned first.\n\nCurrently, only sorting by name or creationTimestamp desc is supported.", + // "location": "query", + // "type": "string" + // }, + // "pageToken": { + // "description": "Specifies a page token to use. Set pageToken to the nextPageToken returned by a previous list request to get the next page of results.", + // "location": "query", + // "type": "string" + // }, + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "zone": { + // "description": "The name of the zone for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/zones/{zone}/nodeGroups/{nodeGroup}/listNodes", + // "response": { + // "$ref": "NodeGroupsListNodes" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute", + // "https://www.googleapis.com/auth/compute.readonly" + // ] + // } + +} + +// Pages invokes f for each page of results. +// A non-nil error returned from f will halt the iteration. +// The provided context supersedes any context provided to the Context method. +func (c *NodeGroupsListNodesCall) Pages(ctx context.Context, f func(*NodeGroupsListNodes) error) error { + c.ctx_ = ctx + defer c.PageToken(c.urlParams_.Get("pageToken")) // reset paging to original point + for { + x, err := c.Do() + if err != nil { + return err + } + if err := f(x); err != nil { + return err + } + if x.NextPageToken == "" { + return nil + } + c.PageToken(x.NextPageToken) + } +} + // method id "compute.nodeGroups.setIamPolicy": type NodeGroupsSetIamPolicyCall struct { @@ -86473,9 +94134,13 @@ func (c *NodeGroupsSetIamPolicyCall) doRequest(alt string) (*http.Response, erro } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/nodeGroups/{resource}/setIamPolicy") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -86540,9 +94205,9 @@ func (c *NodeGroupsSetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Policy, // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -86649,9 +94314,13 @@ func (c *NodeGroupsSetNodeTemplateCall) doRequest(alt string) (*http.Response, e } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/nodeGroups/{nodeGroup}/setNodeTemplate") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -86812,9 +94481,13 @@ func (c *NodeGroupsTestIamPermissionsCall) doRequest(alt string) (*http.Response } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/nodeGroups/{resource}/testIamPermissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -86879,9 +94552,9 @@ func (c *NodeGroupsTestIamPermissionsCall) Do(opts ...googleapi.CallOption) (*Te // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -87036,9 +94709,13 @@ func (c *NodeTemplatesAggregatedListCall) doRequest(alt string) (*http.Response, } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/aggregated/nodeTemplates") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -87229,9 +94906,13 @@ func (c *NodeTemplatesDeleteCall) doRequest(alt string) (*http.Response, error) reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/nodeTemplates/{nodeTemplate}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -87396,9 +95077,13 @@ func (c *NodeTemplatesGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/nodeTemplates/{nodeTemplate}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -87559,9 +95244,13 @@ func (c *NodeTemplatesGetIamPolicyCall) doRequest(alt string) (*http.Response, e } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/nodeTemplates/{resource}/getIamPolicy") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -87633,9 +95322,9 @@ func (c *NodeTemplatesGetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Polic // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -87732,9 +95421,13 @@ func (c *NodeTemplatesInsertCall) doRequest(alt string) (*http.Response, error) } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/nodeTemplates") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -87954,9 +95647,13 @@ func (c *NodeTemplatesListCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/nodeTemplates") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -88145,9 +95842,13 @@ func (c *NodeTemplatesSetIamPolicyCall) doRequest(alt string) (*http.Response, e } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/nodeTemplates/{resource}/setIamPolicy") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -88219,9 +95920,9 @@ func (c *NodeTemplatesSetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Polic // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -88303,9 +96004,13 @@ func (c *NodeTemplatesTestIamPermissionsCall) doRequest(alt string) (*http.Respo } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/nodeTemplates/{resource}/testIamPermissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -88377,9 +96082,9 @@ func (c *NodeTemplatesTestIamPermissionsCall) Do(opts ...googleapi.CallOption) ( // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -88527,9 +96232,13 @@ func (c *NodeTypesAggregatedListCall) doRequest(alt string) (*http.Response, err } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/aggregated/nodeTypes") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -88716,9 +96425,13 @@ func (c *NodeTypesGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/nodeTypes/{nodeType}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -88940,9 +96653,13 @@ func (c *NodeTypesListCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/nodeTypes") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -89069,6 +96786,1862 @@ func (c *NodeTypesListCall) Pages(ctx context.Context, f func(*NodeTypeList) err } } +// method id "compute.organizationSecurityPolicies.addAssociation": + +type OrganizationSecurityPoliciesAddAssociationCall struct { + s *Service + securityPolicy string + securitypolicyassociation *SecurityPolicyAssociation + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// AddAssociation: Inserts an association for the specified security +// policy. +func (r *OrganizationSecurityPoliciesService) AddAssociation(securityPolicy string, securitypolicyassociation *SecurityPolicyAssociation) *OrganizationSecurityPoliciesAddAssociationCall { + c := &OrganizationSecurityPoliciesAddAssociationCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.securityPolicy = securityPolicy + c.securitypolicyassociation = securitypolicyassociation + return c +} + +// RequestId sets the optional parameter "requestId": An optional +// request ID to identify requests. Specify a unique request ID so that +// if you must retry your request, the server will know to ignore the +// request if it has already been completed. +// +// For example, consider a situation where you make an initial request +// and the request times out. If you make the request again with the +// same request ID, the server can check if original operation with the +// same request ID was received, and if so, will ignore the second +// request. This prevents clients from accidentally creating duplicate +// commitments. +// +// The request ID must be a valid UUID with the exception that zero UUID +// is not supported (00000000-0000-0000-0000-000000000000). +func (c *OrganizationSecurityPoliciesAddAssociationCall) RequestId(requestId string) *OrganizationSecurityPoliciesAddAssociationCall { + c.urlParams_.Set("requestId", requestId) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *OrganizationSecurityPoliciesAddAssociationCall) Fields(s ...googleapi.Field) *OrganizationSecurityPoliciesAddAssociationCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *OrganizationSecurityPoliciesAddAssociationCall) Context(ctx context.Context) *OrganizationSecurityPoliciesAddAssociationCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *OrganizationSecurityPoliciesAddAssociationCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *OrganizationSecurityPoliciesAddAssociationCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.securitypolicyassociation) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "locations/global/securityPolicies/{securityPolicy}/addAssociation") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "securityPolicy": c.securityPolicy, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.organizationSecurityPolicies.addAssociation" call. +// Exactly one of *Operation or error will be non-nil. Any non-2xx +// status code is an error. Response headers are in either +// *Operation.ServerResponse.Header or (if a response was returned at +// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified +// to check whether the returned error was because +// http.StatusNotModified was returned. +func (c *OrganizationSecurityPoliciesAddAssociationCall) Do(opts ...googleapi.CallOption) (*Operation, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Operation{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Inserts an association for the specified security policy.", + // "httpMethod": "POST", + // "id": "compute.organizationSecurityPolicies.addAssociation", + // "parameterOrder": [ + // "securityPolicy" + // ], + // "parameters": { + // "requestId": { + // "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", + // "location": "query", + // "type": "string" + // }, + // "securityPolicy": { + // "description": "Name of the security policy to update.", + // "location": "path", + // "pattern": "[0-9]{0,20}", + // "required": true, + // "type": "string" + // } + // }, + // "path": "locations/global/securityPolicies/{securityPolicy}/addAssociation", + // "request": { + // "$ref": "SecurityPolicyAssociation" + // }, + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + +// method id "compute.organizationSecurityPolicies.addRule": + +type OrganizationSecurityPoliciesAddRuleCall struct { + s *Service + securityPolicy string + securitypolicyrule *SecurityPolicyRule + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// AddRule: Inserts a rule into a security policy. +func (r *OrganizationSecurityPoliciesService) AddRule(securityPolicy string, securitypolicyrule *SecurityPolicyRule) *OrganizationSecurityPoliciesAddRuleCall { + c := &OrganizationSecurityPoliciesAddRuleCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.securityPolicy = securityPolicy + c.securitypolicyrule = securitypolicyrule + return c +} + +// RequestId sets the optional parameter "requestId": An optional +// request ID to identify requests. Specify a unique request ID so that +// if you must retry your request, the server will know to ignore the +// request if it has already been completed. +// +// For example, consider a situation where you make an initial request +// and the request times out. If you make the request again with the +// same request ID, the server can check if original operation with the +// same request ID was received, and if so, will ignore the second +// request. This prevents clients from accidentally creating duplicate +// commitments. +// +// The request ID must be a valid UUID with the exception that zero UUID +// is not supported (00000000-0000-0000-0000-000000000000). +func (c *OrganizationSecurityPoliciesAddRuleCall) RequestId(requestId string) *OrganizationSecurityPoliciesAddRuleCall { + c.urlParams_.Set("requestId", requestId) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *OrganizationSecurityPoliciesAddRuleCall) Fields(s ...googleapi.Field) *OrganizationSecurityPoliciesAddRuleCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *OrganizationSecurityPoliciesAddRuleCall) Context(ctx context.Context) *OrganizationSecurityPoliciesAddRuleCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *OrganizationSecurityPoliciesAddRuleCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *OrganizationSecurityPoliciesAddRuleCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.securitypolicyrule) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "locations/global/securityPolicies/{securityPolicy}/addRule") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "securityPolicy": c.securityPolicy, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.organizationSecurityPolicies.addRule" call. +// Exactly one of *Operation or error will be non-nil. Any non-2xx +// status code is an error. Response headers are in either +// *Operation.ServerResponse.Header or (if a response was returned at +// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified +// to check whether the returned error was because +// http.StatusNotModified was returned. +func (c *OrganizationSecurityPoliciesAddRuleCall) Do(opts ...googleapi.CallOption) (*Operation, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Operation{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Inserts a rule into a security policy.", + // "httpMethod": "POST", + // "id": "compute.organizationSecurityPolicies.addRule", + // "parameterOrder": [ + // "securityPolicy" + // ], + // "parameters": { + // "requestId": { + // "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", + // "location": "query", + // "type": "string" + // }, + // "securityPolicy": { + // "description": "Name of the security policy to update.", + // "location": "path", + // "pattern": "[0-9]{0,20}", + // "required": true, + // "type": "string" + // } + // }, + // "path": "locations/global/securityPolicies/{securityPolicy}/addRule", + // "request": { + // "$ref": "SecurityPolicyRule" + // }, + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + +// method id "compute.organizationSecurityPolicies.delete": + +type OrganizationSecurityPoliciesDeleteCall struct { + s *Service + securityPolicy string + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// Delete: Deletes the specified policy. +func (r *OrganizationSecurityPoliciesService) Delete(securityPolicy string) *OrganizationSecurityPoliciesDeleteCall { + c := &OrganizationSecurityPoliciesDeleteCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.securityPolicy = securityPolicy + return c +} + +// RequestId sets the optional parameter "requestId": An optional +// request ID to identify requests. Specify a unique request ID so that +// if you must retry your request, the server will know to ignore the +// request if it has already been completed. +// +// For example, consider a situation where you make an initial request +// and the request times out. If you make the request again with the +// same request ID, the server can check if original operation with the +// same request ID was received, and if so, will ignore the second +// request. This prevents clients from accidentally creating duplicate +// commitments. +// +// The request ID must be a valid UUID with the exception that zero UUID +// is not supported (00000000-0000-0000-0000-000000000000). +func (c *OrganizationSecurityPoliciesDeleteCall) RequestId(requestId string) *OrganizationSecurityPoliciesDeleteCall { + c.urlParams_.Set("requestId", requestId) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *OrganizationSecurityPoliciesDeleteCall) Fields(s ...googleapi.Field) *OrganizationSecurityPoliciesDeleteCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *OrganizationSecurityPoliciesDeleteCall) Context(ctx context.Context) *OrganizationSecurityPoliciesDeleteCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *OrganizationSecurityPoliciesDeleteCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *OrganizationSecurityPoliciesDeleteCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "locations/global/securityPolicies/{securityPolicy}") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "securityPolicy": c.securityPolicy, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.organizationSecurityPolicies.delete" call. +// Exactly one of *Operation or error will be non-nil. Any non-2xx +// status code is an error. Response headers are in either +// *Operation.ServerResponse.Header or (if a response was returned at +// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified +// to check whether the returned error was because +// http.StatusNotModified was returned. +func (c *OrganizationSecurityPoliciesDeleteCall) Do(opts ...googleapi.CallOption) (*Operation, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Operation{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Deletes the specified policy.", + // "httpMethod": "DELETE", + // "id": "compute.organizationSecurityPolicies.delete", + // "parameterOrder": [ + // "securityPolicy" + // ], + // "parameters": { + // "requestId": { + // "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", + // "location": "query", + // "type": "string" + // }, + // "securityPolicy": { + // "description": "Name of the security policy to delete.", + // "location": "path", + // "pattern": "[0-9]{0,20}", + // "required": true, + // "type": "string" + // } + // }, + // "path": "locations/global/securityPolicies/{securityPolicy}", + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + +// method id "compute.organizationSecurityPolicies.get": + +type OrganizationSecurityPoliciesGetCall struct { + s *Service + securityPolicy string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// Get: List all of the ordered rules present in a single specified +// policy. +func (r *OrganizationSecurityPoliciesService) Get(securityPolicy string) *OrganizationSecurityPoliciesGetCall { + c := &OrganizationSecurityPoliciesGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.securityPolicy = securityPolicy + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *OrganizationSecurityPoliciesGetCall) Fields(s ...googleapi.Field) *OrganizationSecurityPoliciesGetCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// IfNoneMatch sets the optional parameter which makes the operation +// fail if the object's ETag matches the given value. This is useful for +// getting updates only after the object has changed since the last +// request. Use googleapi.IsNotModified to check whether the response +// error from Do is the result of In-None-Match. +func (c *OrganizationSecurityPoliciesGetCall) IfNoneMatch(entityTag string) *OrganizationSecurityPoliciesGetCall { + c.ifNoneMatch_ = entityTag + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *OrganizationSecurityPoliciesGetCall) Context(ctx context.Context) *OrganizationSecurityPoliciesGetCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *OrganizationSecurityPoliciesGetCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *OrganizationSecurityPoliciesGetCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + if c.ifNoneMatch_ != "" { + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) + } + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "locations/global/securityPolicies/{securityPolicy}") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "securityPolicy": c.securityPolicy, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.organizationSecurityPolicies.get" call. +// Exactly one of *SecurityPolicy or error will be non-nil. Any non-2xx +// status code is an error. Response headers are in either +// *SecurityPolicy.ServerResponse.Header or (if a response was returned +// at all) in error.(*googleapi.Error).Header. Use +// googleapi.IsNotModified to check whether the returned error was +// because http.StatusNotModified was returned. +func (c *OrganizationSecurityPoliciesGetCall) Do(opts ...googleapi.CallOption) (*SecurityPolicy, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &SecurityPolicy{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "List all of the ordered rules present in a single specified policy.", + // "httpMethod": "GET", + // "id": "compute.organizationSecurityPolicies.get", + // "parameterOrder": [ + // "securityPolicy" + // ], + // "parameters": { + // "securityPolicy": { + // "description": "Name of the security policy to get.", + // "location": "path", + // "pattern": "[0-9]{0,20}", + // "required": true, + // "type": "string" + // } + // }, + // "path": "locations/global/securityPolicies/{securityPolicy}", + // "response": { + // "$ref": "SecurityPolicy" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute", + // "https://www.googleapis.com/auth/compute.readonly" + // ] + // } + +} + +// method id "compute.organizationSecurityPolicies.getAssociation": + +type OrganizationSecurityPoliciesGetAssociationCall struct { + s *Service + securityPolicy string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// GetAssociation: Gets an association with the specified name. +func (r *OrganizationSecurityPoliciesService) GetAssociation(securityPolicy string) *OrganizationSecurityPoliciesGetAssociationCall { + c := &OrganizationSecurityPoliciesGetAssociationCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.securityPolicy = securityPolicy + return c +} + +// Name sets the optional parameter "name": The name of the association +// to get from the security policy. +func (c *OrganizationSecurityPoliciesGetAssociationCall) Name(name string) *OrganizationSecurityPoliciesGetAssociationCall { + c.urlParams_.Set("name", name) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *OrganizationSecurityPoliciesGetAssociationCall) Fields(s ...googleapi.Field) *OrganizationSecurityPoliciesGetAssociationCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// IfNoneMatch sets the optional parameter which makes the operation +// fail if the object's ETag matches the given value. This is useful for +// getting updates only after the object has changed since the last +// request. Use googleapi.IsNotModified to check whether the response +// error from Do is the result of In-None-Match. +func (c *OrganizationSecurityPoliciesGetAssociationCall) IfNoneMatch(entityTag string) *OrganizationSecurityPoliciesGetAssociationCall { + c.ifNoneMatch_ = entityTag + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *OrganizationSecurityPoliciesGetAssociationCall) Context(ctx context.Context) *OrganizationSecurityPoliciesGetAssociationCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *OrganizationSecurityPoliciesGetAssociationCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *OrganizationSecurityPoliciesGetAssociationCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + if c.ifNoneMatch_ != "" { + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) + } + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "locations/global/securityPolicies/{securityPolicy}/getAssociation") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "securityPolicy": c.securityPolicy, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.organizationSecurityPolicies.getAssociation" call. +// Exactly one of *SecurityPolicyAssociation or error will be non-nil. +// Any non-2xx status code is an error. Response headers are in either +// *SecurityPolicyAssociation.ServerResponse.Header or (if a response +// was returned at all) in error.(*googleapi.Error).Header. Use +// googleapi.IsNotModified to check whether the returned error was +// because http.StatusNotModified was returned. +func (c *OrganizationSecurityPoliciesGetAssociationCall) Do(opts ...googleapi.CallOption) (*SecurityPolicyAssociation, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &SecurityPolicyAssociation{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Gets an association with the specified name.", + // "httpMethod": "GET", + // "id": "compute.organizationSecurityPolicies.getAssociation", + // "parameterOrder": [ + // "securityPolicy" + // ], + // "parameters": { + // "name": { + // "description": "The name of the association to get from the security policy.", + // "location": "query", + // "type": "string" + // }, + // "securityPolicy": { + // "description": "Name of the security policy to which the queried rule belongs.", + // "location": "path", + // "pattern": "[0-9]{0,20}", + // "required": true, + // "type": "string" + // } + // }, + // "path": "locations/global/securityPolicies/{securityPolicy}/getAssociation", + // "response": { + // "$ref": "SecurityPolicyAssociation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute", + // "https://www.googleapis.com/auth/compute.readonly" + // ] + // } + +} + +// method id "compute.organizationSecurityPolicies.getRule": + +type OrganizationSecurityPoliciesGetRuleCall struct { + s *Service + securityPolicy string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// GetRule: Gets a rule at the specified priority. +func (r *OrganizationSecurityPoliciesService) GetRule(securityPolicy string) *OrganizationSecurityPoliciesGetRuleCall { + c := &OrganizationSecurityPoliciesGetRuleCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.securityPolicy = securityPolicy + return c +} + +// Priority sets the optional parameter "priority": The priority of the +// rule to get from the security policy. +func (c *OrganizationSecurityPoliciesGetRuleCall) Priority(priority int64) *OrganizationSecurityPoliciesGetRuleCall { + c.urlParams_.Set("priority", fmt.Sprint(priority)) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *OrganizationSecurityPoliciesGetRuleCall) Fields(s ...googleapi.Field) *OrganizationSecurityPoliciesGetRuleCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// IfNoneMatch sets the optional parameter which makes the operation +// fail if the object's ETag matches the given value. This is useful for +// getting updates only after the object has changed since the last +// request. Use googleapi.IsNotModified to check whether the response +// error from Do is the result of In-None-Match. +func (c *OrganizationSecurityPoliciesGetRuleCall) IfNoneMatch(entityTag string) *OrganizationSecurityPoliciesGetRuleCall { + c.ifNoneMatch_ = entityTag + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *OrganizationSecurityPoliciesGetRuleCall) Context(ctx context.Context) *OrganizationSecurityPoliciesGetRuleCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *OrganizationSecurityPoliciesGetRuleCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *OrganizationSecurityPoliciesGetRuleCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + if c.ifNoneMatch_ != "" { + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) + } + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "locations/global/securityPolicies/{securityPolicy}/getRule") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "securityPolicy": c.securityPolicy, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.organizationSecurityPolicies.getRule" call. +// Exactly one of *SecurityPolicyRule or error will be non-nil. Any +// non-2xx status code is an error. Response headers are in either +// *SecurityPolicyRule.ServerResponse.Header or (if a response was +// returned at all) in error.(*googleapi.Error).Header. Use +// googleapi.IsNotModified to check whether the returned error was +// because http.StatusNotModified was returned. +func (c *OrganizationSecurityPoliciesGetRuleCall) Do(opts ...googleapi.CallOption) (*SecurityPolicyRule, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &SecurityPolicyRule{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Gets a rule at the specified priority.", + // "httpMethod": "GET", + // "id": "compute.organizationSecurityPolicies.getRule", + // "parameterOrder": [ + // "securityPolicy" + // ], + // "parameters": { + // "priority": { + // "description": "The priority of the rule to get from the security policy.", + // "format": "int32", + // "location": "query", + // "type": "integer" + // }, + // "securityPolicy": { + // "description": "Name of the security policy to which the queried rule belongs.", + // "location": "path", + // "pattern": "[0-9]{0,20}", + // "required": true, + // "type": "string" + // } + // }, + // "path": "locations/global/securityPolicies/{securityPolicy}/getRule", + // "response": { + // "$ref": "SecurityPolicyRule" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute", + // "https://www.googleapis.com/auth/compute.readonly" + // ] + // } + +} + +// method id "compute.organizationSecurityPolicies.insert": + +type OrganizationSecurityPoliciesInsertCall struct { + s *Service + securitypolicy *SecurityPolicy + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// Insert: Creates a new policy in the specified project using the data +// included in the request. +func (r *OrganizationSecurityPoliciesService) Insert(securitypolicy *SecurityPolicy) *OrganizationSecurityPoliciesInsertCall { + c := &OrganizationSecurityPoliciesInsertCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.securitypolicy = securitypolicy + return c +} + +// ParentId sets the optional parameter "parentId": Parent ID for this +// request. +func (c *OrganizationSecurityPoliciesInsertCall) ParentId(parentId string) *OrganizationSecurityPoliciesInsertCall { + c.urlParams_.Set("parentId", parentId) + return c +} + +// RequestId sets the optional parameter "requestId": An optional +// request ID to identify requests. Specify a unique request ID so that +// if you must retry your request, the server will know to ignore the +// request if it has already been completed. +// +// For example, consider a situation where you make an initial request +// and the request times out. If you make the request again with the +// same request ID, the server can check if original operation with the +// same request ID was received, and if so, will ignore the second +// request. This prevents clients from accidentally creating duplicate +// commitments. +// +// The request ID must be a valid UUID with the exception that zero UUID +// is not supported (00000000-0000-0000-0000-000000000000). +func (c *OrganizationSecurityPoliciesInsertCall) RequestId(requestId string) *OrganizationSecurityPoliciesInsertCall { + c.urlParams_.Set("requestId", requestId) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *OrganizationSecurityPoliciesInsertCall) Fields(s ...googleapi.Field) *OrganizationSecurityPoliciesInsertCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *OrganizationSecurityPoliciesInsertCall) Context(ctx context.Context) *OrganizationSecurityPoliciesInsertCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *OrganizationSecurityPoliciesInsertCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *OrganizationSecurityPoliciesInsertCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.securitypolicy) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "locations/global/securityPolicies") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.organizationSecurityPolicies.insert" call. +// Exactly one of *Operation or error will be non-nil. Any non-2xx +// status code is an error. Response headers are in either +// *Operation.ServerResponse.Header or (if a response was returned at +// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified +// to check whether the returned error was because +// http.StatusNotModified was returned. +func (c *OrganizationSecurityPoliciesInsertCall) Do(opts ...googleapi.CallOption) (*Operation, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Operation{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Creates a new policy in the specified project using the data included in the request.", + // "httpMethod": "POST", + // "id": "compute.organizationSecurityPolicies.insert", + // "parameters": { + // "parentId": { + // "description": "Parent ID for this request.", + // "location": "query", + // "type": "string" + // }, + // "requestId": { + // "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", + // "location": "query", + // "type": "string" + // } + // }, + // "path": "locations/global/securityPolicies", + // "request": { + // "$ref": "SecurityPolicy" + // }, + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + +// method id "compute.organizationSecurityPolicies.list": + +type OrganizationSecurityPoliciesListCall struct { + s *Service + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// List: List all the policies that have been configured for the +// specified project. +func (r *OrganizationSecurityPoliciesService) List() *OrganizationSecurityPoliciesListCall { + c := &OrganizationSecurityPoliciesListCall{s: r.s, urlParams_: make(gensupport.URLParams)} + return c +} + +// Filter sets the optional parameter "filter": A filter expression that +// filters resources listed in the response. The expression must specify +// the field name, a comparison operator, and the value that you want to +// use for filtering. The value must be a string, a number, or a +// boolean. The comparison operator must be either =, !=, >, or <. +// +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. +// +// You can also filter nested fields. For example, you could specify +// scheduling.automaticRestart = false to include instances only if they +// are not scheduled for automatic restarts. You can use filtering on +// nested fields to filter based on resource labels. +// +// To filter on multiple expressions, provide each separate expression +// within parentheses. For example, (scheduling.automaticRestart = true) +// (cpuPlatform = "Intel Skylake"). By default, each expression is an +// AND expression. However, you can include AND and OR expressions +// explicitly. For example, (cpuPlatform = "Intel Skylake") OR +// (cpuPlatform = "Intel Broadwell") AND (scheduling.automaticRestart = +// true). +func (c *OrganizationSecurityPoliciesListCall) Filter(filter string) *OrganizationSecurityPoliciesListCall { + c.urlParams_.Set("filter", filter) + return c +} + +// MaxResults sets the optional parameter "maxResults": The maximum +// number of results per page that should be returned. If the number of +// available results is larger than maxResults, Compute Engine returns a +// nextPageToken that can be used to get the next page of results in +// subsequent list requests. Acceptable values are 0 to 500, inclusive. +// (Default: 500) +func (c *OrganizationSecurityPoliciesListCall) MaxResults(maxResults int64) *OrganizationSecurityPoliciesListCall { + c.urlParams_.Set("maxResults", fmt.Sprint(maxResults)) + return c +} + +// OrderBy sets the optional parameter "orderBy": Sorts list results by +// a certain order. By default, results are returned in alphanumerical +// order based on the resource name. +// +// You can also sort results in descending order based on the creation +// timestamp using orderBy="creationTimestamp desc". This sorts results +// based on the creationTimestamp field in reverse chronological order +// (newest result first). Use this to sort resources like operations so +// that the newest operation is returned first. +// +// Currently, only sorting by name or creationTimestamp desc is +// supported. +func (c *OrganizationSecurityPoliciesListCall) OrderBy(orderBy string) *OrganizationSecurityPoliciesListCall { + c.urlParams_.Set("orderBy", orderBy) + return c +} + +// PageToken sets the optional parameter "pageToken": Specifies a page +// token to use. Set pageToken to the nextPageToken returned by a +// previous list request to get the next page of results. +func (c *OrganizationSecurityPoliciesListCall) PageToken(pageToken string) *OrganizationSecurityPoliciesListCall { + c.urlParams_.Set("pageToken", pageToken) + return c +} + +// ParentId sets the optional parameter "parentId": Parent ID for this +// request. +func (c *OrganizationSecurityPoliciesListCall) ParentId(parentId string) *OrganizationSecurityPoliciesListCall { + c.urlParams_.Set("parentId", parentId) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *OrganizationSecurityPoliciesListCall) Fields(s ...googleapi.Field) *OrganizationSecurityPoliciesListCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// IfNoneMatch sets the optional parameter which makes the operation +// fail if the object's ETag matches the given value. This is useful for +// getting updates only after the object has changed since the last +// request. Use googleapi.IsNotModified to check whether the response +// error from Do is the result of In-None-Match. +func (c *OrganizationSecurityPoliciesListCall) IfNoneMatch(entityTag string) *OrganizationSecurityPoliciesListCall { + c.ifNoneMatch_ = entityTag + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *OrganizationSecurityPoliciesListCall) Context(ctx context.Context) *OrganizationSecurityPoliciesListCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *OrganizationSecurityPoliciesListCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *OrganizationSecurityPoliciesListCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + if c.ifNoneMatch_ != "" { + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) + } + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "locations/global/securityPolicies") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.organizationSecurityPolicies.list" call. +// Exactly one of *SecurityPolicyList or error will be non-nil. Any +// non-2xx status code is an error. Response headers are in either +// *SecurityPolicyList.ServerResponse.Header or (if a response was +// returned at all) in error.(*googleapi.Error).Header. Use +// googleapi.IsNotModified to check whether the returned error was +// because http.StatusNotModified was returned. +func (c *OrganizationSecurityPoliciesListCall) Do(opts ...googleapi.CallOption) (*SecurityPolicyList, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &SecurityPolicyList{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "List all the policies that have been configured for the specified project.", + // "httpMethod": "GET", + // "id": "compute.organizationSecurityPolicies.list", + // "parameters": { + // "filter": { + // "description": "A filter expression that filters resources listed in the response. The expression must specify the field name, a comparison operator, and the value that you want to use for filtering. The value must be a string, a number, or a boolean. The comparison operator must be either =, !=, \u003e, or \u003c.\n\nFor example, if you are filtering Compute Engine instances, you can exclude instances named example-instance by specifying name != example-instance.\n\nYou can also filter nested fields. For example, you could specify scheduling.automaticRestart = false to include instances only if they are not scheduled for automatic restarts. You can use filtering on nested fields to filter based on resource labels.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart = true) (cpuPlatform = \"Intel Skylake\"). By default, each expression is an AND expression. However, you can include AND and OR expressions explicitly. For example, (cpuPlatform = \"Intel Skylake\") OR (cpuPlatform = \"Intel Broadwell\") AND (scheduling.automaticRestart = true).", + // "location": "query", + // "type": "string" + // }, + // "maxResults": { + // "default": "500", + // "description": "The maximum number of results per page that should be returned. If the number of available results is larger than maxResults, Compute Engine returns a nextPageToken that can be used to get the next page of results in subsequent list requests. Acceptable values are 0 to 500, inclusive. (Default: 500)", + // "format": "uint32", + // "location": "query", + // "minimum": "0", + // "type": "integer" + // }, + // "orderBy": { + // "description": "Sorts list results by a certain order. By default, results are returned in alphanumerical order based on the resource name.\n\nYou can also sort results in descending order based on the creation timestamp using orderBy=\"creationTimestamp desc\". This sorts results based on the creationTimestamp field in reverse chronological order (newest result first). Use this to sort resources like operations so that the newest operation is returned first.\n\nCurrently, only sorting by name or creationTimestamp desc is supported.", + // "location": "query", + // "type": "string" + // }, + // "pageToken": { + // "description": "Specifies a page token to use. Set pageToken to the nextPageToken returned by a previous list request to get the next page of results.", + // "location": "query", + // "type": "string" + // }, + // "parentId": { + // "description": "Parent ID for this request.", + // "location": "query", + // "type": "string" + // } + // }, + // "path": "locations/global/securityPolicies", + // "response": { + // "$ref": "SecurityPolicyList" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute", + // "https://www.googleapis.com/auth/compute.readonly" + // ] + // } + +} + +// Pages invokes f for each page of results. +// A non-nil error returned from f will halt the iteration. +// The provided context supersedes any context provided to the Context method. +func (c *OrganizationSecurityPoliciesListCall) Pages(ctx context.Context, f func(*SecurityPolicyList) error) error { + c.ctx_ = ctx + defer c.PageToken(c.urlParams_.Get("pageToken")) // reset paging to original point + for { + x, err := c.Do() + if err != nil { + return err + } + if err := f(x); err != nil { + return err + } + if x.NextPageToken == "" { + return nil + } + c.PageToken(x.NextPageToken) + } +} + +// method id "compute.organizationSecurityPolicies.patchRule": + +type OrganizationSecurityPoliciesPatchRuleCall struct { + s *Service + securityPolicy string + securitypolicyrule *SecurityPolicyRule + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// PatchRule: Patches a rule at the specified priority. +func (r *OrganizationSecurityPoliciesService) PatchRule(securityPolicy string, securitypolicyrule *SecurityPolicyRule) *OrganizationSecurityPoliciesPatchRuleCall { + c := &OrganizationSecurityPoliciesPatchRuleCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.securityPolicy = securityPolicy + c.securitypolicyrule = securitypolicyrule + return c +} + +// Priority sets the optional parameter "priority": The priority of the +// rule to patch. +func (c *OrganizationSecurityPoliciesPatchRuleCall) Priority(priority int64) *OrganizationSecurityPoliciesPatchRuleCall { + c.urlParams_.Set("priority", fmt.Sprint(priority)) + return c +} + +// RequestId sets the optional parameter "requestId": An optional +// request ID to identify requests. Specify a unique request ID so that +// if you must retry your request, the server will know to ignore the +// request if it has already been completed. +// +// For example, consider a situation where you make an initial request +// and the request times out. If you make the request again with the +// same request ID, the server can check if original operation with the +// same request ID was received, and if so, will ignore the second +// request. This prevents clients from accidentally creating duplicate +// commitments. +// +// The request ID must be a valid UUID with the exception that zero UUID +// is not supported (00000000-0000-0000-0000-000000000000). +func (c *OrganizationSecurityPoliciesPatchRuleCall) RequestId(requestId string) *OrganizationSecurityPoliciesPatchRuleCall { + c.urlParams_.Set("requestId", requestId) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *OrganizationSecurityPoliciesPatchRuleCall) Fields(s ...googleapi.Field) *OrganizationSecurityPoliciesPatchRuleCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *OrganizationSecurityPoliciesPatchRuleCall) Context(ctx context.Context) *OrganizationSecurityPoliciesPatchRuleCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *OrganizationSecurityPoliciesPatchRuleCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *OrganizationSecurityPoliciesPatchRuleCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.securitypolicyrule) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "locations/global/securityPolicies/{securityPolicy}/patchRule") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "securityPolicy": c.securityPolicy, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.organizationSecurityPolicies.patchRule" call. +// Exactly one of *Operation or error will be non-nil. Any non-2xx +// status code is an error. Response headers are in either +// *Operation.ServerResponse.Header or (if a response was returned at +// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified +// to check whether the returned error was because +// http.StatusNotModified was returned. +func (c *OrganizationSecurityPoliciesPatchRuleCall) Do(opts ...googleapi.CallOption) (*Operation, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Operation{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Patches a rule at the specified priority.", + // "httpMethod": "POST", + // "id": "compute.organizationSecurityPolicies.patchRule", + // "parameterOrder": [ + // "securityPolicy" + // ], + // "parameters": { + // "priority": { + // "description": "The priority of the rule to patch.", + // "format": "int32", + // "location": "query", + // "type": "integer" + // }, + // "requestId": { + // "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", + // "location": "query", + // "type": "string" + // }, + // "securityPolicy": { + // "description": "Name of the security policy to update.", + // "location": "path", + // "pattern": "[0-9]{0,20}", + // "required": true, + // "type": "string" + // } + // }, + // "path": "locations/global/securityPolicies/{securityPolicy}/patchRule", + // "request": { + // "$ref": "SecurityPolicyRule" + // }, + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + +// method id "compute.organizationSecurityPolicies.removeAssociation": + +type OrganizationSecurityPoliciesRemoveAssociationCall struct { + s *Service + securityPolicy string + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// RemoveAssociation: Removes an association for the specified security +// policy. +func (r *OrganizationSecurityPoliciesService) RemoveAssociation(securityPolicy string) *OrganizationSecurityPoliciesRemoveAssociationCall { + c := &OrganizationSecurityPoliciesRemoveAssociationCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.securityPolicy = securityPolicy + return c +} + +// Name sets the optional parameter "name": Name for the attachment that +// will be removed. +func (c *OrganizationSecurityPoliciesRemoveAssociationCall) Name(name string) *OrganizationSecurityPoliciesRemoveAssociationCall { + c.urlParams_.Set("name", name) + return c +} + +// RequestId sets the optional parameter "requestId": An optional +// request ID to identify requests. Specify a unique request ID so that +// if you must retry your request, the server will know to ignore the +// request if it has already been completed. +// +// For example, consider a situation where you make an initial request +// and the request times out. If you make the request again with the +// same request ID, the server can check if original operation with the +// same request ID was received, and if so, will ignore the second +// request. This prevents clients from accidentally creating duplicate +// commitments. +// +// The request ID must be a valid UUID with the exception that zero UUID +// is not supported (00000000-0000-0000-0000-000000000000). +func (c *OrganizationSecurityPoliciesRemoveAssociationCall) RequestId(requestId string) *OrganizationSecurityPoliciesRemoveAssociationCall { + c.urlParams_.Set("requestId", requestId) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *OrganizationSecurityPoliciesRemoveAssociationCall) Fields(s ...googleapi.Field) *OrganizationSecurityPoliciesRemoveAssociationCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *OrganizationSecurityPoliciesRemoveAssociationCall) Context(ctx context.Context) *OrganizationSecurityPoliciesRemoveAssociationCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *OrganizationSecurityPoliciesRemoveAssociationCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *OrganizationSecurityPoliciesRemoveAssociationCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "locations/global/securityPolicies/{securityPolicy}/removeAssociation") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "securityPolicy": c.securityPolicy, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.organizationSecurityPolicies.removeAssociation" call. +// Exactly one of *Operation or error will be non-nil. Any non-2xx +// status code is an error. Response headers are in either +// *Operation.ServerResponse.Header or (if a response was returned at +// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified +// to check whether the returned error was because +// http.StatusNotModified was returned. +func (c *OrganizationSecurityPoliciesRemoveAssociationCall) Do(opts ...googleapi.CallOption) (*Operation, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Operation{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Removes an association for the specified security policy.", + // "httpMethod": "POST", + // "id": "compute.organizationSecurityPolicies.removeAssociation", + // "parameterOrder": [ + // "securityPolicy" + // ], + // "parameters": { + // "name": { + // "description": "Name for the attachment that will be removed.", + // "location": "query", + // "type": "string" + // }, + // "requestId": { + // "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", + // "location": "query", + // "type": "string" + // }, + // "securityPolicy": { + // "description": "Name of the security policy to update.", + // "location": "path", + // "pattern": "[0-9]{0,20}", + // "required": true, + // "type": "string" + // } + // }, + // "path": "locations/global/securityPolicies/{securityPolicy}/removeAssociation", + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + +// method id "compute.organizationSecurityPolicies.removeRule": + +type OrganizationSecurityPoliciesRemoveRuleCall struct { + s *Service + securityPolicy string + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// RemoveRule: Deletes a rule at the specified priority. +func (r *OrganizationSecurityPoliciesService) RemoveRule(securityPolicy string) *OrganizationSecurityPoliciesRemoveRuleCall { + c := &OrganizationSecurityPoliciesRemoveRuleCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.securityPolicy = securityPolicy + return c +} + +// Priority sets the optional parameter "priority": The priority of the +// rule to remove from the security policy. +func (c *OrganizationSecurityPoliciesRemoveRuleCall) Priority(priority int64) *OrganizationSecurityPoliciesRemoveRuleCall { + c.urlParams_.Set("priority", fmt.Sprint(priority)) + return c +} + +// RequestId sets the optional parameter "requestId": An optional +// request ID to identify requests. Specify a unique request ID so that +// if you must retry your request, the server will know to ignore the +// request if it has already been completed. +// +// For example, consider a situation where you make an initial request +// and the request times out. If you make the request again with the +// same request ID, the server can check if original operation with the +// same request ID was received, and if so, will ignore the second +// request. This prevents clients from accidentally creating duplicate +// commitments. +// +// The request ID must be a valid UUID with the exception that zero UUID +// is not supported (00000000-0000-0000-0000-000000000000). +func (c *OrganizationSecurityPoliciesRemoveRuleCall) RequestId(requestId string) *OrganizationSecurityPoliciesRemoveRuleCall { + c.urlParams_.Set("requestId", requestId) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *OrganizationSecurityPoliciesRemoveRuleCall) Fields(s ...googleapi.Field) *OrganizationSecurityPoliciesRemoveRuleCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *OrganizationSecurityPoliciesRemoveRuleCall) Context(ctx context.Context) *OrganizationSecurityPoliciesRemoveRuleCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *OrganizationSecurityPoliciesRemoveRuleCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *OrganizationSecurityPoliciesRemoveRuleCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "locations/global/securityPolicies/{securityPolicy}/removeRule") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "securityPolicy": c.securityPolicy, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.organizationSecurityPolicies.removeRule" call. +// Exactly one of *Operation or error will be non-nil. Any non-2xx +// status code is an error. Response headers are in either +// *Operation.ServerResponse.Header or (if a response was returned at +// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified +// to check whether the returned error was because +// http.StatusNotModified was returned. +func (c *OrganizationSecurityPoliciesRemoveRuleCall) Do(opts ...googleapi.CallOption) (*Operation, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Operation{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Deletes a rule at the specified priority.", + // "httpMethod": "POST", + // "id": "compute.organizationSecurityPolicies.removeRule", + // "parameterOrder": [ + // "securityPolicy" + // ], + // "parameters": { + // "priority": { + // "description": "The priority of the rule to remove from the security policy.", + // "format": "int32", + // "location": "query", + // "type": "integer" + // }, + // "requestId": { + // "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", + // "location": "query", + // "type": "string" + // }, + // "securityPolicy": { + // "description": "Name of the security policy to update.", + // "location": "path", + // "pattern": "[0-9]{0,20}", + // "required": true, + // "type": "string" + // } + // }, + // "path": "locations/global/securityPolicies/{securityPolicy}/removeRule", + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + // method id "compute.projects.disableXpnHost": type ProjectsDisableXpnHostCall struct { @@ -89138,9 +98711,13 @@ func (c *ProjectsDisableXpnHostCall) doRequest(alt string) (*http.Response, erro reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/disableXpnHost") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -89295,9 +98872,13 @@ func (c *ProjectsDisableXpnResourceCall) doRequest(alt string) (*http.Response, } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/disableXpnResource") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -89447,9 +99028,13 @@ func (c *ProjectsEnableXpnHostCall) doRequest(alt string) (*http.Response, error reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/enableXpnHost") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -89605,9 +99190,13 @@ func (c *ProjectsEnableXpnResourceCall) doRequest(alt string) (*http.Response, e } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/enableXpnResource") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -89753,9 +99342,13 @@ func (c *ProjectsGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -89894,9 +99487,13 @@ func (c *ProjectsGetXpnHostCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/getXpnHost") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -89988,25 +99585,64 @@ func (r *ProjectsService) GetXpnResources(project string) *ProjectsGetXpnResourc return c } -// Filter sets the optional parameter "filter": +// Filter sets the optional parameter "filter": A filter expression that +// filters resources listed in the response. The expression must specify +// the field name, a comparison operator, and the value that you want to +// use for filtering. The value must be a string, a number, or a +// boolean. The comparison operator must be either =, !=, >, or <. +// +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. +// +// You can also filter nested fields. For example, you could specify +// scheduling.automaticRestart = false to include instances only if they +// are not scheduled for automatic restarts. You can use filtering on +// nested fields to filter based on resource labels. +// +// To filter on multiple expressions, provide each separate expression +// within parentheses. For example, (scheduling.automaticRestart = true) +// (cpuPlatform = "Intel Skylake"). By default, each expression is an +// AND expression. However, you can include AND and OR expressions +// explicitly. For example, (cpuPlatform = "Intel Skylake") OR +// (cpuPlatform = "Intel Broadwell") AND (scheduling.automaticRestart = +// true). func (c *ProjectsGetXpnResourcesCall) Filter(filter string) *ProjectsGetXpnResourcesCall { c.urlParams_.Set("filter", filter) return c } -// MaxResults sets the optional parameter "maxResults": +// MaxResults sets the optional parameter "maxResults": The maximum +// number of results per page that should be returned. If the number of +// available results is larger than maxResults, Compute Engine returns a +// nextPageToken that can be used to get the next page of results in +// subsequent list requests. Acceptable values are 0 to 500, inclusive. +// (Default: 500) func (c *ProjectsGetXpnResourcesCall) MaxResults(maxResults int64) *ProjectsGetXpnResourcesCall { c.urlParams_.Set("maxResults", fmt.Sprint(maxResults)) return c } -// OrderBy sets the optional parameter "order_by": +// OrderBy sets the optional parameter "order_by": Sorts list results by +// a certain order. By default, results are returned in alphanumerical +// order based on the resource name. +// +// You can also sort results in descending order based on the creation +// timestamp using orderBy="creationTimestamp desc". This sorts results +// based on the creationTimestamp field in reverse chronological order +// (newest result first). Use this to sort resources like operations so +// that the newest operation is returned first. +// +// Currently, only sorting by name or creationTimestamp desc is +// supported. func (c *ProjectsGetXpnResourcesCall) OrderBy(orderBy string) *ProjectsGetXpnResourcesCall { c.urlParams_.Set("order_by", orderBy) return c } -// PageToken sets the optional parameter "pageToken": +// PageToken sets the optional parameter "pageToken": Specifies a page +// token to use. Set pageToken to the nextPageToken returned by a +// previous list request to get the next page of results. func (c *ProjectsGetXpnResourcesCall) PageToken(pageToken string) *ProjectsGetXpnResourcesCall { c.urlParams_.Set("pageToken", pageToken) return c @@ -90058,9 +99694,13 @@ func (c *ProjectsGetXpnResourcesCall) doRequest(alt string) (*http.Response, err } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/getXpnResources") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -90114,21 +99754,25 @@ func (c *ProjectsGetXpnResourcesCall) Do(opts ...googleapi.CallOption) (*Project // ], // "parameters": { // "filter": { + // "description": "A filter expression that filters resources listed in the response. The expression must specify the field name, a comparison operator, and the value that you want to use for filtering. The value must be a string, a number, or a boolean. The comparison operator must be either =, !=, \u003e, or \u003c.\n\nFor example, if you are filtering Compute Engine instances, you can exclude instances named example-instance by specifying name != example-instance.\n\nYou can also filter nested fields. For example, you could specify scheduling.automaticRestart = false to include instances only if they are not scheduled for automatic restarts. You can use filtering on nested fields to filter based on resource labels.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart = true) (cpuPlatform = \"Intel Skylake\"). By default, each expression is an AND expression. However, you can include AND and OR expressions explicitly. For example, (cpuPlatform = \"Intel Skylake\") OR (cpuPlatform = \"Intel Broadwell\") AND (scheduling.automaticRestart = true).", // "location": "query", // "type": "string" // }, // "maxResults": { // "default": "500", + // "description": "The maximum number of results per page that should be returned. If the number of available results is larger than maxResults, Compute Engine returns a nextPageToken that can be used to get the next page of results in subsequent list requests. Acceptable values are 0 to 500, inclusive. (Default: 500)", // "format": "uint32", // "location": "query", // "minimum": "0", // "type": "integer" // }, // "order_by": { + // "description": "Sorts list results by a certain order. By default, results are returned in alphanumerical order based on the resource name.\n\nYou can also sort results in descending order based on the creation timestamp using orderBy=\"creationTimestamp desc\". This sorts results based on the creationTimestamp field in reverse chronological order (newest result first). Use this to sort resources like operations so that the newest operation is returned first.\n\nCurrently, only sorting by name or creationTimestamp desc is supported.", // "location": "query", // "type": "string" // }, // "pageToken": { + // "description": "Specifies a page token to use. Set pageToken to the nextPageToken returned by a previous list request to get the next page of results.", // "location": "query", // "type": "string" // }, @@ -90193,25 +99837,64 @@ func (r *ProjectsService) ListXpnHosts(project string, projectslistxpnhostsreque return c } -// Filter sets the optional parameter "filter": +// Filter sets the optional parameter "filter": A filter expression that +// filters resources listed in the response. The expression must specify +// the field name, a comparison operator, and the value that you want to +// use for filtering. The value must be a string, a number, or a +// boolean. The comparison operator must be either =, !=, >, or <. +// +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. +// +// You can also filter nested fields. For example, you could specify +// scheduling.automaticRestart = false to include instances only if they +// are not scheduled for automatic restarts. You can use filtering on +// nested fields to filter based on resource labels. +// +// To filter on multiple expressions, provide each separate expression +// within parentheses. For example, (scheduling.automaticRestart = true) +// (cpuPlatform = "Intel Skylake"). By default, each expression is an +// AND expression. However, you can include AND and OR expressions +// explicitly. For example, (cpuPlatform = "Intel Skylake") OR +// (cpuPlatform = "Intel Broadwell") AND (scheduling.automaticRestart = +// true). func (c *ProjectsListXpnHostsCall) Filter(filter string) *ProjectsListXpnHostsCall { c.urlParams_.Set("filter", filter) return c } -// MaxResults sets the optional parameter "maxResults": +// MaxResults sets the optional parameter "maxResults": The maximum +// number of results per page that should be returned. If the number of +// available results is larger than maxResults, Compute Engine returns a +// nextPageToken that can be used to get the next page of results in +// subsequent list requests. Acceptable values are 0 to 500, inclusive. +// (Default: 500) func (c *ProjectsListXpnHostsCall) MaxResults(maxResults int64) *ProjectsListXpnHostsCall { c.urlParams_.Set("maxResults", fmt.Sprint(maxResults)) return c } -// OrderBy sets the optional parameter "order_by": +// OrderBy sets the optional parameter "order_by": Sorts list results by +// a certain order. By default, results are returned in alphanumerical +// order based on the resource name. +// +// You can also sort results in descending order based on the creation +// timestamp using orderBy="creationTimestamp desc". This sorts results +// based on the creationTimestamp field in reverse chronological order +// (newest result first). Use this to sort resources like operations so +// that the newest operation is returned first. +// +// Currently, only sorting by name or creationTimestamp desc is +// supported. func (c *ProjectsListXpnHostsCall) OrderBy(orderBy string) *ProjectsListXpnHostsCall { c.urlParams_.Set("order_by", orderBy) return c } -// PageToken sets the optional parameter "pageToken": +// PageToken sets the optional parameter "pageToken": Specifies a page +// token to use. Set pageToken to the nextPageToken returned by a +// previous list request to get the next page of results. func (c *ProjectsListXpnHostsCall) PageToken(pageToken string) *ProjectsListXpnHostsCall { c.urlParams_.Set("pageToken", pageToken) return c @@ -90255,9 +99938,13 @@ func (c *ProjectsListXpnHostsCall) doRequest(alt string) (*http.Response, error) } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/listXpnHosts") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -90311,21 +99998,25 @@ func (c *ProjectsListXpnHostsCall) Do(opts ...googleapi.CallOption) (*XpnHostLis // ], // "parameters": { // "filter": { + // "description": "A filter expression that filters resources listed in the response. The expression must specify the field name, a comparison operator, and the value that you want to use for filtering. The value must be a string, a number, or a boolean. The comparison operator must be either =, !=, \u003e, or \u003c.\n\nFor example, if you are filtering Compute Engine instances, you can exclude instances named example-instance by specifying name != example-instance.\n\nYou can also filter nested fields. For example, you could specify scheduling.automaticRestart = false to include instances only if they are not scheduled for automatic restarts. You can use filtering on nested fields to filter based on resource labels.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart = true) (cpuPlatform = \"Intel Skylake\"). By default, each expression is an AND expression. However, you can include AND and OR expressions explicitly. For example, (cpuPlatform = \"Intel Skylake\") OR (cpuPlatform = \"Intel Broadwell\") AND (scheduling.automaticRestart = true).", // "location": "query", // "type": "string" // }, // "maxResults": { // "default": "500", + // "description": "The maximum number of results per page that should be returned. If the number of available results is larger than maxResults, Compute Engine returns a nextPageToken that can be used to get the next page of results in subsequent list requests. Acceptable values are 0 to 500, inclusive. (Default: 500)", // "format": "uint32", // "location": "query", // "minimum": "0", // "type": "integer" // }, // "order_by": { + // "description": "Sorts list results by a certain order. By default, results are returned in alphanumerical order based on the resource name.\n\nYou can also sort results in descending order based on the creation timestamp using orderBy=\"creationTimestamp desc\". This sorts results based on the creationTimestamp field in reverse chronological order (newest result first). Use this to sort resources like operations so that the newest operation is returned first.\n\nCurrently, only sorting by name or creationTimestamp desc is supported.", // "location": "query", // "type": "string" // }, // "pageToken": { + // "description": "Specifies a page token to use. Set pageToken to the nextPageToken returned by a previous list request to get the next page of results.", // "location": "query", // "type": "string" // }, @@ -90449,9 +100140,13 @@ func (c *ProjectsMoveDiskCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/moveDisk") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -90609,9 +100304,13 @@ func (c *ProjectsMoveInstanceCall) doRequest(alt string) (*http.Response, error) } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/moveInstance") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -90770,9 +100469,13 @@ func (c *ProjectsSetCommonInstanceMetadataCall) doRequest(alt string) (*http.Res } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/setCommonInstanceMetadata") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -90932,9 +100635,13 @@ func (c *ProjectsSetDefaultNetworkTierCall) doRequest(alt string) (*http.Respons } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/setDefaultNetworkTier") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -91093,9 +100800,13 @@ func (c *ProjectsSetDefaultServiceAccountCall) doRequest(alt string) (*http.Resp } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/setDefaultServiceAccount") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -91256,9 +100967,13 @@ func (c *ProjectsSetUsageExportBucketCall) doRequest(alt string) (*http.Response } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/setUsageExportBucket") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -91415,9 +101130,13 @@ func (c *RegionAutoscalersDeleteCall) doRequest(alt string) (*http.Response, err reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/autoscalers/{autoscaler}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -91581,9 +101300,13 @@ func (c *RegionAutoscalersGetCall) doRequest(alt string) (*http.Response, error) } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/autoscalers/{autoscaler}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -91754,9 +101477,13 @@ func (c *RegionAutoscalersInsertCall) doRequest(alt string) (*http.Response, err } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/autoscalers") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -91976,9 +101703,13 @@ func (c *RegionAutoscalersListCall) doRequest(alt string) (*http.Response, error } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/autoscalers") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -92192,9 +101923,13 @@ func (c *RegionAutoscalersPatchCall) doRequest(alt string) (*http.Response, erro } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/autoscalers") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PATCH", urls, body) + req, err := http.NewRequest("PATCH", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -92352,9 +102087,13 @@ func (c *RegionAutoscalersTestIamPermissionsCall) doRequest(alt string) (*http.R } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/autoscalers/{resource}/testIamPermissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -92426,9 +102165,9 @@ func (c *RegionAutoscalersTestIamPermissionsCall) Do(opts ...googleapi.CallOptio // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -92535,9 +102274,13 @@ func (c *RegionAutoscalersUpdateCall) doRequest(alt string) (*http.Response, err } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/autoscalers") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PUT", urls, body) + req, err := http.NewRequest("PUT", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -92706,9 +102449,13 @@ func (c *RegionBackendServicesDeleteCall) doRequest(alt string) (*http.Response, reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/backendServices/{backendService}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -92872,9 +102619,13 @@ func (c *RegionBackendServicesGetCall) doRequest(alt string) (*http.Response, er } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/backendServices/{backendService}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -93028,9 +102779,13 @@ func (c *RegionBackendServicesGetHealthCall) doRequest(alt string) (*http.Respon } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/backendServices/{backendService}/getHealth") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -93206,9 +102961,13 @@ func (c *RegionBackendServicesInsertCall) doRequest(alt string) (*http.Response, } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/backendServices") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -93428,9 +103187,13 @@ func (c *RegionBackendServicesListCall) doRequest(alt string) (*http.Response, e } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/backendServices") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -93642,9 +103405,13 @@ func (c *RegionBackendServicesPatchCall) doRequest(alt string) (*http.Response, } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/backendServices/{backendService}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PATCH", urls, body) + req, err := http.NewRequest("PATCH", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -93704,7 +103471,7 @@ func (c *RegionBackendServicesPatchCall) Do(opts ...googleapi.CallOption) (*Oper // "backendService": { // "description": "Name of the BackendService resource to patch.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -93805,9 +103572,13 @@ func (c *RegionBackendServicesTestIamPermissionsCall) doRequest(alt string) (*ht } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/backendServices/{resource}/testIamPermissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -93879,9 +103650,9 @@ func (c *RegionBackendServicesTestIamPermissionsCall) Do(opts ...googleapi.CallO // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -93985,9 +103756,13 @@ func (c *RegionBackendServicesUpdateCall) doRequest(alt string) (*http.Response, } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/backendServices/{backendService}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PUT", urls, body) + req, err := http.NewRequest("PUT", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -94213,9 +103988,13 @@ func (c *RegionCommitmentsAggregatedListCall) doRequest(alt string) (*http.Respo } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/aggregated/commitments") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -94402,9 +104181,13 @@ func (c *RegionCommitmentsGetCall) doRequest(alt string) (*http.Response, error) } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/commitments/{commitment}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -94575,9 +104358,13 @@ func (c *RegionCommitmentsInsertCall) doRequest(alt string) (*http.Response, err } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/commitments") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -94797,9 +104584,13 @@ func (c *RegionCommitmentsListCall) doRequest(alt string) (*http.Response, error } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/commitments") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -94988,9 +104779,13 @@ func (c *RegionCommitmentsTestIamPermissionsCall) doRequest(alt string) (*http.R } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/commitments/{resource}/testIamPermissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -95062,9 +104857,9 @@ func (c *RegionCommitmentsTestIamPermissionsCall) Do(opts ...googleapi.CallOptio // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -95154,9 +104949,13 @@ func (c *RegionDiskTypesGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/diskTypes/{diskType}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -95378,9 +105177,13 @@ func (c *RegionDiskTypesListCall) doRequest(alt string) (*http.Response, error) } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/diskTypes") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -95507,6 +105310,193 @@ func (c *RegionDiskTypesListCall) Pages(ctx context.Context, f func(*RegionDiskT } } +// method id "compute.regionDisks.addResourcePolicies": + +type RegionDisksAddResourcePoliciesCall struct { + s *Service + project string + region string + disk string + regiondisksaddresourcepoliciesrequest *RegionDisksAddResourcePoliciesRequest + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// AddResourcePolicies: Adds existing resource policies to a regional +// disk. You can only add one policy which will be applied to this disk +// for scheduling snapshot creation. +func (r *RegionDisksService) AddResourcePolicies(project string, region string, disk string, regiondisksaddresourcepoliciesrequest *RegionDisksAddResourcePoliciesRequest) *RegionDisksAddResourcePoliciesCall { + c := &RegionDisksAddResourcePoliciesCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.region = region + c.disk = disk + c.regiondisksaddresourcepoliciesrequest = regiondisksaddresourcepoliciesrequest + return c +} + +// RequestId sets the optional parameter "requestId": An optional +// request ID to identify requests. Specify a unique request ID so that +// if you must retry your request, the server will know to ignore the +// request if it has already been completed. +// +// For example, consider a situation where you make an initial request +// and the request times out. If you make the request again with the +// same request ID, the server can check if original operation with the +// same request ID was received, and if so, will ignore the second +// request. This prevents clients from accidentally creating duplicate +// commitments. +// +// The request ID must be a valid UUID with the exception that zero UUID +// is not supported (00000000-0000-0000-0000-000000000000). +func (c *RegionDisksAddResourcePoliciesCall) RequestId(requestId string) *RegionDisksAddResourcePoliciesCall { + c.urlParams_.Set("requestId", requestId) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *RegionDisksAddResourcePoliciesCall) Fields(s ...googleapi.Field) *RegionDisksAddResourcePoliciesCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *RegionDisksAddResourcePoliciesCall) Context(ctx context.Context) *RegionDisksAddResourcePoliciesCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *RegionDisksAddResourcePoliciesCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *RegionDisksAddResourcePoliciesCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.regiondisksaddresourcepoliciesrequest) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/disks/{disk}/addResourcePolicies") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "region": c.region, + "disk": c.disk, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.regionDisks.addResourcePolicies" call. +// Exactly one of *Operation or error will be non-nil. Any non-2xx +// status code is an error. Response headers are in either +// *Operation.ServerResponse.Header or (if a response was returned at +// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified +// to check whether the returned error was because +// http.StatusNotModified was returned. +func (c *RegionDisksAddResourcePoliciesCall) Do(opts ...googleapi.CallOption) (*Operation, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Operation{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Adds existing resource policies to a regional disk. You can only add one policy which will be applied to this disk for scheduling snapshot creation.", + // "httpMethod": "POST", + // "id": "compute.regionDisks.addResourcePolicies", + // "parameterOrder": [ + // "project", + // "region", + // "disk" + // ], + // "parameters": { + // "disk": { + // "description": "The disk name for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + // "required": true, + // "type": "string" + // }, + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "region": { + // "description": "The name of the region for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // }, + // "requestId": { + // "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", + // "location": "query", + // "type": "string" + // } + // }, + // "path": "{project}/regions/{region}/disks/{disk}/addResourcePolicies", + // "request": { + // "$ref": "RegionDisksAddResourcePoliciesRequest" + // }, + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + // method id "compute.regionDisks.createSnapshot": type RegionDisksCreateSnapshotCall struct { @@ -95593,9 +105583,13 @@ func (c *RegionDisksCreateSnapshotCall) doRequest(alt string) (*http.Response, e } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/disks/{disk}/createSnapshot") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -95655,7 +105649,7 @@ func (c *RegionDisksCreateSnapshotCall) Do(opts ...googleapi.CallOption) (*Opera // "disk": { // "description": "Name of the regional persistent disk to snapshot.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -95774,9 +105768,13 @@ func (c *RegionDisksDeleteCall) doRequest(alt string) (*http.Response, error) { reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/disks/{disk}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -95939,9 +105937,13 @@ func (c *RegionDisksGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/disks/{disk}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -96001,7 +106003,7 @@ func (c *RegionDisksGetCall) Do(opts ...googleapi.CallOption) (*Disk, error) { // "disk": { // "description": "Name of the regional persistent disk to return.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -96119,9 +106121,13 @@ func (c *RegionDisksInsertCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/disks") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -96346,9 +106352,13 @@ func (c *RegionDisksListCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/disks") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -96475,6 +106485,192 @@ func (c *RegionDisksListCall) Pages(ctx context.Context, f func(*DiskList) error } } +// method id "compute.regionDisks.removeResourcePolicies": + +type RegionDisksRemoveResourcePoliciesCall struct { + s *Service + project string + region string + disk string + regiondisksremoveresourcepoliciesrequest *RegionDisksRemoveResourcePoliciesRequest + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// RemoveResourcePolicies: Removes resource policies from a regional +// disk. +func (r *RegionDisksService) RemoveResourcePolicies(project string, region string, disk string, regiondisksremoveresourcepoliciesrequest *RegionDisksRemoveResourcePoliciesRequest) *RegionDisksRemoveResourcePoliciesCall { + c := &RegionDisksRemoveResourcePoliciesCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.region = region + c.disk = disk + c.regiondisksremoveresourcepoliciesrequest = regiondisksremoveresourcepoliciesrequest + return c +} + +// RequestId sets the optional parameter "requestId": An optional +// request ID to identify requests. Specify a unique request ID so that +// if you must retry your request, the server will know to ignore the +// request if it has already been completed. +// +// For example, consider a situation where you make an initial request +// and the request times out. If you make the request again with the +// same request ID, the server can check if original operation with the +// same request ID was received, and if so, will ignore the second +// request. This prevents clients from accidentally creating duplicate +// commitments. +// +// The request ID must be a valid UUID with the exception that zero UUID +// is not supported (00000000-0000-0000-0000-000000000000). +func (c *RegionDisksRemoveResourcePoliciesCall) RequestId(requestId string) *RegionDisksRemoveResourcePoliciesCall { + c.urlParams_.Set("requestId", requestId) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *RegionDisksRemoveResourcePoliciesCall) Fields(s ...googleapi.Field) *RegionDisksRemoveResourcePoliciesCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *RegionDisksRemoveResourcePoliciesCall) Context(ctx context.Context) *RegionDisksRemoveResourcePoliciesCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *RegionDisksRemoveResourcePoliciesCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *RegionDisksRemoveResourcePoliciesCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.regiondisksremoveresourcepoliciesrequest) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/disks/{disk}/removeResourcePolicies") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "region": c.region, + "disk": c.disk, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.regionDisks.removeResourcePolicies" call. +// Exactly one of *Operation or error will be non-nil. Any non-2xx +// status code is an error. Response headers are in either +// *Operation.ServerResponse.Header or (if a response was returned at +// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified +// to check whether the returned error was because +// http.StatusNotModified was returned. +func (c *RegionDisksRemoveResourcePoliciesCall) Do(opts ...googleapi.CallOption) (*Operation, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Operation{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Removes resource policies from a regional disk.", + // "httpMethod": "POST", + // "id": "compute.regionDisks.removeResourcePolicies", + // "parameterOrder": [ + // "project", + // "region", + // "disk" + // ], + // "parameters": { + // "disk": { + // "description": "The disk name for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + // "required": true, + // "type": "string" + // }, + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "region": { + // "description": "The name of the region for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // }, + // "requestId": { + // "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", + // "location": "query", + // "type": "string" + // } + // }, + // "path": "{project}/regions/{region}/disks/{disk}/removeResourcePolicies", + // "request": { + // "$ref": "RegionDisksRemoveResourcePoliciesRequest" + // }, + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + // method id "compute.regionDisks.resize": type RegionDisksResizeCall struct { @@ -96555,9 +106751,13 @@ func (c *RegionDisksResizeCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/disks/{disk}/resize") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -96617,7 +106817,7 @@ func (c *RegionDisksResizeCall) Do(opts ...googleapi.CallOption) (*Operation, er // "disk": { // "description": "Name of the regional persistent disk.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -96736,9 +106936,13 @@ func (c *RegionDisksSetLabelsCall) doRequest(alt string) (*http.Response, error) } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/disks/{resource}/setLabels") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -96815,9 +107019,9 @@ func (c *RegionDisksSetLabelsCall) Do(opts ...googleapi.CallOption) (*Operation, // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -96899,9 +107103,13 @@ func (c *RegionDisksTestIamPermissionsCall) doRequest(alt string) (*http.Respons } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/disks/{resource}/testIamPermissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -96973,9 +107181,9 @@ func (c *RegionDisksTestIamPermissionsCall) Do(opts ...googleapi.CallOption) (*T // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -97069,9 +107277,13 @@ func (c *RegionHealthChecksDeleteCall) doRequest(alt string) (*http.Response, er reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/healthChecks/{healthCheck}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -97236,9 +107448,13 @@ func (c *RegionHealthChecksGetCall) doRequest(alt string) (*http.Response, error } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/healthChecks/{healthCheck}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -97409,9 +107625,13 @@ func (c *RegionHealthChecksInsertCall) doRequest(alt string) (*http.Response, er } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/healthChecks") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -97631,9 +107851,13 @@ func (c *RegionHealthChecksListCall) doRequest(alt string) (*http.Response, erro } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/healthChecks") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -97842,9 +108066,13 @@ func (c *RegionHealthChecksPatchCall) doRequest(alt string) (*http.Response, err } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/healthChecks/{healthCheck}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PATCH", urls, body) + req, err := http.NewRequest("PATCH", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -98005,9 +108233,13 @@ func (c *RegionHealthChecksTestIamPermissionsCall) doRequest(alt string) (*http. } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/healthChecks/{resource}/testIamPermissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -98079,9 +108311,9 @@ func (c *RegionHealthChecksTestIamPermissionsCall) Do(opts ...googleapi.CallOpti // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -98183,9 +108415,13 @@ func (c *RegionHealthChecksUpdateCall) doRequest(alt string) (*http.Response, er } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/healthChecks/{healthCheck}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PUT", urls, body) + req, err := http.NewRequest("PUT", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -98297,10 +108533,10 @@ type RegionInstanceGroupManagersAbandonInstancesCall struct { header_ http.Header } -// AbandonInstances: Schedules a group action to remove the specified -// instances from the managed instance group. Abandoning an instance -// does not delete the instance, but it does remove the instance from -// any target pools that are applied by the managed instance group. This +// AbandonInstances: Flags the specified instances to be immediately +// removed from the managed instance group. Abandoning an instance does +// not delete the instance, but it does remove the instance from any +// target pools that are applied by the managed instance group. This // method reduces the targetSize of the managed instance group by the // number of instances that you abandon. This operation is marked as // DONE when the action is scheduled even if the instances have not yet @@ -98380,9 +108616,13 @@ func (c *RegionInstanceGroupManagersAbandonInstancesCall) doRequest(alt string) } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/instanceGroupManagers/{instanceGroupManager}/abandonInstances") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -98430,7 +108670,7 @@ func (c *RegionInstanceGroupManagersAbandonInstancesCall) Do(opts ...googleapi.C } return ret, nil // { - // "description": "Schedules a group action to remove the specified instances from the managed instance group. Abandoning an instance does not delete the instance, but it does remove the instance from any target pools that are applied by the managed instance group. This method reduces the targetSize of the managed instance group by the number of instances that you abandon. This operation is marked as DONE when the action is scheduled even if the instances have not yet been removed from the group. You must separately verify the status of the abandoning action with the listmanagedinstances method.\n\nIf the group is part of a backend service that has enabled connection draining, it can take up to 60 seconds after the connection draining duration has elapsed before the VM instance is removed or deleted.\n\nYou can specify a maximum of 1000 instances with this method per request.", + // "description": "Flags the specified instances to be immediately removed from the managed instance group. Abandoning an instance does not delete the instance, but it does remove the instance from any target pools that are applied by the managed instance group. This method reduces the targetSize of the managed instance group by the number of instances that you abandon. This operation is marked as DONE when the action is scheduled even if the instances have not yet been removed from the group. You must separately verify the status of the abandoning action with the listmanagedinstances method.\n\nIf the group is part of a backend service that has enabled connection draining, it can take up to 60 seconds after the connection draining duration has elapsed before the VM instance is removed or deleted.\n\nYou can specify a maximum of 1000 instances with this method per request.", // "httpMethod": "POST", // "id": "compute.regionInstanceGroupManagers.abandonInstances", // "parameterOrder": [ @@ -98541,9 +108781,13 @@ func (c *RegionInstanceGroupManagersApplyUpdatesToInstancesCall) doRequest(alt s } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/instanceGroupManagers/{instanceGroupManager}/applyUpdatesToInstances") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -98709,9 +108953,13 @@ func (c *RegionInstanceGroupManagersDeleteCall) doRequest(alt string) (*http.Res reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/instanceGroupManagers/{instanceGroupManager}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -98818,14 +109066,15 @@ type RegionInstanceGroupManagersDeleteInstancesCall struct { header_ http.Header } -// DeleteInstances: Schedules a group action to delete the specified -// instances in the managed instance group. The instances are also +// DeleteInstances: Flags the specified instances in the managed +// instance group to be immediately deleted. The instances are also // removed from any target pools of which they were a member. This // method reduces the targetSize of the managed instance group by the -// number of instances that you delete. This operation is marked as DONE -// when the action is scheduled even if the instances are still being -// deleted. You must separately verify the status of the deleting action -// with the listmanagedinstances method. +// number of instances that you delete. The deleteInstances operation is +// marked DONE if the deleteInstances request is successful. The +// underlying actions take additional time. You must separately verify +// the status of the deleting action with the listmanagedinstances +// method. // // If the group is part of a backend service that has enabled connection // draining, it can take up to 60 seconds after the connection draining @@ -98900,9 +109149,13 @@ func (c *RegionInstanceGroupManagersDeleteInstancesCall) doRequest(alt string) ( } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/instanceGroupManagers/{instanceGroupManager}/deleteInstances") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -98950,7 +109203,7 @@ func (c *RegionInstanceGroupManagersDeleteInstancesCall) Do(opts ...googleapi.Ca } return ret, nil // { - // "description": "Schedules a group action to delete the specified instances in the managed instance group. The instances are also removed from any target pools of which they were a member. This method reduces the targetSize of the managed instance group by the number of instances that you delete. This operation is marked as DONE when the action is scheduled even if the instances are still being deleted. You must separately verify the status of the deleting action with the listmanagedinstances method.\n\nIf the group is part of a backend service that has enabled connection draining, it can take up to 60 seconds after the connection draining duration has elapsed before the VM instance is removed or deleted.\n\nYou can specify a maximum of 1000 instances with this method per request.", + // "description": "Flags the specified instances in the managed instance group to be immediately deleted. The instances are also removed from any target pools of which they were a member. This method reduces the targetSize of the managed instance group by the number of instances that you delete. The deleteInstances operation is marked DONE if the deleteInstances request is successful. The underlying actions take additional time. You must separately verify the status of the deleting action with the listmanagedinstances method.\n\nIf the group is part of a backend service that has enabled connection draining, it can take up to 60 seconds after the connection draining duration has elapsed before the VM instance is removed or deleted.\n\nYou can specify a maximum of 1000 instances with this method per request.", // "httpMethod": "POST", // "id": "compute.regionInstanceGroupManagers.deleteInstances", // "parameterOrder": [ @@ -99061,9 +109314,13 @@ func (c *RegionInstanceGroupManagersDeletePerInstanceConfigsCall) doRequest(alt } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/instanceGroupManagers/{instanceGroupManager}/deletePerInstanceConfigs") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -99224,9 +109481,13 @@ func (c *RegionInstanceGroupManagersGetCall) doRequest(alt string) (*http.Respon } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/instanceGroupManagers/{instanceGroupManager}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -99329,12 +109590,12 @@ type RegionInstanceGroupManagersInsertCall struct { } // Insert: Creates a managed instance group using the information that -// you specify in the request. After the group is created, it schedules -// an action to create instances in the group using the specified -// instance template. This operation is marked as DONE when the group is -// created even if the instances in the group have not yet been created. -// You must separately verify the status of the individual instances -// with the listmanagedinstances method. +// you specify in the request. After the group is created, instances in +// the group are created using the specified instance template. This +// operation is marked as DONE when the group is created even if the +// instances in the group have not yet been created. You must separately +// verify the status of the individual instances with the +// listmanagedinstances method. // // A regional managed instance group can contain up to 2000 instances. func (r *RegionInstanceGroupManagersService) Insert(project string, region string, instancegroupmanager *InstanceGroupManager) *RegionInstanceGroupManagersInsertCall { @@ -99402,9 +109663,13 @@ func (c *RegionInstanceGroupManagersInsertCall) doRequest(alt string) (*http.Res } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/instanceGroupManagers") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -99451,7 +109716,7 @@ func (c *RegionInstanceGroupManagersInsertCall) Do(opts ...googleapi.CallOption) } return ret, nil // { - // "description": "Creates a managed instance group using the information that you specify in the request. After the group is created, it schedules an action to create instances in the group using the specified instance template. This operation is marked as DONE when the group is created even if the instances in the group have not yet been created. You must separately verify the status of the individual instances with the listmanagedinstances method.\n\nA regional managed instance group can contain up to 2000 instances.", + // "description": "Creates a managed instance group using the information that you specify in the request. After the group is created, instances in the group are created using the specified instance template. This operation is marked as DONE when the group is created even if the instances in the group have not yet been created. You must separately verify the status of the individual instances with the listmanagedinstances method.\n\nA regional managed instance group can contain up to 2000 instances.", // "httpMethod": "POST", // "id": "compute.regionInstanceGroupManagers.insert", // "parameterOrder": [ @@ -99623,9 +109888,13 @@ func (c *RegionInstanceGroupManagersListCall) doRequest(alt string) (*http.Respo } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/instanceGroupManagers") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -99775,25 +110044,64 @@ func (r *RegionInstanceGroupManagersService) ListManagedInstances(project string return c } -// Filter sets the optional parameter "filter": +// Filter sets the optional parameter "filter": A filter expression that +// filters resources listed in the response. The expression must specify +// the field name, a comparison operator, and the value that you want to +// use for filtering. The value must be a string, a number, or a +// boolean. The comparison operator must be either =, !=, >, or <. +// +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. +// +// You can also filter nested fields. For example, you could specify +// scheduling.automaticRestart = false to include instances only if they +// are not scheduled for automatic restarts. You can use filtering on +// nested fields to filter based on resource labels. +// +// To filter on multiple expressions, provide each separate expression +// within parentheses. For example, (scheduling.automaticRestart = true) +// (cpuPlatform = "Intel Skylake"). By default, each expression is an +// AND expression. However, you can include AND and OR expressions +// explicitly. For example, (cpuPlatform = "Intel Skylake") OR +// (cpuPlatform = "Intel Broadwell") AND (scheduling.automaticRestart = +// true). func (c *RegionInstanceGroupManagersListManagedInstancesCall) Filter(filter string) *RegionInstanceGroupManagersListManagedInstancesCall { c.urlParams_.Set("filter", filter) return c } -// MaxResults sets the optional parameter "maxResults": +// MaxResults sets the optional parameter "maxResults": The maximum +// number of results per page that should be returned. If the number of +// available results is larger than maxResults, Compute Engine returns a +// nextPageToken that can be used to get the next page of results in +// subsequent list requests. Acceptable values are 0 to 500, inclusive. +// (Default: 500) func (c *RegionInstanceGroupManagersListManagedInstancesCall) MaxResults(maxResults int64) *RegionInstanceGroupManagersListManagedInstancesCall { c.urlParams_.Set("maxResults", fmt.Sprint(maxResults)) return c } -// OrderBy sets the optional parameter "order_by": +// OrderBy sets the optional parameter "order_by": Sorts list results by +// a certain order. By default, results are returned in alphanumerical +// order based on the resource name. +// +// You can also sort results in descending order based on the creation +// timestamp using orderBy="creationTimestamp desc". This sorts results +// based on the creationTimestamp field in reverse chronological order +// (newest result first). Use this to sort resources like operations so +// that the newest operation is returned first. +// +// Currently, only sorting by name or creationTimestamp desc is +// supported. func (c *RegionInstanceGroupManagersListManagedInstancesCall) OrderBy(orderBy string) *RegionInstanceGroupManagersListManagedInstancesCall { c.urlParams_.Set("order_by", orderBy) return c } -// PageToken sets the optional parameter "pageToken": +// PageToken sets the optional parameter "pageToken": Specifies a page +// token to use. Set pageToken to the nextPageToken returned by a +// previous list request to get the next page of results. func (c *RegionInstanceGroupManagersListManagedInstancesCall) PageToken(pageToken string) *RegionInstanceGroupManagersListManagedInstancesCall { c.urlParams_.Set("pageToken", pageToken) return c @@ -99832,9 +110140,13 @@ func (c *RegionInstanceGroupManagersListManagedInstancesCall) doRequest(alt stri reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/instanceGroupManagers/{instanceGroupManager}/listManagedInstances") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -99894,6 +110206,7 @@ func (c *RegionInstanceGroupManagersListManagedInstancesCall) Do(opts ...googlea // ], // "parameters": { // "filter": { + // "description": "A filter expression that filters resources listed in the response. The expression must specify the field name, a comparison operator, and the value that you want to use for filtering. The value must be a string, a number, or a boolean. The comparison operator must be either =, !=, \u003e, or \u003c.\n\nFor example, if you are filtering Compute Engine instances, you can exclude instances named example-instance by specifying name != example-instance.\n\nYou can also filter nested fields. For example, you could specify scheduling.automaticRestart = false to include instances only if they are not scheduled for automatic restarts. You can use filtering on nested fields to filter based on resource labels.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart = true) (cpuPlatform = \"Intel Skylake\"). By default, each expression is an AND expression. However, you can include AND and OR expressions explicitly. For example, (cpuPlatform = \"Intel Skylake\") OR (cpuPlatform = \"Intel Broadwell\") AND (scheduling.automaticRestart = true).", // "location": "query", // "type": "string" // }, @@ -99905,16 +110218,19 @@ func (c *RegionInstanceGroupManagersListManagedInstancesCall) Do(opts ...googlea // }, // "maxResults": { // "default": "500", + // "description": "The maximum number of results per page that should be returned. If the number of available results is larger than maxResults, Compute Engine returns a nextPageToken that can be used to get the next page of results in subsequent list requests. Acceptable values are 0 to 500, inclusive. (Default: 500)", // "format": "uint32", // "location": "query", // "minimum": "0", // "type": "integer" // }, // "order_by": { + // "description": "Sorts list results by a certain order. By default, results are returned in alphanumerical order based on the resource name.\n\nYou can also sort results in descending order based on the creation timestamp using orderBy=\"creationTimestamp desc\". This sorts results based on the creationTimestamp field in reverse chronological order (newest result first). Use this to sort resources like operations so that the newest operation is returned first.\n\nCurrently, only sorting by name or creationTimestamp desc is supported.", // "location": "query", // "type": "string" // }, // "pageToken": { + // "description": "Specifies a page token to use. Set pageToken to the nextPageToken returned by a previous list request to get the next page of results.", // "location": "query", // "type": "string" // }, @@ -100084,9 +110400,13 @@ func (c *RegionInstanceGroupManagersListPerInstanceConfigsCall) doRequest(alt st reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/instanceGroupManagers/{instanceGroupManager}/listPerInstanceConfigs") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -100308,9 +110628,13 @@ func (c *RegionInstanceGroupManagersPatchCall) doRequest(alt string) (*http.Resp } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/instanceGroupManagers/{instanceGroupManager}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PATCH", urls, body) + req, err := http.NewRequest("PATCH", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -100420,11 +110744,11 @@ type RegionInstanceGroupManagersRecreateInstancesCall struct { header_ http.Header } -// RecreateInstances: Schedules a group action to recreate the specified -// instances in the managed instance group. The instances are deleted +// RecreateInstances: Flags the specified instances in the managed +// instance group to be immediately recreated. The instances are deleted // and recreated using the current instance template for the managed -// instance group. This operation is marked as DONE when the action is -// scheduled even if the instances have not yet been recreated. You must +// instance group. This operation is marked as DONE when the flag is set +// even if the instances have not yet been recreated. You must // separately verify the status of the recreating action with the // listmanagedinstances method. // @@ -100501,9 +110825,13 @@ func (c *RegionInstanceGroupManagersRecreateInstancesCall) doRequest(alt string) } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/instanceGroupManagers/{instanceGroupManager}/recreateInstances") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -100551,7 +110879,7 @@ func (c *RegionInstanceGroupManagersRecreateInstancesCall) Do(opts ...googleapi. } return ret, nil // { - // "description": "Schedules a group action to recreate the specified instances in the managed instance group. The instances are deleted and recreated using the current instance template for the managed instance group. This operation is marked as DONE when the action is scheduled even if the instances have not yet been recreated. You must separately verify the status of the recreating action with the listmanagedinstances method.\n\nIf the group is part of a backend service that has enabled connection draining, it can take up to 60 seconds after the connection draining duration has elapsed before the VM instance is removed or deleted.\n\nYou can specify a maximum of 1000 instances with this method per request.", + // "description": "Flags the specified instances in the managed instance group to be immediately recreated. The instances are deleted and recreated using the current instance template for the managed instance group. This operation is marked as DONE when the flag is set even if the instances have not yet been recreated. You must separately verify the status of the recreating action with the listmanagedinstances method.\n\nIf the group is part of a backend service that has enabled connection draining, it can take up to 60 seconds after the connection draining duration has elapsed before the VM instance is removed or deleted.\n\nYou can specify a maximum of 1000 instances with this method per request.", // "httpMethod": "POST", // "id": "compute.regionInstanceGroupManagers.recreateInstances", // "parameterOrder": [ @@ -100612,14 +110940,15 @@ type RegionInstanceGroupManagersResizeCall struct { header_ http.Header } -// Resize: Changes the intended size for the managed instance group. If -// you increase the size, the group schedules actions to create new -// instances using the current instance template. If you decrease the -// size, the group schedules delete actions on one or more instances. -// The resize operation is marked DONE when the resize actions are -// scheduled even if the group has not yet added or deleted any -// instances. You must separately verify the status of the creating or -// deleting actions with the listmanagedinstances method. +// Resize: Changes the intended size of the managed instance group. If +// you increase the size, the group creates new instances using the +// current instance template. If you decrease the size, the group +// deletes one or more instances. +// +// The resize operation is marked DONE if the resize request is +// successful. The underlying actions take additional time. You must +// separately verify the status of the creating or deleting actions with +// the listmanagedinstances method. // // If the group is part of a backend service that has enabled connection // draining, it can take up to 60 seconds after the connection draining @@ -100685,9 +111014,13 @@ func (c *RegionInstanceGroupManagersResizeCall) doRequest(alt string) (*http.Res reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/instanceGroupManagers/{instanceGroupManager}/resize") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -100735,7 +111068,7 @@ func (c *RegionInstanceGroupManagersResizeCall) Do(opts ...googleapi.CallOption) } return ret, nil // { - // "description": "Changes the intended size for the managed instance group. If you increase the size, the group schedules actions to create new instances using the current instance template. If you decrease the size, the group schedules delete actions on one or more instances. The resize operation is marked DONE when the resize actions are scheduled even if the group has not yet added or deleted any instances. You must separately verify the status of the creating or deleting actions with the listmanagedinstances method.\n\nIf the group is part of a backend service that has enabled connection draining, it can take up to 60 seconds after the connection draining duration has elapsed before the VM instance is removed or deleted.", + // "description": "Changes the intended size of the managed instance group. If you increase the size, the group creates new instances using the current instance template. If you decrease the size, the group deletes one or more instances.\n\nThe resize operation is marked DONE if the resize request is successful. The underlying actions take additional time. You must separately verify the status of the creating or deleting actions with the listmanagedinstances method.\n\nIf the group is part of a backend service that has enabled connection draining, it can take up to 60 seconds after the connection draining duration has elapsed before the VM instance is removed or deleted.", // "httpMethod": "POST", // "id": "compute.regionInstanceGroupManagers.resize", // "parameterOrder": [ @@ -100804,7 +111137,8 @@ type RegionInstanceGroupManagersSetAutoHealingPoliciesCall struct { } // SetAutoHealingPolicies: Modifies the autohealing policy for the -// instances in this managed instance group. +// instances in this managed instance group. [Deprecated] This method is +// deprecated. Please use Patch instead. func (r *RegionInstanceGroupManagersService) SetAutoHealingPolicies(project string, region string, instanceGroupManager string, regioninstancegroupmanagerssetautohealingrequest *RegionInstanceGroupManagersSetAutoHealingRequest) *RegionInstanceGroupManagersSetAutoHealingPoliciesCall { c := &RegionInstanceGroupManagersSetAutoHealingPoliciesCall{s: r.s, urlParams_: make(gensupport.URLParams)} c.project = project @@ -100871,9 +111205,13 @@ func (c *RegionInstanceGroupManagersSetAutoHealingPoliciesCall) doRequest(alt st } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/instanceGroupManagers/{instanceGroupManager}/setAutoHealingPolicies") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -100921,7 +111259,7 @@ func (c *RegionInstanceGroupManagersSetAutoHealingPoliciesCall) Do(opts ...googl } return ret, nil // { - // "description": "Modifies the autohealing policy for the instances in this managed instance group.", + // "description": "Modifies the autohealing policy for the instances in this managed instance group. [Deprecated] This method is deprecated. Please use Patch instead.", // "httpMethod": "POST", // "id": "compute.regionInstanceGroupManagers.setAutoHealingPolicies", // "parameterOrder": [ @@ -101052,9 +111390,13 @@ func (c *RegionInstanceGroupManagersSetInstanceTemplateCall) doRequest(alt strin } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/instanceGroupManagers/{instanceGroupManager}/setInstanceTemplate") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -101233,9 +111575,13 @@ func (c *RegionInstanceGroupManagersSetTargetPoolsCall) doRequest(alt string) (* } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/instanceGroupManagers/{instanceGroupManager}/setTargetPools") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -101394,9 +111740,13 @@ func (c *RegionInstanceGroupManagersTestIamPermissionsCall) doRequest(alt string } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/instanceGroupManagers/{resource}/testIamPermissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -101468,9 +111818,9 @@ func (c *RegionInstanceGroupManagersTestIamPermissionsCall) Do(opts ...googleapi // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -101575,9 +111925,13 @@ func (c *RegionInstanceGroupManagersUpdateCall) doRequest(alt string) (*http.Res } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/instanceGroupManagers/{instanceGroupManager}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PUT", urls, body) + req, err := http.NewRequest("PUT", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -101700,6 +112054,25 @@ func (r *RegionInstanceGroupManagersService) UpdatePerInstanceConfigs(project st return c } +// RequestId sets the optional parameter "requestId": An optional +// request ID to identify requests. Specify a unique request ID so that +// if you must retry your request, the server will know to ignore the +// request if it has already been completed. +// +// For example, consider a situation where you make an initial request +// and the request times out. If you make the request again with the +// same request ID, the server can check if original operation with the +// same request ID was received, and if so, will ignore the second +// request. This prevents clients from accidentally creating duplicate +// commitments. +// +// The request ID must be a valid UUID with the exception that zero UUID +// is not supported (00000000-0000-0000-0000-000000000000). +func (c *RegionInstanceGroupManagersUpdatePerInstanceConfigsCall) RequestId(requestId string) *RegionInstanceGroupManagersUpdatePerInstanceConfigsCall { + c.urlParams_.Set("requestId", requestId) + return c +} + // Fields allows partial responses to be retrieved. See // https://developers.google.com/gdata/docs/2.0/basics#PartialResponse // for more information. @@ -101738,9 +112111,13 @@ func (c *RegionInstanceGroupManagersUpdatePerInstanceConfigsCall) doRequest(alt } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/instanceGroupManagers/{instanceGroupManager}/updatePerInstanceConfigs") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -101815,6 +112192,11 @@ func (c *RegionInstanceGroupManagersUpdatePerInstanceConfigsCall) Do(opts ...goo // "location": "path", // "required": true, // "type": "string" + // }, + // "requestId": { + // "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", + // "location": "query", + // "type": "string" // } // }, // "path": "{project}/regions/{region}/instanceGroupManagers/{instanceGroupManager}/updatePerInstanceConfigs", @@ -101900,9 +112282,13 @@ func (c *RegionInstanceGroupsGetCall) doRequest(alt string) (*http.Response, err } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/instanceGroups/{instanceGroup}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -102122,9 +112508,13 @@ func (c *RegionInstanceGroupsListCall) doRequest(alt string) (*http.Response, er } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/instanceGroups") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -102377,9 +112767,13 @@ func (c *RegionInstanceGroupsListInstancesCall) doRequest(alt string) (*http.Res } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/instanceGroups/{instanceGroup}/listInstances") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -102598,9 +112992,13 @@ func (c *RegionInstanceGroupsSetNamedPortsCall) doRequest(alt string) (*http.Res } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/instanceGroups/{instanceGroup}/setNamedPorts") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -102759,9 +113157,13 @@ func (c *RegionInstanceGroupsTestIamPermissionsCall) doRequest(alt string) (*htt } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/instanceGroups/{resource}/testIamPermissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -102833,9 +113235,9 @@ func (c *RegionInstanceGroupsTestIamPermissionsCall) Do(opts ...googleapi.CallOp // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -102911,9 +113313,13 @@ func (c *RegionOperationsDeleteCall) doRequest(alt string) (*http.Response, erro reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/operations/{operation}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -103045,9 +113451,13 @@ func (c *RegionOperationsGetCall) doRequest(alt string) (*http.Response, error) } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/operations/{operation}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -103270,9 +113680,13 @@ func (c *RegionOperationsListCall) doRequest(alt string) (*http.Response, error) } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/operations") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -103462,9 +113876,13 @@ func (c *RegionOperationsWaitCall) doRequest(alt string) (*http.Response, error) reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/operations/{operation}/wait") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -103556,6 +113974,950 @@ func (c *RegionOperationsWaitCall) Do(opts ...googleapi.CallOption) (*Operation, } +// method id "compute.regionSslCertificates.delete": + +type RegionSslCertificatesDeleteCall struct { + s *Service + project string + region string + sslCertificate string + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// Delete: Deletes the specified SslCertificate resource in the region. +func (r *RegionSslCertificatesService) Delete(project string, region string, sslCertificate string) *RegionSslCertificatesDeleteCall { + c := &RegionSslCertificatesDeleteCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.region = region + c.sslCertificate = sslCertificate + return c +} + +// RequestId sets the optional parameter "requestId": An optional +// request ID to identify requests. Specify a unique request ID so that +// if you must retry your request, the server will know to ignore the +// request if it has already been completed. +// +// For example, consider a situation where you make an initial request +// and the request times out. If you make the request again with the +// same request ID, the server can check if original operation with the +// same request ID was received, and if so, will ignore the second +// request. This prevents clients from accidentally creating duplicate +// commitments. +// +// The request ID must be a valid UUID with the exception that zero UUID +// is not supported (00000000-0000-0000-0000-000000000000). +func (c *RegionSslCertificatesDeleteCall) RequestId(requestId string) *RegionSslCertificatesDeleteCall { + c.urlParams_.Set("requestId", requestId) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *RegionSslCertificatesDeleteCall) Fields(s ...googleapi.Field) *RegionSslCertificatesDeleteCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *RegionSslCertificatesDeleteCall) Context(ctx context.Context) *RegionSslCertificatesDeleteCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *RegionSslCertificatesDeleteCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *RegionSslCertificatesDeleteCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/sslCertificates/{sslCertificate}") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "region": c.region, + "sslCertificate": c.sslCertificate, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.regionSslCertificates.delete" call. +// Exactly one of *Operation or error will be non-nil. Any non-2xx +// status code is an error. Response headers are in either +// *Operation.ServerResponse.Header or (if a response was returned at +// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified +// to check whether the returned error was because +// http.StatusNotModified was returned. +func (c *RegionSslCertificatesDeleteCall) Do(opts ...googleapi.CallOption) (*Operation, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Operation{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Deletes the specified SslCertificate resource in the region.", + // "httpMethod": "DELETE", + // "id": "compute.regionSslCertificates.delete", + // "parameterOrder": [ + // "project", + // "region", + // "sslCertificate" + // ], + // "parameters": { + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "region": { + // "description": "Name of the region scoping this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // }, + // "requestId": { + // "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", + // "location": "query", + // "type": "string" + // }, + // "sslCertificate": { + // "description": "Name of the SslCertificate resource to delete.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/regions/{region}/sslCertificates/{sslCertificate}", + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + +// method id "compute.regionSslCertificates.get": + +type RegionSslCertificatesGetCall struct { + s *Service + project string + region string + sslCertificate string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// Get: Returns the specified SslCertificate resource in the specified +// region. Get a list of available SSL certificates by making a list() +// request. +func (r *RegionSslCertificatesService) Get(project string, region string, sslCertificate string) *RegionSslCertificatesGetCall { + c := &RegionSslCertificatesGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.region = region + c.sslCertificate = sslCertificate + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *RegionSslCertificatesGetCall) Fields(s ...googleapi.Field) *RegionSslCertificatesGetCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// IfNoneMatch sets the optional parameter which makes the operation +// fail if the object's ETag matches the given value. This is useful for +// getting updates only after the object has changed since the last +// request. Use googleapi.IsNotModified to check whether the response +// error from Do is the result of In-None-Match. +func (c *RegionSslCertificatesGetCall) IfNoneMatch(entityTag string) *RegionSslCertificatesGetCall { + c.ifNoneMatch_ = entityTag + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *RegionSslCertificatesGetCall) Context(ctx context.Context) *RegionSslCertificatesGetCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *RegionSslCertificatesGetCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *RegionSslCertificatesGetCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + if c.ifNoneMatch_ != "" { + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) + } + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/sslCertificates/{sslCertificate}") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "region": c.region, + "sslCertificate": c.sslCertificate, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.regionSslCertificates.get" call. +// Exactly one of *SslCertificate or error will be non-nil. Any non-2xx +// status code is an error. Response headers are in either +// *SslCertificate.ServerResponse.Header or (if a response was returned +// at all) in error.(*googleapi.Error).Header. Use +// googleapi.IsNotModified to check whether the returned error was +// because http.StatusNotModified was returned. +func (c *RegionSslCertificatesGetCall) Do(opts ...googleapi.CallOption) (*SslCertificate, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &SslCertificate{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Returns the specified SslCertificate resource in the specified region. Get a list of available SSL certificates by making a list() request.", + // "httpMethod": "GET", + // "id": "compute.regionSslCertificates.get", + // "parameterOrder": [ + // "project", + // "region", + // "sslCertificate" + // ], + // "parameters": { + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "region": { + // "description": "Name of the region scoping this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // }, + // "sslCertificate": { + // "description": "Name of the SslCertificate resource to return.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/regions/{region}/sslCertificates/{sslCertificate}", + // "response": { + // "$ref": "SslCertificate" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute", + // "https://www.googleapis.com/auth/compute.readonly" + // ] + // } + +} + +// method id "compute.regionSslCertificates.insert": + +type RegionSslCertificatesInsertCall struct { + s *Service + project string + region string + sslcertificate *SslCertificate + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// Insert: Creates a SslCertificate resource in the specified project +// and region using the data included in the request +func (r *RegionSslCertificatesService) Insert(project string, region string, sslcertificate *SslCertificate) *RegionSslCertificatesInsertCall { + c := &RegionSslCertificatesInsertCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.region = region + c.sslcertificate = sslcertificate + return c +} + +// RequestId sets the optional parameter "requestId": An optional +// request ID to identify requests. Specify a unique request ID so that +// if you must retry your request, the server will know to ignore the +// request if it has already been completed. +// +// For example, consider a situation where you make an initial request +// and the request times out. If you make the request again with the +// same request ID, the server can check if original operation with the +// same request ID was received, and if so, will ignore the second +// request. This prevents clients from accidentally creating duplicate +// commitments. +// +// The request ID must be a valid UUID with the exception that zero UUID +// is not supported (00000000-0000-0000-0000-000000000000). +func (c *RegionSslCertificatesInsertCall) RequestId(requestId string) *RegionSslCertificatesInsertCall { + c.urlParams_.Set("requestId", requestId) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *RegionSslCertificatesInsertCall) Fields(s ...googleapi.Field) *RegionSslCertificatesInsertCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *RegionSslCertificatesInsertCall) Context(ctx context.Context) *RegionSslCertificatesInsertCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *RegionSslCertificatesInsertCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *RegionSslCertificatesInsertCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.sslcertificate) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/sslCertificates") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "region": c.region, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.regionSslCertificates.insert" call. +// Exactly one of *Operation or error will be non-nil. Any non-2xx +// status code is an error. Response headers are in either +// *Operation.ServerResponse.Header or (if a response was returned at +// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified +// to check whether the returned error was because +// http.StatusNotModified was returned. +func (c *RegionSslCertificatesInsertCall) Do(opts ...googleapi.CallOption) (*Operation, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Operation{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Creates a SslCertificate resource in the specified project and region using the data included in the request", + // "httpMethod": "POST", + // "id": "compute.regionSslCertificates.insert", + // "parameterOrder": [ + // "project", + // "region" + // ], + // "parameters": { + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "region": { + // "description": "Name of the region scoping this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // }, + // "requestId": { + // "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", + // "location": "query", + // "type": "string" + // } + // }, + // "path": "{project}/regions/{region}/sslCertificates", + // "request": { + // "$ref": "SslCertificate" + // }, + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + +// method id "compute.regionSslCertificates.list": + +type RegionSslCertificatesListCall struct { + s *Service + project string + region string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// List: Retrieves the list of SslCertificate resources available to the +// specified project in the specified region. +func (r *RegionSslCertificatesService) List(project string, region string) *RegionSslCertificatesListCall { + c := &RegionSslCertificatesListCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.region = region + return c +} + +// Filter sets the optional parameter "filter": A filter expression that +// filters resources listed in the response. The expression must specify +// the field name, a comparison operator, and the value that you want to +// use for filtering. The value must be a string, a number, or a +// boolean. The comparison operator must be either =, !=, >, or <. +// +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. +// +// You can also filter nested fields. For example, you could specify +// scheduling.automaticRestart = false to include instances only if they +// are not scheduled for automatic restarts. You can use filtering on +// nested fields to filter based on resource labels. +// +// To filter on multiple expressions, provide each separate expression +// within parentheses. For example, (scheduling.automaticRestart = true) +// (cpuPlatform = "Intel Skylake"). By default, each expression is an +// AND expression. However, you can include AND and OR expressions +// explicitly. For example, (cpuPlatform = "Intel Skylake") OR +// (cpuPlatform = "Intel Broadwell") AND (scheduling.automaticRestart = +// true). +func (c *RegionSslCertificatesListCall) Filter(filter string) *RegionSslCertificatesListCall { + c.urlParams_.Set("filter", filter) + return c +} + +// MaxResults sets the optional parameter "maxResults": The maximum +// number of results per page that should be returned. If the number of +// available results is larger than maxResults, Compute Engine returns a +// nextPageToken that can be used to get the next page of results in +// subsequent list requests. Acceptable values are 0 to 500, inclusive. +// (Default: 500) +func (c *RegionSslCertificatesListCall) MaxResults(maxResults int64) *RegionSslCertificatesListCall { + c.urlParams_.Set("maxResults", fmt.Sprint(maxResults)) + return c +} + +// OrderBy sets the optional parameter "orderBy": Sorts list results by +// a certain order. By default, results are returned in alphanumerical +// order based on the resource name. +// +// You can also sort results in descending order based on the creation +// timestamp using orderBy="creationTimestamp desc". This sorts results +// based on the creationTimestamp field in reverse chronological order +// (newest result first). Use this to sort resources like operations so +// that the newest operation is returned first. +// +// Currently, only sorting by name or creationTimestamp desc is +// supported. +func (c *RegionSslCertificatesListCall) OrderBy(orderBy string) *RegionSslCertificatesListCall { + c.urlParams_.Set("orderBy", orderBy) + return c +} + +// PageToken sets the optional parameter "pageToken": Specifies a page +// token to use. Set pageToken to the nextPageToken returned by a +// previous list request to get the next page of results. +func (c *RegionSslCertificatesListCall) PageToken(pageToken string) *RegionSslCertificatesListCall { + c.urlParams_.Set("pageToken", pageToken) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *RegionSslCertificatesListCall) Fields(s ...googleapi.Field) *RegionSslCertificatesListCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// IfNoneMatch sets the optional parameter which makes the operation +// fail if the object's ETag matches the given value. This is useful for +// getting updates only after the object has changed since the last +// request. Use googleapi.IsNotModified to check whether the response +// error from Do is the result of In-None-Match. +func (c *RegionSslCertificatesListCall) IfNoneMatch(entityTag string) *RegionSslCertificatesListCall { + c.ifNoneMatch_ = entityTag + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *RegionSslCertificatesListCall) Context(ctx context.Context) *RegionSslCertificatesListCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *RegionSslCertificatesListCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *RegionSslCertificatesListCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + if c.ifNoneMatch_ != "" { + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) + } + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/sslCertificates") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "region": c.region, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.regionSslCertificates.list" call. +// Exactly one of *SslCertificateList or error will be non-nil. Any +// non-2xx status code is an error. Response headers are in either +// *SslCertificateList.ServerResponse.Header or (if a response was +// returned at all) in error.(*googleapi.Error).Header. Use +// googleapi.IsNotModified to check whether the returned error was +// because http.StatusNotModified was returned. +func (c *RegionSslCertificatesListCall) Do(opts ...googleapi.CallOption) (*SslCertificateList, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &SslCertificateList{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Retrieves the list of SslCertificate resources available to the specified project in the specified region.", + // "httpMethod": "GET", + // "id": "compute.regionSslCertificates.list", + // "parameterOrder": [ + // "project", + // "region" + // ], + // "parameters": { + // "filter": { + // "description": "A filter expression that filters resources listed in the response. The expression must specify the field name, a comparison operator, and the value that you want to use for filtering. The value must be a string, a number, or a boolean. The comparison operator must be either =, !=, \u003e, or \u003c.\n\nFor example, if you are filtering Compute Engine instances, you can exclude instances named example-instance by specifying name != example-instance.\n\nYou can also filter nested fields. For example, you could specify scheduling.automaticRestart = false to include instances only if they are not scheduled for automatic restarts. You can use filtering on nested fields to filter based on resource labels.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart = true) (cpuPlatform = \"Intel Skylake\"). By default, each expression is an AND expression. However, you can include AND and OR expressions explicitly. For example, (cpuPlatform = \"Intel Skylake\") OR (cpuPlatform = \"Intel Broadwell\") AND (scheduling.automaticRestart = true).", + // "location": "query", + // "type": "string" + // }, + // "maxResults": { + // "default": "500", + // "description": "The maximum number of results per page that should be returned. If the number of available results is larger than maxResults, Compute Engine returns a nextPageToken that can be used to get the next page of results in subsequent list requests. Acceptable values are 0 to 500, inclusive. (Default: 500)", + // "format": "uint32", + // "location": "query", + // "minimum": "0", + // "type": "integer" + // }, + // "orderBy": { + // "description": "Sorts list results by a certain order. By default, results are returned in alphanumerical order based on the resource name.\n\nYou can also sort results in descending order based on the creation timestamp using orderBy=\"creationTimestamp desc\". This sorts results based on the creationTimestamp field in reverse chronological order (newest result first). Use this to sort resources like operations so that the newest operation is returned first.\n\nCurrently, only sorting by name or creationTimestamp desc is supported.", + // "location": "query", + // "type": "string" + // }, + // "pageToken": { + // "description": "Specifies a page token to use. Set pageToken to the nextPageToken returned by a previous list request to get the next page of results.", + // "location": "query", + // "type": "string" + // }, + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "region": { + // "description": "Name of the region scoping this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/regions/{region}/sslCertificates", + // "response": { + // "$ref": "SslCertificateList" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute", + // "https://www.googleapis.com/auth/compute.readonly" + // ] + // } + +} + +// Pages invokes f for each page of results. +// A non-nil error returned from f will halt the iteration. +// The provided context supersedes any context provided to the Context method. +func (c *RegionSslCertificatesListCall) Pages(ctx context.Context, f func(*SslCertificateList) error) error { + c.ctx_ = ctx + defer c.PageToken(c.urlParams_.Get("pageToken")) // reset paging to original point + for { + x, err := c.Do() + if err != nil { + return err + } + if err := f(x); err != nil { + return err + } + if x.NextPageToken == "" { + return nil + } + c.PageToken(x.NextPageToken) + } +} + +// method id "compute.regionSslCertificates.testIamPermissions": + +type RegionSslCertificatesTestIamPermissionsCall struct { + s *Service + project string + region string + resource string + testpermissionsrequest *TestPermissionsRequest + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// TestIamPermissions: Returns permissions that a caller has on the +// specified resource and region. +func (r *RegionSslCertificatesService) TestIamPermissions(project string, region string, resource string, testpermissionsrequest *TestPermissionsRequest) *RegionSslCertificatesTestIamPermissionsCall { + c := &RegionSslCertificatesTestIamPermissionsCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.region = region + c.resource = resource + c.testpermissionsrequest = testpermissionsrequest + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *RegionSslCertificatesTestIamPermissionsCall) Fields(s ...googleapi.Field) *RegionSslCertificatesTestIamPermissionsCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *RegionSslCertificatesTestIamPermissionsCall) Context(ctx context.Context) *RegionSslCertificatesTestIamPermissionsCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *RegionSslCertificatesTestIamPermissionsCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *RegionSslCertificatesTestIamPermissionsCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.testpermissionsrequest) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/sslCertificates/{resource}/testIamPermissions") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "region": c.region, + "resource": c.resource, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.regionSslCertificates.testIamPermissions" call. +// Exactly one of *TestPermissionsResponse or error will be non-nil. Any +// non-2xx status code is an error. Response headers are in either +// *TestPermissionsResponse.ServerResponse.Header or (if a response was +// returned at all) in error.(*googleapi.Error).Header. Use +// googleapi.IsNotModified to check whether the returned error was +// because http.StatusNotModified was returned. +func (c *RegionSslCertificatesTestIamPermissionsCall) Do(opts ...googleapi.CallOption) (*TestPermissionsResponse, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &TestPermissionsResponse{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Returns permissions that a caller has on the specified resource and region.", + // "httpMethod": "POST", + // "id": "compute.regionSslCertificates.testIamPermissions", + // "parameterOrder": [ + // "project", + // "region", + // "resource" + // ], + // "parameters": { + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "region": { + // "description": "The name of the region for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // }, + // "resource": { + // "description": "Name or id of the resource for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/regions/{region}/sslCertificates/{resource}/testIamPermissions", + // "request": { + // "$ref": "TestPermissionsRequest" + // }, + // "response": { + // "$ref": "TestPermissionsResponse" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute", + // "https://www.googleapis.com/auth/compute.readonly" + // ] + // } + +} + // method id "compute.regionTargetHttpProxies.delete": type RegionTargetHttpProxiesDeleteCall struct { @@ -103629,9 +114991,13 @@ func (c *RegionTargetHttpProxiesDeleteCall) doRequest(alt string) (*http.Respons reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/targetHttpProxies/{targetHttpProxy}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -103797,9 +115163,13 @@ func (c *RegionTargetHttpProxiesGetCall) doRequest(alt string) (*http.Response, } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/targetHttpProxies/{targetHttpProxy}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -103970,9 +115340,13 @@ func (c *RegionTargetHttpProxiesInsertCall) doRequest(alt string) (*http.Respons } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/targetHttpProxies") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -104192,9 +115566,13 @@ func (c *RegionTargetHttpProxiesListCall) doRequest(alt string) (*http.Response, } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/targetHttpProxies") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -104401,9 +115779,13 @@ func (c *RegionTargetHttpProxiesSetUrlMapCall) doRequest(alt string) (*http.Resp } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/targetHttpProxies/{targetHttpProxy}/setUrlMap") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -104564,9 +115946,13 @@ func (c *RegionTargetHttpProxiesTestIamPermissionsCall) doRequest(alt string) (* } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/targetHttpProxies/{resource}/testIamPermissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -104638,14 +116024,1328 @@ func (c *RegionTargetHttpProxiesTestIamPermissionsCall) Do(opts ...googleapi.Cal // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/regions/{region}/targetHttpProxies/{resource}/testIamPermissions", + // "request": { + // "$ref": "TestPermissionsRequest" + // }, + // "response": { + // "$ref": "TestPermissionsResponse" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute", + // "https://www.googleapis.com/auth/compute.readonly" + // ] + // } + +} + +// method id "compute.regionTargetHttpsProxies.delete": + +type RegionTargetHttpsProxiesDeleteCall struct { + s *Service + project string + region string + targetHttpsProxy string + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// Delete: Deletes the specified TargetHttpsProxy resource. +func (r *RegionTargetHttpsProxiesService) Delete(project string, region string, targetHttpsProxy string) *RegionTargetHttpsProxiesDeleteCall { + c := &RegionTargetHttpsProxiesDeleteCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.region = region + c.targetHttpsProxy = targetHttpsProxy + return c +} + +// RequestId sets the optional parameter "requestId": An optional +// request ID to identify requests. Specify a unique request ID so that +// if you must retry your request, the server will know to ignore the +// request if it has already been completed. +// +// For example, consider a situation where you make an initial request +// and the request times out. If you make the request again with the +// same request ID, the server can check if original operation with the +// same request ID was received, and if so, will ignore the second +// request. This prevents clients from accidentally creating duplicate +// commitments. +// +// The request ID must be a valid UUID with the exception that zero UUID +// is not supported (00000000-0000-0000-0000-000000000000). +func (c *RegionTargetHttpsProxiesDeleteCall) RequestId(requestId string) *RegionTargetHttpsProxiesDeleteCall { + c.urlParams_.Set("requestId", requestId) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *RegionTargetHttpsProxiesDeleteCall) Fields(s ...googleapi.Field) *RegionTargetHttpsProxiesDeleteCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *RegionTargetHttpsProxiesDeleteCall) Context(ctx context.Context) *RegionTargetHttpsProxiesDeleteCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *RegionTargetHttpsProxiesDeleteCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *RegionTargetHttpsProxiesDeleteCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/targetHttpsProxies/{targetHttpsProxy}") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "region": c.region, + "targetHttpsProxy": c.targetHttpsProxy, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.regionTargetHttpsProxies.delete" call. +// Exactly one of *Operation or error will be non-nil. Any non-2xx +// status code is an error. Response headers are in either +// *Operation.ServerResponse.Header or (if a response was returned at +// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified +// to check whether the returned error was because +// http.StatusNotModified was returned. +func (c *RegionTargetHttpsProxiesDeleteCall) Do(opts ...googleapi.CallOption) (*Operation, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Operation{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Deletes the specified TargetHttpsProxy resource.", + // "httpMethod": "DELETE", + // "id": "compute.regionTargetHttpsProxies.delete", + // "parameterOrder": [ + // "project", + // "region", + // "targetHttpsProxy" + // ], + // "parameters": { + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "region": { + // "description": "Name of the region scoping this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // }, + // "requestId": { + // "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", + // "location": "query", + // "type": "string" + // }, + // "targetHttpsProxy": { + // "description": "Name of the TargetHttpsProxy resource to delete.", // "location": "path", // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", // "required": true, // "type": "string" // } // }, - // "path": "{project}/regions/{region}/targetHttpProxies/{resource}/testIamPermissions", + // "path": "{project}/regions/{region}/targetHttpsProxies/{targetHttpsProxy}", + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + +// method id "compute.regionTargetHttpsProxies.get": + +type RegionTargetHttpsProxiesGetCall struct { + s *Service + project string + region string + targetHttpsProxy string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// Get: Returns the specified TargetHttpsProxy resource in the specified +// region. Gets a list of available target HTTP proxies by making a +// list() request. +func (r *RegionTargetHttpsProxiesService) Get(project string, region string, targetHttpsProxy string) *RegionTargetHttpsProxiesGetCall { + c := &RegionTargetHttpsProxiesGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.region = region + c.targetHttpsProxy = targetHttpsProxy + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *RegionTargetHttpsProxiesGetCall) Fields(s ...googleapi.Field) *RegionTargetHttpsProxiesGetCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// IfNoneMatch sets the optional parameter which makes the operation +// fail if the object's ETag matches the given value. This is useful for +// getting updates only after the object has changed since the last +// request. Use googleapi.IsNotModified to check whether the response +// error from Do is the result of In-None-Match. +func (c *RegionTargetHttpsProxiesGetCall) IfNoneMatch(entityTag string) *RegionTargetHttpsProxiesGetCall { + c.ifNoneMatch_ = entityTag + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *RegionTargetHttpsProxiesGetCall) Context(ctx context.Context) *RegionTargetHttpsProxiesGetCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *RegionTargetHttpsProxiesGetCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *RegionTargetHttpsProxiesGetCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + if c.ifNoneMatch_ != "" { + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) + } + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/targetHttpsProxies/{targetHttpsProxy}") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "region": c.region, + "targetHttpsProxy": c.targetHttpsProxy, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.regionTargetHttpsProxies.get" call. +// Exactly one of *TargetHttpsProxy or error will be non-nil. Any +// non-2xx status code is an error. Response headers are in either +// *TargetHttpsProxy.ServerResponse.Header or (if a response was +// returned at all) in error.(*googleapi.Error).Header. Use +// googleapi.IsNotModified to check whether the returned error was +// because http.StatusNotModified was returned. +func (c *RegionTargetHttpsProxiesGetCall) Do(opts ...googleapi.CallOption) (*TargetHttpsProxy, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &TargetHttpsProxy{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Returns the specified TargetHttpsProxy resource in the specified region. Gets a list of available target HTTP proxies by making a list() request.", + // "httpMethod": "GET", + // "id": "compute.regionTargetHttpsProxies.get", + // "parameterOrder": [ + // "project", + // "region", + // "targetHttpsProxy" + // ], + // "parameters": { + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "region": { + // "description": "Name of the region scoping this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // }, + // "targetHttpsProxy": { + // "description": "Name of the TargetHttpsProxy resource to return.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/regions/{region}/targetHttpsProxies/{targetHttpsProxy}", + // "response": { + // "$ref": "TargetHttpsProxy" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute", + // "https://www.googleapis.com/auth/compute.readonly" + // ] + // } + +} + +// method id "compute.regionTargetHttpsProxies.insert": + +type RegionTargetHttpsProxiesInsertCall struct { + s *Service + project string + region string + targethttpsproxy *TargetHttpsProxy + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// Insert: Creates a TargetHttpsProxy resource in the specified project +// and region using the data included in the request. +func (r *RegionTargetHttpsProxiesService) Insert(project string, region string, targethttpsproxy *TargetHttpsProxy) *RegionTargetHttpsProxiesInsertCall { + c := &RegionTargetHttpsProxiesInsertCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.region = region + c.targethttpsproxy = targethttpsproxy + return c +} + +// RequestId sets the optional parameter "requestId": An optional +// request ID to identify requests. Specify a unique request ID so that +// if you must retry your request, the server will know to ignore the +// request if it has already been completed. +// +// For example, consider a situation where you make an initial request +// and the request times out. If you make the request again with the +// same request ID, the server can check if original operation with the +// same request ID was received, and if so, will ignore the second +// request. This prevents clients from accidentally creating duplicate +// commitments. +// +// The request ID must be a valid UUID with the exception that zero UUID +// is not supported (00000000-0000-0000-0000-000000000000). +func (c *RegionTargetHttpsProxiesInsertCall) RequestId(requestId string) *RegionTargetHttpsProxiesInsertCall { + c.urlParams_.Set("requestId", requestId) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *RegionTargetHttpsProxiesInsertCall) Fields(s ...googleapi.Field) *RegionTargetHttpsProxiesInsertCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *RegionTargetHttpsProxiesInsertCall) Context(ctx context.Context) *RegionTargetHttpsProxiesInsertCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *RegionTargetHttpsProxiesInsertCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *RegionTargetHttpsProxiesInsertCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.targethttpsproxy) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/targetHttpsProxies") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "region": c.region, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.regionTargetHttpsProxies.insert" call. +// Exactly one of *Operation or error will be non-nil. Any non-2xx +// status code is an error. Response headers are in either +// *Operation.ServerResponse.Header or (if a response was returned at +// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified +// to check whether the returned error was because +// http.StatusNotModified was returned. +func (c *RegionTargetHttpsProxiesInsertCall) Do(opts ...googleapi.CallOption) (*Operation, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Operation{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Creates a TargetHttpsProxy resource in the specified project and region using the data included in the request.", + // "httpMethod": "POST", + // "id": "compute.regionTargetHttpsProxies.insert", + // "parameterOrder": [ + // "project", + // "region" + // ], + // "parameters": { + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "region": { + // "description": "Name of the region scoping this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // }, + // "requestId": { + // "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", + // "location": "query", + // "type": "string" + // } + // }, + // "path": "{project}/regions/{region}/targetHttpsProxies", + // "request": { + // "$ref": "TargetHttpsProxy" + // }, + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + +// method id "compute.regionTargetHttpsProxies.list": + +type RegionTargetHttpsProxiesListCall struct { + s *Service + project string + region string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// List: Retrieves the list of TargetHttpsProxy resources available to +// the specified project in the specified region. +func (r *RegionTargetHttpsProxiesService) List(project string, region string) *RegionTargetHttpsProxiesListCall { + c := &RegionTargetHttpsProxiesListCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.region = region + return c +} + +// Filter sets the optional parameter "filter": A filter expression that +// filters resources listed in the response. The expression must specify +// the field name, a comparison operator, and the value that you want to +// use for filtering. The value must be a string, a number, or a +// boolean. The comparison operator must be either =, !=, >, or <. +// +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. +// +// You can also filter nested fields. For example, you could specify +// scheduling.automaticRestart = false to include instances only if they +// are not scheduled for automatic restarts. You can use filtering on +// nested fields to filter based on resource labels. +// +// To filter on multiple expressions, provide each separate expression +// within parentheses. For example, (scheduling.automaticRestart = true) +// (cpuPlatform = "Intel Skylake"). By default, each expression is an +// AND expression. However, you can include AND and OR expressions +// explicitly. For example, (cpuPlatform = "Intel Skylake") OR +// (cpuPlatform = "Intel Broadwell") AND (scheduling.automaticRestart = +// true). +func (c *RegionTargetHttpsProxiesListCall) Filter(filter string) *RegionTargetHttpsProxiesListCall { + c.urlParams_.Set("filter", filter) + return c +} + +// MaxResults sets the optional parameter "maxResults": The maximum +// number of results per page that should be returned. If the number of +// available results is larger than maxResults, Compute Engine returns a +// nextPageToken that can be used to get the next page of results in +// subsequent list requests. Acceptable values are 0 to 500, inclusive. +// (Default: 500) +func (c *RegionTargetHttpsProxiesListCall) MaxResults(maxResults int64) *RegionTargetHttpsProxiesListCall { + c.urlParams_.Set("maxResults", fmt.Sprint(maxResults)) + return c +} + +// OrderBy sets the optional parameter "orderBy": Sorts list results by +// a certain order. By default, results are returned in alphanumerical +// order based on the resource name. +// +// You can also sort results in descending order based on the creation +// timestamp using orderBy="creationTimestamp desc". This sorts results +// based on the creationTimestamp field in reverse chronological order +// (newest result first). Use this to sort resources like operations so +// that the newest operation is returned first. +// +// Currently, only sorting by name or creationTimestamp desc is +// supported. +func (c *RegionTargetHttpsProxiesListCall) OrderBy(orderBy string) *RegionTargetHttpsProxiesListCall { + c.urlParams_.Set("orderBy", orderBy) + return c +} + +// PageToken sets the optional parameter "pageToken": Specifies a page +// token to use. Set pageToken to the nextPageToken returned by a +// previous list request to get the next page of results. +func (c *RegionTargetHttpsProxiesListCall) PageToken(pageToken string) *RegionTargetHttpsProxiesListCall { + c.urlParams_.Set("pageToken", pageToken) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *RegionTargetHttpsProxiesListCall) Fields(s ...googleapi.Field) *RegionTargetHttpsProxiesListCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// IfNoneMatch sets the optional parameter which makes the operation +// fail if the object's ETag matches the given value. This is useful for +// getting updates only after the object has changed since the last +// request. Use googleapi.IsNotModified to check whether the response +// error from Do is the result of In-None-Match. +func (c *RegionTargetHttpsProxiesListCall) IfNoneMatch(entityTag string) *RegionTargetHttpsProxiesListCall { + c.ifNoneMatch_ = entityTag + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *RegionTargetHttpsProxiesListCall) Context(ctx context.Context) *RegionTargetHttpsProxiesListCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *RegionTargetHttpsProxiesListCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *RegionTargetHttpsProxiesListCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + if c.ifNoneMatch_ != "" { + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) + } + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/targetHttpsProxies") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "region": c.region, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.regionTargetHttpsProxies.list" call. +// Exactly one of *TargetHttpsProxyList or error will be non-nil. Any +// non-2xx status code is an error. Response headers are in either +// *TargetHttpsProxyList.ServerResponse.Header or (if a response was +// returned at all) in error.(*googleapi.Error).Header. Use +// googleapi.IsNotModified to check whether the returned error was +// because http.StatusNotModified was returned. +func (c *RegionTargetHttpsProxiesListCall) Do(opts ...googleapi.CallOption) (*TargetHttpsProxyList, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &TargetHttpsProxyList{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Retrieves the list of TargetHttpsProxy resources available to the specified project in the specified region.", + // "httpMethod": "GET", + // "id": "compute.regionTargetHttpsProxies.list", + // "parameterOrder": [ + // "project", + // "region" + // ], + // "parameters": { + // "filter": { + // "description": "A filter expression that filters resources listed in the response. The expression must specify the field name, a comparison operator, and the value that you want to use for filtering. The value must be a string, a number, or a boolean. The comparison operator must be either =, !=, \u003e, or \u003c.\n\nFor example, if you are filtering Compute Engine instances, you can exclude instances named example-instance by specifying name != example-instance.\n\nYou can also filter nested fields. For example, you could specify scheduling.automaticRestart = false to include instances only if they are not scheduled for automatic restarts. You can use filtering on nested fields to filter based on resource labels.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart = true) (cpuPlatform = \"Intel Skylake\"). By default, each expression is an AND expression. However, you can include AND and OR expressions explicitly. For example, (cpuPlatform = \"Intel Skylake\") OR (cpuPlatform = \"Intel Broadwell\") AND (scheduling.automaticRestart = true).", + // "location": "query", + // "type": "string" + // }, + // "maxResults": { + // "default": "500", + // "description": "The maximum number of results per page that should be returned. If the number of available results is larger than maxResults, Compute Engine returns a nextPageToken that can be used to get the next page of results in subsequent list requests. Acceptable values are 0 to 500, inclusive. (Default: 500)", + // "format": "uint32", + // "location": "query", + // "minimum": "0", + // "type": "integer" + // }, + // "orderBy": { + // "description": "Sorts list results by a certain order. By default, results are returned in alphanumerical order based on the resource name.\n\nYou can also sort results in descending order based on the creation timestamp using orderBy=\"creationTimestamp desc\". This sorts results based on the creationTimestamp field in reverse chronological order (newest result first). Use this to sort resources like operations so that the newest operation is returned first.\n\nCurrently, only sorting by name or creationTimestamp desc is supported.", + // "location": "query", + // "type": "string" + // }, + // "pageToken": { + // "description": "Specifies a page token to use. Set pageToken to the nextPageToken returned by a previous list request to get the next page of results.", + // "location": "query", + // "type": "string" + // }, + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "region": { + // "description": "Name of the region scoping this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/regions/{region}/targetHttpsProxies", + // "response": { + // "$ref": "TargetHttpsProxyList" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute", + // "https://www.googleapis.com/auth/compute.readonly" + // ] + // } + +} + +// Pages invokes f for each page of results. +// A non-nil error returned from f will halt the iteration. +// The provided context supersedes any context provided to the Context method. +func (c *RegionTargetHttpsProxiesListCall) Pages(ctx context.Context, f func(*TargetHttpsProxyList) error) error { + c.ctx_ = ctx + defer c.PageToken(c.urlParams_.Get("pageToken")) // reset paging to original point + for { + x, err := c.Do() + if err != nil { + return err + } + if err := f(x); err != nil { + return err + } + if x.NextPageToken == "" { + return nil + } + c.PageToken(x.NextPageToken) + } +} + +// method id "compute.regionTargetHttpsProxies.setSslCertificates": + +type RegionTargetHttpsProxiesSetSslCertificatesCall struct { + s *Service + project string + region string + targetHttpsProxy string + regiontargethttpsproxiessetsslcertificatesrequest *RegionTargetHttpsProxiesSetSslCertificatesRequest + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// SetSslCertificates: Replaces SslCertificates for TargetHttpsProxy. +func (r *RegionTargetHttpsProxiesService) SetSslCertificates(project string, region string, targetHttpsProxy string, regiontargethttpsproxiessetsslcertificatesrequest *RegionTargetHttpsProxiesSetSslCertificatesRequest) *RegionTargetHttpsProxiesSetSslCertificatesCall { + c := &RegionTargetHttpsProxiesSetSslCertificatesCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.region = region + c.targetHttpsProxy = targetHttpsProxy + c.regiontargethttpsproxiessetsslcertificatesrequest = regiontargethttpsproxiessetsslcertificatesrequest + return c +} + +// RequestId sets the optional parameter "requestId": An optional +// request ID to identify requests. Specify a unique request ID so that +// if you must retry your request, the server will know to ignore the +// request if it has already been completed. +// +// For example, consider a situation where you make an initial request +// and the request times out. If you make the request again with the +// same request ID, the server can check if original operation with the +// same request ID was received, and if so, will ignore the second +// request. This prevents clients from accidentally creating duplicate +// commitments. +// +// The request ID must be a valid UUID with the exception that zero UUID +// is not supported (00000000-0000-0000-0000-000000000000). +func (c *RegionTargetHttpsProxiesSetSslCertificatesCall) RequestId(requestId string) *RegionTargetHttpsProxiesSetSslCertificatesCall { + c.urlParams_.Set("requestId", requestId) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *RegionTargetHttpsProxiesSetSslCertificatesCall) Fields(s ...googleapi.Field) *RegionTargetHttpsProxiesSetSslCertificatesCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *RegionTargetHttpsProxiesSetSslCertificatesCall) Context(ctx context.Context) *RegionTargetHttpsProxiesSetSslCertificatesCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *RegionTargetHttpsProxiesSetSslCertificatesCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *RegionTargetHttpsProxiesSetSslCertificatesCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.regiontargethttpsproxiessetsslcertificatesrequest) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/targetHttpsProxies/{targetHttpsProxy}/setSslCertificates") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "region": c.region, + "targetHttpsProxy": c.targetHttpsProxy, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.regionTargetHttpsProxies.setSslCertificates" call. +// Exactly one of *Operation or error will be non-nil. Any non-2xx +// status code is an error. Response headers are in either +// *Operation.ServerResponse.Header or (if a response was returned at +// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified +// to check whether the returned error was because +// http.StatusNotModified was returned. +func (c *RegionTargetHttpsProxiesSetSslCertificatesCall) Do(opts ...googleapi.CallOption) (*Operation, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Operation{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Replaces SslCertificates for TargetHttpsProxy.", + // "httpMethod": "POST", + // "id": "compute.regionTargetHttpsProxies.setSslCertificates", + // "parameterOrder": [ + // "project", + // "region", + // "targetHttpsProxy" + // ], + // "parameters": { + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "region": { + // "description": "Name of the region scoping this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // }, + // "requestId": { + // "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", + // "location": "query", + // "type": "string" + // }, + // "targetHttpsProxy": { + // "description": "Name of the TargetHttpsProxy resource to set an SslCertificates resource for.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/regions/{region}/targetHttpsProxies/{targetHttpsProxy}/setSslCertificates", + // "request": { + // "$ref": "RegionTargetHttpsProxiesSetSslCertificatesRequest" + // }, + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + +// method id "compute.regionTargetHttpsProxies.setUrlMap": + +type RegionTargetHttpsProxiesSetUrlMapCall struct { + s *Service + project string + region string + targetHttpsProxy string + urlmapreference *UrlMapReference + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// SetUrlMap: Changes the URL map for TargetHttpsProxy. +func (r *RegionTargetHttpsProxiesService) SetUrlMap(project string, region string, targetHttpsProxy string, urlmapreference *UrlMapReference) *RegionTargetHttpsProxiesSetUrlMapCall { + c := &RegionTargetHttpsProxiesSetUrlMapCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.region = region + c.targetHttpsProxy = targetHttpsProxy + c.urlmapreference = urlmapreference + return c +} + +// RequestId sets the optional parameter "requestId": An optional +// request ID to identify requests. Specify a unique request ID so that +// if you must retry your request, the server will know to ignore the +// request if it has already been completed. +// +// For example, consider a situation where you make an initial request +// and the request times out. If you make the request again with the +// same request ID, the server can check if original operation with the +// same request ID was received, and if so, will ignore the second +// request. This prevents clients from accidentally creating duplicate +// commitments. +// +// The request ID must be a valid UUID with the exception that zero UUID +// is not supported (00000000-0000-0000-0000-000000000000). +func (c *RegionTargetHttpsProxiesSetUrlMapCall) RequestId(requestId string) *RegionTargetHttpsProxiesSetUrlMapCall { + c.urlParams_.Set("requestId", requestId) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *RegionTargetHttpsProxiesSetUrlMapCall) Fields(s ...googleapi.Field) *RegionTargetHttpsProxiesSetUrlMapCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *RegionTargetHttpsProxiesSetUrlMapCall) Context(ctx context.Context) *RegionTargetHttpsProxiesSetUrlMapCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *RegionTargetHttpsProxiesSetUrlMapCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *RegionTargetHttpsProxiesSetUrlMapCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.urlmapreference) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/targetHttpsProxies/{targetHttpsProxy}/setUrlMap") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "region": c.region, + "targetHttpsProxy": c.targetHttpsProxy, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.regionTargetHttpsProxies.setUrlMap" call. +// Exactly one of *Operation or error will be non-nil. Any non-2xx +// status code is an error. Response headers are in either +// *Operation.ServerResponse.Header or (if a response was returned at +// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified +// to check whether the returned error was because +// http.StatusNotModified was returned. +func (c *RegionTargetHttpsProxiesSetUrlMapCall) Do(opts ...googleapi.CallOption) (*Operation, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Operation{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Changes the URL map for TargetHttpsProxy.", + // "httpMethod": "POST", + // "id": "compute.regionTargetHttpsProxies.setUrlMap", + // "parameterOrder": [ + // "project", + // "region", + // "targetHttpsProxy" + // ], + // "parameters": { + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "region": { + // "description": "Name of the region scoping this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // }, + // "requestId": { + // "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", + // "location": "query", + // "type": "string" + // }, + // "targetHttpsProxy": { + // "description": "Name of the TargetHttpsProxy to set a URL map for.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/regions/{region}/targetHttpsProxies/{targetHttpsProxy}/setUrlMap", + // "request": { + // "$ref": "UrlMapReference" + // }, + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + +// method id "compute.regionTargetHttpsProxies.testIamPermissions": + +type RegionTargetHttpsProxiesTestIamPermissionsCall struct { + s *Service + project string + region string + resource string + testpermissionsrequest *TestPermissionsRequest + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// TestIamPermissions: Returns permissions that a caller has on the +// specified resource. +func (r *RegionTargetHttpsProxiesService) TestIamPermissions(project string, region string, resource string, testpermissionsrequest *TestPermissionsRequest) *RegionTargetHttpsProxiesTestIamPermissionsCall { + c := &RegionTargetHttpsProxiesTestIamPermissionsCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.region = region + c.resource = resource + c.testpermissionsrequest = testpermissionsrequest + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *RegionTargetHttpsProxiesTestIamPermissionsCall) Fields(s ...googleapi.Field) *RegionTargetHttpsProxiesTestIamPermissionsCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *RegionTargetHttpsProxiesTestIamPermissionsCall) Context(ctx context.Context) *RegionTargetHttpsProxiesTestIamPermissionsCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *RegionTargetHttpsProxiesTestIamPermissionsCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *RegionTargetHttpsProxiesTestIamPermissionsCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.testpermissionsrequest) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/targetHttpsProxies/{resource}/testIamPermissions") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "region": c.region, + "resource": c.resource, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.regionTargetHttpsProxies.testIamPermissions" call. +// Exactly one of *TestPermissionsResponse or error will be non-nil. Any +// non-2xx status code is an error. Response headers are in either +// *TestPermissionsResponse.ServerResponse.Header or (if a response was +// returned at all) in error.(*googleapi.Error).Header. Use +// googleapi.IsNotModified to check whether the returned error was +// because http.StatusNotModified was returned. +func (c *RegionTargetHttpsProxiesTestIamPermissionsCall) Do(opts ...googleapi.CallOption) (*TestPermissionsResponse, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &TestPermissionsResponse{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Returns permissions that a caller has on the specified resource.", + // "httpMethod": "POST", + // "id": "compute.regionTargetHttpsProxies.testIamPermissions", + // "parameterOrder": [ + // "project", + // "region", + // "resource" + // ], + // "parameters": { + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "region": { + // "description": "The name of the region for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // }, + // "resource": { + // "description": "Name or id of the resource for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/regions/{region}/targetHttpsProxies/{resource}/testIamPermissions", // "request": { // "$ref": "TestPermissionsRequest" // }, @@ -104722,9 +117422,13 @@ func (c *RegionUrlMapsDeleteCall) doRequest(alt string) (*http.Response, error) reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/urlMaps/{urlMap}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -104889,9 +117593,13 @@ func (c *RegionUrlMapsGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/urlMaps/{urlMap}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -105050,9 +117758,13 @@ func (c *RegionUrlMapsInsertCall) doRequest(alt string) (*http.Response, error) } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/urlMaps") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -105142,6 +117854,180 @@ func (c *RegionUrlMapsInsertCall) Do(opts ...googleapi.CallOption) (*Operation, } +// method id "compute.regionUrlMaps.invalidateCache": + +type RegionUrlMapsInvalidateCacheCall struct { + s *Service + project string + region string + urlMap string + cacheinvalidationrule *CacheInvalidationRule + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// InvalidateCache: Initiates a cache invalidation operation, +// invalidating the specified path, scoped to the specified UrlMap. +func (r *RegionUrlMapsService) InvalidateCache(project string, region string, urlMap string, cacheinvalidationrule *CacheInvalidationRule) *RegionUrlMapsInvalidateCacheCall { + c := &RegionUrlMapsInvalidateCacheCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.region = region + c.urlMap = urlMap + c.cacheinvalidationrule = cacheinvalidationrule + return c +} + +// RequestId sets the optional parameter "requestId": begin_interface: +// MixerMutationRequestBuilder Request ID to support idempotency. +func (c *RegionUrlMapsInvalidateCacheCall) RequestId(requestId string) *RegionUrlMapsInvalidateCacheCall { + c.urlParams_.Set("requestId", requestId) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *RegionUrlMapsInvalidateCacheCall) Fields(s ...googleapi.Field) *RegionUrlMapsInvalidateCacheCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *RegionUrlMapsInvalidateCacheCall) Context(ctx context.Context) *RegionUrlMapsInvalidateCacheCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *RegionUrlMapsInvalidateCacheCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *RegionUrlMapsInvalidateCacheCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.cacheinvalidationrule) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/urlMaps/{urlMap}/invalidateCache") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "region": c.region, + "urlMap": c.urlMap, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.regionUrlMaps.invalidateCache" call. +// Exactly one of *Operation or error will be non-nil. Any non-2xx +// status code is an error. Response headers are in either +// *Operation.ServerResponse.Header or (if a response was returned at +// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified +// to check whether the returned error was because +// http.StatusNotModified was returned. +func (c *RegionUrlMapsInvalidateCacheCall) Do(opts ...googleapi.CallOption) (*Operation, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Operation{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Initiates a cache invalidation operation, invalidating the specified path, scoped to the specified UrlMap.", + // "httpMethod": "POST", + // "id": "compute.regionUrlMaps.invalidateCache", + // "parameterOrder": [ + // "project", + // "region", + // "urlMap" + // ], + // "parameters": { + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "region": { + // "description": "Name of the region scoping this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // }, + // "requestId": { + // "description": "begin_interface: MixerMutationRequestBuilder Request ID to support idempotency.", + // "location": "query", + // "type": "string" + // }, + // "urlMap": { + // "description": "Name of the UrlMap scoping this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/regions/{region}/urlMaps/{urlMap}/invalidateCache", + // "request": { + // "$ref": "CacheInvalidationRule" + // }, + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + // method id "compute.regionUrlMaps.list": type RegionUrlMapsListCall struct { @@ -105272,9 +118158,13 @@ func (c *RegionUrlMapsListCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/urlMaps") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -105471,9 +118361,13 @@ func (c *RegionUrlMapsPatchCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/urlMaps/{urlMap}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PATCH", urls, body) + req, err := http.NewRequest("PATCH", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -105634,9 +118528,13 @@ func (c *RegionUrlMapsTestIamPermissionsCall) doRequest(alt string) (*http.Respo } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/urlMaps/{resource}/testIamPermissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -105708,9 +118606,9 @@ func (c *RegionUrlMapsTestIamPermissionsCall) Do(opts ...googleapi.CallOption) ( // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -105800,9 +118698,13 @@ func (c *RegionUrlMapsUpdateCall) doRequest(alt string) (*http.Response, error) } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/urlMaps/{urlMap}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PUT", urls, body) + req, err := http.NewRequest("PUT", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -105964,9 +118866,13 @@ func (c *RegionUrlMapsValidateCall) doRequest(alt string) (*http.Response, error } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/urlMaps/{urlMap}/validate") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -106128,9 +119034,13 @@ func (c *RegionsGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -106342,9 +119252,13 @@ func (c *RegionsListCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -106589,9 +119503,13 @@ func (c *ResourcePoliciesAggregatedListCall) doRequest(alt string) (*http.Respon } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/aggregated/resourcePolicies") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -106782,9 +119700,13 @@ func (c *ResourcePoliciesDeleteCall) doRequest(alt string) (*http.Response, erro reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/resourcePolicies/{resourcePolicy}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -106948,9 +119870,13 @@ func (c *ResourcePoliciesGetCall) doRequest(alt string) (*http.Response, error) } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/resourcePolicies/{resourcePolicy}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -107111,9 +120037,13 @@ func (c *ResourcePoliciesGetIamPolicyCall) doRequest(alt string) (*http.Response } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/resourcePolicies/{resource}/getIamPolicy") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -107185,9 +120115,9 @@ func (c *ResourcePoliciesGetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Po // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -107283,9 +120213,13 @@ func (c *ResourcePoliciesInsertCall) doRequest(alt string) (*http.Response, erro } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/resourcePolicies") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -107505,9 +120439,13 @@ func (c *ResourcePoliciesListCall) doRequest(alt string) (*http.Response, error) } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/resourcePolicies") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -107517,13 +120455,13 @@ func (c *ResourcePoliciesListCall) doRequest(alt string) (*http.Response, error) } // Do executes the "compute.resourcePolicies.list" call. -// Exactly one of *ResourcePoliciesList or error will be non-nil. Any +// Exactly one of *ResourcePolicyList or error will be non-nil. Any // non-2xx status code is an error. Response headers are in either -// *ResourcePoliciesList.ServerResponse.Header or (if a response was +// *ResourcePolicyList.ServerResponse.Header or (if a response was // returned at all) in error.(*googleapi.Error).Header. Use // googleapi.IsNotModified to check whether the returned error was // because http.StatusNotModified was returned. -func (c *ResourcePoliciesListCall) Do(opts ...googleapi.CallOption) (*ResourcePoliciesList, error) { +func (c *ResourcePoliciesListCall) Do(opts ...googleapi.CallOption) (*ResourcePolicyList, error) { gensupport.SetOptions(c.urlParams_, opts...) res, err := c.doRequest("json") if res != nil && res.StatusCode == http.StatusNotModified { @@ -107542,7 +120480,7 @@ func (c *ResourcePoliciesListCall) Do(opts ...googleapi.CallOption) (*ResourcePo if err := googleapi.CheckResponse(res); err != nil { return nil, err } - ret := &ResourcePoliciesList{ + ret := &ResourcePolicyList{ ServerResponse: googleapi.ServerResponse{ Header: res.Header, HTTPStatusCode: res.StatusCode, @@ -107602,7 +120540,7 @@ func (c *ResourcePoliciesListCall) Do(opts ...googleapi.CallOption) (*ResourcePo // }, // "path": "{project}/regions/{region}/resourcePolicies", // "response": { - // "$ref": "ResourcePoliciesList" + // "$ref": "ResourcePolicyList" // }, // "scopes": [ // "https://www.googleapis.com/auth/cloud-platform", @@ -107616,7 +120554,7 @@ func (c *ResourcePoliciesListCall) Do(opts ...googleapi.CallOption) (*ResourcePo // Pages invokes f for each page of results. // A non-nil error returned from f will halt the iteration. // The provided context supersedes any context provided to the Context method. -func (c *ResourcePoliciesListCall) Pages(ctx context.Context, f func(*ResourcePoliciesList) error) error { +func (c *ResourcePoliciesListCall) Pages(ctx context.Context, f func(*ResourcePolicyList) error) error { c.ctx_ = ctx defer c.PageToken(c.urlParams_.Get("pageToken")) // reset paging to original point for { @@ -107696,9 +120634,13 @@ func (c *ResourcePoliciesSetIamPolicyCall) doRequest(alt string) (*http.Response } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/resourcePolicies/{resource}/setIamPolicy") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -107770,9 +120712,9 @@ func (c *ResourcePoliciesSetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Po // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -107854,9 +120796,13 @@ func (c *ResourcePoliciesTestIamPermissionsCall) doRequest(alt string) (*http.Re } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/resourcePolicies/{resource}/testIamPermissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -107928,9 +120874,9 @@ func (c *ResourcePoliciesTestIamPermissionsCall) Do(opts ...googleapi.CallOption // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -108078,9 +121024,13 @@ func (c *RoutersAggregatedListCall) doRequest(alt string) (*http.Response, error } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/aggregated/routers") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -108271,9 +121221,13 @@ func (c *RoutersDeleteCall) doRequest(alt string) (*http.Response, error) { reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/routers/{router}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -108438,9 +121392,13 @@ func (c *RoutersGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/routers/{router}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -108664,9 +121622,13 @@ func (c *RoutersGetNatMappingInfoCall) doRequest(alt string) (*http.Response, er } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/routers/{router}/getNatMappingInfo") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -108871,9 +121833,13 @@ func (c *RoutersGetRouterStatusCall) doRequest(alt string) (*http.Response, erro } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/routers/{router}/getRouterStatus") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -109044,9 +122010,13 @@ func (c *RoutersInsertCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/routers") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -109266,9 +122236,13 @@ func (c *RoutersListCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/routers") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -109477,9 +122451,13 @@ func (c *RoutersPatchCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/routers/{router}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PATCH", urls, body) + req, err := http.NewRequest("PATCH", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -109641,9 +122619,13 @@ func (c *RoutersPreviewCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/routers/{router}/preview") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -109800,9 +122782,13 @@ func (c *RoutersTestIamPermissionsCall) doRequest(alt string) (*http.Response, e } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/routers/{resource}/testIamPermissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -109874,9 +122860,9 @@ func (c *RoutersTestIamPermissionsCall) Do(opts ...googleapi.CallOption) (*TestP // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -109978,9 +122964,13 @@ func (c *RoutersUpdateCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/routers/{router}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PUT", urls, body) + req, err := http.NewRequest("PUT", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -110151,9 +123141,13 @@ func (c *RoutesDeleteCall) doRequest(alt string) (*http.Response, error) { reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/routes/{route}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -110223,7 +123217,7 @@ func (c *RoutesDeleteCall) Do(opts ...googleapi.CallOption) (*Operation, error) // "route": { // "description": "Name of the Route resource to delete.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -110308,9 +123302,13 @@ func (c *RoutesGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/routes/{route}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -110375,7 +123373,7 @@ func (c *RoutesGetCall) Do(opts ...googleapi.CallOption) (*Route, error) { // "route": { // "description": "Name of the Route resource to return.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -110471,9 +123469,13 @@ func (c *RoutesInsertCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/routes") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -110683,9 +123685,13 @@ func (c *RoutesListCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/routes") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -110863,9 +123869,13 @@ func (c *RoutesTestIamPermissionsCall) doRequest(alt string) (*http.Response, er } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/routes/{resource}/testIamPermissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -110928,9 +123938,9 @@ func (c *RoutesTestIamPermissionsCall) Do(opts ...googleapi.CallOption) (*TestPe // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "(?:[-a-z0-9_]{0,62}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -111017,9 +124027,13 @@ func (c *SecurityPoliciesAddRuleCall) doRequest(alt string) (*http.Response, err } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/securityPolicies/{securityPolicy}/addRule") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -111180,9 +124194,13 @@ func (c *SecurityPoliciesDeleteCall) doRequest(alt string) (*http.Response, erro reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/securityPolicies/{securityPolicy}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -111336,9 +124354,13 @@ func (c *SecurityPoliciesGetCall) doRequest(alt string) (*http.Response, error) } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/securityPolicies/{securityPolicy}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -111494,9 +124516,13 @@ func (c *SecurityPoliciesGetRuleCall) doRequest(alt string) (*http.Response, err } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/securityPolicies/{securityPolicy}/getRule") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -111669,9 +124695,13 @@ func (c *SecurityPoliciesInsertCall) doRequest(alt string) (*http.Response, erro } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/securityPolicies") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -111885,9 +124915,13 @@ func (c *SecurityPoliciesListCall) doRequest(alt string) (*http.Response, error) } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/securityPolicies") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -112133,9 +125167,13 @@ func (c *SecurityPoliciesListPreconfiguredExpressionSetsCall) doRequest(alt stri } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/securityPolicies/listPreconfiguredExpressionSets") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -112313,9 +125351,13 @@ func (c *SecurityPoliciesPatchCall) doRequest(alt string) (*http.Response, error } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/securityPolicies/{securityPolicy}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PATCH", urls, body) + req, err := http.NewRequest("PATCH", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -112478,9 +125520,13 @@ func (c *SecurityPoliciesPatchRuleCall) doRequest(alt string) (*http.Response, e } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/securityPolicies/{securityPolicy}/patchRule") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -112635,9 +125681,13 @@ func (c *SecurityPoliciesRemoveRuleCall) doRequest(alt string) (*http.Response, reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/securityPolicies/{securityPolicy}/removeRule") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -112785,9 +125835,13 @@ func (c *SecurityPoliciesSetLabelsCall) doRequest(alt string) (*http.Response, e } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/securityPolicies/{resource}/setLabels") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -112850,9 +125904,9 @@ func (c *SecurityPoliciesSetLabelsCall) Do(opts ...googleapi.CallOption) (*Opera // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -112932,9 +125986,13 @@ func (c *SecurityPoliciesTestIamPermissionsCall) doRequest(alt string) (*http.Re } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/securityPolicies/{resource}/testIamPermissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -112997,9 +126055,9 @@ func (c *SecurityPoliciesTestIamPermissionsCall) Do(opts ...googleapi.CallOption // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "(?:[-a-z0-9_]{0,62}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -113037,7 +126095,7 @@ type SnapshotsDeleteCall struct { // deletion is needed for subsequent snapshots, the data will be moved // to the next corresponding snapshot. // -// For more information, see Deleting snaphots. +// For more information, see Deleting snapshots. // For details, see https://cloud.google.com/compute/docs/reference/latest/snapshots/delete func (r *SnapshotsService) Delete(project string, snapshot string) *SnapshotsDeleteCall { c := &SnapshotsDeleteCall{s: r.s, urlParams_: make(gensupport.URLParams)} @@ -113098,9 +126156,13 @@ func (c *SnapshotsDeleteCall) doRequest(alt string) (*http.Response, error) { reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/snapshots/{snapshot}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -113147,7 +126209,7 @@ func (c *SnapshotsDeleteCall) Do(opts ...googleapi.CallOption) (*Operation, erro } return ret, nil // { - // "description": "Deletes the specified Snapshot resource. Keep in mind that deleting a single snapshot might not necessarily delete all the data on that snapshot. If any data on the snapshot that is marked for deletion is needed for subsequent snapshots, the data will be moved to the next corresponding snapshot.\n\nFor more information, see Deleting snaphots.", + // "description": "Deletes the specified Snapshot resource. Keep in mind that deleting a single snapshot might not necessarily delete all the data on that snapshot. If any data on the snapshot that is marked for deletion is needed for subsequent snapshots, the data will be moved to the next corresponding snapshot.\n\nFor more information, see Deleting snapshots.", // "httpMethod": "DELETE", // "id": "compute.snapshots.delete", // "parameterOrder": [ @@ -113170,7 +126232,7 @@ func (c *SnapshotsDeleteCall) Do(opts ...googleapi.CallOption) (*Operation, erro // "snapshot": { // "description": "Name of the Snapshot resource to delete.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -113255,9 +126317,13 @@ func (c *SnapshotsGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/snapshots/{snapshot}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -113322,7 +126388,7 @@ func (c *SnapshotsGetCall) Do(opts ...googleapi.CallOption) (*Snapshot, error) { // "snapshot": { // "description": "Name of the Snapshot resource to return.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -113407,9 +126473,13 @@ func (c *SnapshotsGetIamPolicyCall) doRequest(alt string) (*http.Response, error } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/snapshots/{resource}/getIamPolicy") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -113472,9 +126542,9 @@ func (c *SnapshotsGetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Policy, e // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z0-9](?:[-a-z0-9_]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -113621,9 +126691,13 @@ func (c *SnapshotsListCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/snapshots") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -113801,9 +126875,13 @@ func (c *SnapshotsSetIamPolicyCall) doRequest(alt string) (*http.Response, error } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/snapshots/{resource}/setIamPolicy") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -113866,9 +126944,9 @@ func (c *SnapshotsSetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Policy, e // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z0-9](?:[-a-z0-9_]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -113948,9 +127026,13 @@ func (c *SnapshotsSetLabelsCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/snapshots/{resource}/setLabels") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -114013,9 +127095,9 @@ func (c *SnapshotsSetLabelsCall) Do(opts ...googleapi.CallOption) (*Operation, e // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -114095,9 +127177,13 @@ func (c *SnapshotsTestIamPermissionsCall) doRequest(alt string) (*http.Response, } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/snapshots/{resource}/testIamPermissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -114160,9 +127246,9 @@ func (c *SnapshotsTestIamPermissionsCall) Do(opts ...googleapi.CallOption) (*Tes // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "(?:[-a-z0-9_]{0,62}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -114183,6 +127269,258 @@ func (c *SnapshotsTestIamPermissionsCall) Do(opts ...googleapi.CallOption) (*Tes } +// method id "compute.sslCertificates.aggregatedList": + +type SslCertificatesAggregatedListCall struct { + s *Service + project string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// AggregatedList: Retrieves the list of all SslCertificate resources, +// regional and global, available to the specified project. +func (r *SslCertificatesService) AggregatedList(project string) *SslCertificatesAggregatedListCall { + c := &SslCertificatesAggregatedListCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + return c +} + +// Filter sets the optional parameter "filter": A filter expression that +// filters resources listed in the response. The expression must specify +// the field name, a comparison operator, and the value that you want to +// use for filtering. The value must be a string, a number, or a +// boolean. The comparison operator must be either =, !=, >, or <. +// +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. +// +// You can also filter nested fields. For example, you could specify +// scheduling.automaticRestart = false to include instances only if they +// are not scheduled for automatic restarts. You can use filtering on +// nested fields to filter based on resource labels. +// +// To filter on multiple expressions, provide each separate expression +// within parentheses. For example, (scheduling.automaticRestart = true) +// (cpuPlatform = "Intel Skylake"). By default, each expression is an +// AND expression. However, you can include AND and OR expressions +// explicitly. For example, (cpuPlatform = "Intel Skylake") OR +// (cpuPlatform = "Intel Broadwell") AND (scheduling.automaticRestart = +// true). +func (c *SslCertificatesAggregatedListCall) Filter(filter string) *SslCertificatesAggregatedListCall { + c.urlParams_.Set("filter", filter) + return c +} + +// MaxResults sets the optional parameter "maxResults": The maximum +// number of results per page that should be returned. If the number of +// available results is larger than maxResults, Compute Engine returns a +// nextPageToken that can be used to get the next page of results in +// subsequent list requests. Acceptable values are 0 to 500, inclusive. +// (Default: 500) +func (c *SslCertificatesAggregatedListCall) MaxResults(maxResults int64) *SslCertificatesAggregatedListCall { + c.urlParams_.Set("maxResults", fmt.Sprint(maxResults)) + return c +} + +// OrderBy sets the optional parameter "orderBy": Sorts list results by +// a certain order. By default, results are returned in alphanumerical +// order based on the resource name. +// +// You can also sort results in descending order based on the creation +// timestamp using orderBy="creationTimestamp desc". This sorts results +// based on the creationTimestamp field in reverse chronological order +// (newest result first). Use this to sort resources like operations so +// that the newest operation is returned first. +// +// Currently, only sorting by name or creationTimestamp desc is +// supported. +func (c *SslCertificatesAggregatedListCall) OrderBy(orderBy string) *SslCertificatesAggregatedListCall { + c.urlParams_.Set("orderBy", orderBy) + return c +} + +// PageToken sets the optional parameter "pageToken": Specifies a page +// token to use. Set pageToken to the nextPageToken returned by a +// previous list request to get the next page of results. +func (c *SslCertificatesAggregatedListCall) PageToken(pageToken string) *SslCertificatesAggregatedListCall { + c.urlParams_.Set("pageToken", pageToken) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *SslCertificatesAggregatedListCall) Fields(s ...googleapi.Field) *SslCertificatesAggregatedListCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// IfNoneMatch sets the optional parameter which makes the operation +// fail if the object's ETag matches the given value. This is useful for +// getting updates only after the object has changed since the last +// request. Use googleapi.IsNotModified to check whether the response +// error from Do is the result of In-None-Match. +func (c *SslCertificatesAggregatedListCall) IfNoneMatch(entityTag string) *SslCertificatesAggregatedListCall { + c.ifNoneMatch_ = entityTag + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *SslCertificatesAggregatedListCall) Context(ctx context.Context) *SslCertificatesAggregatedListCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *SslCertificatesAggregatedListCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *SslCertificatesAggregatedListCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + if c.ifNoneMatch_ != "" { + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) + } + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/aggregated/sslCertificates") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.sslCertificates.aggregatedList" call. +// Exactly one of *SslCertificateAggregatedList or error will be +// non-nil. Any non-2xx status code is an error. Response headers are in +// either *SslCertificateAggregatedList.ServerResponse.Header or (if a +// response was returned at all) in error.(*googleapi.Error).Header. Use +// googleapi.IsNotModified to check whether the returned error was +// because http.StatusNotModified was returned. +func (c *SslCertificatesAggregatedListCall) Do(opts ...googleapi.CallOption) (*SslCertificateAggregatedList, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &SslCertificateAggregatedList{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Retrieves the list of all SslCertificate resources, regional and global, available to the specified project.", + // "httpMethod": "GET", + // "id": "compute.sslCertificates.aggregatedList", + // "parameterOrder": [ + // "project" + // ], + // "parameters": { + // "filter": { + // "description": "A filter expression that filters resources listed in the response. The expression must specify the field name, a comparison operator, and the value that you want to use for filtering. The value must be a string, a number, or a boolean. The comparison operator must be either =, !=, \u003e, or \u003c.\n\nFor example, if you are filtering Compute Engine instances, you can exclude instances named example-instance by specifying name != example-instance.\n\nYou can also filter nested fields. For example, you could specify scheduling.automaticRestart = false to include instances only if they are not scheduled for automatic restarts. You can use filtering on nested fields to filter based on resource labels.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart = true) (cpuPlatform = \"Intel Skylake\"). By default, each expression is an AND expression. However, you can include AND and OR expressions explicitly. For example, (cpuPlatform = \"Intel Skylake\") OR (cpuPlatform = \"Intel Broadwell\") AND (scheduling.automaticRestart = true).", + // "location": "query", + // "type": "string" + // }, + // "maxResults": { + // "default": "500", + // "description": "The maximum number of results per page that should be returned. If the number of available results is larger than maxResults, Compute Engine returns a nextPageToken that can be used to get the next page of results in subsequent list requests. Acceptable values are 0 to 500, inclusive. (Default: 500)", + // "format": "uint32", + // "location": "query", + // "minimum": "0", + // "type": "integer" + // }, + // "orderBy": { + // "description": "Sorts list results by a certain order. By default, results are returned in alphanumerical order based on the resource name.\n\nYou can also sort results in descending order based on the creation timestamp using orderBy=\"creationTimestamp desc\". This sorts results based on the creationTimestamp field in reverse chronological order (newest result first). Use this to sort resources like operations so that the newest operation is returned first.\n\nCurrently, only sorting by name or creationTimestamp desc is supported.", + // "location": "query", + // "type": "string" + // }, + // "pageToken": { + // "description": "Specifies a page token to use. Set pageToken to the nextPageToken returned by a previous list request to get the next page of results.", + // "location": "query", + // "type": "string" + // }, + // "project": { + // "description": "Name of the project scoping this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/aggregated/sslCertificates", + // "response": { + // "$ref": "SslCertificateAggregatedList" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute", + // "https://www.googleapis.com/auth/compute.readonly" + // ] + // } + +} + +// Pages invokes f for each page of results. +// A non-nil error returned from f will halt the iteration. +// The provided context supersedes any context provided to the Context method. +func (c *SslCertificatesAggregatedListCall) Pages(ctx context.Context, f func(*SslCertificateAggregatedList) error) error { + c.ctx_ = ctx + defer c.PageToken(c.urlParams_.Get("pageToken")) // reset paging to original point + for { + x, err := c.Do() + if err != nil { + return err + } + if err := f(x); err != nil { + return err + } + if x.NextPageToken == "" { + return nil + } + c.PageToken(x.NextPageToken) + } +} + // method id "compute.sslCertificates.delete": type SslCertificatesDeleteCall struct { @@ -114254,9 +127592,13 @@ func (c *SslCertificatesDeleteCall) doRequest(alt string) (*http.Response, error reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/sslCertificates/{sslCertificate}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -114410,9 +127752,13 @@ func (c *SslCertificatesGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/sslCertificates/{sslCertificate}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -114572,9 +127918,13 @@ func (c *SslCertificatesInsertCall) doRequest(alt string) (*http.Response, error } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/sslCertificates") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -114783,9 +128133,13 @@ func (c *SslCertificatesListCall) doRequest(alt string) (*http.Response, error) } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/sslCertificates") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -114963,9 +128317,13 @@ func (c *SslCertificatesTestIamPermissionsCall) doRequest(alt string) (*http.Res } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/sslCertificates/{resource}/testIamPermissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -115028,9 +128386,9 @@ func (c *SslCertificatesTestIamPermissionsCall) Do(opts ...googleapi.CallOption) // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "(?:[-a-z0-9_]{0,62}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -115124,9 +128482,13 @@ func (c *SslPoliciesDeleteCall) doRequest(alt string) (*http.Response, error) { reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/sslPolicies/{sslPolicy}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -115279,9 +128641,13 @@ func (c *SslPoliciesGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/sslPolicies/{sslPolicy}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -115440,9 +128806,13 @@ func (c *SslPoliciesInsertCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/sslPolicies") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -115651,9 +129021,13 @@ func (c *SslPoliciesListCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/sslPolicies") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -115899,9 +129273,13 @@ func (c *SslPoliciesListAvailableFeaturesCall) doRequest(alt string) (*http.Resp } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/sslPolicies/listAvailableFeatures") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -116079,9 +129457,13 @@ func (c *SslPoliciesPatchCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/sslPolicies/{sslPolicy}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PATCH", urls, body) + req, err := http.NewRequest("PATCH", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -116230,9 +129612,13 @@ func (c *SslPoliciesTestIamPermissionsCall) doRequest(alt string) (*http.Respons } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/sslPolicies/{resource}/testIamPermissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -116295,9 +129681,9 @@ func (c *SslPoliciesTestIamPermissionsCall) Do(opts ...googleapi.CallOption) (*T // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "(?:[-a-z0-9_]{0,62}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -116445,9 +129831,13 @@ func (c *SubnetworksAggregatedListCall) doRequest(alt string) (*http.Response, e } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/aggregated/subnetworks") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -116638,9 +130028,13 @@ func (c *SubnetworksDeleteCall) doRequest(alt string) (*http.Response, error) { reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/subnetworks/{subnetwork}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -116817,9 +130211,13 @@ func (c *SubnetworksExpandIpCidrRangeCall) doRequest(alt string) (*http.Response } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/subnetworks/{subnetwork}/expandIpCidrRange") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -116987,9 +130385,13 @@ func (c *SubnetworksGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/subnetworks/{subnetwork}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -117150,9 +130552,13 @@ func (c *SubnetworksGetIamPolicyCall) doRequest(alt string) (*http.Response, err } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/subnetworks/{resource}/getIamPolicy") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -117224,9 +130630,9 @@ func (c *SubnetworksGetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Policy, // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -117323,9 +130729,13 @@ func (c *SubnetworksInsertCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/subnetworks") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -117545,9 +130955,13 @@ func (c *SubnetworksListCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/subnetworks") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -117801,9 +131215,13 @@ func (c *SubnetworksListUsableCall) doRequest(alt string) (*http.Response, error } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/aggregated/subnetworks/listUsable") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -117935,11 +131353,9 @@ type SubnetworksPatchCall struct { } // Patch: Patches the specified subnetwork with the data included in the -// request. Only the following fields within the subnetwork resource can -// be specified in the request: secondary_ip_range, -// allow_subnet_cidr_routes_overlap and role. It is also mandatory to -// specify the current fingeprint of the subnetwork resource being -// patched. +// request. Only certain fields can up updated with a patch request as +// indicated in the field descriptions. You must specify the current +// fingeprint of the subnetwork resource being patched. func (r *SubnetworksService) Patch(project string, region string, subnetwork string, subnetwork2 *Subnetwork) *SubnetworksPatchCall { c := &SubnetworksPatchCall{s: r.s, urlParams_: make(gensupport.URLParams)} c.project = project @@ -117949,6 +131365,21 @@ func (r *SubnetworksService) Patch(project string, region string, subnetwork str return c } +// DrainTimeoutSeconds sets the optional parameter +// "drainTimeoutSeconds": The drain timeout specifies the upper bound in +// seconds on the amount of time allowed to drain connections from the +// current ACTIVE subnetwork to the current BACKUP subnetwork. The drain +// timeout is only applicable when the following conditions are true: - +// the subnetwork being patched has purpose = +// INTERNAL_HTTPS_LOAD_BALANCER - the subnetwork being patched has role +// = BACKUP - the patch request is setting the role to ACTIVE. Note that +// after this patch operation the roles of the ACTIVE and BACKUP +// subnetworks will be swapped. +func (c *SubnetworksPatchCall) DrainTimeoutSeconds(drainTimeoutSeconds int64) *SubnetworksPatchCall { + c.urlParams_.Set("drainTimeoutSeconds", fmt.Sprint(drainTimeoutSeconds)) + return c +} + // RequestId sets the optional parameter "requestId": An optional // request ID to identify requests. Specify a unique request ID so that // if you must retry your request, the server will know to ignore the @@ -118006,9 +131437,13 @@ func (c *SubnetworksPatchCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/subnetworks/{subnetwork}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PATCH", urls, body) + req, err := http.NewRequest("PATCH", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -118056,7 +131491,7 @@ func (c *SubnetworksPatchCall) Do(opts ...googleapi.CallOption) (*Operation, err } return ret, nil // { - // "description": "Patches the specified subnetwork with the data included in the request. Only the following fields within the subnetwork resource can be specified in the request: secondary_ip_range, allow_subnet_cidr_routes_overlap and role. It is also mandatory to specify the current fingeprint of the subnetwork resource being patched.", + // "description": "Patches the specified subnetwork with the data included in the request. Only certain fields can up updated with a patch request as indicated in the field descriptions. You must specify the current fingeprint of the subnetwork resource being patched.", // "httpMethod": "PATCH", // "id": "compute.subnetworks.patch", // "parameterOrder": [ @@ -118065,6 +131500,12 @@ func (c *SubnetworksPatchCall) Do(opts ...googleapi.CallOption) (*Operation, err // "subnetwork" // ], // "parameters": { + // "drainTimeoutSeconds": { + // "description": "The drain timeout specifies the upper bound in seconds on the amount of time allowed to drain connections from the current ACTIVE subnetwork to the current BACKUP subnetwork. The drain timeout is only applicable when the following conditions are true: - the subnetwork being patched has purpose = INTERNAL_HTTPS_LOAD_BALANCER - the subnetwork being patched has role = BACKUP - the patch request is setting the role to ACTIVE. Note that after this patch operation the roles of the ACTIVE and BACKUP subnetworks will be swapped.", + // "format": "int32", + // "location": "query", + // "type": "integer" + // }, // "project": { // "description": "Project ID for this request.", // "location": "path", @@ -118169,9 +131610,13 @@ func (c *SubnetworksSetIamPolicyCall) doRequest(alt string) (*http.Response, err } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/subnetworks/{resource}/setIamPolicy") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -118243,9 +131688,9 @@ func (c *SubnetworksSetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Policy, // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -118347,9 +131792,13 @@ func (c *SubnetworksSetPrivateIpGoogleAccessCall) doRequest(alt string) (*http.R } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/subnetworks/{subnetwork}/setPrivateIpGoogleAccess") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -118510,9 +131959,13 @@ func (c *SubnetworksTestIamPermissionsCall) doRequest(alt string) (*http.Respons } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/subnetworks/{resource}/testIamPermissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -118584,9 +132037,9 @@ func (c *SubnetworksTestIamPermissionsCall) Do(opts ...googleapi.CallOption) (*T // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -118735,9 +132188,13 @@ func (c *TargetHttpProxiesAggregatedListCall) doRequest(alt string) (*http.Respo } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/aggregated/targetHttpProxies") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -118927,9 +132384,13 @@ func (c *TargetHttpProxiesDeleteCall) doRequest(alt string) (*http.Response, err reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/targetHttpProxies/{targetHttpProxy}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -119084,9 +132545,13 @@ func (c *TargetHttpProxiesGetCall) doRequest(alt string) (*http.Response, error) } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/targetHttpProxies/{targetHttpProxy}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -119247,9 +132712,13 @@ func (c *TargetHttpProxiesInsertCall) doRequest(alt string) (*http.Response, err } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/targetHttpProxies") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -119459,9 +132928,13 @@ func (c *TargetHttpProxiesListCall) doRequest(alt string) (*http.Response, error } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/targetHttpProxies") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -119658,9 +133131,13 @@ func (c *TargetHttpProxiesSetUrlMapCall) doRequest(alt string) (*http.Response, } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/targetHttpProxies/{targetHttpProxy}/setUrlMap") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -119810,9 +133287,13 @@ func (c *TargetHttpProxiesTestIamPermissionsCall) doRequest(alt string) (*http.R } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/targetHttpProxies/{resource}/testIamPermissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -119875,9 +133356,9 @@ func (c *TargetHttpProxiesTestIamPermissionsCall) Do(opts ...googleapi.CallOptio // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "(?:[-a-z0-9_]{0,62}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -119898,6 +133379,258 @@ func (c *TargetHttpProxiesTestIamPermissionsCall) Do(opts ...googleapi.CallOptio } +// method id "compute.targetHttpsProxies.aggregatedList": + +type TargetHttpsProxiesAggregatedListCall struct { + s *Service + project string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// AggregatedList: Retrieves the list of all TargetHttpsProxy resources, +// regional and global, available to the specified project. +func (r *TargetHttpsProxiesService) AggregatedList(project string) *TargetHttpsProxiesAggregatedListCall { + c := &TargetHttpsProxiesAggregatedListCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + return c +} + +// Filter sets the optional parameter "filter": A filter expression that +// filters resources listed in the response. The expression must specify +// the field name, a comparison operator, and the value that you want to +// use for filtering. The value must be a string, a number, or a +// boolean. The comparison operator must be either =, !=, >, or <. +// +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. +// +// You can also filter nested fields. For example, you could specify +// scheduling.automaticRestart = false to include instances only if they +// are not scheduled for automatic restarts. You can use filtering on +// nested fields to filter based on resource labels. +// +// To filter on multiple expressions, provide each separate expression +// within parentheses. For example, (scheduling.automaticRestart = true) +// (cpuPlatform = "Intel Skylake"). By default, each expression is an +// AND expression. However, you can include AND and OR expressions +// explicitly. For example, (cpuPlatform = "Intel Skylake") OR +// (cpuPlatform = "Intel Broadwell") AND (scheduling.automaticRestart = +// true). +func (c *TargetHttpsProxiesAggregatedListCall) Filter(filter string) *TargetHttpsProxiesAggregatedListCall { + c.urlParams_.Set("filter", filter) + return c +} + +// MaxResults sets the optional parameter "maxResults": The maximum +// number of results per page that should be returned. If the number of +// available results is larger than maxResults, Compute Engine returns a +// nextPageToken that can be used to get the next page of results in +// subsequent list requests. Acceptable values are 0 to 500, inclusive. +// (Default: 500) +func (c *TargetHttpsProxiesAggregatedListCall) MaxResults(maxResults int64) *TargetHttpsProxiesAggregatedListCall { + c.urlParams_.Set("maxResults", fmt.Sprint(maxResults)) + return c +} + +// OrderBy sets the optional parameter "orderBy": Sorts list results by +// a certain order. By default, results are returned in alphanumerical +// order based on the resource name. +// +// You can also sort results in descending order based on the creation +// timestamp using orderBy="creationTimestamp desc". This sorts results +// based on the creationTimestamp field in reverse chronological order +// (newest result first). Use this to sort resources like operations so +// that the newest operation is returned first. +// +// Currently, only sorting by name or creationTimestamp desc is +// supported. +func (c *TargetHttpsProxiesAggregatedListCall) OrderBy(orderBy string) *TargetHttpsProxiesAggregatedListCall { + c.urlParams_.Set("orderBy", orderBy) + return c +} + +// PageToken sets the optional parameter "pageToken": Specifies a page +// token to use. Set pageToken to the nextPageToken returned by a +// previous list request to get the next page of results. +func (c *TargetHttpsProxiesAggregatedListCall) PageToken(pageToken string) *TargetHttpsProxiesAggregatedListCall { + c.urlParams_.Set("pageToken", pageToken) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *TargetHttpsProxiesAggregatedListCall) Fields(s ...googleapi.Field) *TargetHttpsProxiesAggregatedListCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// IfNoneMatch sets the optional parameter which makes the operation +// fail if the object's ETag matches the given value. This is useful for +// getting updates only after the object has changed since the last +// request. Use googleapi.IsNotModified to check whether the response +// error from Do is the result of In-None-Match. +func (c *TargetHttpsProxiesAggregatedListCall) IfNoneMatch(entityTag string) *TargetHttpsProxiesAggregatedListCall { + c.ifNoneMatch_ = entityTag + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *TargetHttpsProxiesAggregatedListCall) Context(ctx context.Context) *TargetHttpsProxiesAggregatedListCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *TargetHttpsProxiesAggregatedListCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *TargetHttpsProxiesAggregatedListCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + if c.ifNoneMatch_ != "" { + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) + } + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/aggregated/targetHttpsProxies") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.targetHttpsProxies.aggregatedList" call. +// Exactly one of *TargetHttpsProxyAggregatedList or error will be +// non-nil. Any non-2xx status code is an error. Response headers are in +// either *TargetHttpsProxyAggregatedList.ServerResponse.Header or (if a +// response was returned at all) in error.(*googleapi.Error).Header. Use +// googleapi.IsNotModified to check whether the returned error was +// because http.StatusNotModified was returned. +func (c *TargetHttpsProxiesAggregatedListCall) Do(opts ...googleapi.CallOption) (*TargetHttpsProxyAggregatedList, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &TargetHttpsProxyAggregatedList{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Retrieves the list of all TargetHttpsProxy resources, regional and global, available to the specified project.", + // "httpMethod": "GET", + // "id": "compute.targetHttpsProxies.aggregatedList", + // "parameterOrder": [ + // "project" + // ], + // "parameters": { + // "filter": { + // "description": "A filter expression that filters resources listed in the response. The expression must specify the field name, a comparison operator, and the value that you want to use for filtering. The value must be a string, a number, or a boolean. The comparison operator must be either =, !=, \u003e, or \u003c.\n\nFor example, if you are filtering Compute Engine instances, you can exclude instances named example-instance by specifying name != example-instance.\n\nYou can also filter nested fields. For example, you could specify scheduling.automaticRestart = false to include instances only if they are not scheduled for automatic restarts. You can use filtering on nested fields to filter based on resource labels.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart = true) (cpuPlatform = \"Intel Skylake\"). By default, each expression is an AND expression. However, you can include AND and OR expressions explicitly. For example, (cpuPlatform = \"Intel Skylake\") OR (cpuPlatform = \"Intel Broadwell\") AND (scheduling.automaticRestart = true).", + // "location": "query", + // "type": "string" + // }, + // "maxResults": { + // "default": "500", + // "description": "The maximum number of results per page that should be returned. If the number of available results is larger than maxResults, Compute Engine returns a nextPageToken that can be used to get the next page of results in subsequent list requests. Acceptable values are 0 to 500, inclusive. (Default: 500)", + // "format": "uint32", + // "location": "query", + // "minimum": "0", + // "type": "integer" + // }, + // "orderBy": { + // "description": "Sorts list results by a certain order. By default, results are returned in alphanumerical order based on the resource name.\n\nYou can also sort results in descending order based on the creation timestamp using orderBy=\"creationTimestamp desc\". This sorts results based on the creationTimestamp field in reverse chronological order (newest result first). Use this to sort resources like operations so that the newest operation is returned first.\n\nCurrently, only sorting by name or creationTimestamp desc is supported.", + // "location": "query", + // "type": "string" + // }, + // "pageToken": { + // "description": "Specifies a page token to use. Set pageToken to the nextPageToken returned by a previous list request to get the next page of results.", + // "location": "query", + // "type": "string" + // }, + // "project": { + // "description": "Name of the project scoping this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/aggregated/targetHttpsProxies", + // "response": { + // "$ref": "TargetHttpsProxyAggregatedList" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute", + // "https://www.googleapis.com/auth/compute.readonly" + // ] + // } + +} + +// Pages invokes f for each page of results. +// A non-nil error returned from f will halt the iteration. +// The provided context supersedes any context provided to the Context method. +func (c *TargetHttpsProxiesAggregatedListCall) Pages(ctx context.Context, f func(*TargetHttpsProxyAggregatedList) error) error { + c.ctx_ = ctx + defer c.PageToken(c.urlParams_.Get("pageToken")) // reset paging to original point + for { + x, err := c.Do() + if err != nil { + return err + } + if err := f(x); err != nil { + return err + } + if x.NextPageToken == "" { + return nil + } + c.PageToken(x.NextPageToken) + } +} + // method id "compute.targetHttpsProxies.delete": type TargetHttpsProxiesDeleteCall struct { @@ -119969,9 +133702,13 @@ func (c *TargetHttpsProxiesDeleteCall) doRequest(alt string) (*http.Response, er reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/targetHttpsProxies/{targetHttpsProxy}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -120125,9 +133862,13 @@ func (c *TargetHttpsProxiesGetCall) doRequest(alt string) (*http.Response, error } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/targetHttpsProxies/{targetHttpsProxy}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -120287,9 +134028,13 @@ func (c *TargetHttpsProxiesInsertCall) doRequest(alt string) (*http.Response, er } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/targetHttpsProxies") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -120498,9 +134243,13 @@ func (c *TargetHttpsProxiesListCall) doRequest(alt string) (*http.Response, erro } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/targetHttpsProxies") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -120696,9 +134445,13 @@ func (c *TargetHttpsProxiesSetQuicOverrideCall) doRequest(alt string) (*http.Res } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/targetHttpsProxies/{targetHttpsProxy}/setQuicOverride") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -120865,9 +134618,13 @@ func (c *TargetHttpsProxiesSetSslCertificatesCall) doRequest(alt string) (*http. } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/targetHttpsProxies/{targetHttpsProxy}/setSslCertificates") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -121039,9 +134796,13 @@ func (c *TargetHttpsProxiesSetSslPolicyCall) doRequest(alt string) (*http.Respon } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/targetHttpsProxies/{targetHttpsProxy}/setSslPolicy") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -121208,9 +134969,13 @@ func (c *TargetHttpsProxiesSetUrlMapCall) doRequest(alt string) (*http.Response, } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/targetHttpsProxies/{targetHttpsProxy}/setUrlMap") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -121360,9 +135125,13 @@ func (c *TargetHttpsProxiesTestIamPermissionsCall) doRequest(alt string) (*http. } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/targetHttpsProxies/{resource}/testIamPermissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -121425,9 +135194,9 @@ func (c *TargetHttpsProxiesTestIamPermissionsCall) Do(opts ...googleapi.CallOpti // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "(?:[-a-z0-9_]{0,62}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -121576,9 +135345,13 @@ func (c *TargetInstancesAggregatedListCall) doRequest(alt string) (*http.Respons } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/aggregated/targetInstances") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -121770,9 +135543,13 @@ func (c *TargetInstancesDeleteCall) doRequest(alt string) (*http.Response, error reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/targetInstances/{targetInstance}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -121938,9 +135715,13 @@ func (c *TargetInstancesGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/targetInstances/{targetInstance}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -122112,9 +135893,13 @@ func (c *TargetInstancesInsertCall) doRequest(alt string) (*http.Response, error } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/targetInstances") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -122335,9 +136120,13 @@ func (c *TargetInstancesListCall) doRequest(alt string) (*http.Response, error) } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/targetInstances") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -122526,9 +136315,13 @@ func (c *TargetInstancesTestIamPermissionsCall) doRequest(alt string) (*http.Res } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/targetInstances/{resource}/testIamPermissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -122593,9 +136386,9 @@ func (c *TargetInstancesTestIamPermissionsCall) Do(opts ...googleapi.CallOption) // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -122704,9 +136497,13 @@ func (c *TargetPoolsAddHealthCheckCall) doRequest(alt string) (*http.Response, e } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/targetPools/{targetPool}/addHealthCheck") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -122886,9 +136683,13 @@ func (c *TargetPoolsAddInstanceCall) doRequest(alt string) (*http.Response, erro } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/targetPools/{targetPool}/addInstance") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -123115,9 +136916,13 @@ func (c *TargetPoolsAggregatedListCall) doRequest(alt string) (*http.Response, e } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/aggregated/targetPools") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -123309,9 +137114,13 @@ func (c *TargetPoolsDeleteCall) doRequest(alt string) (*http.Response, error) { reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/targetPools/{targetPool}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -123477,9 +137286,13 @@ func (c *TargetPoolsGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/targetPools/{targetPool}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -123634,9 +137447,13 @@ func (c *TargetPoolsGetHealthCall) doRequest(alt string) (*http.Response, error) } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/targetPools/{targetPool}/getHealth") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -123811,9 +137628,13 @@ func (c *TargetPoolsInsertCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/targetPools") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -124034,9 +137855,13 @@ func (c *TargetPoolsListCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/targetPools") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -124244,9 +138069,13 @@ func (c *TargetPoolsRemoveHealthCheckCall) doRequest(alt string) (*http.Response } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/targetPools/{targetPool}/removeHealthCheck") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -124426,9 +138255,13 @@ func (c *TargetPoolsRemoveInstanceCall) doRequest(alt string) (*http.Response, e } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/targetPools/{targetPool}/removeInstance") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -124615,9 +138448,13 @@ func (c *TargetPoolsSetBackupCall) doRequest(alt string) (*http.Response, error) } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/targetPools/{targetPool}/setBackup") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -124784,9 +138621,13 @@ func (c *TargetPoolsTestIamPermissionsCall) doRequest(alt string) (*http.Respons } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/targetPools/{resource}/testIamPermissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -124858,9 +138699,9 @@ func (c *TargetPoolsTestIamPermissionsCall) Do(opts ...googleapi.CallOption) (*T // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -124952,9 +138793,13 @@ func (c *TargetSslProxiesDeleteCall) doRequest(alt string) (*http.Response, erro reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/targetSslProxies/{targetSslProxy}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -125108,9 +138953,13 @@ func (c *TargetSslProxiesGetCall) doRequest(alt string) (*http.Response, error) } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/targetSslProxies/{targetSslProxy}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -125270,9 +139119,13 @@ func (c *TargetSslProxiesInsertCall) doRequest(alt string) (*http.Response, erro } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/targetSslProxies") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -125481,9 +139334,13 @@ func (c *TargetSslProxiesListCall) doRequest(alt string) (*http.Response, error) } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/targetSslProxies") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -125679,9 +139536,13 @@ func (c *TargetSslProxiesSetBackendServiceCall) doRequest(alt string) (*http.Res } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/targetSslProxies/{targetSslProxy}/setBackendService") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -125849,9 +139710,13 @@ func (c *TargetSslProxiesSetProxyHeaderCall) doRequest(alt string) (*http.Respon } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/targetSslProxies/{targetSslProxy}/setProxyHeader") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -126019,9 +139884,13 @@ func (c *TargetSslProxiesSetSslCertificatesCall) doRequest(alt string) (*http.Re } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/targetSslProxies/{targetSslProxy}/setSslCertificates") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -126192,9 +140061,13 @@ func (c *TargetSslProxiesSetSslPolicyCall) doRequest(alt string) (*http.Response } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/targetSslProxies/{targetSslProxy}/setSslPolicy") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -126343,9 +140216,13 @@ func (c *TargetSslProxiesTestIamPermissionsCall) doRequest(alt string) (*http.Re } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/targetSslProxies/{resource}/testIamPermissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -126408,9 +140285,9 @@ func (c *TargetSslProxiesTestIamPermissionsCall) Do(opts ...googleapi.CallOption // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "(?:[-a-z0-9_]{0,62}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -126502,9 +140379,13 @@ func (c *TargetTcpProxiesDeleteCall) doRequest(alt string) (*http.Response, erro reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/targetTcpProxies/{targetTcpProxy}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -126658,9 +140539,13 @@ func (c *TargetTcpProxiesGetCall) doRequest(alt string) (*http.Response, error) } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/targetTcpProxies/{targetTcpProxy}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -126820,9 +140705,13 @@ func (c *TargetTcpProxiesInsertCall) doRequest(alt string) (*http.Response, erro } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/targetTcpProxies") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -127031,9 +140920,13 @@ func (c *TargetTcpProxiesListCall) doRequest(alt string) (*http.Response, error) } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/targetTcpProxies") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -127229,9 +141122,13 @@ func (c *TargetTcpProxiesSetBackendServiceCall) doRequest(alt string) (*http.Res } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/targetTcpProxies/{targetTcpProxy}/setBackendService") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -127399,9 +141296,13 @@ func (c *TargetTcpProxiesSetProxyHeaderCall) doRequest(alt string) (*http.Respon } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/targetTcpProxies/{targetTcpProxy}/setProxyHeader") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -127551,9 +141452,13 @@ func (c *TargetTcpProxiesTestIamPermissionsCall) doRequest(alt string) (*http.Re } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/targetTcpProxies/{resource}/testIamPermissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -127616,9 +141521,9 @@ func (c *TargetTcpProxiesTestIamPermissionsCall) Do(opts ...googleapi.CallOption // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "(?:[-a-z0-9_]{0,62}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -127766,9 +141671,13 @@ func (c *TargetVpnGatewaysAggregatedListCall) doRequest(alt string) (*http.Respo } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/aggregated/targetVpnGateways") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -127959,9 +141868,13 @@ func (c *TargetVpnGatewaysDeleteCall) doRequest(alt string) (*http.Response, err reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/targetVpnGateways/{targetVpnGateway}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -128126,9 +142039,13 @@ func (c *TargetVpnGatewaysGetCall) doRequest(alt string) (*http.Response, error) } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/targetVpnGateways/{targetVpnGateway}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -128299,9 +142216,13 @@ func (c *TargetVpnGatewaysInsertCall) doRequest(alt string) (*http.Response, err } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/targetVpnGateways") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -128521,9 +142442,13 @@ func (c *TargetVpnGatewaysListCall) doRequest(alt string) (*http.Response, error } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/targetVpnGateways") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -128731,9 +142656,13 @@ func (c *TargetVpnGatewaysSetLabelsCall) doRequest(alt string) (*http.Response, } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/targetVpnGateways/{resource}/setLabels") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -128810,9 +142739,9 @@ func (c *TargetVpnGatewaysSetLabelsCall) Do(opts ...googleapi.CallOption) (*Oper // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -128894,9 +142823,13 @@ func (c *TargetVpnGatewaysTestIamPermissionsCall) doRequest(alt string) (*http.R } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/targetVpnGateways/{resource}/testIamPermissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -128968,9 +142901,9 @@ func (c *TargetVpnGatewaysTestIamPermissionsCall) Do(opts ...googleapi.CallOptio // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -128991,6 +142924,258 @@ func (c *TargetVpnGatewaysTestIamPermissionsCall) Do(opts ...googleapi.CallOptio } +// method id "compute.urlMaps.aggregatedList": + +type UrlMapsAggregatedListCall struct { + s *Service + project string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// AggregatedList: Retrieves the list of all UrlMap resources, regional +// and global, available to the specified project. +func (r *UrlMapsService) AggregatedList(project string) *UrlMapsAggregatedListCall { + c := &UrlMapsAggregatedListCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + return c +} + +// Filter sets the optional parameter "filter": A filter expression that +// filters resources listed in the response. The expression must specify +// the field name, a comparison operator, and the value that you want to +// use for filtering. The value must be a string, a number, or a +// boolean. The comparison operator must be either =, !=, >, or <. +// +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. +// +// You can also filter nested fields. For example, you could specify +// scheduling.automaticRestart = false to include instances only if they +// are not scheduled for automatic restarts. You can use filtering on +// nested fields to filter based on resource labels. +// +// To filter on multiple expressions, provide each separate expression +// within parentheses. For example, (scheduling.automaticRestart = true) +// (cpuPlatform = "Intel Skylake"). By default, each expression is an +// AND expression. However, you can include AND and OR expressions +// explicitly. For example, (cpuPlatform = "Intel Skylake") OR +// (cpuPlatform = "Intel Broadwell") AND (scheduling.automaticRestart = +// true). +func (c *UrlMapsAggregatedListCall) Filter(filter string) *UrlMapsAggregatedListCall { + c.urlParams_.Set("filter", filter) + return c +} + +// MaxResults sets the optional parameter "maxResults": The maximum +// number of results per page that should be returned. If the number of +// available results is larger than maxResults, Compute Engine returns a +// nextPageToken that can be used to get the next page of results in +// subsequent list requests. Acceptable values are 0 to 500, inclusive. +// (Default: 500) +func (c *UrlMapsAggregatedListCall) MaxResults(maxResults int64) *UrlMapsAggregatedListCall { + c.urlParams_.Set("maxResults", fmt.Sprint(maxResults)) + return c +} + +// OrderBy sets the optional parameter "orderBy": Sorts list results by +// a certain order. By default, results are returned in alphanumerical +// order based on the resource name. +// +// You can also sort results in descending order based on the creation +// timestamp using orderBy="creationTimestamp desc". This sorts results +// based on the creationTimestamp field in reverse chronological order +// (newest result first). Use this to sort resources like operations so +// that the newest operation is returned first. +// +// Currently, only sorting by name or creationTimestamp desc is +// supported. +func (c *UrlMapsAggregatedListCall) OrderBy(orderBy string) *UrlMapsAggregatedListCall { + c.urlParams_.Set("orderBy", orderBy) + return c +} + +// PageToken sets the optional parameter "pageToken": Specifies a page +// token to use. Set pageToken to the nextPageToken returned by a +// previous list request to get the next page of results. +func (c *UrlMapsAggregatedListCall) PageToken(pageToken string) *UrlMapsAggregatedListCall { + c.urlParams_.Set("pageToken", pageToken) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *UrlMapsAggregatedListCall) Fields(s ...googleapi.Field) *UrlMapsAggregatedListCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// IfNoneMatch sets the optional parameter which makes the operation +// fail if the object's ETag matches the given value. This is useful for +// getting updates only after the object has changed since the last +// request. Use googleapi.IsNotModified to check whether the response +// error from Do is the result of In-None-Match. +func (c *UrlMapsAggregatedListCall) IfNoneMatch(entityTag string) *UrlMapsAggregatedListCall { + c.ifNoneMatch_ = entityTag + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *UrlMapsAggregatedListCall) Context(ctx context.Context) *UrlMapsAggregatedListCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *UrlMapsAggregatedListCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *UrlMapsAggregatedListCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + if c.ifNoneMatch_ != "" { + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) + } + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/aggregated/urlMaps") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.urlMaps.aggregatedList" call. +// Exactly one of *UrlMapsAggregatedList or error will be non-nil. Any +// non-2xx status code is an error. Response headers are in either +// *UrlMapsAggregatedList.ServerResponse.Header or (if a response was +// returned at all) in error.(*googleapi.Error).Header. Use +// googleapi.IsNotModified to check whether the returned error was +// because http.StatusNotModified was returned. +func (c *UrlMapsAggregatedListCall) Do(opts ...googleapi.CallOption) (*UrlMapsAggregatedList, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &UrlMapsAggregatedList{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Retrieves the list of all UrlMap resources, regional and global, available to the specified project.", + // "httpMethod": "GET", + // "id": "compute.urlMaps.aggregatedList", + // "parameterOrder": [ + // "project" + // ], + // "parameters": { + // "filter": { + // "description": "A filter expression that filters resources listed in the response. The expression must specify the field name, a comparison operator, and the value that you want to use for filtering. The value must be a string, a number, or a boolean. The comparison operator must be either =, !=, \u003e, or \u003c.\n\nFor example, if you are filtering Compute Engine instances, you can exclude instances named example-instance by specifying name != example-instance.\n\nYou can also filter nested fields. For example, you could specify scheduling.automaticRestart = false to include instances only if they are not scheduled for automatic restarts. You can use filtering on nested fields to filter based on resource labels.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart = true) (cpuPlatform = \"Intel Skylake\"). By default, each expression is an AND expression. However, you can include AND and OR expressions explicitly. For example, (cpuPlatform = \"Intel Skylake\") OR (cpuPlatform = \"Intel Broadwell\") AND (scheduling.automaticRestart = true).", + // "location": "query", + // "type": "string" + // }, + // "maxResults": { + // "default": "500", + // "description": "The maximum number of results per page that should be returned. If the number of available results is larger than maxResults, Compute Engine returns a nextPageToken that can be used to get the next page of results in subsequent list requests. Acceptable values are 0 to 500, inclusive. (Default: 500)", + // "format": "uint32", + // "location": "query", + // "minimum": "0", + // "type": "integer" + // }, + // "orderBy": { + // "description": "Sorts list results by a certain order. By default, results are returned in alphanumerical order based on the resource name.\n\nYou can also sort results in descending order based on the creation timestamp using orderBy=\"creationTimestamp desc\". This sorts results based on the creationTimestamp field in reverse chronological order (newest result first). Use this to sort resources like operations so that the newest operation is returned first.\n\nCurrently, only sorting by name or creationTimestamp desc is supported.", + // "location": "query", + // "type": "string" + // }, + // "pageToken": { + // "description": "Specifies a page token to use. Set pageToken to the nextPageToken returned by a previous list request to get the next page of results.", + // "location": "query", + // "type": "string" + // }, + // "project": { + // "description": "Name of the project scoping this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/aggregated/urlMaps", + // "response": { + // "$ref": "UrlMapsAggregatedList" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute", + // "https://www.googleapis.com/auth/compute.readonly" + // ] + // } + +} + +// Pages invokes f for each page of results. +// A non-nil error returned from f will halt the iteration. +// The provided context supersedes any context provided to the Context method. +func (c *UrlMapsAggregatedListCall) Pages(ctx context.Context, f func(*UrlMapsAggregatedList) error) error { + c.ctx_ = ctx + defer c.PageToken(c.urlParams_.Get("pageToken")) // reset paging to original point + for { + x, err := c.Do() + if err != nil { + return err + } + if err := f(x); err != nil { + return err + } + if x.NextPageToken == "" { + return nil + } + c.PageToken(x.NextPageToken) + } +} + // method id "compute.urlMaps.delete": type UrlMapsDeleteCall struct { @@ -129063,9 +143248,13 @@ func (c *UrlMapsDeleteCall) doRequest(alt string) (*http.Response, error) { reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/urlMaps/{urlMap}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -129220,9 +143409,13 @@ func (c *UrlMapsGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/urlMaps/{urlMap}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -129383,9 +143576,13 @@ func (c *UrlMapsInsertCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/urlMaps") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -129545,9 +143742,13 @@ func (c *UrlMapsInvalidateCacheCall) doRequest(alt string) (*http.Response, erro } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/urlMaps/{urlMap}/invalidateCache") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -129766,9 +143967,13 @@ func (c *UrlMapsListCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/urlMaps") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -129967,9 +144172,13 @@ func (c *UrlMapsPatchCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/urlMaps/{urlMap}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PATCH", urls, body) + req, err := http.NewRequest("PATCH", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -130119,9 +144328,13 @@ func (c *UrlMapsTestIamPermissionsCall) doRequest(alt string) (*http.Response, e } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/urlMaps/{resource}/testIamPermissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -130184,9 +144397,9 @@ func (c *UrlMapsTestIamPermissionsCall) Do(opts ...googleapi.CallOption) (*TestP // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "(?:[-a-z0-9_]{0,62}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -130287,9 +144500,13 @@ func (c *UrlMapsUpdateCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/urlMaps/{urlMap}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PUT", urls, body) + req, err := http.NewRequest("PUT", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -130441,9 +144658,13 @@ func (c *UrlMapsValidateCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/urlMaps/{urlMap}/validate") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -130655,9 +144876,13 @@ func (c *VpnGatewaysAggregatedListCall) doRequest(alt string) (*http.Response, e } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/aggregated/vpnGateways") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -130848,9 +145073,13 @@ func (c *VpnGatewaysDeleteCall) doRequest(alt string) (*http.Response, error) { reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/vpnGateways/{vpnGateway}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -131015,9 +145244,13 @@ func (c *VpnGatewaysGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/vpnGateways/{vpnGateway}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -131188,9 +145421,13 @@ func (c *VpnGatewaysInsertCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/vpnGateways") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -131410,9 +145647,13 @@ func (c *VpnGatewaysListCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/vpnGateways") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -131620,9 +145861,13 @@ func (c *VpnGatewaysSetLabelsCall) doRequest(alt string) (*http.Response, error) } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/vpnGateways/{resource}/setLabels") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -131699,9 +145944,9 @@ func (c *VpnGatewaysSetLabelsCall) Do(opts ...googleapi.CallOption) (*Operation, // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -131783,9 +146028,13 @@ func (c *VpnGatewaysTestIamPermissionsCall) doRequest(alt string) (*http.Respons } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/vpnGateways/{resource}/testIamPermissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -131857,9 +146106,9 @@ func (c *VpnGatewaysTestIamPermissionsCall) Do(opts ...googleapi.CallOption) (*T // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -132007,9 +146256,13 @@ func (c *VpnTunnelsAggregatedListCall) doRequest(alt string) (*http.Response, er } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/aggregated/vpnTunnels") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -132200,9 +146453,13 @@ func (c *VpnTunnelsDeleteCall) doRequest(alt string) (*http.Response, error) { reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/vpnTunnels/{vpnTunnel}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -132367,9 +146624,13 @@ func (c *VpnTunnelsGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/vpnTunnels/{vpnTunnel}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -132540,9 +146801,13 @@ func (c *VpnTunnelsInsertCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/vpnTunnels") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -132762,9 +147027,13 @@ func (c *VpnTunnelsListCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/vpnTunnels") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -132972,9 +147241,13 @@ func (c *VpnTunnelsSetLabelsCall) doRequest(alt string) (*http.Response, error) } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/vpnTunnels/{resource}/setLabels") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -133051,9 +147324,9 @@ func (c *VpnTunnelsSetLabelsCall) Do(opts ...googleapi.CallOption) (*Operation, // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -133135,9 +147408,13 @@ func (c *VpnTunnelsTestIamPermissionsCall) doRequest(alt string) (*http.Response } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/vpnTunnels/{resource}/testIamPermissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -133209,9 +147486,9 @@ func (c *VpnTunnelsTestIamPermissionsCall) Do(opts ...googleapi.CallOption) (*Te // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -133287,9 +147564,13 @@ func (c *ZoneOperationsDeleteCall) doRequest(alt string) (*http.Response, error) reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/operations/{operation}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -133421,9 +147702,13 @@ func (c *ZoneOperationsGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/operations/{operation}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -133646,9 +147931,13 @@ func (c *ZoneOperationsListCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/operations") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -133838,9 +148127,13 @@ func (c *ZoneOperationsWaitCall) doRequest(alt string) (*http.Response, error) { reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/operations/{operation}/wait") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -134000,9 +148293,13 @@ func (c *ZonesGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -134214,9 +148511,13 @@ func (c *ZonesListCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, diff --git a/vendor/google.golang.org/api/compute/v0.beta/BUILD b/vendor/google.golang.org/api/compute/v0.beta/BUILD index d399dc66b75..30a9e4b9802 100644 --- a/vendor/google.golang.org/api/compute/v0.beta/BUILD +++ b/vendor/google.golang.org/api/compute/v0.beta/BUILD @@ -7,8 +7,6 @@ go_library( importpath = "google.golang.org/api/compute/v0.beta", visibility = ["//visibility:public"], deps = [ - "//vendor/golang.org/x/net/context:go_default_library", - "//vendor/golang.org/x/net/context/ctxhttp:go_default_library", "//vendor/google.golang.org/api/gensupport:go_default_library", "//vendor/google.golang.org/api/googleapi:go_default_library", ], diff --git a/vendor/google.golang.org/api/compute/v0.beta/compute-api.json b/vendor/google.golang.org/api/compute/v0.beta/compute-api.json index fb646841b6a..37e0d739e4f 100644 --- a/vendor/google.golang.org/api/compute/v0.beta/compute-api.json +++ b/vendor/google.golang.org/api/compute/v0.beta/compute-api.json @@ -29,7 +29,7 @@ "description": "Creates and runs virtual machines on Google Cloud Platform.", "discoveryVersion": "v1", "documentationLink": "https://developers.google.com/compute/docs/reference/latest/", - "etag": "\"Zkyw9ACJZUvcYmlFaKGChzhmtnE/XxPbeTDXrLPRv1hWo1J5w2hfNX8\"", + "etag": "\"J3WqvAcMk4eQjJXvfSI4Yr8VouA/hpAivS3Oe8CKVoCbwnyJCYDdS-0\"", "icons": { "x16": "https://www.google.com/images/icons/product/compute_engine-16.png", "x32": "https://www.google.com/images/icons/product/compute_engine-32.png" @@ -505,9 +505,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -549,14 +549,384 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + "required": true, + "type": "string" + } + }, + "path": "{project}/regions/{region}/addresses/{resource}/testIamPermissions", + "request": { + "$ref": "TestPermissionsRequest" + }, + "response": { + "$ref": "TestPermissionsResponse" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute", + "https://www.googleapis.com/auth/compute.readonly" + ] + } + } + }, + "allocations": { + "methods": { + "aggregatedList": { + "description": "Retrieves an aggregated list of allocations.", + "httpMethod": "GET", + "id": "compute.allocations.aggregatedList", + "parameterOrder": [ + "project" + ], + "parameters": { + "filter": { + "description": "A filter expression that filters resources listed in the response. The expression must specify the field name, a comparison operator, and the value that you want to use for filtering. The value must be a string, a number, or a boolean. The comparison operator must be either =, !=, \u003e, or \u003c.\n\nFor example, if you are filtering Compute Engine instances, you can exclude instances named example-instance by specifying name != example-instance.\n\nYou can also filter nested fields. For example, you could specify scheduling.automaticRestart = false to include instances only if they are not scheduled for automatic restarts. You can use filtering on nested fields to filter based on resource labels.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart = true) (cpuPlatform = \"Intel Skylake\"). By default, each expression is an AND expression. However, you can include AND and OR expressions explicitly. For example, (cpuPlatform = \"Intel Skylake\") OR (cpuPlatform = \"Intel Broadwell\") AND (scheduling.automaticRestart = true).", + "location": "query", + "type": "string" + }, + "maxResults": { + "default": "500", + "description": "The maximum number of results per page that should be returned. If the number of available results is larger than maxResults, Compute Engine returns a nextPageToken that can be used to get the next page of results in subsequent list requests. Acceptable values are 0 to 500, inclusive. (Default: 500)", + "format": "uint32", + "location": "query", + "minimum": "0", + "type": "integer" + }, + "orderBy": { + "description": "Sorts list results by a certain order. By default, results are returned in alphanumerical order based on the resource name.\n\nYou can also sort results in descending order based on the creation timestamp using orderBy=\"creationTimestamp desc\". This sorts results based on the creationTimestamp field in reverse chronological order (newest result first). Use this to sort resources like operations so that the newest operation is returned first.\n\nCurrently, only sorting by name or creationTimestamp desc is supported.", + "location": "query", + "type": "string" + }, + "pageToken": { + "description": "Specifies a page token to use. Set pageToken to the nextPageToken returned by a previous list request to get the next page of results.", + "location": "query", + "type": "string" + }, + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + } + }, + "path": "{project}/aggregated/allocations", + "response": { + "$ref": "AllocationAggregatedList" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute", + "https://www.googleapis.com/auth/compute.readonly" + ] + }, + "delete": { + "description": "Deletes the specified allocation.", + "httpMethod": "DELETE", + "id": "compute.allocations.delete", + "parameterOrder": [ + "project", + "zone", + "allocation" + ], + "parameters": { + "allocation": { + "description": "Name of the allocation to delete.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + }, + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "requestId": { + "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", + "location": "query", + "type": "string" + }, + "zone": { + "description": "Name of the zone for this request.", "location": "path", "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", "required": true, "type": "string" } }, - "path": "{project}/regions/{region}/addresses/{resource}/testIamPermissions", + "path": "{project}/zones/{zone}/allocations/{allocation}", + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute" + ] + }, + "get": { + "description": "Retrieves all information of the specified allocation.", + "httpMethod": "GET", + "id": "compute.allocations.get", + "parameterOrder": [ + "project", + "zone", + "allocation" + ], + "parameters": { + "allocation": { + "description": "Name of the allocation to retrieve.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + }, + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "zone": { + "description": "Name of the zone for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + } + }, + "path": "{project}/zones/{zone}/allocations/{allocation}", + "response": { + "$ref": "Allocation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute", + "https://www.googleapis.com/auth/compute.readonly" + ] + }, + "getIamPolicy": { + "description": "Gets the access control policy for a resource. May be empty if no such policy or resource exists.", + "httpMethod": "GET", + "id": "compute.allocations.getIamPolicy", + "parameterOrder": [ + "project", + "zone", + "resource" + ], + "parameters": { + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "resource": { + "description": "Name or id of the resource for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + "required": true, + "type": "string" + }, + "zone": { + "description": "The name of the zone for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + } + }, + "path": "{project}/zones/{zone}/allocations/{resource}/getIamPolicy", + "response": { + "$ref": "Policy" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute", + "https://www.googleapis.com/auth/compute.readonly" + ] + }, + "insert": { + "description": "Creates a new allocation.", + "httpMethod": "POST", + "id": "compute.allocations.insert", + "parameterOrder": [ + "project", + "zone" + ], + "parameters": { + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "requestId": { + "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", + "location": "query", + "type": "string" + }, + "zone": { + "description": "Name of the zone for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + } + }, + "path": "{project}/zones/{zone}/allocations", + "request": { + "$ref": "Allocation" + }, + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute" + ] + }, + "list": { + "description": "A list all the allocations that have been configured for the specified project in specified zone.", + "httpMethod": "GET", + "id": "compute.allocations.list", + "parameterOrder": [ + "project", + "zone" + ], + "parameters": { + "filter": { + "description": "A filter expression that filters resources listed in the response. The expression must specify the field name, a comparison operator, and the value that you want to use for filtering. The value must be a string, a number, or a boolean. The comparison operator must be either =, !=, \u003e, or \u003c.\n\nFor example, if you are filtering Compute Engine instances, you can exclude instances named example-instance by specifying name != example-instance.\n\nYou can also filter nested fields. For example, you could specify scheduling.automaticRestart = false to include instances only if they are not scheduled for automatic restarts. You can use filtering on nested fields to filter based on resource labels.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart = true) (cpuPlatform = \"Intel Skylake\"). By default, each expression is an AND expression. However, you can include AND and OR expressions explicitly. For example, (cpuPlatform = \"Intel Skylake\") OR (cpuPlatform = \"Intel Broadwell\") AND (scheduling.automaticRestart = true).", + "location": "query", + "type": "string" + }, + "maxResults": { + "default": "500", + "description": "The maximum number of results per page that should be returned. If the number of available results is larger than maxResults, Compute Engine returns a nextPageToken that can be used to get the next page of results in subsequent list requests. Acceptable values are 0 to 500, inclusive. (Default: 500)", + "format": "uint32", + "location": "query", + "minimum": "0", + "type": "integer" + }, + "orderBy": { + "description": "Sorts list results by a certain order. By default, results are returned in alphanumerical order based on the resource name.\n\nYou can also sort results in descending order based on the creation timestamp using orderBy=\"creationTimestamp desc\". This sorts results based on the creationTimestamp field in reverse chronological order (newest result first). Use this to sort resources like operations so that the newest operation is returned first.\n\nCurrently, only sorting by name or creationTimestamp desc is supported.", + "location": "query", + "type": "string" + }, + "pageToken": { + "description": "Specifies a page token to use. Set pageToken to the nextPageToken returned by a previous list request to get the next page of results.", + "location": "query", + "type": "string" + }, + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "zone": { + "description": "Name of the zone for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + } + }, + "path": "{project}/zones/{zone}/allocations", + "response": { + "$ref": "AllocationList" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute", + "https://www.googleapis.com/auth/compute.readonly" + ] + }, + "setIamPolicy": { + "description": "Sets the access control policy on the specified resource. Replaces any existing policy.", + "httpMethod": "POST", + "id": "compute.allocations.setIamPolicy", + "parameterOrder": [ + "project", + "zone", + "resource" + ], + "parameters": { + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "resource": { + "description": "Name or id of the resource for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + "required": true, + "type": "string" + }, + "zone": { + "description": "The name of the zone for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + } + }, + "path": "{project}/zones/{zone}/allocations/{resource}/setIamPolicy", + "request": { + "$ref": "ZoneSetPolicyRequest" + }, + "response": { + "$ref": "Policy" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute" + ] + }, + "testIamPermissions": { + "description": "Returns permissions that a caller has on the specified resource.", + "httpMethod": "POST", + "id": "compute.allocations.testIamPermissions", + "parameterOrder": [ + "project", + "zone", + "resource" + ], + "parameters": { + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "resource": { + "description": "Name or id of the resource for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + "required": true, + "type": "string" + }, + "zone": { + "description": "The name of the zone for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + } + }, + "path": "{project}/zones/{zone}/allocations/{resource}/testIamPermissions", "request": { "$ref": "TestPermissionsRequest" }, @@ -873,9 +1243,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -952,7 +1322,7 @@ "backendBuckets": { "methods": { "addSignedUrlKey": { - "description": "Adds the given Signed URL Key to the backend bucket.", + "description": "Adds a key for validating requests with signed URLs for this backend bucket.", "httpMethod": "POST", "id": "compute.backendBuckets.addSignedUrlKey", "parameterOrder": [ @@ -1030,7 +1400,7 @@ ] }, "deleteSignedUrlKey": { - "description": "Deletes the given Signed URL Key from the backend bucket.", + "description": "Deletes a key for validating requests with signed URLs for this backend bucket.", "httpMethod": "POST", "id": "compute.backendBuckets.deleteSignedUrlKey", "parameterOrder": [ @@ -1276,7 +1646,7 @@ "backendServices": { "methods": { "addSignedUrlKey": { - "description": "Adds the given Signed URL Key to the specified backend service.", + "description": "Adds a key for validating requests with signed URLs for this backend service.", "httpMethod": "POST", "id": "compute.backendServices.addSignedUrlKey", "parameterOrder": [ @@ -1403,7 +1773,7 @@ ] }, "deleteSignedUrlKey": { - "description": "Deletes the given Signed URL Key from the specified backend service.", + "description": "Deletes a key for validating requests with signed URLs for this backend service.", "httpMethod": "POST", "id": "compute.backendServices.deleteSignedUrlKey", "parameterOrder": [ @@ -1447,7 +1817,7 @@ ] }, "get": { - "description": "Returns the specified BackendService resource. Gets a list of available backend services by making a list() request.", + "description": "Returns the specified BackendService resource. Gets a list of available backend services.", "httpMethod": "GET", "id": "compute.backendServices.get", "parameterOrder": [ @@ -1610,7 +1980,7 @@ "backendService": { "description": "Name of the BackendService resource to patch.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -1696,9 +2066,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "(?:[-a-z0-9_]{0,62}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -1913,6 +2283,55 @@ }, "disks": { "methods": { + "addResourcePolicies": { + "description": "Adds existing resource policies to a disk. You can only add one policy which will be applied to this disk for scheduling snapshot creation.", + "httpMethod": "POST", + "id": "compute.disks.addResourcePolicies", + "parameterOrder": [ + "project", + "zone", + "disk" + ], + "parameters": { + "disk": { + "description": "The disk name for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + "required": true, + "type": "string" + }, + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "requestId": { + "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", + "location": "query", + "type": "string" + }, + "zone": { + "description": "The name of the zone for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + } + }, + "path": "{project}/zones/{zone}/disks/{disk}/addResourcePolicies", + "request": { + "$ref": "DisksAddResourcePoliciesRequest" + }, + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute" + ] + }, "aggregatedList": { "description": "Retrieves an aggregated list of persistent disks.", "httpMethod": "GET", @@ -1975,7 +2394,7 @@ "disk": { "description": "Name of the persistent disk to snapshot.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -2073,7 +2492,7 @@ "disk": { "description": "Name of the persistent disk to return.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -2102,6 +2521,48 @@ "https://www.googleapis.com/auth/compute.readonly" ] }, + "getIamPolicy": { + "description": "Gets the access control policy for a resource. May be empty if no such policy or resource exists.", + "httpMethod": "GET", + "id": "compute.disks.getIamPolicy", + "parameterOrder": [ + "project", + "zone", + "resource" + ], + "parameters": { + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "resource": { + "description": "Name or id of the resource for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + "required": true, + "type": "string" + }, + "zone": { + "description": "The name of the zone for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + } + }, + "path": "{project}/zones/{zone}/disks/{resource}/getIamPolicy", + "response": { + "$ref": "Policy" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute", + "https://www.googleapis.com/auth/compute.readonly" + ] + }, "insert": { "description": "Creates a persistent disk in the specified project using the data in the request. You can create a disk with a sourceImage, a sourceSnapshot, or create an empty 500 GB data disk by omitting all properties. You can also create a disk that is larger than the default size by specifying the sizeGb property.", "httpMethod": "POST", @@ -2205,6 +2666,55 @@ "https://www.googleapis.com/auth/compute.readonly" ] }, + "removeResourcePolicies": { + "description": "Removes resource policies from a disk.", + "httpMethod": "POST", + "id": "compute.disks.removeResourcePolicies", + "parameterOrder": [ + "project", + "zone", + "disk" + ], + "parameters": { + "disk": { + "description": "The disk name for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + "required": true, + "type": "string" + }, + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "requestId": { + "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", + "location": "query", + "type": "string" + }, + "zone": { + "description": "The name of the zone for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + } + }, + "path": "{project}/zones/{zone}/disks/{disk}/removeResourcePolicies", + "request": { + "$ref": "DisksRemoveResourcePoliciesRequest" + }, + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute" + ] + }, "resize": { "description": "Resizes the specified persistent disk. You can only increase the size of the disk.", "httpMethod": "POST", @@ -2218,7 +2728,7 @@ "disk": { "description": "The name of the persistent disk.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -2254,6 +2764,50 @@ "https://www.googleapis.com/auth/compute" ] }, + "setIamPolicy": { + "description": "Sets the access control policy on the specified resource. Replaces any existing policy.", + "httpMethod": "POST", + "id": "compute.disks.setIamPolicy", + "parameterOrder": [ + "project", + "zone", + "resource" + ], + "parameters": { + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "resource": { + "description": "Name or id of the resource for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + "required": true, + "type": "string" + }, + "zone": { + "description": "The name of the zone for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + } + }, + "path": "{project}/zones/{zone}/disks/{resource}/setIamPolicy", + "request": { + "$ref": "ZoneSetPolicyRequest" + }, + "response": { + "$ref": "Policy" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute" + ] + }, "setLabels": { "description": "Sets the labels on a disk. To learn more about labels, read the Labeling Resources documentation.", "httpMethod": "POST", @@ -2277,9 +2831,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -2321,9 +2875,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -2364,7 +2918,7 @@ "firewall": { "description": "Name of the firewall rule to delete.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -2402,7 +2956,7 @@ "firewall": { "description": "Name of the firewall rule to return.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -2518,7 +3072,7 @@ "firewall": { "description": "Name of the firewall rule to patch.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -2564,9 +3118,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "(?:[-a-z0-9_]{0,62}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -2596,7 +3150,7 @@ "firewall": { "description": "Name of the firewall rule to update.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -2894,9 +3448,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -2987,9 +3541,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -3182,9 +3736,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -3218,9 +3772,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "(?:[-a-z0-9_]{0,62}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -3413,9 +3967,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -3490,9 +4044,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "(?:[-a-z0-9_]{0,62}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -3892,9 +4446,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "(?:[-a-z0-9_]{0,62}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -4169,9 +4723,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "(?:[-a-z0-9_]{0,62}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -4446,9 +5000,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "(?:[-a-z0-9_]{0,62}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -4523,7 +5077,7 @@ "image": { "description": "Name of the image resource to delete.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -4561,7 +5115,7 @@ "image": { "description": "Image name.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -4602,7 +5156,7 @@ "image": { "description": "Name of the image resource to return.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -4636,7 +5190,7 @@ "family": { "description": "Name of the image family to search for.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -4658,6 +5212,40 @@ "https://www.googleapis.com/auth/compute.readonly" ] }, + "getIamPolicy": { + "description": "Gets the access control policy for a resource. May be empty if no such policy or resource exists.", + "httpMethod": "GET", + "id": "compute.images.getIamPolicy", + "parameterOrder": [ + "project", + "resource" + ], + "parameters": { + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "resource": { + "description": "Name or id of the resource for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + "required": true, + "type": "string" + } + }, + "path": "{project}/global/images/{resource}/getIamPolicy", + "response": { + "$ref": "Policy" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute", + "https://www.googleapis.com/auth/compute.readonly" + ] + }, "insert": { "description": "Creates an image in the specified project using the data included in the request.", "httpMethod": "POST", @@ -4748,6 +5336,42 @@ "https://www.googleapis.com/auth/compute.readonly" ] }, + "setIamPolicy": { + "description": "Sets the access control policy on the specified resource. Replaces any existing policy.", + "httpMethod": "POST", + "id": "compute.images.setIamPolicy", + "parameterOrder": [ + "project", + "resource" + ], + "parameters": { + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "resource": { + "description": "Name or id of the resource for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + "required": true, + "type": "string" + } + }, + "path": "{project}/global/images/{resource}/setIamPolicy", + "request": { + "$ref": "GlobalSetPolicyRequest" + }, + "response": { + "$ref": "Policy" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute" + ] + }, "setLabels": { "description": "Sets the labels on an image. To learn more about labels, read the Labeling Resources documentation.", "httpMethod": "POST", @@ -4765,9 +5389,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -4801,9 +5425,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "(?:[-a-z0-9_]{0,62}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -4826,7 +5450,7 @@ "instanceGroupManagers": { "methods": { "abandonInstances": { - "description": "Schedules a group action to remove the specified instances from the managed instance group. Abandoning an instance does not delete the instance, but it does remove the instance from any target pools that are applied by the managed instance group. This method reduces the targetSize of the managed instance group by the number of instances that you abandon. This operation is marked as DONE when the action is scheduled even if the instances have not yet been removed from the group. You must separately verify the status of the abandoning action with the listmanagedinstances method.\n\nIf the group is part of a backend service that has enabled connection draining, it can take up to 60 seconds after the connection draining duration has elapsed before the VM instance is removed or deleted.\n\nYou can specify a maximum of 1000 instances with this method per request.", + "description": "Flags the specified instances to be removed from the managed instance group. Abandoning an instance does not delete the instance, but it does remove the instance from any target pools that are applied by the managed instance group. This method reduces the targetSize of the managed instance group by the number of instances that you abandon. This operation is marked as DONE when the action is scheduled even if the instances have not yet been removed from the group. You must separately verify the status of the abandoning action with the listmanagedinstances method.\n\nIf the group is part of a backend service that has enabled connection draining, it can take up to 60 seconds after the connection draining duration has elapsed before the VM instance is removed or deleted.\n\nYou can specify a maximum of 1000 instances with this method per request.", "httpMethod": "POST", "id": "compute.instanceGroupManagers.abandonInstances", "parameterOrder": [ @@ -4966,7 +5590,7 @@ ] }, "deleteInstances": { - "description": "Schedules a group action to delete the specified instances in the managed instance group. The instances are also removed from any target pools of which they were a member. This method reduces the targetSize of the managed instance group by the number of instances that you delete. This operation is marked as DONE when the action is scheduled even if the instances are still being deleted. You must separately verify the status of the deleting action with the listmanagedinstances method.\n\nIf the group is part of a backend service that has enabled connection draining, it can take up to 60 seconds after the connection draining duration has elapsed before the VM instance is removed or deleted.\n\nYou can specify a maximum of 1000 instances with this method per request.", + "description": "Flags the specified instances in the managed instance group for immediate deletion. The instances are also removed from any target pools of which they were a member. This method reduces the targetSize of the managed instance group by the number of instances that you delete. This operation is marked as DONE when the action is scheduled even if the instances are still being deleted. You must separately verify the status of the deleting action with the listmanagedinstances method.\n\nIf the group is part of a backend service that has enabled connection draining, it can take up to 60 seconds after the connection draining duration has elapsed before the VM instance is removed or deleted.\n\nYou can specify a maximum of 1000 instances with this method per request.", "httpMethod": "POST", "id": "compute.instanceGroupManagers.deleteInstances", "parameterOrder": [ @@ -5053,7 +5677,7 @@ ] }, "insert": { - "description": "Creates a managed instance group using the information that you specify in the request. After the group is created, it schedules an action to create instances in the group using the specified instance template. This operation is marked as DONE when the group is created even if the instances in the group have not yet been created. You must separately verify the status of the individual instances with the listmanagedinstances method.\n\nA managed instance group can have up to 1000 VM instances per group. Please contact Cloud Support if you need an increase in this limit.", + "description": "Creates a managed instance group using the information that you specify in the request. After the group is created, instances in the group are created using the specified instance template. This operation is marked as DONE when the group is created even if the instances in the group have not yet been created. You must separately verify the status of the individual instances with the listmanagedinstances method.\n\nA managed instance group can have up to 1000 VM instances per group. Please contact Cloud Support if you need an increase in this limit.", "httpMethod": "POST", "id": "compute.instanceGroupManagers.insert", "parameterOrder": [ @@ -5159,6 +5783,7 @@ ], "parameters": { "filter": { + "description": "A filter expression that filters resources listed in the response. The expression must specify the field name, a comparison operator, and the value that you want to use for filtering. The value must be a string, a number, or a boolean. The comparison operator must be either =, !=, \u003e, or \u003c.\n\nFor example, if you are filtering Compute Engine instances, you can exclude instances named example-instance by specifying name != example-instance.\n\nYou can also filter nested fields. For example, you could specify scheduling.automaticRestart = false to include instances only if they are not scheduled for automatic restarts. You can use filtering on nested fields to filter based on resource labels.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart = true) (cpuPlatform = \"Intel Skylake\"). By default, each expression is an AND expression. However, you can include AND and OR expressions explicitly. For example, (cpuPlatform = \"Intel Skylake\") OR (cpuPlatform = \"Intel Broadwell\") AND (scheduling.automaticRestart = true).", "location": "query", "type": "string" }, @@ -5170,16 +5795,19 @@ }, "maxResults": { "default": "500", + "description": "The maximum number of results per page that should be returned. If the number of available results is larger than maxResults, Compute Engine returns a nextPageToken that can be used to get the next page of results in subsequent list requests. Acceptable values are 0 to 500, inclusive. (Default: 500)", "format": "uint32", "location": "query", "minimum": "0", "type": "integer" }, "order_by": { + "description": "Sorts list results by a certain order. By default, results are returned in alphanumerical order based on the resource name.\n\nYou can also sort results in descending order based on the creation timestamp using orderBy=\"creationTimestamp desc\". This sorts results based on the creationTimestamp field in reverse chronological order (newest result first). Use this to sort resources like operations so that the newest operation is returned first.\n\nCurrently, only sorting by name or creationTimestamp desc is supported.", "location": "query", "type": "string" }, "pageToken": { + "description": "Specifies a page token to use. Set pageToken to the nextPageToken returned by a previous list request to get the next page of results.", "location": "query", "type": "string" }, @@ -5255,7 +5883,7 @@ ] }, "recreateInstances": { - "description": "Schedules a group action to recreate the specified instances in the managed instance group. The instances are deleted and recreated using the current instance template for the managed instance group. This operation is marked as DONE when the action is scheduled even if the instances have not yet been recreated. You must separately verify the status of the recreating action with the listmanagedinstances method.\n\nIf the group is part of a backend service that has enabled connection draining, it can take up to 60 seconds after the connection draining duration has elapsed before the VM instance is removed or deleted.\n\nYou can specify a maximum of 1000 instances with this method per request.", + "description": "Flags the specified instances in the managed instance group to be immediately recreated. The instances are deleted and recreated using the current instance template for the managed instance group. This operation is marked as DONE when the flag is set even if the instances have not yet been recreated. You must separately verify the status of the recreating action with the listmanagedinstances method.\n\nIf the group is part of a backend service that has enabled connection draining, it can take up to 60 seconds after the connection draining duration has elapsed before the VM instance is removed or deleted.\n\nYou can specify a maximum of 1000 instances with this method per request.", "httpMethod": "POST", "id": "compute.instanceGroupManagers.recreateInstances", "parameterOrder": [ @@ -5302,7 +5930,7 @@ ] }, "resize": { - "description": "Resizes the managed instance group. If you increase the size, the group creates new instances using the current instance template. If you decrease the size, the group deletes instances. The resize operation is marked DONE when the resize actions are scheduled even if the group has not yet added or deleted any instances. You must separately verify the status of the creating or deleting actions with the listmanagedinstances method.\n\nIf the group is part of a backend service that has enabled connection draining, it can take up to 60 seconds after the connection draining duration has elapsed before the VM instance is removed or deleted.", + "description": "Resizes the managed instance group. If you increase the size, the group creates new instances using the current instance template. If you decrease the size, the group deletes instances. The resize operation is marked DONE when the resize actions are scheduled even if the group has not yet added or deleted any instances. You must separately verify the status of the creating or deleting actions with the listmanagedinstances method.\n\nWhen resizing down, the instance group arbitrarily chooses the order in which VMs are deleted. The group takes into account some VM attributes when making the selection including:\n\n+ The status of the VM instance. + The health of the VM instance. + The instance template version the VM is based on. + For regional managed instance groups, the location of the VM instance.\n\nThis list is subject to change.\n\nIf the group is part of a backend service that has enabled connection draining, it can take up to 60 seconds after the connection draining duration has elapsed before the VM instance is removed or deleted.", "httpMethod": "POST", "id": "compute.instanceGroupManagers.resize", "parameterOrder": [ @@ -5401,7 +6029,7 @@ ] }, "setAutoHealingPolicies": { - "description": "Modifies the autohealing policies.", + "description": "Modifies the autohealing policies. [Deprecated] This method is deprecated. Please use Patch instead.", "httpMethod": "POST", "id": "compute.instanceGroupManagers.setAutoHealingPolicies", "parameterOrder": [ @@ -5559,9 +6187,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -6091,9 +6719,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -6194,6 +6822,40 @@ "https://www.googleapis.com/auth/compute.readonly" ] }, + "getIamPolicy": { + "description": "Gets the access control policy for a resource. May be empty if no such policy or resource exists.", + "httpMethod": "GET", + "id": "compute.instanceTemplates.getIamPolicy", + "parameterOrder": [ + "project", + "resource" + ], + "parameters": { + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "resource": { + "description": "Name or id of the resource for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + "required": true, + "type": "string" + } + }, + "path": "{project}/global/instanceTemplates/{resource}/getIamPolicy", + "response": { + "$ref": "Policy" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute", + "https://www.googleapis.com/auth/compute.readonly" + ] + }, "insert": { "description": "Creates an instance template in the specified project using the data that is included in the request. If you are creating a new template to update an existing instance group, your new instance template must use the same network or, if applicable, the same subnetwork as the original template.", "httpMethod": "POST", @@ -6276,6 +6938,42 @@ "https://www.googleapis.com/auth/compute.readonly" ] }, + "setIamPolicy": { + "description": "Sets the access control policy on the specified resource. Replaces any existing policy.", + "httpMethod": "POST", + "id": "compute.instanceTemplates.setIamPolicy", + "parameterOrder": [ + "project", + "resource" + ], + "parameters": { + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "resource": { + "description": "Name or id of the resource for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + "required": true, + "type": "string" + } + }, + "path": "{project}/global/instanceTemplates/{resource}/setIamPolicy", + "request": { + "$ref": "GlobalSetPolicyRequest" + }, + "response": { + "$ref": "Policy" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute" + ] + }, "testIamPermissions": { "description": "Returns permissions that a caller has on the specified resource.", "httpMethod": "POST", @@ -6293,9 +6991,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "(?:[-a-z0-9_]{0,62}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -6331,7 +7029,7 @@ "instance": { "description": "The instance name for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -6374,7 +7072,7 @@ ] }, "aggregatedList": { - "description": "Retrieves aggregated list of instances.", + "description": "Retrieves aggregated list of all of the instances in your project across all regions and zones.", "httpMethod": "GET", "id": "compute.instances.aggregatedList", "parameterOrder": [ @@ -6440,7 +7138,7 @@ "instance": { "description": "The instance name for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -6489,7 +7187,7 @@ "instance": { "description": "Name of the instance resource to delete.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -6543,7 +7241,7 @@ "instance": { "description": "The instance name for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -6594,15 +7292,15 @@ ], "parameters": { "deviceName": { - "description": "Disk device name to detach.", + "description": "The device name of the disk to detach. Make a get() request on the instance to view currently attached disks and device names.", "location": "query", "required": true, "type": "string" }, "instance": { - "description": "Instance name.", + "description": "Instance name for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -6648,7 +7346,7 @@ "instance": { "description": "Name of the instance resource to return.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -6677,8 +7375,102 @@ "https://www.googleapis.com/auth/compute.readonly" ] }, + "getGuestAttributes": { + "description": "Returns the specified guest attributes entry.", + "httpMethod": "GET", + "id": "compute.instances.getGuestAttributes", + "parameterOrder": [ + "project", + "zone", + "instance" + ], + "parameters": { + "instance": { + "description": "Name of the instance scoping this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + "required": true, + "type": "string" + }, + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "queryPath": { + "description": "Specifies the guest attributes path to be queried.", + "location": "query", + "type": "string" + }, + "variableKey": { + "description": "Specifies the key for the guest attributes entry.", + "location": "query", + "type": "string" + }, + "zone": { + "description": "The name of the zone for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + } + }, + "path": "{project}/zones/{zone}/instances/{instance}/getGuestAttributes", + "response": { + "$ref": "GuestAttributes" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute", + "https://www.googleapis.com/auth/compute.readonly" + ] + }, + "getIamPolicy": { + "description": "Gets the access control policy for a resource. May be empty if no such policy or resource exists.", + "httpMethod": "GET", + "id": "compute.instances.getIamPolicy", + "parameterOrder": [ + "project", + "zone", + "resource" + ], + "parameters": { + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "resource": { + "description": "Name or id of the resource for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + "required": true, + "type": "string" + }, + "zone": { + "description": "The name of the zone for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + } + }, + "path": "{project}/zones/{zone}/instances/{resource}/getIamPolicy", + "response": { + "$ref": "Policy" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute", + "https://www.googleapis.com/auth/compute.readonly" + ] + }, "getSerialPortOutput": { - "description": "Returns the specified instance's serial port output.", + "description": "Returns the last 1 MB of serial port output from the specified instance.", "httpMethod": "GET", "id": "compute.instances.getSerialPortOutput", "parameterOrder": [ @@ -6690,7 +7482,7 @@ "instance": { "description": "Name of the instance scoping this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -6734,6 +7526,48 @@ "https://www.googleapis.com/auth/compute.readonly" ] }, + "getShieldedVmIdentity": { + "description": "Returns the Shielded VM Identity of an instance", + "httpMethod": "GET", + "id": "compute.instances.getShieldedVmIdentity", + "parameterOrder": [ + "project", + "zone", + "instance" + ], + "parameters": { + "instance": { + "description": "Name of the instance scoping this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + "required": true, + "type": "string" + }, + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "zone": { + "description": "The name of the zone for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + } + }, + "path": "{project}/zones/{zone}/instances/{instance}/getShieldedVmIdentity", + "response": { + "$ref": "ShieldedVmIdentity" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute", + "https://www.googleapis.com/auth/compute.readonly" + ] + }, "insert": { "description": "Creates an instance resource in the specified project using the data included in the request.", "httpMethod": "POST", @@ -6756,7 +7590,7 @@ "type": "string" }, "sourceInstanceTemplate": { - "description": "Specifies instance template to create the instance.\n\nThis field is optional. It can be a full or partial URL. For example, the following are all valid URLs to an instance template: \n- https://www.googleapis.com/compute/v1/projects/project/global/global/instanceTemplates/instanceTemplate \n- projects/project/global/global/instanceTemplates/instanceTemplate \n- global/instancesTemplates/instanceTemplate", + "description": "Specifies instance template to create the instance.\n\nThis field is optional. It can be a full or partial URL. For example, the following are all valid URLs to an instance template: \n- https://www.googleapis.com/compute/v1/projects/project/global/instanceTemplates/instanceTemplate \n- projects/project/global/instanceTemplates/instanceTemplate \n- global/instanceTemplates/instanceTemplate", "location": "query", "type": "string" }, @@ -6838,7 +7672,7 @@ ] }, "listReferrers": { - "description": "Retrieves the list of referrers to instances contained within the specified zone.", + "description": "Retrieves the list of referrers to instances contained within the specified zone. For more information, read Viewing Referrers to VM Instances.", "httpMethod": "GET", "id": "compute.instances.listReferrers", "parameterOrder": [ @@ -6855,7 +7689,7 @@ "instance": { "description": "Name of the target instance scoping this request, or '-' if the request should span over all instances in the container.", "location": "path", - "pattern": "-|[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "-|[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -6915,7 +7749,7 @@ "instance": { "description": "Name of the instance scoping this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -6948,6 +7782,55 @@ "https://www.googleapis.com/auth/compute" ] }, + "resume": { + "description": "Resumes an instance that was suspended using the instances().suspend method.", + "httpMethod": "POST", + "id": "compute.instances.resume", + "parameterOrder": [ + "project", + "zone", + "instance" + ], + "parameters": { + "instance": { + "description": "Name of the instance resource to resume.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + "required": true, + "type": "string" + }, + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "requestId": { + "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", + "location": "query", + "type": "string" + }, + "zone": { + "description": "The name of the zone for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + } + }, + "path": "{project}/zones/{zone}/instances/{instance}/resume", + "request": { + "$ref": "InstancesResumeRequest" + }, + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute" + ] + }, "setDeletionProtection": { "description": "Sets deletion protection on the instance.", "httpMethod": "POST", @@ -6977,9 +7860,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -7019,16 +7902,16 @@ "type": "boolean" }, "deviceName": { - "description": "The device name of the disk to modify.", + "description": "The device name of the disk to modify. Make a get() request on the instance to view currently attached disks and device names.", "location": "query", "pattern": "\\w[\\w.-]{0,254}", "required": true, "type": "string" }, "instance": { - "description": "The instance name.", + "description": "The instance name for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -7061,6 +7944,50 @@ "https://www.googleapis.com/auth/compute" ] }, + "setIamPolicy": { + "description": "Sets the access control policy on the specified resource. Replaces any existing policy.", + "httpMethod": "POST", + "id": "compute.instances.setIamPolicy", + "parameterOrder": [ + "project", + "zone", + "resource" + ], + "parameters": { + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "resource": { + "description": "Name or id of the resource for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + "required": true, + "type": "string" + }, + "zone": { + "description": "The name of the zone for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + } + }, + "path": "{project}/zones/{zone}/instances/{resource}/setIamPolicy", + "request": { + "$ref": "ZoneSetPolicyRequest" + }, + "response": { + "$ref": "Policy" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute" + ] + }, "setLabels": { "description": "Sets labels on an instance. To learn more about labels, read the Labeling Resources documentation.", "httpMethod": "POST", @@ -7074,7 +8001,7 @@ "instance": { "description": "Name of the instance scoping this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -7123,7 +8050,7 @@ "instance": { "description": "Name of the instance scoping this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -7172,7 +8099,7 @@ "instance": { "description": "Name of the instance scoping this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -7221,7 +8148,7 @@ "instance": { "description": "Name of the instance scoping this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -7270,7 +8197,7 @@ "instance": { "description": "Name of the instance scoping this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -7317,9 +8244,9 @@ ], "parameters": { "instance": { - "description": "Instance name.", + "description": "Instance name for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -7368,7 +8295,7 @@ "instance": { "description": "Name of the instance resource to start.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -7405,7 +8332,7 @@ ] }, "setShieldedVmIntegrityPolicy": { - "description": "Sets the Shielded VM integrity policy for an instance. This method supports PATCH semantics and uses the JSON merge patch format and processing rules.", + "description": "Sets the Shielded VM integrity policy for a VM instance. You can only use this method on a running VM instance. This method supports PATCH semantics and uses the JSON merge patch format and processing rules.", "httpMethod": "PATCH", "id": "compute.instances.setShieldedVmIntegrityPolicy", "parameterOrder": [ @@ -7417,7 +8344,7 @@ "instance": { "description": "Name of the instance scoping this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -7454,7 +8381,7 @@ ] }, "setTags": { - "description": "Sets tags for the specified instance to the data included in the request.", + "description": "Sets network tags for the specified instance to the data included in the request.", "httpMethod": "POST", "id": "compute.instances.setTags", "parameterOrder": [ @@ -7466,7 +8393,7 @@ "instance": { "description": "Name of the instance scoping this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -7515,7 +8442,7 @@ "instance": { "description": "Name of the instance scoping this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -7556,7 +8483,7 @@ "instance": { "description": "Name of the instance resource to start.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -7602,7 +8529,7 @@ "instance": { "description": "Name of the instance resource to start.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -7651,7 +8578,7 @@ "instance": { "description": "Name of the instance resource to stop.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -7684,6 +8611,57 @@ "https://www.googleapis.com/auth/compute" ] }, + "suspend": { + "description": "This method suspends a running instance, saving its state to persistent storage, and allows you to resume the instance at a later time. Suspended instances incur reduced per-minute, virtual machine usage charges while they are suspended. Any resources the virtual machine is using, such as persistent disks and static IP addresses, will continue to be charged until they are deleted.", + "httpMethod": "POST", + "id": "compute.instances.suspend", + "parameterOrder": [ + "project", + "zone", + "instance" + ], + "parameters": { + "discardLocalSsd": { + "description": "If true, discard the contents of any attached localSSD partitions. Default value is false (== preserve localSSD data).", + "location": "query", + "type": "boolean" + }, + "instance": { + "description": "Name of the instance resource to suspend.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + "required": true, + "type": "string" + }, + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "requestId": { + "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", + "location": "query", + "type": "string" + }, + "zone": { + "description": "The name of the zone for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + } + }, + "path": "{project}/zones/{zone}/instances/{instance}/suspend", + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute" + ] + }, "testIamPermissions": { "description": "Returns permissions that a caller has on the specified resource.", "httpMethod": "POST", @@ -7702,9 +8680,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -7743,7 +8721,7 @@ "instance": { "description": "The instance name for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -7785,6 +8763,55 @@ "https://www.googleapis.com/auth/compute" ] }, + "updateDisplayDevice": { + "description": "Updates the Display config for a VM instance. You can only use this method on a stopped VM instance. This method supports PATCH semantics and uses the JSON merge patch format and processing rules.", + "httpMethod": "PATCH", + "id": "compute.instances.updateDisplayDevice", + "parameterOrder": [ + "project", + "zone", + "instance" + ], + "parameters": { + "instance": { + "description": "Name of the instance scoping this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + }, + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "requestId": { + "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", + "location": "query", + "type": "string" + }, + "zone": { + "description": "The name of the zone for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + } + }, + "path": "{project}/zones/{zone}/instances/{instance}/updateDisplayDevice", + "request": { + "$ref": "DisplayDevice" + }, + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute" + ] + }, "updateNetworkInterface": { "description": "Updates an instance's network interface. This method follows PATCH semantics.", "httpMethod": "PATCH", @@ -7799,7 +8826,7 @@ "instance": { "description": "The instance name for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -7842,7 +8869,7 @@ ] }, "updateShieldedVmConfig": { - "description": "Updates the Shielded VM config for an instance. This method supports PATCH semantics and uses the JSON merge patch format and processing rules.", + "description": "Updates the Shielded VM config for a VM instance. You can only use this method on a stopped VM instance. This method supports PATCH semantics and uses the JSON merge patch format and processing rules.", "httpMethod": "PATCH", "id": "compute.instances.updateShieldedVmConfig", "parameterOrder": [ @@ -7854,7 +8881,7 @@ "instance": { "description": "Name of the instance scoping this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -8208,9 +9235,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -8252,9 +9279,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -8435,6 +9462,40 @@ "https://www.googleapis.com/auth/compute.readonly" ] }, + "getDiagnostics": { + "description": "Returns the interconnectDiagnostics for the specified interconnect.", + "httpMethod": "GET", + "id": "compute.interconnects.getDiagnostics", + "parameterOrder": [ + "project", + "interconnect" + ], + "parameters": { + "interconnect": { + "description": "Name of the interconnect resource to query.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + }, + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + } + }, + "path": "{project}/global/interconnects/{interconnect}/getDiagnostics", + "response": { + "$ref": "InterconnectsGetDiagnosticsResponse" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute", + "https://www.googleapis.com/auth/compute.readonly" + ] + }, "insert": { "description": "Creates a Interconnect in the specified project using the data included in the request.", "httpMethod": "POST", @@ -8575,9 +9636,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -8611,9 +9672,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "(?:[-a-z0-9_]{0,62}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -8829,6 +9890,42 @@ "https://www.googleapis.com/auth/compute", "https://www.googleapis.com/auth/compute.readonly" ] + }, + "setIamPolicy": { + "description": "Sets the access control policy on the specified resource. Replaces any existing policy.", + "httpMethod": "POST", + "id": "compute.licenses.setIamPolicy", + "parameterOrder": [ + "project", + "resource" + ], + "parameters": { + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "resource": { + "description": "Name or id of the resource for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + "required": true, + "type": "string" + } + }, + "path": "{project}/global/licenses/{resource}/setIamPolicy", + "request": { + "$ref": "GlobalSetPolicyRequest" + }, + "response": { + "$ref": "Policy" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute" + ] } } }, @@ -9393,9 +10490,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -9436,7 +10533,7 @@ "network": { "description": "Name of the network resource to add peering to.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -9477,7 +10574,7 @@ "network": { "description": "Name of the network to delete.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -9515,7 +10612,7 @@ "network": { "description": "Name of the network to return.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -9619,6 +10716,86 @@ "https://www.googleapis.com/auth/compute.readonly" ] }, + "listPeeringRoutes": { + "description": "Lists the peering routes exchanged over peering connection.", + "httpMethod": "GET", + "id": "compute.networks.listPeeringRoutes", + "parameterOrder": [ + "project", + "network" + ], + "parameters": { + "direction": { + "description": "The direction of the exchanged routes.", + "enum": [ + "INCOMING", + "OUTGOING" + ], + "enumDescriptions": [ + "", + "" + ], + "location": "query", + "type": "string" + }, + "filter": { + "description": "A filter expression that filters resources listed in the response. The expression must specify the field name, a comparison operator, and the value that you want to use for filtering. The value must be a string, a number, or a boolean. The comparison operator must be either =, !=, \u003e, or \u003c.\n\nFor example, if you are filtering Compute Engine instances, you can exclude instances named example-instance by specifying name != example-instance.\n\nYou can also filter nested fields. For example, you could specify scheduling.automaticRestart = false to include instances only if they are not scheduled for automatic restarts. You can use filtering on nested fields to filter based on resource labels.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart = true) (cpuPlatform = \"Intel Skylake\"). By default, each expression is an AND expression. However, you can include AND and OR expressions explicitly. For example, (cpuPlatform = \"Intel Skylake\") OR (cpuPlatform = \"Intel Broadwell\") AND (scheduling.automaticRestart = true).", + "location": "query", + "type": "string" + }, + "maxResults": { + "default": "500", + "description": "The maximum number of results per page that should be returned. If the number of available results is larger than maxResults, Compute Engine returns a nextPageToken that can be used to get the next page of results in subsequent list requests. Acceptable values are 0 to 500, inclusive. (Default: 500)", + "format": "uint32", + "location": "query", + "minimum": "0", + "type": "integer" + }, + "network": { + "description": "Name of the network for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + "required": true, + "type": "string" + }, + "orderBy": { + "description": "Sorts list results by a certain order. By default, results are returned in alphanumerical order based on the resource name.\n\nYou can also sort results in descending order based on the creation timestamp using orderBy=\"creationTimestamp desc\". This sorts results based on the creationTimestamp field in reverse chronological order (newest result first). Use this to sort resources like operations so that the newest operation is returned first.\n\nCurrently, only sorting by name or creationTimestamp desc is supported.", + "location": "query", + "type": "string" + }, + "pageToken": { + "description": "Specifies a page token to use. Set pageToken to the nextPageToken returned by a previous list request to get the next page of results.", + "location": "query", + "type": "string" + }, + "peeringName": { + "description": "The response will show routes exchanged over the given peering connection.", + "location": "query", + "type": "string" + }, + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "region": { + "description": "The region of the request. The response will include all subnet routes, static routes and dynamic routes in the region.", + "location": "query", + "type": "string" + } + }, + "path": "{project}/global/networks/{network}/listPeeringRoutes", + "response": { + "$ref": "ExchangedPeeringRoutesList" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute", + "https://www.googleapis.com/auth/compute.readonly" + ] + }, "patch": { "description": "Patches the specified network with the data included in the request. Only the following fields can be modified: routingConfig.routingMode.", "httpMethod": "PATCH", @@ -9631,7 +10808,7 @@ "network": { "description": "Name of the network to update.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -9672,7 +10849,7 @@ "network": { "description": "Name of the network resource to remove peering from.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -9713,7 +10890,7 @@ "network": { "description": "Name of the network to be updated.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -9756,9 +10933,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "(?:[-a-z0-9_]{0,62}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -9775,6 +10952,47 @@ "https://www.googleapis.com/auth/compute", "https://www.googleapis.com/auth/compute.readonly" ] + }, + "updatePeering": { + "description": "Updates the specified network peering with the data included in the request Only the following fields can be modified: NetworkPeering.export_custom_routes, and NetworkPeering.import_custom_routes", + "httpMethod": "PATCH", + "id": "compute.networks.updatePeering", + "parameterOrder": [ + "project", + "network" + ], + "parameters": { + "network": { + "description": "Name of the network resource which the updated peering is belonging to.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + "required": true, + "type": "string" + }, + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "requestId": { + "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", + "location": "query", + "type": "string" + } + }, + "path": "{project}/global/networks/{network}/updatePeering", + "request": { + "$ref": "NetworksUpdatePeeringRequest" + }, + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute" + ] } } }, @@ -9791,7 +11009,7 @@ ], "parameters": { "nodeGroup": { - "description": "Name of the NodeGroup resource to delete.", + "description": "Name of the NodeGroup resource.", "location": "path", "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", "required": true, @@ -9830,7 +11048,7 @@ ] }, "aggregatedList": { - "description": "Retrieves an aggregated list of node groups.", + "description": "Retrieves an aggregated list of node groups. Note: use nodeGroups.listNodes for more details about each group.", "httpMethod": "GET", "id": "compute.nodeGroups.aggregatedList", "parameterOrder": [ @@ -9974,7 +11192,7 @@ ] }, "get": { - "description": "Returns the specified NodeGroup. Get a list of available NodeGroups by making a list() request.", + "description": "Returns the specified NodeGroup. Get a list of available NodeGroups by making a list() request. Note: the \"nodes\" field should not be used. Use nodeGroups.listNodes instead.", "httpMethod": "GET", "id": "compute.nodeGroups.get", "parameterOrder": [ @@ -10033,9 +11251,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -10107,7 +11325,7 @@ ] }, "list": { - "description": "Retrieves a list of node groups available to the specified project.", + "description": "Retrieves a list of node groups available to the specified project. Note: use nodeGroups.listNodes for more details about each group.", "httpMethod": "GET", "id": "compute.nodeGroups.list", "parameterOrder": [ @@ -10163,6 +11381,71 @@ "https://www.googleapis.com/auth/compute.readonly" ] }, + "listNodes": { + "description": "Lists nodes in the node group.", + "httpMethod": "POST", + "id": "compute.nodeGroups.listNodes", + "parameterOrder": [ + "project", + "zone", + "nodeGroup" + ], + "parameters": { + "filter": { + "description": "A filter expression that filters resources listed in the response. The expression must specify the field name, a comparison operator, and the value that you want to use for filtering. The value must be a string, a number, or a boolean. The comparison operator must be either =, !=, \u003e, or \u003c.\n\nFor example, if you are filtering Compute Engine instances, you can exclude instances named example-instance by specifying name != example-instance.\n\nYou can also filter nested fields. For example, you could specify scheduling.automaticRestart = false to include instances only if they are not scheduled for automatic restarts. You can use filtering on nested fields to filter based on resource labels.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart = true) (cpuPlatform = \"Intel Skylake\"). By default, each expression is an AND expression. However, you can include AND and OR expressions explicitly. For example, (cpuPlatform = \"Intel Skylake\") OR (cpuPlatform = \"Intel Broadwell\") AND (scheduling.automaticRestart = true).", + "location": "query", + "type": "string" + }, + "maxResults": { + "default": "500", + "description": "The maximum number of results per page that should be returned. If the number of available results is larger than maxResults, Compute Engine returns a nextPageToken that can be used to get the next page of results in subsequent list requests. Acceptable values are 0 to 500, inclusive. (Default: 500)", + "format": "uint32", + "location": "query", + "minimum": "0", + "type": "integer" + }, + "nodeGroup": { + "description": "Name of the NodeGroup resource whose nodes you want to list.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + }, + "orderBy": { + "description": "Sorts list results by a certain order. By default, results are returned in alphanumerical order based on the resource name.\n\nYou can also sort results in descending order based on the creation timestamp using orderBy=\"creationTimestamp desc\". This sorts results based on the creationTimestamp field in reverse chronological order (newest result first). Use this to sort resources like operations so that the newest operation is returned first.\n\nCurrently, only sorting by name or creationTimestamp desc is supported.", + "location": "query", + "type": "string" + }, + "pageToken": { + "description": "Specifies a page token to use. Set pageToken to the nextPageToken returned by a previous list request to get the next page of results.", + "location": "query", + "type": "string" + }, + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "zone": { + "description": "The name of the zone for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + } + }, + "path": "{project}/zones/{zone}/nodeGroups/{nodeGroup}/listNodes", + "response": { + "$ref": "NodeGroupsListNodes" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute", + "https://www.googleapis.com/auth/compute.readonly" + ] + }, "setIamPolicy": { "description": "Sets the access control policy on the specified resource. Replaces any existing policy.", "httpMethod": "POST", @@ -10181,9 +11464,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -10274,9 +11557,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -10467,9 +11750,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -10607,9 +11890,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -10651,9 +11934,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -11013,21 +12296,25 @@ ], "parameters": { "filter": { + "description": "A filter expression that filters resources listed in the response. The expression must specify the field name, a comparison operator, and the value that you want to use for filtering. The value must be a string, a number, or a boolean. The comparison operator must be either =, !=, \u003e, or \u003c.\n\nFor example, if you are filtering Compute Engine instances, you can exclude instances named example-instance by specifying name != example-instance.\n\nYou can also filter nested fields. For example, you could specify scheduling.automaticRestart = false to include instances only if they are not scheduled for automatic restarts. You can use filtering on nested fields to filter based on resource labels.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart = true) (cpuPlatform = \"Intel Skylake\"). By default, each expression is an AND expression. However, you can include AND and OR expressions explicitly. For example, (cpuPlatform = \"Intel Skylake\") OR (cpuPlatform = \"Intel Broadwell\") AND (scheduling.automaticRestart = true).", "location": "query", "type": "string" }, "maxResults": { "default": "500", + "description": "The maximum number of results per page that should be returned. If the number of available results is larger than maxResults, Compute Engine returns a nextPageToken that can be used to get the next page of results in subsequent list requests. Acceptable values are 0 to 500, inclusive. (Default: 500)", "format": "uint32", "location": "query", "minimum": "0", "type": "integer" }, "order_by": { + "description": "Sorts list results by a certain order. By default, results are returned in alphanumerical order based on the resource name.\n\nYou can also sort results in descending order based on the creation timestamp using orderBy=\"creationTimestamp desc\". This sorts results based on the creationTimestamp field in reverse chronological order (newest result first). Use this to sort resources like operations so that the newest operation is returned first.\n\nCurrently, only sorting by name or creationTimestamp desc is supported.", "location": "query", "type": "string" }, "pageToken": { + "description": "Specifies a page token to use. Set pageToken to the nextPageToken returned by a previous list request to get the next page of results.", "location": "query", "type": "string" }, @@ -11057,21 +12344,25 @@ ], "parameters": { "filter": { + "description": "A filter expression that filters resources listed in the response. The expression must specify the field name, a comparison operator, and the value that you want to use for filtering. The value must be a string, a number, or a boolean. The comparison operator must be either =, !=, \u003e, or \u003c.\n\nFor example, if you are filtering Compute Engine instances, you can exclude instances named example-instance by specifying name != example-instance.\n\nYou can also filter nested fields. For example, you could specify scheduling.automaticRestart = false to include instances only if they are not scheduled for automatic restarts. You can use filtering on nested fields to filter based on resource labels.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart = true) (cpuPlatform = \"Intel Skylake\"). By default, each expression is an AND expression. However, you can include AND and OR expressions explicitly. For example, (cpuPlatform = \"Intel Skylake\") OR (cpuPlatform = \"Intel Broadwell\") AND (scheduling.automaticRestart = true).", "location": "query", "type": "string" }, "maxResults": { "default": "500", + "description": "The maximum number of results per page that should be returned. If the number of available results is larger than maxResults, Compute Engine returns a nextPageToken that can be used to get the next page of results in subsequent list requests. Acceptable values are 0 to 500, inclusive. (Default: 500)", "format": "uint32", "location": "query", "minimum": "0", "type": "integer" }, "order_by": { + "description": "Sorts list results by a certain order. By default, results are returned in alphanumerical order based on the resource name.\n\nYou can also sort results in descending order based on the creation timestamp using orderBy=\"creationTimestamp desc\". This sorts results based on the creationTimestamp field in reverse chronological order (newest result first). Use this to sort resources like operations so that the newest operation is returned first.\n\nCurrently, only sorting by name or creationTimestamp desc is supported.", "location": "query", "type": "string" }, "pageToken": { + "description": "Specifies a page token to use. Set pageToken to the nextPageToken returned by a previous list request to get the next page of results.", "location": "query", "type": "string" }, @@ -11525,9 +12816,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -11839,7 +13130,7 @@ "backendService": { "description": "Name of the BackendService resource to patch.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -11900,9 +13191,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -12269,6 +13560,55 @@ }, "regionDisks": { "methods": { + "addResourcePolicies": { + "description": "Adds existing resource policies to a regional disk. You can only add one policy which will be applied to this disk for scheduling snapshot creation.", + "httpMethod": "POST", + "id": "compute.regionDisks.addResourcePolicies", + "parameterOrder": [ + "project", + "region", + "disk" + ], + "parameters": { + "disk": { + "description": "The disk name for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + "required": true, + "type": "string" + }, + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "region": { + "description": "The name of the region for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + }, + "requestId": { + "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", + "location": "query", + "type": "string" + } + }, + "path": "{project}/regions/{region}/disks/{disk}/addResourcePolicies", + "request": { + "$ref": "RegionDisksAddResourcePoliciesRequest" + }, + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute" + ] + }, "createSnapshot": { "description": "Creates a snapshot of this regional disk.", "httpMethod": "POST", @@ -12282,7 +13622,7 @@ "disk": { "description": "Name of the regional persistent disk to snapshot.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -12376,7 +13716,7 @@ "disk": { "description": "Name of the regional persistent disk to return.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -12508,6 +13848,55 @@ "https://www.googleapis.com/auth/compute.readonly" ] }, + "removeResourcePolicies": { + "description": "Removes resource policies from a regional disk.", + "httpMethod": "POST", + "id": "compute.regionDisks.removeResourcePolicies", + "parameterOrder": [ + "project", + "region", + "disk" + ], + "parameters": { + "disk": { + "description": "The disk name for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + "required": true, + "type": "string" + }, + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "region": { + "description": "The name of the region for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + }, + "requestId": { + "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", + "location": "query", + "type": "string" + } + }, + "path": "{project}/regions/{region}/disks/{disk}/removeResourcePolicies", + "request": { + "$ref": "RegionDisksRemoveResourcePoliciesRequest" + }, + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute" + ] + }, "resize": { "description": "Resizes the specified regional persistent disk.", "httpMethod": "POST", @@ -12521,7 +13910,7 @@ "disk": { "description": "Name of the regional persistent disk.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -12587,9 +13976,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -12631,9 +14020,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -12656,7 +14045,7 @@ "regionInstanceGroupManagers": { "methods": { "abandonInstances": { - "description": "Schedules a group action to remove the specified instances from the managed instance group. Abandoning an instance does not delete the instance, but it does remove the instance from any target pools that are applied by the managed instance group. This method reduces the targetSize of the managed instance group by the number of instances that you abandon. This operation is marked as DONE when the action is scheduled even if the instances have not yet been removed from the group. You must separately verify the status of the abandoning action with the listmanagedinstances method.\n\nIf the group is part of a backend service that has enabled connection draining, it can take up to 60 seconds after the connection draining duration has elapsed before the VM instance is removed or deleted.\n\nYou can specify a maximum of 1000 instances with this method per request.", + "description": "Flags the specified instances to be immediately removed from the managed instance group. Abandoning an instance does not delete the instance, but it does remove the instance from any target pools that are applied by the managed instance group. This method reduces the targetSize of the managed instance group by the number of instances that you abandon. This operation is marked as DONE when the action is scheduled even if the instances have not yet been removed from the group. You must separately verify the status of the abandoning action with the listmanagedinstances method.\n\nIf the group is part of a backend service that has enabled connection draining, it can take up to 60 seconds after the connection draining duration has elapsed before the VM instance is removed or deleted.\n\nYou can specify a maximum of 1000 instances with this method per request.", "httpMethod": "POST", "id": "compute.regionInstanceGroupManagers.abandonInstances", "parameterOrder": [ @@ -12747,7 +14136,7 @@ ] }, "deleteInstances": { - "description": "Schedules a group action to delete the specified instances in the managed instance group. The instances are also removed from any target pools of which they were a member. This method reduces the targetSize of the managed instance group by the number of instances that you delete. This operation is marked as DONE when the action is scheduled even if the instances are still being deleted. You must separately verify the status of the deleting action with the listmanagedinstances method.\n\nIf the group is part of a backend service that has enabled connection draining, it can take up to 60 seconds after the connection draining duration has elapsed before the VM instance is removed or deleted.\n\nYou can specify a maximum of 1000 instances with this method per request.", + "description": "Flags the specified instances in the managed instance group to be immediately deleted. The instances are also removed from any target pools of which they were a member. This method reduces the targetSize of the managed instance group by the number of instances that you delete. The deleteInstances operation is marked DONE if the deleteInstances request is successful. The underlying actions take additional time. You must separately verify the status of the deleting action with the listmanagedinstances method.\n\nIf the group is part of a backend service that has enabled connection draining, it can take up to 60 seconds after the connection draining duration has elapsed before the VM instance is removed or deleted.\n\nYou can specify a maximum of 1000 instances with this method per request.", "httpMethod": "POST", "id": "compute.regionInstanceGroupManagers.deleteInstances", "parameterOrder": [ @@ -12834,7 +14223,7 @@ ] }, "insert": { - "description": "Creates a managed instance group using the information that you specify in the request. After the group is created, it schedules an action to create instances in the group using the specified instance template. This operation is marked as DONE when the group is created even if the instances in the group have not yet been created. You must separately verify the status of the individual instances with the listmanagedinstances method.\n\nA regional managed instance group can contain up to 2000 instances.", + "description": "Creates a managed instance group using the information that you specify in the request. After the group is created, instances in the group are created using the specified instance template. This operation is marked as DONE when the group is created even if the instances in the group have not yet been created. You must separately verify the status of the individual instances with the listmanagedinstances method.\n\nA regional managed instance group can contain up to 2000 instances.", "httpMethod": "POST", "id": "compute.regionInstanceGroupManagers.insert", "parameterOrder": [ @@ -12940,6 +14329,7 @@ ], "parameters": { "filter": { + "description": "A filter expression that filters resources listed in the response. The expression must specify the field name, a comparison operator, and the value that you want to use for filtering. The value must be a string, a number, or a boolean. The comparison operator must be either =, !=, \u003e, or \u003c.\n\nFor example, if you are filtering Compute Engine instances, you can exclude instances named example-instance by specifying name != example-instance.\n\nYou can also filter nested fields. For example, you could specify scheduling.automaticRestart = false to include instances only if they are not scheduled for automatic restarts. You can use filtering on nested fields to filter based on resource labels.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart = true) (cpuPlatform = \"Intel Skylake\"). By default, each expression is an AND expression. However, you can include AND and OR expressions explicitly. For example, (cpuPlatform = \"Intel Skylake\") OR (cpuPlatform = \"Intel Broadwell\") AND (scheduling.automaticRestart = true).", "location": "query", "type": "string" }, @@ -12951,16 +14341,19 @@ }, "maxResults": { "default": "500", + "description": "The maximum number of results per page that should be returned. If the number of available results is larger than maxResults, Compute Engine returns a nextPageToken that can be used to get the next page of results in subsequent list requests. Acceptable values are 0 to 500, inclusive. (Default: 500)", "format": "uint32", "location": "query", "minimum": "0", "type": "integer" }, "order_by": { + "description": "Sorts list results by a certain order. By default, results are returned in alphanumerical order based on the resource name.\n\nYou can also sort results in descending order based on the creation timestamp using orderBy=\"creationTimestamp desc\". This sorts results based on the creationTimestamp field in reverse chronological order (newest result first). Use this to sort resources like operations so that the newest operation is returned first.\n\nCurrently, only sorting by name or creationTimestamp desc is supported.", "location": "query", "type": "string" }, "pageToken": { + "description": "Specifies a page token to use. Set pageToken to the nextPageToken returned by a previous list request to get the next page of results.", "location": "query", "type": "string" }, @@ -13036,7 +14429,7 @@ ] }, "recreateInstances": { - "description": "Schedules a group action to recreate the specified instances in the managed instance group. The instances are deleted and recreated using the current instance template for the managed instance group. This operation is marked as DONE when the action is scheduled even if the instances have not yet been recreated. You must separately verify the status of the recreating action with the listmanagedinstances method.\n\nIf the group is part of a backend service that has enabled connection draining, it can take up to 60 seconds after the connection draining duration has elapsed before the VM instance is removed or deleted.\n\nYou can specify a maximum of 1000 instances with this method per request.", + "description": "Flags the specified instances in the managed instance group to be immediately recreated. The instances are deleted and recreated using the current instance template for the managed instance group. This operation is marked as DONE when the flag is set even if the instances have not yet been recreated. You must separately verify the status of the recreating action with the listmanagedinstances method.\n\nIf the group is part of a backend service that has enabled connection draining, it can take up to 60 seconds after the connection draining duration has elapsed before the VM instance is removed or deleted.\n\nYou can specify a maximum of 1000 instances with this method per request.", "httpMethod": "POST", "id": "compute.regionInstanceGroupManagers.recreateInstances", "parameterOrder": [ @@ -13083,7 +14476,7 @@ ] }, "resize": { - "description": "Changes the intended size for the managed instance group. If you increase the size, the group schedules actions to create new instances using the current instance template. If you decrease the size, the group schedules delete actions on one or more instances. The resize operation is marked DONE when the resize actions are scheduled even if the group has not yet added or deleted any instances. You must separately verify the status of the creating or deleting actions with the listmanagedinstances method.\n\nIf the group is part of a backend service that has enabled connection draining, it can take up to 60 seconds after the connection draining duration has elapsed before the VM instance is removed or deleted.", + "description": "Changes the intended size of the managed instance group. If you increase the size, the group creates new instances using the current instance template. If you decrease the size, the group deletes one or more instances.\n\nThe resize operation is marked DONE if the resize request is successful. The underlying actions take additional time. You must separately verify the status of the creating or deleting actions with the listmanagedinstances method.\n\nIf the group is part of a backend service that has enabled connection draining, it can take up to 60 seconds after the connection draining duration has elapsed before the VM instance is removed or deleted.", "httpMethod": "POST", "id": "compute.regionInstanceGroupManagers.resize", "parameterOrder": [ @@ -13136,7 +14529,7 @@ ] }, "setAutoHealingPolicies": { - "description": "Modifies the autohealing policy for the instances in this managed instance group.", + "description": "Modifies the autohealing policy for the instances in this managed instance group. [Deprecated] This method is deprecated. Please use Patch instead.", "httpMethod": "POST", "id": "compute.regionInstanceGroupManagers.setAutoHealingPolicies", "parameterOrder": [ @@ -13301,9 +14694,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -13606,9 +14999,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -13856,6 +15249,290 @@ } } }, + "resourcePolicies": { + "methods": { + "aggregatedList": { + "description": "Retrieves an aggregated list of resource policies.", + "httpMethod": "GET", + "id": "compute.resourcePolicies.aggregatedList", + "parameterOrder": [ + "project" + ], + "parameters": { + "filter": { + "description": "A filter expression that filters resources listed in the response. The expression must specify the field name, a comparison operator, and the value that you want to use for filtering. The value must be a string, a number, or a boolean. The comparison operator must be either =, !=, \u003e, or \u003c.\n\nFor example, if you are filtering Compute Engine instances, you can exclude instances named example-instance by specifying name != example-instance.\n\nYou can also filter nested fields. For example, you could specify scheduling.automaticRestart = false to include instances only if they are not scheduled for automatic restarts. You can use filtering on nested fields to filter based on resource labels.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart = true) (cpuPlatform = \"Intel Skylake\"). By default, each expression is an AND expression. However, you can include AND and OR expressions explicitly. For example, (cpuPlatform = \"Intel Skylake\") OR (cpuPlatform = \"Intel Broadwell\") AND (scheduling.automaticRestart = true).", + "location": "query", + "type": "string" + }, + "maxResults": { + "default": "500", + "description": "The maximum number of results per page that should be returned. If the number of available results is larger than maxResults, Compute Engine returns a nextPageToken that can be used to get the next page of results in subsequent list requests. Acceptable values are 0 to 500, inclusive. (Default: 500)", + "format": "uint32", + "location": "query", + "minimum": "0", + "type": "integer" + }, + "orderBy": { + "description": "Sorts list results by a certain order. By default, results are returned in alphanumerical order based on the resource name.\n\nYou can also sort results in descending order based on the creation timestamp using orderBy=\"creationTimestamp desc\". This sorts results based on the creationTimestamp field in reverse chronological order (newest result first). Use this to sort resources like operations so that the newest operation is returned first.\n\nCurrently, only sorting by name or creationTimestamp desc is supported.", + "location": "query", + "type": "string" + }, + "pageToken": { + "description": "Specifies a page token to use. Set pageToken to the nextPageToken returned by a previous list request to get the next page of results.", + "location": "query", + "type": "string" + }, + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + } + }, + "path": "{project}/aggregated/resourcePolicies", + "response": { + "$ref": "ResourcePolicyAggregatedList" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute", + "https://www.googleapis.com/auth/compute.readonly" + ] + }, + "delete": { + "description": "Deletes the specified resource policy.", + "httpMethod": "DELETE", + "id": "compute.resourcePolicies.delete", + "parameterOrder": [ + "project", + "region", + "resourcePolicy" + ], + "parameters": { + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "region": { + "description": "Name of the region for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + }, + "requestId": { + "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", + "location": "query", + "type": "string" + }, + "resourcePolicy": { + "description": "Name of the resource policy to delete.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + } + }, + "path": "{project}/regions/{region}/resourcePolicies/{resourcePolicy}", + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute" + ] + }, + "get": { + "description": "Retrieves all information of the specified resource policy.", + "httpMethod": "GET", + "id": "compute.resourcePolicies.get", + "parameterOrder": [ + "project", + "region", + "resourcePolicy" + ], + "parameters": { + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "region": { + "description": "Name of the region for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + }, + "resourcePolicy": { + "description": "Name of the resource policy to retrieve.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + } + }, + "path": "{project}/regions/{region}/resourcePolicies/{resourcePolicy}", + "response": { + "$ref": "ResourcePolicy" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute", + "https://www.googleapis.com/auth/compute.readonly" + ] + }, + "insert": { + "description": "Creates a new resource policy.", + "httpMethod": "POST", + "id": "compute.resourcePolicies.insert", + "parameterOrder": [ + "project", + "region" + ], + "parameters": { + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "region": { + "description": "Name of the region for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + }, + "requestId": { + "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", + "location": "query", + "type": "string" + } + }, + "path": "{project}/regions/{region}/resourcePolicies", + "request": { + "$ref": "ResourcePolicy" + }, + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute" + ] + }, + "list": { + "description": "A list all the resource policies that have been configured for the specified project in specified region.", + "httpMethod": "GET", + "id": "compute.resourcePolicies.list", + "parameterOrder": [ + "project", + "region" + ], + "parameters": { + "filter": { + "description": "A filter expression that filters resources listed in the response. The expression must specify the field name, a comparison operator, and the value that you want to use for filtering. The value must be a string, a number, or a boolean. The comparison operator must be either =, !=, \u003e, or \u003c.\n\nFor example, if you are filtering Compute Engine instances, you can exclude instances named example-instance by specifying name != example-instance.\n\nYou can also filter nested fields. For example, you could specify scheduling.automaticRestart = false to include instances only if they are not scheduled for automatic restarts. You can use filtering on nested fields to filter based on resource labels.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart = true) (cpuPlatform = \"Intel Skylake\"). By default, each expression is an AND expression. However, you can include AND and OR expressions explicitly. For example, (cpuPlatform = \"Intel Skylake\") OR (cpuPlatform = \"Intel Broadwell\") AND (scheduling.automaticRestart = true).", + "location": "query", + "type": "string" + }, + "maxResults": { + "default": "500", + "description": "The maximum number of results per page that should be returned. If the number of available results is larger than maxResults, Compute Engine returns a nextPageToken that can be used to get the next page of results in subsequent list requests. Acceptable values are 0 to 500, inclusive. (Default: 500)", + "format": "uint32", + "location": "query", + "minimum": "0", + "type": "integer" + }, + "orderBy": { + "description": "Sorts list results by a certain order. By default, results are returned in alphanumerical order based on the resource name.\n\nYou can also sort results in descending order based on the creation timestamp using orderBy=\"creationTimestamp desc\". This sorts results based on the creationTimestamp field in reverse chronological order (newest result first). Use this to sort resources like operations so that the newest operation is returned first.\n\nCurrently, only sorting by name or creationTimestamp desc is supported.", + "location": "query", + "type": "string" + }, + "pageToken": { + "description": "Specifies a page token to use. Set pageToken to the nextPageToken returned by a previous list request to get the next page of results.", + "location": "query", + "type": "string" + }, + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "region": { + "description": "Name of the region for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + } + }, + "path": "{project}/regions/{region}/resourcePolicies", + "response": { + "$ref": "ResourcePolicyList" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute", + "https://www.googleapis.com/auth/compute.readonly" + ] + }, + "testIamPermissions": { + "description": "Returns permissions that a caller has on the specified resource.", + "httpMethod": "POST", + "id": "compute.resourcePolicies.testIamPermissions", + "parameterOrder": [ + "project", + "region", + "resource" + ], + "parameters": { + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "region": { + "description": "The name of the region for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + }, + "resource": { + "description": "Name or id of the resource for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + "required": true, + "type": "string" + } + }, + "path": "{project}/regions/{region}/resourcePolicies/{resource}/testIamPermissions", + "request": { + "$ref": "TestPermissionsRequest" + }, + "response": { + "$ref": "TestPermissionsResponse" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute", + "https://www.googleapis.com/auth/compute.readonly" + ] + } + } + }, "routers": { "methods": { "aggregatedList": { @@ -13995,6 +15672,71 @@ "https://www.googleapis.com/auth/compute.readonly" ] }, + "getNatMappingInfo": { + "description": "Retrieves runtime Nat mapping information of VM endpoints.", + "httpMethod": "GET", + "id": "compute.routers.getNatMappingInfo", + "parameterOrder": [ + "project", + "region", + "router" + ], + "parameters": { + "filter": { + "description": "A filter expression that filters resources listed in the response. The expression must specify the field name, a comparison operator, and the value that you want to use for filtering. The value must be a string, a number, or a boolean. The comparison operator must be either =, !=, \u003e, or \u003c.\n\nFor example, if you are filtering Compute Engine instances, you can exclude instances named example-instance by specifying name != example-instance.\n\nYou can also filter nested fields. For example, you could specify scheduling.automaticRestart = false to include instances only if they are not scheduled for automatic restarts. You can use filtering on nested fields to filter based on resource labels.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart = true) (cpuPlatform = \"Intel Skylake\"). By default, each expression is an AND expression. However, you can include AND and OR expressions explicitly. For example, (cpuPlatform = \"Intel Skylake\") OR (cpuPlatform = \"Intel Broadwell\") AND (scheduling.automaticRestart = true).", + "location": "query", + "type": "string" + }, + "maxResults": { + "default": "500", + "description": "The maximum number of results per page that should be returned. If the number of available results is larger than maxResults, Compute Engine returns a nextPageToken that can be used to get the next page of results in subsequent list requests. Acceptable values are 0 to 500, inclusive. (Default: 500)", + "format": "uint32", + "location": "query", + "minimum": "0", + "type": "integer" + }, + "orderBy": { + "description": "Sorts list results by a certain order. By default, results are returned in alphanumerical order based on the resource name.\n\nYou can also sort results in descending order based on the creation timestamp using orderBy=\"creationTimestamp desc\". This sorts results based on the creationTimestamp field in reverse chronological order (newest result first). Use this to sort resources like operations so that the newest operation is returned first.\n\nCurrently, only sorting by name or creationTimestamp desc is supported.", + "location": "query", + "type": "string" + }, + "pageToken": { + "description": "Specifies a page token to use. Set pageToken to the nextPageToken returned by a previous list request to get the next page of results.", + "location": "query", + "type": "string" + }, + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "region": { + "description": "Name of the region for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + }, + "router": { + "description": "Name of the Router resource to query for Nat Mapping information of VM endpoints.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + } + }, + "path": "{project}/regions/{region}/routers/{router}/getNatMappingInfo", + "response": { + "$ref": "VmEndpointNatMappingsList" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute", + "https://www.googleapis.com/auth/compute.readonly" + ] + }, "getRouterStatus": { "description": "Retrieves runtime information of the specified router.", "httpMethod": "GET", @@ -14254,9 +15996,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -14351,7 +16093,7 @@ "route": { "description": "Name of the Route resource to delete.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -14384,7 +16126,7 @@ "route": { "description": "Name of the Route resource to return.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -14498,9 +16240,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "(?:[-a-z0-9_]{0,62}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -14544,6 +16286,11 @@ "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", "required": true, "type": "string" + }, + "validateOnly": { + "description": "If true, the request will not be committed.", + "location": "query", + "type": "boolean" } }, "path": "{project}/global/securityPolicies/{securityPolicy}/addRule", @@ -14689,6 +16436,11 @@ "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", "location": "query", "type": "string" + }, + "validateOnly": { + "description": "If true, the request will not be committed.", + "location": "query", + "type": "boolean" } }, "path": "{project}/global/securityPolicies", @@ -14869,6 +16621,11 @@ "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", "required": true, "type": "string" + }, + "validateOnly": { + "description": "If true, the request will not be committed.", + "location": "query", + "type": "boolean" } }, "path": "{project}/global/securityPolicies/{securityPolicy}/patchRule", @@ -14922,6 +16679,42 @@ "https://www.googleapis.com/auth/compute" ] }, + "setLabels": { + "description": "Sets the labels on a security policy. To learn more about labels, read the Labeling Resources documentation.", + "httpMethod": "POST", + "id": "compute.securityPolicies.setLabels", + "parameterOrder": [ + "project", + "resource" + ], + "parameters": { + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "resource": { + "description": "Name or id of the resource for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + "required": true, + "type": "string" + } + }, + "path": "{project}/global/securityPolicies/{resource}/setLabels", + "request": { + "$ref": "GlobalSetLabelsRequest" + }, + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute" + ] + }, "testIamPermissions": { "description": "Returns permissions that a caller has on the specified resource.", "httpMethod": "POST", @@ -14939,9 +16732,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "(?:[-a-z0-9_]{0,62}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -14964,7 +16757,7 @@ "snapshots": { "methods": { "delete": { - "description": "Deletes the specified Snapshot resource. Keep in mind that deleting a single snapshot might not necessarily delete all the data on that snapshot. If any data on the snapshot that is marked for deletion is needed for subsequent snapshots, the data will be moved to the next corresponding snapshot.\n\nFor more information, see Deleting snaphots.", + "description": "Deletes the specified Snapshot resource. Keep in mind that deleting a single snapshot might not necessarily delete all the data on that snapshot. If any data on the snapshot that is marked for deletion is needed for subsequent snapshots, the data will be moved to the next corresponding snapshot.\n\nFor more information, see Deleting snapshots.", "httpMethod": "DELETE", "id": "compute.snapshots.delete", "parameterOrder": [ @@ -14987,7 +16780,7 @@ "snapshot": { "description": "Name of the Snapshot resource to delete.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -15020,7 +16813,7 @@ "snapshot": { "description": "Name of the Snapshot resource to return.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -15035,6 +16828,40 @@ "https://www.googleapis.com/auth/compute.readonly" ] }, + "getIamPolicy": { + "description": "Gets the access control policy for a resource. May be empty if no such policy or resource exists.", + "httpMethod": "GET", + "id": "compute.snapshots.getIamPolicy", + "parameterOrder": [ + "project", + "resource" + ], + "parameters": { + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "resource": { + "description": "Name or id of the resource for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + "required": true, + "type": "string" + } + }, + "path": "{project}/global/snapshots/{resource}/getIamPolicy", + "response": { + "$ref": "Policy" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute", + "https://www.googleapis.com/auth/compute.readonly" + ] + }, "list": { "description": "Retrieves the list of Snapshot resources contained within the specified project.", "httpMethod": "GET", @@ -15084,6 +16911,42 @@ "https://www.googleapis.com/auth/compute.readonly" ] }, + "setIamPolicy": { + "description": "Sets the access control policy on the specified resource. Replaces any existing policy.", + "httpMethod": "POST", + "id": "compute.snapshots.setIamPolicy", + "parameterOrder": [ + "project", + "resource" + ], + "parameters": { + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "resource": { + "description": "Name or id of the resource for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + "required": true, + "type": "string" + } + }, + "path": "{project}/global/snapshots/{resource}/setIamPolicy", + "request": { + "$ref": "GlobalSetPolicyRequest" + }, + "response": { + "$ref": "Policy" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute" + ] + }, "setLabels": { "description": "Sets the labels on a snapshot. To learn more about labels, read the Labeling Resources documentation.", "httpMethod": "POST", @@ -15101,9 +16964,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -15137,9 +17000,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "(?:[-a-z0-9_]{0,62}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -15332,9 +17195,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "(?:[-a-z0-9_]{0,62}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -15614,9 +17477,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "(?:[-a-z0-9_]{0,62}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -15849,9 +17712,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -16014,7 +17877,7 @@ ] }, "patch": { - "description": "Patches the specified subnetwork with the data included in the request. Only the following fields within the subnetwork resource can be specified in the request: secondary_ip_range, allow_subnet_cidr_routes_overlap and role. It is also mandatory to specify the current fingeprint of the subnetwork resource being patched.", + "description": "Patches the specified subnetwork with the data included in the request. Only certain fields can up updated with a patch request as indicated in the field descriptions. You must specify the current fingeprint of the subnetwork resource being patched.", "httpMethod": "PATCH", "id": "compute.subnetworks.patch", "parameterOrder": [ @@ -16087,9 +17950,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -16180,9 +18043,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -16416,9 +18279,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "(?:[-a-z0-9_]{0,62}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -16773,9 +18636,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "(?:[-a-z0-9_]{0,62}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -17050,9 +18913,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -17637,9 +19500,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -17995,9 +19858,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "(?:[-a-z0-9_]{0,62}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -18524,9 +20387,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -18568,9 +20431,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -18845,9 +20708,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "(?:[-a-z0-9_]{0,62}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -19211,9 +21074,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -19255,9 +21118,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -19506,6 +21369,7 @@ } } }, + "revision": "20181130", "rootUrl": "https://www.googleapis.com/", "schemas": { "AcceleratorConfig": { @@ -19995,7 +21859,7 @@ "type": "string" }, "labelFingerprint": { - "description": "A fingerprint for the labels being applied to this Address, which is essentially a hash of the labels set used for optimistic locking. The fingerprint is initially generated by Compute Engine and changes after every request to modify or update labels. You must always provide an up-to-date fingerprint hash in order to update or change labels.\n\nTo see the latest fingerprint, make a get() request to retrieve an Address.", + "description": "A fingerprint for the labels being applied to this Address, which is essentially a hash of the labels set used for optimistic locking. The fingerprint is initially generated by Compute Engine and changes after every request to modify or update labels. You must always provide an up-to-date fingerprint hash in order to update or change labels, otherwise the request will fail with error 412 conditionNotMet.\n\nTo see the latest fingerprint, make a get() request to retrieve an Address.", "format": "byte", "type": "string" }, @@ -20021,7 +21885,7 @@ "type": "string" }, "networkTier": { - "description": "This signifies the networking tier used for configuring this Address and can only take the following values: PREMIUM , STANDARD.\n\nIf this field is not specified, it is assumed to be PREMIUM.", + "description": "This signifies the networking tier used for configuring this Address and can only take the following values: PREMIUM, STANDARD. Global forwarding rules can only be Premium Tier. Regional forwarding rules can be either Premium or Standard Tier. Standard Tier addresses applied to regional forwarding rules can be used with any external load balancer. Regional forwarding rules in Premium Tier can only be used with a Network load balancer.\n\nIf this field is not specified, it is assumed to be PREMIUM.", "enum": [ "PREMIUM", "STANDARD" @@ -20042,11 +21906,9 @@ "enum": [ "DNS_RESOLVER", "GCE_ENDPOINT", - "UNSPECIFIED_PURPOSE", "VPC_PEERING" ], "enumDescriptions": [ - "", "", "", "" @@ -20422,6 +22284,477 @@ }, "type": "object" }, + "Allocation": { + "description": "Allocation resource", + "id": "Allocation", + "properties": { + "creationTimestamp": { + "description": "[Output Only] Creation timestamp in RFC3339 text format.", + "type": "string" + }, + "description": { + "type": "string" + }, + "id": { + "description": "[Output Only] The unique identifier for the resource. This identifier is defined by the server.", + "format": "uint64", + "type": "string" + }, + "kind": { + "default": "compute#allocation", + "description": "[Output Only] Type of the resource. Always compute#allocations for allocations.", + "type": "string" + }, + "name": { + "annotations": { + "required": [ + "compute.instances.insert" + ] + }, + "description": "The name of the resource, provided by the client when initially creating the resource. The resource name must be 1-63 characters long, and comply with RFC1035. Specifically, the name must be 1-63 characters long and match the regular expression `[a-z]([-a-z0-9]*[a-z0-9])?` which means the first character must be a lowercase letter, and all following characters must be a dash, lowercase letter, or digit, except the last character, which cannot be a dash.", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "type": "string" + }, + "selfLink": { + "description": "[Output Only] Server-defined fully-qualified URL for this resource.", + "type": "string" + }, + "specificAllocation": { + "$ref": "AllocationSpecificSKUAllocation" + }, + "specificAllocationRequired": { + "description": "Indicates whether the allocation can be consumed by VMs with \"any allocation\" defined. If the field is set, then only VMs that target the allocation by name using --allocation-affinity can consume this allocation.", + "type": "boolean" + }, + "zone": { + "type": "string" + } + }, + "type": "object" + }, + "AllocationAffinity": { + "description": "AllocationAffinity is the configuration of desired allocation which this instance could take capacity from.", + "id": "AllocationAffinity", + "properties": { + "consumeAllocationType": { + "enum": [ + "ANY_ALLOCATION", + "NO_ALLOCATION", + "SPECIFIC_ALLOCATION", + "UNSPECIFIED" + ], + "enumDescriptions": [ + "", + "", + "", + "" + ], + "type": "string" + }, + "key": { + "description": "Corresponds to the label key of allocation resource.", + "type": "string" + }, + "values": { + "description": "Corresponds to the label values of allocation resource.", + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object" + }, + "AllocationAggregatedList": { + "description": "Contains a list of allocations.", + "id": "AllocationAggregatedList", + "properties": { + "id": { + "description": "[Output Only] Unique identifier for the resource; defined by the server.", + "type": "string" + }, + "items": { + "additionalProperties": { + "$ref": "AllocationsScopedList", + "description": "Name of the scope containing this set of allocations." + }, + "description": "A list of Allocation resources.", + "type": "object" + }, + "kind": { + "default": "compute#allocationAggregatedList", + "description": "Type of resource.", + "type": "string" + }, + "nextPageToken": { + "description": "[Output Only] This token allows you to get the next page of results for list requests. If the number of results is larger than maxResults, use the nextPageToken as a value for the query parameter pageToken in the next list request. Subsequent list requests will have their own nextPageToken to continue paging through the results.", + "type": "string" + }, + "selfLink": { + "description": "[Output Only] Server-defined URL for this resource.", + "type": "string" + }, + "warning": { + "description": "[Output Only] Informational warning message.", + "properties": { + "code": { + "description": "[Output Only] A warning code, if applicable. For example, Compute Engine returns NO_RESULTS_ON_PAGE if there are no results in the response.", + "enum": [ + "CLEANUP_FAILED", + "DEPRECATED_RESOURCE_USED", + "DEPRECATED_TYPE_USED", + "DISK_SIZE_LARGER_THAN_IMAGE_SIZE", + "EXPERIMENTAL_TYPE_USED", + "EXTERNAL_API_WARNING", + "FIELD_VALUE_OVERRIDEN", + "INJECTED_KERNELS_DEPRECATED", + "MISSING_TYPE_DEPENDENCY", + "NEXT_HOP_ADDRESS_NOT_ASSIGNED", + "NEXT_HOP_CANNOT_IP_FORWARD", + "NEXT_HOP_INSTANCE_NOT_FOUND", + "NEXT_HOP_INSTANCE_NOT_ON_NETWORK", + "NEXT_HOP_NOT_RUNNING", + "NOT_CRITICAL_ERROR", + "NO_RESULTS_ON_PAGE", + "REQUIRED_TOS_AGREEMENT", + "RESOURCE_IN_USE_BY_OTHER_RESOURCE_WARNING", + "RESOURCE_NOT_DELETED", + "SCHEMA_VALIDATION_IGNORED", + "SINGLE_INSTANCE_PROPERTY_TEMPLATE", + "UNDECLARED_PROPERTIES", + "UNREACHABLE" + ], + "enumDescriptions": [ + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "" + ], + "type": "string" + }, + "data": { + "description": "[Output Only] Metadata about this warning in key: value format. For example:\n\"data\": [ { \"key\": \"scope\", \"value\": \"zones/us-east1-d\" }", + "items": { + "properties": { + "key": { + "description": "[Output Only] A key that provides more detail on the warning being returned. For example, for warnings where there are no results in a list request for a particular zone, this key might be scope and the key value might be the zone name. Other examples might be a key indicating a deprecated resource and a suggested replacement, or a warning about invalid network settings (for example, if an instance attempts to perform IP forwarding but is not enabled for IP forwarding).", + "type": "string" + }, + "value": { + "description": "[Output Only] A warning data value corresponding to the key.", + "type": "string" + } + }, + "type": "object" + }, + "type": "array" + }, + "message": { + "description": "[Output Only] A human-readable description of the warning code.", + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object" + }, + "AllocationList": { + "id": "AllocationList", + "properties": { + "id": { + "description": "[Output Only] The unique identifier for the resource. This identifier is defined by the server.", + "type": "string" + }, + "items": { + "description": "[Output Only] A list of Allocation resources.", + "items": { + "$ref": "Allocation" + }, + "type": "array" + }, + "kind": { + "default": "compute#allocationList", + "description": "[Output Only] Type of resource.Always compute#allocationsList for listsof allocations", + "type": "string" + }, + "nextPageToken": { + "description": "[Output Only] This token allows you to get the next page of results for list requests. If the number of results is larger than maxResults, use the nextPageToken as a value for the query parameter pageToken in the next list request. Subsequent list requests will have their own nextPageToken to continue paging through the results.", + "type": "string" + }, + "selfLink": { + "description": "[Output Only] Server-defined URL for this resource.", + "type": "string" + }, + "warning": { + "description": "[Output Only] Informational warning message.", + "properties": { + "code": { + "description": "[Output Only] A warning code, if applicable. For example, Compute Engine returns NO_RESULTS_ON_PAGE if there are no results in the response.", + "enum": [ + "CLEANUP_FAILED", + "DEPRECATED_RESOURCE_USED", + "DEPRECATED_TYPE_USED", + "DISK_SIZE_LARGER_THAN_IMAGE_SIZE", + "EXPERIMENTAL_TYPE_USED", + "EXTERNAL_API_WARNING", + "FIELD_VALUE_OVERRIDEN", + "INJECTED_KERNELS_DEPRECATED", + "MISSING_TYPE_DEPENDENCY", + "NEXT_HOP_ADDRESS_NOT_ASSIGNED", + "NEXT_HOP_CANNOT_IP_FORWARD", + "NEXT_HOP_INSTANCE_NOT_FOUND", + "NEXT_HOP_INSTANCE_NOT_ON_NETWORK", + "NEXT_HOP_NOT_RUNNING", + "NOT_CRITICAL_ERROR", + "NO_RESULTS_ON_PAGE", + "REQUIRED_TOS_AGREEMENT", + "RESOURCE_IN_USE_BY_OTHER_RESOURCE_WARNING", + "RESOURCE_NOT_DELETED", + "SCHEMA_VALIDATION_IGNORED", + "SINGLE_INSTANCE_PROPERTY_TEMPLATE", + "UNDECLARED_PROPERTIES", + "UNREACHABLE" + ], + "enumDescriptions": [ + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "" + ], + "type": "string" + }, + "data": { + "description": "[Output Only] Metadata about this warning in key: value format. For example:\n\"data\": [ { \"key\": \"scope\", \"value\": \"zones/us-east1-d\" }", + "items": { + "properties": { + "key": { + "description": "[Output Only] A key that provides more detail on the warning being returned. For example, for warnings where there are no results in a list request for a particular zone, this key might be scope and the key value might be the zone name. Other examples might be a key indicating a deprecated resource and a suggested replacement, or a warning about invalid network settings (for example, if an instance attempts to perform IP forwarding but is not enabled for IP forwarding).", + "type": "string" + }, + "value": { + "description": "[Output Only] A warning data value corresponding to the key.", + "type": "string" + } + }, + "type": "object" + }, + "type": "array" + }, + "message": { + "description": "[Output Only] A human-readable description of the warning code.", + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object" + }, + "AllocationSpecificSKUAllocation": { + "description": "This allocation type allows to pre allocate specific instance configuration.", + "id": "AllocationSpecificSKUAllocation", + "properties": { + "count": { + "description": "Specifies number of resources that are allocated.", + "format": "int64", + "type": "string" + }, + "inUseCount": { + "description": "[OutputOnly] Indicates how many resource are in use.", + "format": "int64", + "type": "string" + }, + "instanceProperties": { + "$ref": "AllocationSpecificSKUAllocationAllocatedInstanceProperties" + } + }, + "type": "object" + }, + "AllocationSpecificSKUAllocationAllocatedInstanceProperties": { + "description": "Properties of the SKU instances being reserved.", + "id": "AllocationSpecificSKUAllocationAllocatedInstanceProperties", + "properties": { + "guestAccelerators": { + "description": "Specifies accelerator type and count.", + "items": { + "$ref": "AcceleratorConfig" + }, + "type": "array" + }, + "localSsds": { + "description": "Specifies amount of local ssd to reserve with each instance. The type of disk is local-ssd.", + "items": { + "$ref": "AllocationSpecificSKUAllocationAllocatedInstancePropertiesAllocatedDisk" + }, + "type": "array" + }, + "machineType": { + "description": "Specifies type of machine (name only) which has fixed number of vCPUs and fixed amount of memory. This also includes specifying custom machine type following custom-NUMBER_OF_CPUS-AMOUNT_OF_MEMORY pattern.", + "type": "string" + }, + "minCpuPlatform": { + "description": "Minimum cpu platform the allocation.", + "type": "string" + } + }, + "type": "object" + }, + "AllocationSpecificSKUAllocationAllocatedInstancePropertiesAllocatedDisk": { + "id": "AllocationSpecificSKUAllocationAllocatedInstancePropertiesAllocatedDisk", + "properties": { + "diskSizeGb": { + "description": "Specifies the size of the disk in base-2 GB.", + "format": "int64", + "type": "string" + }, + "interface": { + "description": "Specifies the disk interface to use for attaching this disk, which is either SCSI or NVME. The default is SCSI. For performance characteristics of SCSI over NVMe, see Local SSD performance.", + "enum": [ + "NVME", + "SCSI" + ], + "enumDescriptions": [ + "", + "" + ], + "type": "string" + } + }, + "type": "object" + }, + "AllocationsScopedList": { + "id": "AllocationsScopedList", + "properties": { + "allocations": { + "description": "A list of allocations contained in this scope.", + "items": { + "$ref": "Allocation" + }, + "type": "array" + }, + "warning": { + "description": "Informational warning which replaces the list of allocations when the list is empty.", + "properties": { + "code": { + "description": "[Output Only] A warning code, if applicable. For example, Compute Engine returns NO_RESULTS_ON_PAGE if there are no results in the response.", + "enum": [ + "CLEANUP_FAILED", + "DEPRECATED_RESOURCE_USED", + "DEPRECATED_TYPE_USED", + "DISK_SIZE_LARGER_THAN_IMAGE_SIZE", + "EXPERIMENTAL_TYPE_USED", + "EXTERNAL_API_WARNING", + "FIELD_VALUE_OVERRIDEN", + "INJECTED_KERNELS_DEPRECATED", + "MISSING_TYPE_DEPENDENCY", + "NEXT_HOP_ADDRESS_NOT_ASSIGNED", + "NEXT_HOP_CANNOT_IP_FORWARD", + "NEXT_HOP_INSTANCE_NOT_FOUND", + "NEXT_HOP_INSTANCE_NOT_ON_NETWORK", + "NEXT_HOP_NOT_RUNNING", + "NOT_CRITICAL_ERROR", + "NO_RESULTS_ON_PAGE", + "REQUIRED_TOS_AGREEMENT", + "RESOURCE_IN_USE_BY_OTHER_RESOURCE_WARNING", + "RESOURCE_NOT_DELETED", + "SCHEMA_VALIDATION_IGNORED", + "SINGLE_INSTANCE_PROPERTY_TEMPLATE", + "UNDECLARED_PROPERTIES", + "UNREACHABLE" + ], + "enumDescriptions": [ + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "" + ], + "type": "string" + }, + "data": { + "description": "[Output Only] Metadata about this warning in key: value format. For example:\n\"data\": [ { \"key\": \"scope\", \"value\": \"zones/us-east1-d\" }", + "items": { + "properties": { + "key": { + "description": "[Output Only] A key that provides more detail on the warning being returned. For example, for warnings where there are no results in a list request for a particular zone, this key might be scope and the key value might be the zone name. Other examples might be a key indicating a deprecated resource and a suggested replacement, or a warning about invalid network settings (for example, if an instance attempts to perform IP forwarding but is not enabled for IP forwarding).", + "type": "string" + }, + "value": { + "description": "[Output Only] A warning data value corresponding to the key.", + "type": "string" + } + }, + "type": "object" + }, + "type": "array" + }, + "message": { + "description": "[Output Only] A human-readable description of the warning code.", + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object" + }, "AttachedDisk": { "description": "An instance-attached disk resource.", "id": "AttachedDisk", @@ -20517,8 +22850,12 @@ "description": "[Input Only] Specifies the parameters for a new disk that will be created alongside the new instance. Use initialization parameters to create boot disks or local SSDs attached to the new instance.\n\nThis property is mutually exclusive with the source property; you can only define one or the other, but not both.", "id": "AttachedDiskInitializeParams", "properties": { + "description": { + "description": "An optional description. Provide this property when creating the disk.", + "type": "string" + }, "diskName": { - "description": "Specifies the disk name. If not specified, the default is to use the name of the instance.", + "description": "Specifies the disk name. If not specified, the default is to use the name of the instance. If the disk with the instance name exists already in the given zone/region, a new name will be automatically generated.", "type": "string" }, "diskSizeGb": { @@ -20526,18 +22863,6 @@ "format": "int64", "type": "string" }, - "diskStorageType": { - "description": "[Deprecated] Storage type of the disk.", - "enum": [ - "HDD", - "SSD" - ], - "enumDescriptions": [ - "", - "" - ], - "type": "string" - }, "diskType": { "description": "Specifies the disk type to use to create the instance. If not specified, the default is pd-standard, specified using the full URL. For example:\nhttps://www.googleapis.com/compute/v1/projects/project/zones/zone/diskTypes/pd-standard\n\n\nOther values include pd-ssd and local-ssd. If you define this field, you can provide either the full or partial URL. For example, the following are valid values: \n- https://www.googleapis.com/compute/v1/projects/project/zones/zone/diskTypes/diskType \n- projects/project/zones/zone/diskTypes/diskType \n- zones/zone/diskTypes/diskType Note that for InstanceTemplate, this is the name of the disk type, not URL.", "type": "string" @@ -20550,7 +22875,7 @@ "type": "object" }, "sourceImage": { - "description": "The source image to create this disk. When creating a new instance, one of initializeParams.sourceImage or disks.source is required except for local SSD.\n\nTo create a disk with one of the public operating system images, specify the image by its family name. For example, specify family/debian-8 to use the latest Debian 8 image:\nprojects/debian-cloud/global/images/family/debian-8\n\n\nAlternatively, use a specific version of a public operating system image:\nprojects/debian-cloud/global/images/debian-8-jessie-vYYYYMMDD\n\n\nTo create a disk with a custom image that you created, specify the image name in the following format:\nglobal/images/my-custom-image\n\n\nYou can also specify a custom image by its image family, which returns the latest version of the image in that family. Replace the image name with family/family-name:\nglobal/images/family/my-image-family\n\n\nIf the source image is deleted later, this field will not be set.", + "description": "The source image to create this disk. When creating a new instance, one of initializeParams.sourceImage or disks.source is required except for local SSD.\n\nTo create a disk with one of the public operating system images, specify the image by its family name. For example, specify family/debian-9 to use the latest Debian 9 image:\nprojects/debian-cloud/global/images/family/debian-9\n\n\nAlternatively, use a specific version of a public operating system image:\nprojects/debian-cloud/global/images/debian-9-stretch-vYYYYMMDD\n\n\nTo create a disk with a custom image that you created, specify the image name in the following format:\nglobal/images/my-custom-image\n\n\nYou can also specify a custom image by its image family, which returns the latest version of the image in that family. Replace the image name with family/family-name:\nglobal/images/family/my-image-family\n\n\nIf the source image is deleted later, this field will not be set.", "type": "string" }, "sourceImageEncryptionKey": { @@ -21156,7 +23481,7 @@ "type": "number" }, "utilizationTargetType": { - "description": "Defines how target utilization value is expressed for a Stackdriver Monitoring metric. Either GAUGE, DELTA_PER_SECOND, or DELTA_PER_MINUTE. If not specified, the default is GAUGE.", + "description": "Defines how target utilization value is expressed for a Stackdriver Monitoring metric. Either GAUGE, DELTA_PER_SECOND, or DELTA_PER_MINUTE.", "enum": [ "DELTA_PER_MINUTE", "DELTA_PER_SECOND", @@ -21212,7 +23537,7 @@ "type": "string" }, "group": { - "description": "The fully-qualified URL of a Instance Group resource. This instance group defines the list of instances that serve traffic. Member virtual machine instances from each instance group must live in the same zone as the instance group itself. No two backends in a backend service are allowed to use same Instance Group resource.\n\nNote that you must specify an Instance Group resource using the fully-qualified URL, rather than a partial URL.\n\nWhen the BackendService has load balancing scheme INTERNAL, the instance group must be within the same region as the BackendService.", + "description": "The fully-qualified URL of an Instance Group or Network Endpoint Group resource. In case of instance group this defines the list of instances that serve traffic. Member virtual machine instances from each instance group must live in the same zone as the instance group itself. No two backends in a backend service are allowed to use same Instance Group resource.\n\nFor Network Endpoint Groups this defines list of endpoints. All endpoints of Network Endpoint Group must be hosted on instances located in the same zone as the Network Endpoint Group.\n\nBackend service can not contain mix of Instance Group and Network Endpoint Group backends.\n\nNote that you must specify an Instance Group or Network Endpoint Group resource using the fully-qualified URL, rather than a partial URL.\n\nWhen the BackendService has load balancing scheme INTERNAL, the instance group must be within the same region as the BackendService. Network Endpoint Groups are not supported for INTERNAL load balancing scheme.", "type": "string" }, "maxConnections": { @@ -21263,7 +23588,7 @@ }, "cdnPolicy": { "$ref": "BackendBucketCdnPolicy", - "description": "Cloud CDN Coniguration for this BackendBucket." + "description": "Cloud CDN configuration for this BackendBucket." }, "creationTimestamp": { "description": "[Output Only] Creation timestamp in RFC3339 text format.", @@ -21304,12 +23629,12 @@ "id": "BackendBucketCdnPolicy", "properties": { "signedUrlCacheMaxAgeSec": { - "description": "Number of seconds up to which the response to a signed URL request will be cached in the CDN. After this time period, the Signed URL will be revalidated before being served. Defaults to 1hr (3600s). If this field is set, Cloud CDN will internally act as though all responses from this bucket had a ?Cache-Control: public, max-age=[TTL]? header, regardless of any existing Cache-Control header. The actual headers served in responses will not be altered.", + "description": "Maximum number of seconds the response to a signed URL request will be considered fresh. After this time period, the response will be revalidated before being served. Defaults to 1hr (3600s). When serving responses to signed URL requests, Cloud CDN will internally behave as though all responses from this backend had a \"Cache-Control: public, max-age=[TTL]\" header, regardless of any existing Cache-Control header. The actual headers served in responses will not be altered.", "format": "int64", "type": "string" }, "signedUrlKeyNames": { - "description": "[Output Only] Names of the keys currently configured for Cloud CDN Signed URL on this backend bucket.", + "description": "[Output Only] Names of the keys for signing request URLs.", "items": { "type": "string" }, @@ -21473,7 +23798,7 @@ "type": "boolean" }, "fingerprint": { - "description": "Fingerprint of this resource. A hash of the contents stored in this object. This field is used in optimistic locking. This field will be ignored when inserting a BackendService. An up-to-date fingerprint must be provided in order to update the BackendService.", + "description": "Fingerprint of this resource. A hash of the contents stored in this object. This field is used in optimistic locking. This field will be ignored when inserting a BackendService. An up-to-date fingerprint must be provided in order to update the BackendService, otherwise the request will fail with error 412 conditionNotMet.\n\nTo see the latest fingerprint, make a get() request to retrieve a BackendService.", "format": "byte", "type": "string" }, @@ -21705,12 +24030,12 @@ "description": "The CacheKeyPolicy for this CdnPolicy." }, "signedUrlCacheMaxAgeSec": { - "description": "Number of seconds up to which the response to a signed URL request will be cached in the CDN. After this time period, the Signed URL will be revalidated before being served. Defaults to 1hr (3600s). If this field is set, Cloud CDN will internally act as though all responses from this backend had a ?Cache-Control: public, max-age=[TTL]? header, regardless of any existing Cache-Control header. The actual headers served in responses will not be altered.", + "description": "Maximum number of seconds the response to a signed URL request will be considered fresh. After this time period, the response will be revalidated before being served. Defaults to 1hr (3600s). When serving responses to signed URL requests, Cloud CDN will internally behave as though all responses from this backend had a \"Cache-Control: public, max-age=[TTL]\" header, regardless of any existing Cache-Control header. The actual headers served in responses will not be altered.", "format": "int64", "type": "string" }, "signedUrlKeyNames": { - "description": "[Output Only] Names of the keys currently configured for Cloud CDN Signed URL on this backend service.", + "description": "[Output Only] Names of the keys for signing request URLs.", "items": { "type": "string" }, @@ -21723,6 +24048,7 @@ "id": "BackendServiceGroupHealth", "properties": { "healthStatus": { + "description": "Health state of the backend instances or endpoints in requested instance or network endpoint group, determined based on configured health checks.", "items": { "$ref": "HealthStatus" }, @@ -21977,7 +24303,7 @@ "properties": { "condition": { "$ref": "Expr", - "description": "The condition that is associated with this binding. NOTE: an unsatisfied condition will not allow user access via current binding. Different bindings, including their conditions, are examined independently. This field is only visible as GOOGLE_INTERNAL or CONDITION_TRUSTED_TESTER." + "description": "Unimplemented. The condition that is associated with this binding. NOTE: an unsatisfied condition will not allow user access via current binding. Different bindings, including their conditions, are examined independently." }, "members": { "description": "Specifies the identities requesting access for a Cloud Platform resource. `members` can have the following values:\n\n* `allUsers`: A special identifier that represents anyone who is on the internet; with or without a Google account.\n\n* `allAuthenticatedUsers`: A special identifier that represents anyone who is authenticated with a Google account or a service account.\n\n* `user:{emailid}`: An email address that represents a specific Google account. For example, `alice@gmail.com` .\n\n\n\n* `serviceAccount:{emailid}`: An email address that represents a service account. For example, `my-other-app@appspot.gserviceaccount.com`.\n\n* `group:{emailid}`: An email address that represents a Google group. For example, `admins@example.com`.\n\n\n\n* `domain:{domain}`: A Google Apps domain name that represents all the users of that domain. For example, `google.com` or `example.com`.", @@ -22043,6 +24369,13 @@ "description": "Represents a Commitment resource. Creating a Commitment resource means that you are purchasing a committed use contract with an explicit start and end time. You can create commitments based on vCPUs and memory usage and receive discounted rates. For full details, read Signing Up for Committed Use Discounts.\n\nCommitted use discounts are subject to Google Cloud Platform's Service Specific Terms. By purchasing a committed use discount, you agree to these terms. Committed use discounts will not renew, so you must purchase a new commitment to continue receiving discounts. (== resource_for beta.commitments ==) (== resource_for v1.commitments ==)", "id": "Commitment", "properties": { + "allocations": { + "description": "List of allocations for this commitment.", + "items": { + "$ref": "Allocation" + }, + "type": "array" + }, "creationTimestamp": { "description": "[Output Only] Creation timestamp in RFC3339 text format.", "type": "string" @@ -22646,7 +24979,7 @@ "type": "string" }, "labelFingerprint": { - "description": "A fingerprint for the labels being applied to this disk, which is essentially a hash of the labels set used for optimistic locking. The fingerprint is initially generated by Compute Engine and changes after every request to modify or update labels. You must always provide an up-to-date fingerprint hash in order to update or change labels.\n\nTo see the latest fingerprint, make a get() request to retrieve a disk.", + "description": "A fingerprint for the labels being applied to this disk, which is essentially a hash of the labels set used for optimistic locking. The fingerprint is initially generated by Compute Engine and changes after every request to modify or update labels. You must always provide an up-to-date fingerprint hash in order to update or change labels, otherwise the request will fail with error 412 conditionNotMet.\n\nTo see the latest fingerprint, make a get() request to retrieve a disk.", "format": "byte", "type": "string" }, @@ -22674,7 +25007,7 @@ "type": "array" }, "licenses": { - "description": "Any applicable publicly visible licenses.", + "description": "A list of publicly visible licenses. Reserved for Google's use.", "items": { "type": "string" }, @@ -22694,6 +25027,11 @@ "description": "Internal use only.", "type": "string" }, + "physicalBlockSizeBytes": { + "description": "Physical block size of the persistent disk, in bytes. If not present in a request, a default value is used. Currently supported sizes are 4096 and 16384, other sizes may be added in the future. If an unsupported value is requested, the error message will list the supported values for the caller's project.", + "format": "int64", + "type": "string" + }, "region": { "description": "[Output Only] URL of the region where the disk resides. Only applicable for regional resources. You must specify this field as part of the HTTP request URL. It is not settable as a field in the request body.", "type": "string" @@ -22705,6 +25043,13 @@ }, "type": "array" }, + "resourcePolicies": { + "description": "Resource policies applied to this disk for automatic snapshot creations.", + "items": { + "type": "string" + }, + "type": "array" + }, "selfLink": { "description": "[Output Only] Server-defined fully-qualified URL for this resource.", "type": "string" @@ -22715,7 +25060,7 @@ "type": "string" }, "sourceImage": { - "description": "The source image used to create this disk. If the source image is deleted, this field will not be set.\n\nTo create a disk with one of the public operating system images, specify the image by its family name. For example, specify family/debian-8 to use the latest Debian 8 image:\nprojects/debian-cloud/global/images/family/debian-8\n\n\nAlternatively, use a specific version of a public operating system image:\nprojects/debian-cloud/global/images/debian-8-jessie-vYYYYMMDD\n\n\nTo create a disk with a custom image that you created, specify the image name in the following format:\nglobal/images/my-custom-image\n\n\nYou can also specify a custom image by its image family, which returns the latest version of the image in that family. Replace the image name with family/family-name:\nglobal/images/family/my-image-family", + "description": "The source image used to create this disk. If the source image is deleted, this field will not be set.\n\nTo create a disk with one of the public operating system images, specify the image by its family name. For example, specify family/debian-9 to use the latest Debian 9 image:\nprojects/debian-cloud/global/images/family/debian-9\n\n\nAlternatively, use a specific version of a public operating system image:\nprojects/debian-cloud/global/images/debian-9-stretch-vYYYYMMDD\n\n\nTo create a disk with a custom image that you created, specify the image name in the following format:\nglobal/images/my-custom-image\n\n\nYou can also specify a custom image by its image family, which returns the latest version of the image in that family. Replace the image name with family/family-name:\nglobal/images/family/my-image-family", "type": "string" }, "sourceImageEncryptionKey": { @@ -23436,6 +25781,32 @@ }, "type": "object" }, + "DisksAddResourcePoliciesRequest": { + "id": "DisksAddResourcePoliciesRequest", + "properties": { + "resourcePolicies": { + "description": "Resource policies to be added to this disk.", + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object" + }, + "DisksRemoveResourcePoliciesRequest": { + "id": "DisksRemoveResourcePoliciesRequest", + "properties": { + "resourcePolicies": { + "description": "Resource policies to be removed from this disk.", + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object" + }, "DisksResizeRequest": { "id": "DisksResizeRequest", "properties": { @@ -23541,10 +25912,22 @@ }, "type": "object" }, + "DisplayDevice": { + "description": "A set of Display Device options", + "id": "DisplayDevice", + "properties": { + "enableDisplay": { + "description": "Defines whether the instance has Display enabled.", + "type": "boolean" + } + }, + "type": "object" + }, "DistributionPolicy": { "id": "DistributionPolicy", "properties": { "zones": { + "description": "Zones where the regional managed instance group will create and manage instances.", "items": { "$ref": "DistributionPolicyZoneConfiguration" }, @@ -23563,12 +25946,160 @@ "compute.regionInstanceGroupManagers.update" ] }, - "description": "URL of the zone where managed instance group is spawning instances (for regional resources). Zone has to belong to the region where managed instance group is located.", + "description": "The URL of the zone. The zone must exist in the region where the managed instance group is located.", "type": "string" } }, "type": "object" }, + "ExchangedPeeringRoute": { + "id": "ExchangedPeeringRoute", + "properties": { + "destRange": { + "description": "The destination range of the route.", + "type": "string" + }, + "imported": { + "description": "If the peering route is imported if there is no confliction.", + "type": "boolean" + }, + "nextHopRegion": { + "description": "The region of peering route next hop, only applies to dynamic routes.", + "type": "string" + }, + "priority": { + "description": "The priority of the peering route.", + "format": "uint32", + "type": "integer" + }, + "type": { + "description": "The type of the peering route.", + "enum": [ + "DYNAMIC_PEERING_ROUTE", + "STATIC_PEERING_ROUTE", + "SUBNET_PEERING_ROUTE" + ], + "enumDescriptions": [ + "", + "", + "" + ], + "type": "string" + } + }, + "type": "object" + }, + "ExchangedPeeringRoutesList": { + "id": "ExchangedPeeringRoutesList", + "properties": { + "id": { + "description": "[Output Only] Unique identifier for the resource; defined by the server.", + "type": "string" + }, + "items": { + "description": "A list of ExchangedPeeringRoute resources.", + "items": { + "$ref": "ExchangedPeeringRoute" + }, + "type": "array" + }, + "kind": { + "default": "compute#exchangedPeeringRoutesList", + "description": "[Output Only] Type of resource. Always compute#exchangedPeeringRoutesList for exchanged peering routes lists.", + "type": "string" + }, + "nextPageToken": { + "description": "[Output Only] This token allows you to get the next page of results for list requests. If the number of results is larger than maxResults, use the nextPageToken as a value for the query parameter pageToken in the next list request. Subsequent list requests will have their own nextPageToken to continue paging through the results.", + "type": "string" + }, + "selfLink": { + "description": "[Output Only] Server-defined URL for this resource.", + "type": "string" + }, + "warning": { + "description": "[Output Only] Informational warning message.", + "properties": { + "code": { + "description": "[Output Only] A warning code, if applicable. For example, Compute Engine returns NO_RESULTS_ON_PAGE if there are no results in the response.", + "enum": [ + "CLEANUP_FAILED", + "DEPRECATED_RESOURCE_USED", + "DEPRECATED_TYPE_USED", + "DISK_SIZE_LARGER_THAN_IMAGE_SIZE", + "EXPERIMENTAL_TYPE_USED", + "EXTERNAL_API_WARNING", + "FIELD_VALUE_OVERRIDEN", + "INJECTED_KERNELS_DEPRECATED", + "MISSING_TYPE_DEPENDENCY", + "NEXT_HOP_ADDRESS_NOT_ASSIGNED", + "NEXT_HOP_CANNOT_IP_FORWARD", + "NEXT_HOP_INSTANCE_NOT_FOUND", + "NEXT_HOP_INSTANCE_NOT_ON_NETWORK", + "NEXT_HOP_NOT_RUNNING", + "NOT_CRITICAL_ERROR", + "NO_RESULTS_ON_PAGE", + "REQUIRED_TOS_AGREEMENT", + "RESOURCE_IN_USE_BY_OTHER_RESOURCE_WARNING", + "RESOURCE_NOT_DELETED", + "SCHEMA_VALIDATION_IGNORED", + "SINGLE_INSTANCE_PROPERTY_TEMPLATE", + "UNDECLARED_PROPERTIES", + "UNREACHABLE" + ], + "enumDescriptions": [ + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "" + ], + "type": "string" + }, + "data": { + "description": "[Output Only] Metadata about this warning in key: value format. For example:\n\"data\": [ { \"key\": \"scope\", \"value\": \"zones/us-east1-d\" }", + "items": { + "properties": { + "key": { + "description": "[Output Only] A key that provides more detail on the warning being returned. For example, for warnings where there are no results in a list request for a particular zone, this key might be scope and the key value might be the zone name. Other examples might be a key indicating a deprecated resource and a suggested replacement, or a warning about invalid network settings (for example, if an instance attempts to perform IP forwarding but is not enabled for IP forwarding).", + "type": "string" + }, + "value": { + "description": "[Output Only] A warning data value corresponding to the key.", + "type": "string" + } + }, + "type": "object" + }, + "type": "array" + }, + "message": { + "description": "[Output Only] A human-readable description of the warning code.", + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object" + }, "Expr": { "description": "Represents an expression text. Example:\n\ntitle: \"User account presence\" description: \"Determines whether the request has a user account\" expression: \"size(request.user) \u003e 0\"", "id": "Expr", @@ -23668,7 +26199,7 @@ "type": "boolean" }, "enableLogging": { - "description": "This field denotes whether to enable logging for a particular firewall rule. If logging is enabled, logs will be exported to Stackdriver.", + "description": "Deprecated in favor of enable in LogConfig. This field denotes whether to enable logging for a particular firewall rule. If logging is enabled, logs will be exported to Stackdriver.", "type": "boolean" }, "id": { @@ -23681,6 +26212,10 @@ "description": "[Output Only] Type of the resource. Always compute#firewall for firewall rules.", "type": "string" }, + "logConfig": { + "$ref": "FirewallLogConfig", + "description": "This field denotes the logging options for a particular firewall rule. If logging is enabled, logs will be exported to Stackdriver." + }, "name": { "annotations": { "required": [ @@ -23855,6 +26390,17 @@ }, "type": "object" }, + "FirewallLogConfig": { + "description": "The available logging options for a firewall rule.", + "id": "FirewallLogConfig", + "properties": { + "enable": { + "description": "This field denotes whether to enable logging for a particular firewall rule.", + "type": "boolean" + } + }, + "type": "object" + }, "FixedOrPercent": { "description": "Encapsulates numeric value that can be either absolute or relative.", "id": "FixedOrPercent", @@ -23882,11 +26428,11 @@ "id": "ForwardingRule", "properties": { "IPAddress": { - "description": "The IP address that this forwarding rule is serving on behalf of.\n\nAddresses are restricted based on the forwarding rule's load balancing scheme (EXTERNAL or INTERNAL) and scope (global or regional).\n\nWhen the load balancing scheme is EXTERNAL, for global forwarding rules, the address must be a global IP, and for regional forwarding rules, the address must live in the same region as the forwarding rule. If this field is empty, an ephemeral IPv4 address from the same scope (global or regional) will be assigned. A regional forwarding rule supports IPv4 only. A global forwarding rule supports either IPv4 or IPv6.\n\nWhen the load balancing scheme is INTERNAL, this can only be an RFC 1918 IP address belonging to the network/subnet configured for the forwarding rule. By default, if this field is empty, an ephemeral internal IP address will be automatically allocated from the IP range of the subnet or network configured for this forwarding rule.\n\nAn address can be specified either by a literal IP address or a URL reference to an existing Address resource. The following examples are all valid: \n- 100.1.2.3 \n- https://www.googleapis.com/compute/v1/projects/project/regions/region/addresses/address \n- projects/project/regions/region/addresses/address \n- regions/region/addresses/address \n- global/addresses/address \n- address", + "description": "The IP address that this forwarding rule is serving on behalf of.\n\nAddresses are restricted based on the forwarding rule's load balancing scheme (EXTERNAL or INTERNAL) and scope (global or regional).\n\nWhen the load balancing scheme is EXTERNAL, for global forwarding rules, the address must be a global IP, and for regional forwarding rules, the address must live in the same region as the forwarding rule. If this field is empty, an ephemeral IPv4 address from the same scope (global or regional) will be assigned. A regional forwarding rule supports IPv4 only. A global forwarding rule supports either IPv4 or IPv6.\n\nWhen the load balancing scheme is INTERNAL_SELF_MANAGED, this must be a URL reference to an existing Address resource ( internal regional static IP address), with a purpose of GCE_END_POINT and address_type of INTERNAL.\n\nWhen the load balancing scheme is INTERNAL, this can only be an RFC 1918 IP address belonging to the network/subnet configured for the forwarding rule. By default, if this field is empty, an ephemeral internal IP address will be automatically allocated from the IP range of the subnet or network configured for this forwarding rule.\n\nAn address can be specified either by a literal IP address or a URL reference to an existing Address resource. The following examples are all valid: \n- 100.1.2.3 \n- https://www.googleapis.com/compute/v1/projects/project/regions/region/addresses/address \n- projects/project/regions/region/addresses/address \n- regions/region/addresses/address \n- global/addresses/address \n- address", "type": "string" }, "IPProtocol": { - "description": "The IP protocol to which this rule applies. Valid options are TCP, UDP, ESP, AH, SCTP or ICMP.\n\nWhen the load balancing scheme is INTERNAL, only TCP and UDP are valid.", + "description": "The IP protocol to which this rule applies. Valid options are TCP, UDP, ESP, AH, SCTP or ICMP.\n\nWhen the load balancing scheme is INTERNAL, only TCP and UDP are valid. When the load balancing scheme is INTERNAL_SELF_MANAGED, only TCPis valid.", "enum": [ "AH", "ESP", @@ -23905,8 +26451,12 @@ ], "type": "string" }, + "allPorts": { + "description": "This field is used along with the backend_service field for internal load balancing or with the target field for internal TargetInstance. This field cannot be used with port or portRange fields.\n\nWhen the load balancing scheme is INTERNAL and protocol is TCP/UDP, specify this field to allow packets addressed to any ports will be forwarded to the backends configured with this forwarding rule.", + "type": "boolean" + }, "backendService": { - "description": "This field is not used for external load balancing.\n\nFor internal load balancing, this field identifies the BackendService resource to receive the matched traffic.", + "description": "This field is only used for INTERNAL load balancing.\n\nFor internal load balancing, this field identifies the BackendService resource to receive the matched traffic.", "type": "string" }, "creationTimestamp": { @@ -23923,7 +26473,7 @@ "type": "string" }, "ipVersion": { - "description": "The IP Version that will be used by this forwarding rule. Valid options are IPV4 or IPV6. This can only be specified for a global forwarding rule.", + "description": "The IP Version that will be used by this forwarding rule. Valid options are IPV4 or IPV6. This can only be specified for an external global forwarding rule.", "enum": [ "IPV4", "IPV6", @@ -23942,7 +26492,7 @@ "type": "string" }, "labelFingerprint": { - "description": "A fingerprint for the labels being applied to this resource, which is essentially a hash of the labels set used for optimistic locking. The fingerprint is initially generated by Compute Engine and changes after every request to modify or update labels. You must always provide an up-to-date fingerprint hash in order to update or change labels.\n\nTo see the latest fingerprint, make a get() request to retrieve a ForwardingRule.", + "description": "A fingerprint for the labels being applied to this resource, which is essentially a hash of the labels set used for optimistic locking. The fingerprint is initially generated by Compute Engine and changes after every request to modify or update labels. You must always provide an up-to-date fingerprint hash in order to update or change labels, otherwise the request will fail with error 412 conditionNotMet.\n\nTo see the latest fingerprint, make a get() request to retrieve a ForwardingRule.", "format": "byte", "type": "string" }, @@ -23954,7 +26504,7 @@ "type": "object" }, "loadBalancingScheme": { - "description": "This signifies what the ForwardingRule will be used for and can only take the following values: INTERNAL, EXTERNAL The value of INTERNAL means that this will be used for Internal Network Load Balancing (TCP, UDP). The value of EXTERNAL means that this will be used for External Load Balancing (HTTP(S) LB, External TCP/UDP LB, SSL Proxy)", + "description": "This signifies what the ForwardingRule will be used for and can only take the following values: INTERNAL, INTERNAL_SELF_MANAGED, EXTERNAL. The value of INTERNAL means that this will be used for Internal Network Load Balancing (TCP, UDP). The value of INTERNAL_SELF_MANAGED means that this will be used for Internal Global HTTP(S) LB. The value of EXTERNAL means that this will be used for External Load Balancing (HTTP(S) LB, External TCP/UDP LB, SSL Proxy)", "enum": [ "EXTERNAL", "INTERNAL", @@ -23973,7 +26523,7 @@ "type": "string" }, "network": { - "description": "This field is not used for external load balancing.\n\nFor internal load balancing, this field identifies the network that the load balanced IP should belong to for this Forwarding Rule. If this field is not specified, the default network will be used.", + "description": "This field is not used for external load balancing.\n\nFor INTERNAL and INTERNAL_SELF_MANAGED load balancing, this field identifies the network that the load balanced IP should belong to for this Forwarding Rule. If this field is not specified, the default network will be used.", "type": "string" }, "networkTier": { @@ -23993,7 +26543,7 @@ "type": "string" }, "ports": { - "description": "This field is used along with the backend_service field for internal load balancing.\n\nWhen the load balancing scheme is INTERNAL, a single port or a comma separated list of ports can be configured. Only packets addressed to these ports will be forwarded to the backends configured with this forwarding rule.\n\nYou may specify a maximum of up to 5 ports.", + "description": "This field is used along with the backend_service field for internal load balancing.\n\nWhen the load balancing scheme is INTERNAL, a list of ports can be configured, for example, ['80'], ['8000','9000'] etc. Only packets addressed to these ports will be forwarded to the backends configured with this forwarding rule.\n\nYou may specify a maximum of up to 5 ports.", "items": { "type": "string" }, @@ -24017,11 +26567,11 @@ "type": "string" }, "subnetwork": { - "description": "This field is not used for external load balancing.\n\nFor internal load balancing, this field identifies the subnetwork that the load balanced IP should belong to for this Forwarding Rule.\n\nIf the network specified is in auto subnet mode, this field is optional. However, if the network is in custom subnet mode, a subnetwork must be specified.", + "description": "This field is only used for INTERNAL load balancing.\n\nFor internal load balancing, this field identifies the subnetwork that the load balanced IP should belong to for this Forwarding Rule.\n\nIf the network specified is in auto subnet mode, this field is optional. However, if the network is in custom subnet mode, a subnetwork must be specified.", "type": "string" }, "target": { - "description": "The URL of the target resource to receive the matched traffic. For regional forwarding rules, this target must live in the same region as the forwarding rule. For global forwarding rules, this target must be a global load balancing resource. The forwarded traffic must be of a type appropriate to the target object.", + "description": "The URL of the target resource to receive the matched traffic. For regional forwarding rules, this target must live in the same region as the forwarding rule. For global forwarding rules, this target must be a global load balancing resource. The forwarded traffic must be of a type appropriate to the target object. For INTERNAL_SELF_MANAGED\" load balancing, only HTTP and HTTPS targets are valid.", "type": "string" } }, @@ -24358,7 +26908,7 @@ "id": "GlobalSetLabelsRequest", "properties": { "labelFingerprint": { - "description": "The fingerprint of the previous set of labels for this resource, used to detect conflicts. The fingerprint is initially generated by Compute Engine and changes after every request to modify or update labels. You must always provide an up-to-date fingerprint hash when updating or changing labels. Make a get() request to the resource to get the latest fingerprint.", + "description": "The fingerprint of the previous set of labels for this resource, used to detect conflicts. The fingerprint is initially generated by Compute Engine and changes after every request to modify or update labels. You must always provide an up-to-date fingerprint hash when updating or changing labels, otherwise the request will fail with error 412 conditionNotMet. Make a get() request to the resource to get the latest fingerprint.", "format": "byte", "type": "string" }, @@ -24372,6 +26922,92 @@ }, "type": "object" }, + "GlobalSetPolicyRequest": { + "id": "GlobalSetPolicyRequest", + "properties": { + "bindings": { + "description": "Flatten Policy to create a backward compatible wire-format. Deprecated. Use 'policy' to specify bindings.", + "items": { + "$ref": "Binding" + }, + "type": "array" + }, + "etag": { + "description": "Flatten Policy to create a backward compatible wire-format. Deprecated. Use 'policy' to specify the etag.", + "format": "byte", + "type": "string" + }, + "policy": { + "$ref": "Policy", + "description": "REQUIRED: The complete policy to be applied to the 'resource'. The size of the policy is limited to a few 10s of KB. An empty policy is in general a valid policy but certain services (like Projects) might reject them." + } + }, + "type": "object" + }, + "GuestAttributes": { + "description": "A guest attributes entry.", + "id": "GuestAttributes", + "properties": { + "kind": { + "default": "compute#guestAttributes", + "description": "[Output Only] Type of the resource. Always compute#guestAttributes for guest attributes entry.", + "type": "string" + }, + "queryPath": { + "description": "The path to be queried. This can be the default namespace ('/') or a nested namespace ('//') or a specified key ('//')", + "type": "string" + }, + "queryValue": { + "$ref": "GuestAttributesValue", + "description": "[Output Only] The value of the requested queried path." + }, + "selfLink": { + "description": "[Output Only] Server-defined URL for this resource.", + "type": "string" + }, + "variableKey": { + "description": "The key to search for.", + "type": "string" + }, + "variableValue": { + "description": "[Output Only] The value found for the requested key.", + "type": "string" + } + }, + "type": "object" + }, + "GuestAttributesEntry": { + "description": "A guest attributes namespace/key/value entry.", + "id": "GuestAttributesEntry", + "properties": { + "key": { + "description": "Key for the guest attribute entry.", + "type": "string" + }, + "namespace": { + "description": "Namespace for the guest attribute entry.", + "type": "string" + }, + "value": { + "description": "Value for the guest attribute entry.", + "type": "string" + } + }, + "type": "object" + }, + "GuestAttributesValue": { + "description": "Array of guest attribute namespace/key/value tuples.", + "id": "GuestAttributesValue", + "properties": { + "items": { + "items": { + "$ref": "GuestAttributesEntry" + }, + "type": "array" + } + }, + "type": "object" + }, "GuestOsFeature": { "description": "Guest OS features.", "id": "GuestOsFeature", @@ -24627,8 +27263,7 @@ "HTTPS", "INVALID", "SSL", - "TCP", - "UDP" + "TCP" ], "enumDescriptions": [ "", @@ -24636,14 +27271,10 @@ "", "", "", - "", "" ], "type": "string" }, - "udpHealthCheck": { - "$ref": "UDPHealthCheck" - }, "unhealthyThreshold": { "description": "A so-far healthy instance will be marked unhealthy after this many consecutive failures. The default value is 2.", "format": "int32", @@ -25271,7 +27902,7 @@ "type": "string" }, "labelFingerprint": { - "description": "A fingerprint for the labels being applied to this image, which is essentially a hash of the labels used for optimistic locking. The fingerprint is initially generated by Compute Engine and changes after every request to modify or update labels. You must always provide an up-to-date fingerprint hash in order to update or change labels.\n\nTo see the latest fingerprint, make a get() request to retrieve an image.", + "description": "A fingerprint for the labels being applied to this image, which is essentially a hash of the labels used for optimistic locking. The fingerprint is initially generated by Compute Engine and changes after every request to modify or update labels. You must always provide an up-to-date fingerprint hash in order to update or change labels, otherwise the request will fail with error 412 conditionNotMet.\n\nTo see the latest fingerprint, make a get() request to retrieve an image.", "format": "byte", "type": "string" }, @@ -25350,7 +27981,7 @@ "description": "The customer-supplied encryption key of the source disk. Required if the source disk is protected by a customer-supplied encryption key." }, "sourceDiskId": { - "description": "The ID value of the disk used to create this image. This value may be used to determine whether the image was taken from the current or a previous instance of a given disk name.", + "description": "[Output Only] The ID value of the disk used to create this image. This value may be used to determine whether the image was taken from the current or a previous instance of a given disk name.", "type": "string" }, "sourceImage": { @@ -25521,6 +28152,10 @@ "description": "An Instance resource. (== resource_for beta.instances ==) (== resource_for v1.instances ==)", "id": "Instance", "properties": { + "allocationAffinity": { + "$ref": "AllocationAffinity", + "description": "The configuration of desired allocations which this Instance could consume capacity from." + }, "canIpForward": { "description": "Allows this instance to send and receive packets with non-matching destination or source IPs. This is required if you plan to use this instance to forward routes. For more information, see Enabling IP Forwarding.", "type": "boolean" @@ -25548,6 +28183,10 @@ }, "type": "array" }, + "displayDevice": { + "$ref": "DisplayDevice", + "description": "Enables display device for the instance." + }, "guestAccelerators": { "description": "A list of the type and count of accelerator cards attached to the instance.", "items": { @@ -25555,6 +28194,9 @@ }, "type": "array" }, + "hostname": { + "type": "string" + }, "id": { "description": "[Output Only] The unique identifier for the resource. This identifier is defined by the server.", "format": "uint64", @@ -25666,7 +28308,7 @@ }, "tags": { "$ref": "Tags", - "description": "A list of tags to apply to this instance. Tags are used to identify valid sources or targets for network firewalls and are specified by the client during instance creation. The tags can be later modified by the setTags method. Each tag within the list must comply with RFC1035." + "description": "Tags to apply to this instance. Tags are used to identify valid sources or targets for network firewalls and are specified by the client during instance creation. The tags can be later modified by the setTags method. Each tag within the list must comply with RFC1035. Multiple tags can be specified via the 'tags.items' field." }, "zone": { "description": "[Output Only] URL of the zone where the instance resides. You must specify this field as part of the HTTP request URL. It is not settable as a field in the request body.", @@ -26118,7 +28760,7 @@ }, "distributionPolicy": { "$ref": "DistributionPolicy", - "description": "Policy valid only for regional managed instance groups." + "description": "Policy specifying intended distribution of instances in regional managed instance group." }, "failoverAction": { "description": "The action to perform in case of zone failure. Only one value is supported, NO_FAILOVER. The default is NO_FAILOVER.", @@ -26133,7 +28775,7 @@ "type": "string" }, "fingerprint": { - "description": "Fingerprint of this resource. This field may be used in optimistic locking. It will be ignored when inserting an InstanceGroupManager. An up-to-date fingerprint must be provided in order to update the InstanceGroupManager.", + "description": "Fingerprint of this resource. This field may be used in optimistic locking. It will be ignored when inserting an InstanceGroupManager. An up-to-date fingerprint must be provided in order to update the InstanceGroupManager, otherwise the request will fail with error 412 conditionNotMet.\n\nTo see the latest fingerprint, make a get() request to retrieve an InstanceGroupManager.", "format": "byte", "type": "string" }, @@ -26189,6 +28831,10 @@ "description": "The service account to be used as credentials for all operations performed by the managed instance group on instances. The service accounts needs all permissions required to create and delete instances. By default, the service account {projectNumber}@cloudservices.gserviceaccount.com is used.", "type": "string" }, + "status": { + "$ref": "InstanceGroupManagerStatus", + "description": "[Output Only] The status of this managed instance group." + }, "targetPools": { "description": "The URLs for all TargetPool resources to which instances in the instanceGroup field are added. The target pools automatically apply to all of the instances in the managed instance group.", "items": { @@ -26389,6 +29035,7 @@ "type": "object" }, "InstanceGroupManagerAutoHealingPolicy": { + "description": "", "id": "InstanceGroupManagerAutoHealingPolicy", "properties": { "healthCheck": { @@ -26541,6 +29188,16 @@ }, "type": "object" }, + "InstanceGroupManagerStatus": { + "id": "InstanceGroupManagerStatus", + "properties": { + "isStable": { + "description": "[Output Only] A bit indicating whether the managed instance group is in a stable state. A stable state means that: none of the instances in the managed instance group is currently undergoing any type of change (for example, creation, restart, or deletion); no future changes are scheduled for instances in the managed instance group; and the managed instance group itself is not being modified.", + "type": "boolean" + } + }, + "type": "object" + }, "InstanceGroupManagerUpdatePolicy": { "id": "InstanceGroupManagerUpdatePolicy", "properties": { @@ -26558,7 +29215,7 @@ "type": "integer" }, "minimalAction": { - "description": "Minimal action to be taken on an instance. You can specify either RESTART to restart existing instances or REPLACE to delete and create new instances from the target template. If you specify a code\u003eRESTART, the Updater will attempt to perform that action only. However, if the Updater determines that the minimal action you specify is not enough to perform the update, it might perform a more disruptive action.", + "description": "Minimal action to be taken on an instance. You can specify either RESTART to restart existing instances or REPLACE to delete and create new instances from the target template. If you specify a RESTART, the Updater will attempt to perform that action only. However, if the Updater determines that the minimal action you specify is not enough to perform the update, it might perform a more disruptive action.", "enum": [ "REPLACE", "RESTART" @@ -26660,7 +29317,7 @@ "id": "InstanceGroupManagersResizeAdvancedRequest", "properties": { "noCreationRetries": { - "description": "If this flag is true, the managed instance group attempts to create all instances initiated by this resize request only once. If there is an error during creation, the managed instance group does not retry create this instance, and we will decrease the targetSize of the request instead. If the flag is false, the group attemps to recreate each instance continuously until it succeeds.\n\nThis flag matters only in the first attempt of creation of an instance. After an instance is successfully created while this flag is enabled, the instance behaves the same way as all the other instances created with a regular resize request. In particular, if a running instance dies unexpectedly at a later time and needs to be recreated, this mode does not affect the recreation behavior in that scenario.\n\nThis flag is applicable only to the current resize request. It does not influence other resize requests in any way.\n\nYou can see which instances is being creating in which mode by calling the get or listManagedInstances API.", + "description": "If this flag is true, the managed instance group attempts to create all instances initiated by this resize request only once. If there is an error during creation, the managed instance group does not retry create this instance, and we will decrease the targetSize of the request instead. If the flag is false, the group attempts to recreate each instance continuously until it succeeds.\n\nThis flag matters only in the first attempt of creation of an instance. After an instance is successfully created while this flag is enabled, the instance behaves the same way as all the other instances created with a regular resize request. In particular, if a running instance dies unexpectedly at a later time and needs to be recreated, this mode does not affect the recreation behavior in that scenario.\n\nThis flag is applicable only to the current resize request. It does not influence other resize requests in any way.\n\nYou can see which instances is being creating in which mode by calling the get or listManagedInstances API.", "type": "boolean" }, "targetSize": { @@ -27058,7 +29715,7 @@ "id": "InstanceGroupsSetNamedPortsRequest", "properties": { "fingerprint": { - "description": "The fingerprint of the named ports information for this instance group. Use this optional property to prevent conflicts when multiple users change the named ports settings concurrently. Obtain the fingerprint with the instanceGroups.get method. Then, include the fingerprint in your request to ensure that you do not overwrite changes that were applied from another concurrent request.", + "description": "The fingerprint of the named ports information for this instance group. Use this optional property to prevent conflicts when multiple users change the named ports settings concurrently. Obtain the fingerprint with the instanceGroups.get method. Then, include the fingerprint in your request to ensure that you do not overwrite changes that were applied from another concurrent request. A request with an incorrect fingerprint will fail with error 412 conditionNotMet.", "format": "byte", "type": "string" }, @@ -27314,6 +29971,10 @@ "description": "", "id": "InstanceProperties", "properties": { + "allocationAffinity": { + "$ref": "AllocationAffinity", + "description": "The configuration of desired allocations which this Instance could consume capacity from." + }, "canIpForward": { "description": "Enables instances created based on this template to send packets with source IP addresses other than their own and receive packets with destination IP addresses other than their own. If these instances will be used as an IP gateway or it will be set as the next-hop in a Route resource, specify true. If unsure, leave this set to false. See the Enable IP forwarding documentation for more information.", "type": "boolean" @@ -27603,6 +30264,23 @@ }, "type": "object" }, + "InstancesResumeRequest": { + "id": "InstancesResumeRequest", + "properties": { + "disks": { + "description": "Array of disks associated with this instance that are protected with a customer-supplied encryption key.\n\nIn order to resume the instance, the disk url and its corresponding key must be provided.\n\nIf the disk is not protected with a customer-supplied encryption key it should not be specified.", + "items": { + "$ref": "CustomerEncryptionKeyProtectedDisk" + }, + "type": "array" + }, + "instanceEncryptionKey": { + "$ref": "CustomerEncryptionKey", + "description": "Decrypts data associated with an instance that is protected with a customer-supplied encryption key.\n\nIf the instance you are starting is protected with a customer-supplied encryption key, the correct key must be provided otherwise the instance resume will not succeed." + } + }, + "type": "object" + }, "InstancesScopedList": { "id": "InstancesScopedList", "properties": { @@ -27851,7 +30529,7 @@ "type": "string" }, "labelFingerprint": { - "description": "A fingerprint for the labels being applied to this Interconnect, which is essentially a hash of the labels set used for optimistic locking. The fingerprint is initially generated by Compute Engine and changes after every request to modify or update labels. You must always provide an up-to-date fingerprint hash in order to update or change labels.\n\nTo see the latest fingerprint, make a get() request to retrieve an Interconnect.", + "description": "A fingerprint for the labels being applied to this Interconnect, which is essentially a hash of the labels set used for optimistic locking. The fingerprint is initially generated by Compute Engine and changes after every request to modify or update labels. You must always provide an up-to-date fingerprint hash in order to update or change labels, otherwise the request will fail with error 412 conditionNotMet.\n\nTo see the latest fingerprint, make a get() request to retrieve an Interconnect.", "format": "byte", "type": "string" }, @@ -27944,7 +30622,7 @@ "type": "boolean" }, "bandwidth": { - "description": "Provisioned bandwidth capacity for the interconnectAttachment. Can be set by the partner to update the customer's provisioned bandwidth. Output only for for PARTNER type, mutable for PARTNER_PROVIDER, not available for DEDICATED.", + "description": "Provisioned bandwidth capacity for the interconnectAttachment. Can be set by the partner to update the customer's provisioned bandwidth. Output only for PARTNER type, mutable for PARTNER_PROVIDER and DEDICATED.", "enum": [ "BPS_100M", "BPS_10G", @@ -28027,7 +30705,7 @@ "type": "string" }, "labelFingerprint": { - "description": "A fingerprint for the labels being applied to this InterconnectAttachment, which is essentially a hash of the labels set used for optimistic locking. The fingerprint is initially generated by Compute Engine and changes after every request to modify or update labels. You must always provide an up-to-date fingerprint hash in order to update or change labels.\n\nTo see the latest fingerprint, make a get() request to retrieve an InterconnectAttachment.", + "description": "A fingerprint for the labels being applied to this InterconnectAttachment, which is essentially a hash of the labels set used for optimistic locking. The fingerprint is initially generated by Compute Engine and changes after every request to modify or update labels. You must always provide an up-to-date fingerprint hash in order to update or change labels, otherwise the request will fail with error 412 conditionNotMet.\n\nTo see the latest fingerprint, make a get() request to retrieve an InterconnectAttachment.", "format": "byte", "type": "string" }, @@ -28077,7 +30755,7 @@ "type": "string" }, "router": { - "description": "URL of the cloud router to be used for dynamic routing. This router must be in the same region as this InterconnectAttachment. The InterconnectAttachment will automatically connect the Interconnect to the network \u0026 region within which the Cloud Router is configured.", + "description": "URL of the Cloud Router to be used for dynamic routing. This router must be in the same region as this InterconnectAttachment. The InterconnectAttachment will automatically connect the Interconnect to the network \u0026 region within which the Cloud Router is configured.", "type": "string" }, "selfLink": { @@ -28120,7 +30798,7 @@ "type": "string" }, "vlanTag8021q": { - "description": "Available only for DEDICATED and PARTNER_PROVIDER. Desired VLAN tag for this attachment, in the range 2-4094. This field refers to 802.1q VLAN tag, also known as IEEE 802.1Q Only specified at creation time.", + "description": "The IEEE 802.1Q VLAN tag for this attachment, in the range 2-4094. Only specified at creation time.", "format": "int32", "type": "integer" } @@ -28356,7 +31034,7 @@ "id": "InterconnectAttachmentPartnerMetadata", "properties": { "interconnectName": { - "description": "Plain text name of the Interconnect this attachment is connected to, as displayed in the Partner?s portal. For instance ?Chicago 1?. This value may be validated to match approved Partner values.", + "description": "Plain text name of the Interconnect this attachment is connected to, as displayed in the Partner?s portal. For instance \"Chicago 1\". This value may be validated to match approved Partner values.", "type": "string" }, "partnerName": { @@ -28495,6 +31173,129 @@ }, "type": "object" }, + "InterconnectDiagnostics": { + "description": "Diagnostics information about interconnect, contains detailed and current technical information about Google?s side of the connection.", + "id": "InterconnectDiagnostics", + "properties": { + "arpCaches": { + "description": "A list of InterconnectDiagnostics.ARPEntry objects, describing individual neighbors currently seen by the Google router in the ARP cache for the Interconnect. This will be empty when the Interconnect is not bundled.", + "items": { + "$ref": "InterconnectDiagnosticsARPEntry" + }, + "type": "array" + }, + "links": { + "description": "A list of InterconnectDiagnostics.LinkStatus objects, describing the status for each link on the Interconnect.", + "items": { + "$ref": "InterconnectDiagnosticsLinkStatus" + }, + "type": "array" + }, + "macAddress": { + "description": "The MAC address of the Interconnect's bundle interface.", + "type": "string" + } + }, + "type": "object" + }, + "InterconnectDiagnosticsARPEntry": { + "description": "Describing the ARP neighbor entries seen on this link", + "id": "InterconnectDiagnosticsARPEntry", + "properties": { + "ipAddress": { + "description": "The IP address of this ARP neighbor.", + "type": "string" + }, + "macAddress": { + "description": "The MAC address of this ARP neighbor.", + "type": "string" + } + }, + "type": "object" + }, + "InterconnectDiagnosticsLinkLACPStatus": { + "id": "InterconnectDiagnosticsLinkLACPStatus", + "properties": { + "googleSystemId": { + "description": "System ID of the port on Google?s side of the LACP exchange.", + "type": "string" + }, + "neighborSystemId": { + "description": "System ID of the port on the neighbor?s side of the LACP exchange.", + "type": "string" + }, + "state": { + "enum": [ + "ACTIVE", + "DETACHED" + ], + "enumDescriptions": [ + "", + "" + ], + "type": "string" + } + }, + "type": "object" + }, + "InterconnectDiagnosticsLinkOpticalPower": { + "id": "InterconnectDiagnosticsLinkOpticalPower", + "properties": { + "state": { + "enum": [ + "HIGH_ALARM", + "HIGH_WARNING", + "LOW_ALARM", + "LOW_WARNING", + "OK" + ], + "enumDescriptions": [ + "", + "", + "", + "", + "" + ], + "type": "string" + }, + "value": { + "description": "Value of the current optical power, read in dBm. Take a known good optical value, give it a 10% margin and trigger warnings relative to that value. In general, a -7dBm warning and a -11dBm alarm are good optical value estimates for most links.", + "format": "float", + "type": "number" + } + }, + "type": "object" + }, + "InterconnectDiagnosticsLinkStatus": { + "id": "InterconnectDiagnosticsLinkStatus", + "properties": { + "arpCaches": { + "description": "A list of InterconnectDiagnostics.ARPEntry objects, describing the ARP neighbor entries seen on this link. This will be empty if the link is bundled", + "items": { + "$ref": "InterconnectDiagnosticsARPEntry" + }, + "type": "array" + }, + "circuitId": { + "description": "The unique ID for this link assigned during turn up by Google.", + "type": "string" + }, + "googleDemarc": { + "description": "The Demarc address assigned by Google and provided in the LoA.", + "type": "string" + }, + "lacpStatus": { + "$ref": "InterconnectDiagnosticsLinkLACPStatus" + }, + "receivingOpticalPower": { + "$ref": "InterconnectDiagnosticsLinkOpticalPower" + }, + "transmittingOpticalPower": { + "$ref": "InterconnectDiagnosticsLinkOpticalPower" + } + }, + "type": "object" + }, "InterconnectList": { "description": "Response to the list request, and contains a list of interconnects.", "id": "InterconnectList", @@ -28616,7 +31417,7 @@ "type": "string" }, "availabilityZone": { - "description": "[Output Only] Availability zone for this location. Within a metropolitan area (metro), maintenance will not be simultaneously scheduled in more than one availability zone. Example: \"zone1\" or \"zone2\".", + "description": "[Output Only] Availability zone for this InterconnectLocation. Within a metropolitan area (metro), maintenance will not be simultaneously scheduled in more than one availability zone. Example: \"zone1\" or \"zone2\".", "type": "string" }, "city": { @@ -28695,6 +31496,18 @@ "selfLink": { "description": "[Output Only] Server-defined URL for the resource.", "type": "string" + }, + "status": { + "description": "[Output Only] The status of this InterconnectLocation. If the status is AVAILABLE, new Interconnects may be provisioned in this InterconnectLocation. Otherwise, no new Interconnects may be provisioned.", + "enum": [ + "AVAILABLE", + "CLOSED" + ], + "enumDescriptions": [ + "", + "" + ], + "type": "string" } }, "type": "object" @@ -28919,6 +31732,16 @@ }, "type": "object" }, + "InterconnectsGetDiagnosticsResponse": { + "description": "Response for the InterconnectsGetDiagnosticsRequest.", + "id": "InterconnectsGetDiagnosticsResponse", + "properties": { + "result": { + "$ref": "InterconnectDiagnostics" + } + }, + "type": "object" + }, "License": { "description": "A license resource.", "id": "License", @@ -28956,7 +31779,7 @@ "compute.images.insert" ] }, - "description": "[Output Only] Name of the resource. The name is 1-63 characters long and complies with RFC1035.", + "description": "Name of the resource. The name must be 1-63 characters long and comply with RFC1035.", "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", "type": "string" }, @@ -29222,7 +32045,7 @@ "type": "object" }, "LogConfigCounterOptions": { - "description": "Increment a streamz counter with the specified metric and field names.\n\nMetric names should start with a '/', generally be lowercase-only, and end in \"_count\". Field names should not contain an initial slash. The actual exported metric names will have \"/iam/policy\" prepended.\n\nField names correspond to IAM request parameters and field values are their respective values.\n\nAt present the only supported field names are - \"iam_principal\", corresponding to IAMContext.principal; - \"\" (empty string), resulting in one aggretated counter with no field.\n\nExamples: counter { metric: \"/debug_access_count\" field: \"iam_principal\" } ==\u003e increment counter /iam/policy/backend_debug_access_count {iam_principal=[value of IAMContext.principal]}\n\nAt this time we do not support: * multiple field names (though this may be supported in the future) * decrementing the counter * incrementing it by anything other than 1", + "description": "Increment a streamz counter with the specified metric and field names.\n\nMetric names should start with a '/', generally be lowercase-only, and end in \"_count\". Field names should not contain an initial slash. The actual exported metric names will have \"/iam/policy\" prepended.\n\nField names correspond to IAM request parameters and field values are their respective values.\n\nSupported field names: - \"authority\", which is \"[token]\" if IAMContext.token is present, otherwise the value of IAMContext.authority_selector if present, and otherwise a representation of IAMContext.principal; or - \"iam_principal\", a representation of IAMContext.principal even if a token or authority selector is present; or - \"\" (empty string), resulting in a counter with no fields.\n\nExamples: counter { metric: \"/debug_access_count\" field: \"iam_principal\" } ==\u003e increment counter /iam/policy/backend_debug_access_count {iam_principal=[value of IAMContext.principal]}\n\nAt this time we do not support multiple field names (though this may be supported in the future).", "id": "LogConfigCounterOptions", "properties": { "field": { @@ -29241,7 +32064,7 @@ "id": "LogConfigDataAccessOptions", "properties": { "logMode": { - "description": "Whether Gin logging should happen in a fail-closed manner at the caller. This is relevant only in the LocalIAM implementation, for now.", + "description": "Whether Gin logging should happen in a fail-closed manner at the caller. This is relevant only in the LocalIAM implementation, for now.\n\nNOTE: Logging to Gin in a fail-closed manner is currently unsupported while work is being done to satisfy the requirements of go/345. Currently, setting LOG_FAIL_CLOSED mode will have no effect, but still exists because there is active work being done to support it (b/115874152).", "enum": [ "LOG_FAIL_CLOSED", "LOG_MODE_UNSPECIFIED" @@ -29765,7 +32588,7 @@ "id": "Metadata", "properties": { "fingerprint": { - "description": "Specifies a fingerprint for this request, which is essentially a hash of the metadata's contents and used for optimistic locking. The fingerprint is initially generated by Compute Engine and changes after every request to modify or update metadata. You must always provide an up-to-date fingerprint hash in order to update or change metadata.", + "description": "Specifies a fingerprint for this request, which is essentially a hash of the metadata's contents and used for optimistic locking. The fingerprint is initially generated by Compute Engine and changes after every request to modify or update metadata. You must always provide an up-to-date fingerprint hash in order to update or change metadata, otherwise the request will fail with error 412 conditionNotMet.\n\nTo see the latest fingerprint, make a get() request to retrieve the resource.", "format": "byte", "type": "string" }, @@ -29824,7 +32647,7 @@ "type": "object" }, "Network": { - "description": "Represents a Network resource. Read Networks and Firewalls for more information. (== resource_for v1.networks ==) (== resource_for beta.networks ==)", + "description": "Represents a Network resource. Read Virtual Private Cloud (VPC) Network Overview for more information. (== resource_for v1.networks ==) (== resource_for beta.networks ==)", "id": "Network", "properties": { "IPv4Range": { @@ -29833,7 +32656,7 @@ "type": "string" }, "autoCreateSubnetworks": { - "description": "When set to true, the network is created in \"auto subnet mode\". When set to false, the network is in \"custom subnet mode\".\n\nIn \"auto subnet mode\", a newly created network is assigned the default CIDR of 10.128.0.0/9 and it automatically creates one subnetwork per region.", + "description": "When set to true, the VPC network is created in \"auto\" mode. When set to false, the VPC network is created in \"custom\" mode.\n\nAn auto mode VPC network starts with one subnet per region. Each subnet has a predetermined range as described in Auto mode VPC network IP ranges.", "type": "boolean" }, "creationTimestamp": { @@ -29845,7 +32668,7 @@ "type": "string" }, "gatewayIPv4": { - "description": "A gateway address for default routing to other networks. This value is read only and is selected by the Google Compute Engine, typically as the first usable address in the IPv4Range.", + "description": "[Output Only] The gateway address for default routing out of the network. This value is read only and is selected by GCP.", "pattern": "[0-9]{1,3}(?:\\.[0-9]{1,3}){3}", "type": "string" }, @@ -29885,7 +32708,7 @@ "type": "string" }, "subnetworks": { - "description": "[Output Only] Server-defined fully-qualified URLs for all subnetworks in this network.", + "description": "[Output Only] Server-defined fully-qualified URLs for all subnetworks in this VPC network.", "items": { "type": "string" }, @@ -29899,7 +32722,7 @@ "id": "NetworkEndpoint", "properties": { "instance": { - "description": "The name for a specific VM instance that the IP address belongs to. This is required for network endpoints of type GCE_VM_IP and GCE_VM_IP_PORT. The instance must be in the same zone of network endpoint group.\n\nThe name must be 1-63 characters long, and comply with RFC1035.", + "description": "The name for a specific VM instance that the IP address belongs to. This is required for network endpoints of type GCE_VM_IP_PORT. The instance must be in the same zone of network endpoint group.\n\nThe name must be 1-63 characters long, and comply with RFC1035.", "type": "string" }, "ipAddress": { @@ -29922,6 +32745,11 @@ "description": "[Output Only] Creation timestamp in RFC3339 text format.", "type": "string" }, + "defaultPort": { + "description": "The default port used if the port number is not specified in the network endpoint.", + "format": "int32", + "type": "integer" + }, "description": { "description": "An optional description of this resource. Provide this property when you create the resource.", "type": "string" @@ -29938,14 +32766,18 @@ }, "loadBalancer": { "$ref": "NetworkEndpointGroupLbNetworkEndpointGroup", - "description": "This field is only valid when the network endpoint group type is LOAD_BALANCING." + "description": "This field is only valid when the network endpoint group is used for load balancing. [Deprecated] This field is deprecated." }, "name": { "description": "Name of the resource; provided by the client when the resource is created. The name must be 1-63 characters long, and comply with RFC1035. Specifically, the name must be 1-63 characters long and match the regular expression `[a-z]([-a-z0-9]*[a-z0-9])?` which means the first character must be a lowercase letter, and all following characters must be a dash, lowercase letter, or digit, except the last character, which cannot be a dash.", "type": "string" }, + "network": { + "description": "The URL of the network to which all network endpoints in the NEG belong. Uses \"default\" project network if unspecified.", + "type": "string" + }, "networkEndpointType": { - "description": "Type of network endpoints in this network endpoint group. Only supported values for LOAD_BALANCING are GCE_VM_IP or GCE_VM_IP_PORT.", + "description": "Type of network endpoints in this network endpoint group. Currently the only supported value is GCE_VM_IP_PORT.", "enum": [ "GCE_VM_IP_PORT" ], @@ -29962,6 +32794,14 @@ "description": "[Output only] Number of network endpoints in the network endpoint group.", "format": "int32", "type": "integer" + }, + "subnetwork": { + "description": "Optional URL of the subnetwork to which all network endpoints in the NEG belong.", + "type": "string" + }, + "zone": { + "description": "[Output Only] The URL of the zone where the network endpoint group is located.", + "type": "string" } }, "type": "object" @@ -30079,24 +32919,24 @@ "type": "object" }, "NetworkEndpointGroupLbNetworkEndpointGroup": { - "description": "Load balancing specific fields for network endpoint group of type LOAD_BALANCING.", + "description": "Load balancing specific fields for network endpoint group.", "id": "NetworkEndpointGroupLbNetworkEndpointGroup", "properties": { "defaultPort": { - "description": "The default port used if the port number is not specified in the network endpoint. If the network endpoint type is GCE_VM_IP, this field must not be specified.", + "description": "The default port used if the port number is not specified in the network endpoint. [Deprecated] This field is deprecated.", "format": "int32", "type": "integer" }, "network": { - "description": "The URL of the network to which all network endpoints in the NEG belong. Uses \"default\" project network if unspecified.", + "description": "The URL of the network to which all network endpoints in the NEG belong. Uses \"default\" project network if unspecified. [Deprecated] This field is deprecated.", "type": "string" }, "subnetwork": { - "description": "Optional URL of the subnetwork to which all network endpoints in the NEG belong.", + "description": "Optional URL of the subnetwork to which all network endpoints in the NEG belong. [Deprecated] This field is deprecated.", "type": "string" }, "zone": { - "description": "[Output Only] The URL of the zone where the network endpoint group is located.", + "description": "[Output Only] The URL of the zone where the network endpoint group is located. [Deprecated] This field is deprecated.", "type": "string" } }, @@ -30494,7 +33334,7 @@ "type": "array" }, "fingerprint": { - "description": "Fingerprint hash of contents stored in this network interface. This field will be ignored when inserting an Instance or adding a NetworkInterface. An up-to-date fingerprint must be provided in order to update the NetworkInterface.", + "description": "Fingerprint hash of contents stored in this network interface. This field will be ignored when inserting an Instance or adding a NetworkInterface. An up-to-date fingerprint must be provided in order to update the NetworkInterface, otherwise the request will fail with error 412 conditionNotMet.", "format": "byte", "type": "string" }, @@ -30639,7 +33479,19 @@ "id": "NetworkPeering", "properties": { "autoCreateRoutes": { - "description": "Whether full mesh connectivity is created and managed automatically. When it is set to true, Google Compute Engine will automatically create and manage the routes between two networks when the state is ACTIVE. Otherwise, user needs to create routes manually to route packets to peer network.", + "description": "Indicates whether full mesh connectivity is created and managed automatically. When it is set to true, Google Compute Engine will automatically create and manage the routes between two networks when the state is ACTIVE. Otherwise, user needs to create routes manually to route packets to peer network.", + "type": "boolean" + }, + "exchangeSubnetRoutes": { + "description": "Whether full mesh connectivity is created and managed automatically. When it is set to true, Google Compute Engine will automatically create and manage the routes between two networks when the peering state is ACTIVE. Otherwise, user needs to create routes manually to route packets to peer network.", + "type": "boolean" + }, + "exportCustomRoutes": { + "description": "Whether to export the custom routes to peer network.", + "type": "boolean" + }, + "importCustomRoutes": { + "description": "Whether to import the custom routes from peer network.", "type": "boolean" }, "name": { @@ -30674,7 +33526,7 @@ "id": "NetworkRoutingConfig", "properties": { "routingMode": { - "description": "The network-wide routing mode to use. If set to REGIONAL, this network's cloud routers will only advertise routes with subnetworks of this network in the same region as the router. If set to GLOBAL, this network's cloud routers will advertise routes with all subnetworks of this network, across regions.", + "description": "The network-wide routing mode to use. If set to REGIONAL, this network's cloud routers will only advertise routes with subnets of this network in the same region as the router. If set to GLOBAL, this network's cloud routers will advertise routes with all subnets of this network, across regions.", "enum": [ "GLOBAL", "REGIONAL" @@ -30704,6 +33556,10 @@ "description": "Name of the peering, which should conform to RFC1035.", "type": "string" }, + "networkPeering": { + "$ref": "NetworkPeering", + "description": "Network peering parameters. In order to specify route policies for peering using import/export custom routes, you will have to fill all peering related parameters (name, peer network, exchange_subnet_routes) in network_peeringfield. Corresponding fields in NetworksAddPeeringRequest will be deprecated soon." + }, "peerNetwork": { "description": "URL of the peer network. It can be either full URL or partial URL. The peer network may belong to a different project. If the partial URL does not contain project, it is assumed that the peer network is in the same project as the current network.", "type": "string" @@ -30721,6 +33577,15 @@ }, "type": "object" }, + "NetworksUpdatePeeringRequest": { + "id": "NetworksUpdatePeeringRequest", + "properties": { + "networkPeering": { + "$ref": "NetworkPeering" + } + }, + "type": "object" + }, "NodeGroup": { "description": "A NodeGroup resource.", "id": "NodeGroup", @@ -30751,17 +33616,15 @@ "description": "The URL of the node template to which this node group belongs.", "type": "string" }, - "nodes": { - "description": "[Output Only] A list of nodes in this node group.", - "items": { - "$ref": "NodeGroupNode" - }, - "type": "array" - }, "selfLink": { "description": "[Output Only] Server-defined URL for the resource.", "type": "string" }, + "size": { + "description": "[Output Only] The total number of nodes in the node group.", + "format": "int32", + "type": "integer" + }, "status": { "enum": [ "CREATING", @@ -31031,12 +33894,14 @@ "CREATING", "DELETING", "INVALID", - "READY" + "READY", + "REPAIRING" ], "enumDescriptions": [ "", "", "", + "", "" ], "type": "string" @@ -31067,6 +33932,117 @@ }, "type": "object" }, + "NodeGroupsListNodes": { + "id": "NodeGroupsListNodes", + "properties": { + "id": { + "description": "[Output Only] Unique identifier for the resource; defined by the server.", + "type": "string" + }, + "items": { + "description": "A list of Node resources.", + "items": { + "$ref": "NodeGroupNode" + }, + "type": "array" + }, + "kind": { + "default": "compute#nodeGroupsListNodes", + "description": "[Output Only] The resource type, which is always compute.nodeGroupsListNodes for the list of nodes in the specified node group.", + "type": "string" + }, + "nextPageToken": { + "description": "[Output Only] This token allows you to get the next page of results for list requests. If the number of results is larger than maxResults, use the nextPageToken as a value for the query parameter pageToken in the next list request. Subsequent list requests will have their own nextPageToken to continue paging through the results.", + "type": "string" + }, + "selfLink": { + "description": "[Output Only] Server-defined URL for this resource.", + "type": "string" + }, + "warning": { + "description": "[Output Only] Informational warning message.", + "properties": { + "code": { + "description": "[Output Only] A warning code, if applicable. For example, Compute Engine returns NO_RESULTS_ON_PAGE if there are no results in the response.", + "enum": [ + "CLEANUP_FAILED", + "DEPRECATED_RESOURCE_USED", + "DEPRECATED_TYPE_USED", + "DISK_SIZE_LARGER_THAN_IMAGE_SIZE", + "EXPERIMENTAL_TYPE_USED", + "EXTERNAL_API_WARNING", + "FIELD_VALUE_OVERRIDEN", + "INJECTED_KERNELS_DEPRECATED", + "MISSING_TYPE_DEPENDENCY", + "NEXT_HOP_ADDRESS_NOT_ASSIGNED", + "NEXT_HOP_CANNOT_IP_FORWARD", + "NEXT_HOP_INSTANCE_NOT_FOUND", + "NEXT_HOP_INSTANCE_NOT_ON_NETWORK", + "NEXT_HOP_NOT_RUNNING", + "NOT_CRITICAL_ERROR", + "NO_RESULTS_ON_PAGE", + "REQUIRED_TOS_AGREEMENT", + "RESOURCE_IN_USE_BY_OTHER_RESOURCE_WARNING", + "RESOURCE_NOT_DELETED", + "SCHEMA_VALIDATION_IGNORED", + "SINGLE_INSTANCE_PROPERTY_TEMPLATE", + "UNDECLARED_PROPERTIES", + "UNREACHABLE" + ], + "enumDescriptions": [ + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "" + ], + "type": "string" + }, + "data": { + "description": "[Output Only] Metadata about this warning in key: value format. For example:\n\"data\": [ { \"key\": \"scope\", \"value\": \"zones/us-east1-d\" }", + "items": { + "properties": { + "key": { + "description": "[Output Only] A key that provides more detail on the warning being returned. For example, for warnings where there are no results in a list request for a particular zone, this key might be scope and the key value might be the zone name. Other examples might be a key indicating a deprecated resource and a suggested replacement, or a warning about invalid network settings (for example, if an instance attempts to perform IP forwarding but is not enabled for IP forwarding).", + "type": "string" + }, + "value": { + "description": "[Output Only] A warning data value corresponding to the key.", + "type": "string" + } + }, + "type": "object" + }, + "type": "array" + }, + "message": { + "description": "[Output Only] A human-readable description of the warning code.", + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object" + }, "NodeGroupsScopedList": { "id": "NodeGroupsScopedList", "properties": { @@ -31194,7 +34170,7 @@ "type": "string" }, "name": { - "description": "The name of the resource, provided by the client when initially creating the resource. The resource name must be 1-63 characters long, and comply with RFC1035. Specifically, the name must be 1-63 characters long and match the regular expression `[a-z]([-a-z0-9]*[a-z0-9])?` which means the first character must be a lowercase letter, and all following characters must be a dash, lowercase letter, or digit, except the last charaicter, which cannot be a dash.", + "description": "The name of the resource, provided by the client when initially creating the resource. The resource name must be 1-63 characters long, and comply with RFC1035. Specifically, the name must be 1-63 characters long and match the regular expression `[a-z]([-a-z0-9]*[a-z0-9])?` which means the first character must be a lowercase letter, and all following characters must be a dash, lowercase letter, or digit, except the last character, which cannot be a dash.", "type": "string" }, "nodeAffinityLabels": { @@ -32495,7 +35471,7 @@ "id": "PathMatcher", "properties": { "defaultService": { - "description": "The full or partial URL to the BackendService resource. This will be used if none of the pathRules defined by this PathMatcher is matched by the URL's path portion. For example, the following are all valid URLs to a BackendService resource: \n- https://www.googleapis.com/compute/v1/projects/project/global/backendServices/backendService \n- compute/v1/projects/project/global/backendServices/backendService \n- global/backendServices/backendService", + "description": "The full or partial URL to the BackendService resource. This will be used if none of the pathRules or routeRules defined by this PathMatcher are matched. For example, the following are all valid URLs to a BackendService resource: \n- https://www.googleapis.com/compute/v1/projects/project/global/backendServices/backendService \n- compute/v1/projects/project/global/backendServices/backendService \n- global/backendServices/backendService \nUse defaultService instead of defaultRouteAction when simple routing to a backend service is desired and other advanced capabilities like traffic splitting and URL rewrites are not required.\nOnly one of defaultService, defaultRouteAction or defaultUrlRedirect must be set.\nAuthorization requires one or more of the following Google IAM permissions on the specified resource default_service: \n- compute.backendBuckets.use \n- compute.backendServices.use", "type": "string" }, "description": { @@ -32507,7 +35483,7 @@ "type": "string" }, "pathRules": { - "description": "The list of path rules.", + "description": "The list of path rules. Use this list instead of routeRules when routing based on simple path matching is all that's required. The order by which path rules are specified does not matter. Matches are always done on the longest-path-first basis.\nFor example: a pathRule with a path /a/b/c/* will match before /a/b/* irrespective of the order in which those paths appear in this list.\nOnly one of pathRules or routeRules must be set.", "items": { "$ref": "PathRule" }, @@ -32528,7 +35504,7 @@ "type": "array" }, "service": { - "description": "The URL of the BackendService resource if this rule is matched.", + "description": "The URL of the backend service resource if this rule is matched.\nUse service instead of routeAction when simple routing to a backend service is desired and other advanced capabilities like traffic splitting and rewrites are not required.\nOnly one of service, routeAction or urlRedirect should must be set.", "type": "string" } }, @@ -32763,6 +35739,8 @@ "DISKS_TOTAL_GB", "FIREWALLS", "FORWARDING_RULES", + "GLOBAL_INTERNAL_ADDRESSES", + "GPUS_ALL_REGIONS", "HEALTH_CHECKS", "IMAGES", "INSTANCES", @@ -32774,19 +35752,31 @@ "INTERCONNECT_ATTACHMENTS_TOTAL_MBPS", "INTERNAL_ADDRESSES", "IN_USE_ADDRESSES", + "IN_USE_BACKUP_SCHEDULES", "LOCAL_SSD_TOTAL_GB", "NETWORKS", "NETWORK_ENDPOINT_GROUPS", "NVIDIA_K80_GPUS", "NVIDIA_P100_GPUS", + "NVIDIA_P100_VWS_GPUS", + "NVIDIA_P4_GPUS", + "NVIDIA_P4_VWS_GPUS", + "NVIDIA_T4_GPUS", + "NVIDIA_T4_VWS_GPUS", "NVIDIA_V100_GPUS", "PREEMPTIBLE_CPUS", "PREEMPTIBLE_LOCAL_SSD_GB", "PREEMPTIBLE_NVIDIA_K80_GPUS", "PREEMPTIBLE_NVIDIA_P100_GPUS", + "PREEMPTIBLE_NVIDIA_P100_VWS_GPUS", + "PREEMPTIBLE_NVIDIA_P4_GPUS", + "PREEMPTIBLE_NVIDIA_P4_VWS_GPUS", + "PREEMPTIBLE_NVIDIA_T4_GPUS", + "PREEMPTIBLE_NVIDIA_T4_VWS_GPUS", "PREEMPTIBLE_NVIDIA_V100_GPUS", "REGIONAL_AUTOSCALERS", "REGIONAL_INSTANCE_GROUP_MANAGERS", + "RESOURCE_POLICIES", "ROUTERS", "ROUTES", "SECURITY_POLICIES", @@ -32804,6 +35794,7 @@ "TARGET_TCP_PROXIES", "TARGET_VPN_GATEWAYS", "URL_MAPS", + "VPN_GATEWAYS", "VPN_TUNNELS" ], "enumDescriptions": [ @@ -32857,6 +35848,21 @@ "", "", "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", "" ], "type": "string" @@ -33179,6 +36185,32 @@ }, "type": "object" }, + "RegionDisksAddResourcePoliciesRequest": { + "id": "RegionDisksAddResourcePoliciesRequest", + "properties": { + "resourcePolicies": { + "description": "Resource policies to be added to this disk.", + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object" + }, + "RegionDisksRemoveResourcePoliciesRequest": { + "id": "RegionDisksRemoveResourcePoliciesRequest", + "properties": { + "resourcePolicies": { + "description": "Resource policies to be removed from this disk.", + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object" + }, "RegionDisksResizeRequest": { "id": "RegionDisksResizeRequest", "properties": { @@ -33844,7 +36876,546 @@ "id": "ResourceGroupReference", "properties": { "group": { - "description": "A URI referencing one of the instance groups listed in the backend service.", + "description": "A URI referencing one of the instance groups or network endpoint groups listed in the backend service.", + "type": "string" + } + }, + "type": "object" + }, + "ResourcePoliciesScopedList": { + "id": "ResourcePoliciesScopedList", + "properties": { + "resourcePolicies": { + "description": "A list of resourcePolicies contained in this scope.", + "items": { + "$ref": "ResourcePolicy" + }, + "type": "array" + }, + "warning": { + "description": "Informational warning which replaces the list of resourcePolicies when the list is empty.", + "properties": { + "code": { + "description": "[Output Only] A warning code, if applicable. For example, Compute Engine returns NO_RESULTS_ON_PAGE if there are no results in the response.", + "enum": [ + "CLEANUP_FAILED", + "DEPRECATED_RESOURCE_USED", + "DEPRECATED_TYPE_USED", + "DISK_SIZE_LARGER_THAN_IMAGE_SIZE", + "EXPERIMENTAL_TYPE_USED", + "EXTERNAL_API_WARNING", + "FIELD_VALUE_OVERRIDEN", + "INJECTED_KERNELS_DEPRECATED", + "MISSING_TYPE_DEPENDENCY", + "NEXT_HOP_ADDRESS_NOT_ASSIGNED", + "NEXT_HOP_CANNOT_IP_FORWARD", + "NEXT_HOP_INSTANCE_NOT_FOUND", + "NEXT_HOP_INSTANCE_NOT_ON_NETWORK", + "NEXT_HOP_NOT_RUNNING", + "NOT_CRITICAL_ERROR", + "NO_RESULTS_ON_PAGE", + "REQUIRED_TOS_AGREEMENT", + "RESOURCE_IN_USE_BY_OTHER_RESOURCE_WARNING", + "RESOURCE_NOT_DELETED", + "SCHEMA_VALIDATION_IGNORED", + "SINGLE_INSTANCE_PROPERTY_TEMPLATE", + "UNDECLARED_PROPERTIES", + "UNREACHABLE" + ], + "enumDescriptions": [ + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "" + ], + "type": "string" + }, + "data": { + "description": "[Output Only] Metadata about this warning in key: value format. For example:\n\"data\": [ { \"key\": \"scope\", \"value\": \"zones/us-east1-d\" }", + "items": { + "properties": { + "key": { + "description": "[Output Only] A key that provides more detail on the warning being returned. For example, for warnings where there are no results in a list request for a particular zone, this key might be scope and the key value might be the zone name. Other examples might be a key indicating a deprecated resource and a suggested replacement, or a warning about invalid network settings (for example, if an instance attempts to perform IP forwarding but is not enabled for IP forwarding).", + "type": "string" + }, + "value": { + "description": "[Output Only] A warning data value corresponding to the key.", + "type": "string" + } + }, + "type": "object" + }, + "type": "array" + }, + "message": { + "description": "[Output Only] A human-readable description of the warning code.", + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object" + }, + "ResourcePolicy": { + "id": "ResourcePolicy", + "properties": { + "backupSchedulePolicy": { + "$ref": "ResourcePolicyBackupSchedulePolicy", + "description": "Resource policy for persistent disks for creating snapshots." + }, + "creationTimestamp": { + "description": "[Output Only] Creation timestamp in RFC3339 text format.", + "type": "string" + }, + "description": { + "type": "string" + }, + "id": { + "description": "[Output Only] The unique identifier for the resource. This identifier is defined by the server.", + "format": "uint64", + "type": "string" + }, + "kind": { + "default": "compute#resourcePolicy", + "description": "[Output Only] Type of the resource. Always compute#resource_policies for resource policies.", + "type": "string" + }, + "name": { + "annotations": { + "required": [ + "compute.instances.insert" + ] + }, + "description": "The name of the resource, provided by the client when initially creating the resource. The resource name must be 1-63 characters long, and comply with RFC1035. Specifically, the name must be 1-63 characters long and match the regular expression `[a-z]([-a-z0-9]*[a-z0-9])?` which means the first character must be a lowercase letter, and all following characters must be a dash, lowercase letter, or digit, except the last character, which cannot be a dash.", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "type": "string" + }, + "region": { + "type": "string" + }, + "selfLink": { + "description": "[Output Only] Server-defined fully-qualified URL for this resource.", + "type": "string" + } + }, + "type": "object" + }, + "ResourcePolicyAggregatedList": { + "description": "Contains a list of resourcePolicies.", + "id": "ResourcePolicyAggregatedList", + "properties": { + "etag": { + "type": "string" + }, + "id": { + "description": "[Output Only] Unique identifier for the resource; defined by the server.", + "type": "string" + }, + "items": { + "additionalProperties": { + "$ref": "ResourcePoliciesScopedList", + "description": "Name of the scope containing this set of resourcePolicies." + }, + "description": "A list of ResourcePolicy resources.", + "type": "object" + }, + "kind": { + "default": "compute#resourcePolicyAggregatedList", + "description": "Type of resource.", + "type": "string" + }, + "nextPageToken": { + "description": "[Output Only] This token allows you to get the next page of results for list requests. If the number of results is larger than maxResults, use the nextPageToken as a value for the query parameter pageToken in the next list request. Subsequent list requests will have their own nextPageToken to continue paging through the results.", + "type": "string" + }, + "selfLink": { + "description": "[Output Only] Server-defined URL for this resource.", + "type": "string" + }, + "warning": { + "description": "[Output Only] Informational warning message.", + "properties": { + "code": { + "description": "[Output Only] A warning code, if applicable. For example, Compute Engine returns NO_RESULTS_ON_PAGE if there are no results in the response.", + "enum": [ + "CLEANUP_FAILED", + "DEPRECATED_RESOURCE_USED", + "DEPRECATED_TYPE_USED", + "DISK_SIZE_LARGER_THAN_IMAGE_SIZE", + "EXPERIMENTAL_TYPE_USED", + "EXTERNAL_API_WARNING", + "FIELD_VALUE_OVERRIDEN", + "INJECTED_KERNELS_DEPRECATED", + "MISSING_TYPE_DEPENDENCY", + "NEXT_HOP_ADDRESS_NOT_ASSIGNED", + "NEXT_HOP_CANNOT_IP_FORWARD", + "NEXT_HOP_INSTANCE_NOT_FOUND", + "NEXT_HOP_INSTANCE_NOT_ON_NETWORK", + "NEXT_HOP_NOT_RUNNING", + "NOT_CRITICAL_ERROR", + "NO_RESULTS_ON_PAGE", + "REQUIRED_TOS_AGREEMENT", + "RESOURCE_IN_USE_BY_OTHER_RESOURCE_WARNING", + "RESOURCE_NOT_DELETED", + "SCHEMA_VALIDATION_IGNORED", + "SINGLE_INSTANCE_PROPERTY_TEMPLATE", + "UNDECLARED_PROPERTIES", + "UNREACHABLE" + ], + "enumDescriptions": [ + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "" + ], + "type": "string" + }, + "data": { + "description": "[Output Only] Metadata about this warning in key: value format. For example:\n\"data\": [ { \"key\": \"scope\", \"value\": \"zones/us-east1-d\" }", + "items": { + "properties": { + "key": { + "description": "[Output Only] A key that provides more detail on the warning being returned. For example, for warnings where there are no results in a list request for a particular zone, this key might be scope and the key value might be the zone name. Other examples might be a key indicating a deprecated resource and a suggested replacement, or a warning about invalid network settings (for example, if an instance attempts to perform IP forwarding but is not enabled for IP forwarding).", + "type": "string" + }, + "value": { + "description": "[Output Only] A warning data value corresponding to the key.", + "type": "string" + } + }, + "type": "object" + }, + "type": "array" + }, + "message": { + "description": "[Output Only] A human-readable description of the warning code.", + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object" + }, + "ResourcePolicyBackupSchedulePolicy": { + "description": "A backup schedule policy specifies when and how frequently snapshots are to be created for the target disk. Also specifies how many and how long these scheduled snapshots should be retained.", + "id": "ResourcePolicyBackupSchedulePolicy", + "properties": { + "retentionPolicy": { + "$ref": "ResourcePolicyBackupSchedulePolicyRetentionPolicy", + "description": "Retention policy applied to snapshots created by this resource policy." + }, + "schedule": { + "$ref": "ResourcePolicyBackupSchedulePolicySchedule", + "description": "A Vm Maintenance Policy specifies what kind of infrastructure maintenance we are allowed to perform on this VM and when. Schedule that is applied to disks covered by this policy." + }, + "snapshotProperties": { + "$ref": "ResourcePolicyBackupSchedulePolicySnapshotProperties", + "description": "Properties with which snapshots are created such as labels, encryption keys." + } + }, + "type": "object" + }, + "ResourcePolicyBackupSchedulePolicyRetentionPolicy": { + "description": "Policy for retention of scheduled snapshots.", + "id": "ResourcePolicyBackupSchedulePolicyRetentionPolicy", + "properties": { + "maxRetentionDays": { + "description": "Maximum age of the snapshot that is allowed to be kept.", + "format": "int32", + "type": "integer" + }, + "onSourceDiskDelete": { + "description": "Specifies the behavior to apply to scheduled snapshots when the source disk is deleted.", + "enum": [ + "APPLY_RETENTION_POLICY", + "KEEP_AUTO_SNAPSHOTS", + "UNSPECIFIED_ON_SOURCE_DISK_DELETE" + ], + "enumDescriptions": [ + "", + "", + "" + ], + "type": "string" + } + }, + "type": "object" + }, + "ResourcePolicyBackupSchedulePolicySchedule": { + "description": "A schedule for disks where the schedueled operations are performed.", + "id": "ResourcePolicyBackupSchedulePolicySchedule", + "properties": { + "dailySchedule": { + "$ref": "ResourcePolicyDailyCycle" + }, + "hourlySchedule": { + "$ref": "ResourcePolicyHourlyCycle" + }, + "weeklySchedule": { + "$ref": "ResourcePolicyWeeklyCycle" + } + }, + "type": "object" + }, + "ResourcePolicyBackupSchedulePolicySnapshotProperties": { + "description": "Specified snapshot properties for scheduled snapshots created by this policy.", + "id": "ResourcePolicyBackupSchedulePolicySnapshotProperties", + "properties": { + "guestFlush": { + "description": "Indication to perform a ?guest aware? snapshot.", + "type": "boolean" + }, + "labels": { + "additionalProperties": { + "type": "string" + }, + "description": "Labels to apply to scheduled snapshots. These can be later modified by the setLabels method. Label values may be empty.", + "type": "object" + } + }, + "type": "object" + }, + "ResourcePolicyDailyCycle": { + "description": "Time window specified for daily operations.", + "id": "ResourcePolicyDailyCycle", + "properties": { + "daysInCycle": { + "description": "Allows to define schedule that runs every nth day of the month.", + "format": "int32", + "type": "integer" + }, + "duration": { + "description": "[Output only] Duration of the time window, automatically chosen to be smallest possible in the given scenario.", + "type": "string" + }, + "startTime": { + "description": "Time within the window to start the operations. It must be in format \"HH:MM\", where HH : [00-23] and MM : [00-00] GMT.", + "type": "string" + } + }, + "type": "object" + }, + "ResourcePolicyHourlyCycle": { + "description": "Time window specified for hourly operations.", + "id": "ResourcePolicyHourlyCycle", + "properties": { + "duration": { + "description": "[Output only] Duration of the time window, automatically chosen to be smallest possible in the given scenario.", + "type": "string" + }, + "hoursInCycle": { + "description": "Allows to define schedule that runs every nth hour.", + "format": "int32", + "type": "integer" + }, + "startTime": { + "description": "Time within the window to start the operations. It must be in format \"HH:MM\", where HH : [00-23] and MM : [00-00] GMT.", + "type": "string" + } + }, + "type": "object" + }, + "ResourcePolicyList": { + "id": "ResourcePolicyList", + "properties": { + "etag": { + "type": "string" + }, + "id": { + "description": "[Output Only] The unique identifier for the resource. This identifier is defined by the server.", + "type": "string" + }, + "items": { + "description": "[Output Only] A list of ResourcePolicy resources.", + "items": { + "$ref": "ResourcePolicy" + }, + "type": "array" + }, + "kind": { + "default": "compute#resourcePolicyList", + "description": "[Output Only] Type of resource.Always compute#resourcePoliciesList for listsof resourcePolicies", + "type": "string" + }, + "nextPageToken": { + "description": "[Output Only] This token allows you to get the next page of results for list requests. If the number of results is larger than maxResults, use the nextPageToken as a value for the query parameter pageToken in the next list request. Subsequent list requests will have their own nextPageToken to continue paging through the results.", + "type": "string" + }, + "selfLink": { + "description": "[Output Only] Server-defined URL for this resource.", + "type": "string" + }, + "warning": { + "description": "[Output Only] Informational warning message.", + "properties": { + "code": { + "description": "[Output Only] A warning code, if applicable. For example, Compute Engine returns NO_RESULTS_ON_PAGE if there are no results in the response.", + "enum": [ + "CLEANUP_FAILED", + "DEPRECATED_RESOURCE_USED", + "DEPRECATED_TYPE_USED", + "DISK_SIZE_LARGER_THAN_IMAGE_SIZE", + "EXPERIMENTAL_TYPE_USED", + "EXTERNAL_API_WARNING", + "FIELD_VALUE_OVERRIDEN", + "INJECTED_KERNELS_DEPRECATED", + "MISSING_TYPE_DEPENDENCY", + "NEXT_HOP_ADDRESS_NOT_ASSIGNED", + "NEXT_HOP_CANNOT_IP_FORWARD", + "NEXT_HOP_INSTANCE_NOT_FOUND", + "NEXT_HOP_INSTANCE_NOT_ON_NETWORK", + "NEXT_HOP_NOT_RUNNING", + "NOT_CRITICAL_ERROR", + "NO_RESULTS_ON_PAGE", + "REQUIRED_TOS_AGREEMENT", + "RESOURCE_IN_USE_BY_OTHER_RESOURCE_WARNING", + "RESOURCE_NOT_DELETED", + "SCHEMA_VALIDATION_IGNORED", + "SINGLE_INSTANCE_PROPERTY_TEMPLATE", + "UNDECLARED_PROPERTIES", + "UNREACHABLE" + ], + "enumDescriptions": [ + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "" + ], + "type": "string" + }, + "data": { + "description": "[Output Only] Metadata about this warning in key: value format. For example:\n\"data\": [ { \"key\": \"scope\", \"value\": \"zones/us-east1-d\" }", + "items": { + "properties": { + "key": { + "description": "[Output Only] A key that provides more detail on the warning being returned. For example, for warnings where there are no results in a list request for a particular zone, this key might be scope and the key value might be the zone name. Other examples might be a key indicating a deprecated resource and a suggested replacement, or a warning about invalid network settings (for example, if an instance attempts to perform IP forwarding but is not enabled for IP forwarding).", + "type": "string" + }, + "value": { + "description": "[Output Only] A warning data value corresponding to the key.", + "type": "string" + } + }, + "type": "object" + }, + "type": "array" + }, + "message": { + "description": "[Output Only] A human-readable description of the warning code.", + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object" + }, + "ResourcePolicyWeeklyCycle": { + "description": "Time window specified for weekly operations.", + "id": "ResourcePolicyWeeklyCycle", + "properties": { + "dayOfWeeks": { + "description": "Up to 7 intervals/windows, one for each day of the week.", + "items": { + "$ref": "ResourcePolicyWeeklyCycleDayOfWeek" + }, + "type": "array" + } + }, + "type": "object" + }, + "ResourcePolicyWeeklyCycleDayOfWeek": { + "id": "ResourcePolicyWeeklyCycleDayOfWeek", + "properties": { + "day": { + "description": "Allows to define schedule that runs specified day of the week.", + "enum": [ + "FRIDAY", + "INVALID", + "MONDAY", + "SATURDAY", + "SUNDAY", + "THURSDAY", + "TUESDAY", + "WEDNESDAY" + ], + "enumDescriptions": [ + "", + "", + "", + "", + "", + "", + "", + "" + ], + "type": "string" + }, + "duration": { + "description": "[Output only] Duration of the time window, automatically chosen to be smallest possible in the given scenario.", + "type": "string" + }, + "startTime": { + "description": "Time within the window to start the operations. It must be in format \"HH:MM\", where HH : [00-23] and MM : [00-00] GMT.", "type": "string" } }, @@ -33904,6 +37475,10 @@ "description": "The URL to a gateway that should handle matching packets. You can only specify the internet gateway using a full or partial valid URL: projects/\u003cproject-id\u003e/global/gateways/default-internet-gateway", "type": "string" }, + "nextHopIlb": { + "description": "The URL to a forwarding rule of type loadBalancingScheme=INTERNAL that should handle matching packets. You can only specify the forwarding rule as a partial or full URL. For example, the following are all valid URLs: \n- https://www.googleapis.com/compute/v1/projects/project/regions/region/forwardingRules/forwardingRule \n- regions/region/forwardingRules/forwardingRule Note that this can only be used when the destination_range is a public (non-RFC 1918) IP CIDR range.", + "type": "string" + }, "nextHopInstance": { "description": "The URL to an instance that should handle matching packets. You can specify this as a full or partial URL. For example:\nhttps://www.googleapis.com/compute/v1/projects/project/zones/zone/instances/", "type": "string" @@ -34199,6 +37774,13 @@ "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", "type": "string" }, + "nats": { + "description": "A list of Nat services created in this router.", + "items": { + "$ref": "RouterNat" + }, + "type": "array" + }, "network": { "annotations": { "required": [ @@ -34439,7 +38021,7 @@ "type": "string" }, "managementType": { - "description": "[Output Only] Type of how the resource/configuration of the BGP peer is managed. MANAGED_BY_USER is the default value; MANAGED_BY_ATTACHMENT represents an BGP peer that is automatically created for PARTNER interconnectAttachment, Google will automatically create/delete this type of BGP peer when the PARTNER interconnectAttachment is created/deleted.", + "description": "[Output Only] The resource that configures and manages this BGP peer. MANAGED_BY_USER is the default value and can be managed by you or other users; MANAGED_BY_ATTACHMENT is a BGP peer that is configured and managed by Cloud Interconnect, specifically by an InterconnectAttachment of type PARTNER. Google will automatically create, update, and delete this type of BGP peer when the PARTNER InterconnectAttachment is created, updated, or deleted.", "enum": [ "MANAGED_BY_ATTACHMENT", "MANAGED_BY_USER" @@ -34483,7 +38065,7 @@ "type": "string" }, "managementType": { - "description": "[Output Only] Type of how the resource/configuration of the interface is managed. MANAGED_BY_USER is the default value; MANAGED_BY_ATTACHMENT represents an interface that is automatically created for PARTNER type interconnectAttachment, Google will automatically create/update/delete this type of interface when the PARTNER interconnectAttachment is created/provisioned/deleted.", + "description": "[Output Only] The resource that configures and manages this interface. MANAGED_BY_USER is the default value and can be managed by you or other users; MANAGED_BY_ATTACHMENT is an interface that is configured and managed by Cloud Interconnect, specifically by an InterconnectAttachment of type PARTNER. Google will automatically create, update, and delete this type of interface when the PARTNER InterconnectAttachment is created, updated, or deleted.", "enum": [ "MANAGED_BY_ATTACHMENT", "MANAGED_BY_USER" @@ -34614,6 +38196,118 @@ }, "type": "object" }, + "RouterNat": { + "description": "Represents a Nat resource. It enables the VMs within the specified subnetworks to access Internet without external IP addresses. It specifies a list of subnetworks (and the ranges within) that want to use NAT. Customers can also provide the external IPs that would be used for NAT. GCP would auto-allocate ephemeral IPs if no external IPs are provided.", + "id": "RouterNat", + "properties": { + "icmpIdleTimeoutSec": { + "description": "Timeout (in seconds) for ICMP connections. Defaults to 30s if not set.", + "format": "int32", + "type": "integer" + }, + "minPortsPerVm": { + "description": "Minimum number of ports allocated to a VM from this NAT config. If not set, a default number of ports is allocated to a VM. This gets rounded up to the nearest power of 2. Eg. if the value of this field is 50, at least 64 ports will be allocated to a VM.", + "format": "int32", + "type": "integer" + }, + "name": { + "description": "Unique name of this Nat service. The name must be 1-63 characters long and comply with RFC1035.", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "type": "string" + }, + "natIpAllocateOption": { + "description": "Specify the NatIpAllocateOption. If it is AUTO_ONLY, then nat_ip should be empty.", + "enum": [ + "AUTO_ONLY", + "MANUAL_ONLY" + ], + "enumDescriptions": [ + "", + "" + ], + "type": "string" + }, + "natIps": { + "description": "A list of URLs of the IP resources used for this Nat service. These IPs must be valid static external IP addresses assigned to the project. max_length is subject to change post alpha.", + "items": { + "type": "string" + }, + "type": "array" + }, + "sourceSubnetworkIpRangesToNat": { + "description": "Specify the Nat option. If this field contains ALL_SUBNETWORKS_ALL_IP_RANGES or ALL_SUBNETWORKS_ALL_PRIMARY_IP_RANGES, then there should not be any other Router.Nat section in any Router for this network in this region.", + "enum": [ + "ALL_SUBNETWORKS_ALL_IP_RANGES", + "ALL_SUBNETWORKS_ALL_PRIMARY_IP_RANGES", + "LIST_OF_SUBNETWORKS" + ], + "enumDescriptions": [ + "", + "", + "" + ], + "type": "string" + }, + "subnetworks": { + "description": "A list of Subnetwork resources whose traffic should be translated by NAT Gateway. It is used only when LIST_OF_SUBNETWORKS is selected for the SubnetworkIpRangeToNatOption above.", + "items": { + "$ref": "RouterNatSubnetworkToNat" + }, + "type": "array" + }, + "tcpEstablishedIdleTimeoutSec": { + "description": "Timeout (in seconds) for TCP established connections. Defaults to 1200s if not set.", + "format": "int32", + "type": "integer" + }, + "tcpTransitoryIdleTimeoutSec": { + "description": "Timeout (in seconds) for TCP transitory connections. Defaults to 30s if not set.", + "format": "int32", + "type": "integer" + }, + "udpIdleTimeoutSec": { + "description": "Timeout (in seconds) for UDP connections. Defaults to 30s if not set.", + "format": "int32", + "type": "integer" + } + }, + "type": "object" + }, + "RouterNatSubnetworkToNat": { + "description": "Defines the IP ranges that want to use NAT for a subnetwork.", + "id": "RouterNatSubnetworkToNat", + "properties": { + "name": { + "description": "URL for the subnetwork resource to use NAT.", + "type": "string" + }, + "secondaryIpRangeNames": { + "description": "A list of the secondary ranges of the Subnetwork that are allowed to use NAT. This can be populated only if \"LIST_OF_SECONDARY_IP_RANGES\" is one of the values in source_ip_ranges_to_nat.", + "items": { + "type": "string" + }, + "type": "array" + }, + "sourceIpRangesToNat": { + "description": "Specify the options for NAT ranges in the Subnetwork. All usages of single value are valid except NAT_IP_RANGE_OPTION_UNSPECIFIED. The only valid option with multiple values is: [\"PRIMARY_IP_RANGE\", \"LIST_OF_SECONDARY_IP_RANGES\"] Default: [ALL_IP_RANGES]", + "items": { + "enum": [ + "ALL_IP_RANGES", + "LIST_OF_SECONDARY_IP_RANGES", + "PRIMARY_IP_RANGE" + ], + "enumDescriptions": [ + "", + "", + "" + ], + "type": "string" + }, + "type": "array" + } + }, + "type": "object" + }, "RouterStatus": { "id": "RouterStatus", "properties": { @@ -34637,6 +38331,12 @@ }, "type": "array" }, + "natStatus": { + "items": { + "$ref": "RouterStatusNatStatus" + }, + "type": "array" + }, "network": { "description": "URI of the network to which this router belongs.", "type": "string" @@ -34704,6 +38404,48 @@ }, "type": "object" }, + "RouterStatusNatStatus": { + "description": "Status of a NAT contained in this router.", + "id": "RouterStatusNatStatus", + "properties": { + "autoAllocatedNatIps": { + "description": "A list of IPs auto-allocated for NAT. Example: [\"1.1.1.1\", \"129.2.16.89\"]", + "items": { + "type": "string" + }, + "type": "array" + }, + "minExtraNatIpsNeeded": { + "description": "The number of extra IPs to allocate. This will be greater than 0 only if user-specified IPs are NOT enough to allow all configured VMs to use NAT. This value is meaningful only when auto-allocation of NAT IPs is *not* used.", + "format": "int32", + "type": "integer" + }, + "name": { + "description": "Unique name of this NAT.", + "type": "string" + }, + "numVmEndpointsWithNatMappings": { + "description": "Number of VM endpoints (i.e., Nics) that can use NAT.", + "format": "int32", + "type": "integer" + }, + "userAllocatedNatIpResources": { + "description": "A list of fully qualified URLs of reserved IP address resources.", + "items": { + "type": "string" + }, + "type": "array" + }, + "userAllocatedNatIps": { + "description": "A list of IPs user-allocated for NAT. They will be raw IP strings like \"179.12.26.133\".", + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object" + }, "RouterStatusResponse": { "id": "RouterStatusResponse", "properties": { @@ -35022,7 +38764,7 @@ "type": "object" }, "SecurityPolicy": { - "description": "A security policy is comprised of one or more rules. It can also be associated with one or more 'targets'. Next available tag: 11", + "description": "A security policy is comprised of one or more rules. It can also be associated with one or more 'targets'. (== resource_for v1.securityPolicies ==) (== resource_for beta.securityPolicies ==)", "id": "SecurityPolicy", "properties": { "creationTimestamp": { @@ -35034,7 +38776,7 @@ "type": "string" }, "fingerprint": { - "description": "Specifies a fingerprint for this resource, which is essentially a hash of the metadata's contents and used for optimistic locking. The fingerprint is initially generated by Compute Engine and changes after every request to modify or update metadata. You must always provide an up-to-date fingerprint hash in order to update or change metadata.\n\nTo see the latest fingerprint, make get() request to the security policy.", + "description": "Specifies a fingerprint for this resource, which is essentially a hash of the metadata's contents and used for optimistic locking. The fingerprint is initially generated by Compute Engine and changes after every request to modify or update metadata. You must always provide an up-to-date fingerprint hash in order to update or change metadata, otherwise the request will fail with error 412 conditionNotMet.\n\nTo see the latest fingerprint, make get() request to the security policy.", "format": "byte", "type": "string" }, @@ -35048,6 +38790,18 @@ "description": "[Output only] Type of the resource. Always compute#securityPolicyfor security policies", "type": "string" }, + "labelFingerprint": { + "description": "A fingerprint for the labels being applied to this security policy, which is essentially a hash of the labels set used for optimistic locking. The fingerprint is initially generated by Compute Engine and changes after every request to modify or update labels. You must always provide an up-to-date fingerprint hash in order to update or change labels.\n\nTo see the latest fingerprint, make get() request to the security policy.", + "format": "byte", + "type": "string" + }, + "labels": { + "additionalProperties": { + "type": "string" + }, + "description": "Labels to apply to this security policy resource. These can be later modified by the setLabels method. Each label key/value must comply with RFC1035. Label values may be empty.", + "type": "object" + }, "name": { "description": "Name of the resource. Provided by the client when the resource is created. The name must be 1-63 characters long, and comply with RFC1035. Specifically, the name must be 1-63 characters long and match the regular expression `[a-z]([-a-z0-9]*[a-z0-9])?` which means the first character must be a lowercase letter, and all following characters must be a dash, lowercase letter, or digit, except the last character, which cannot be a dash.", "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", @@ -35209,7 +38963,7 @@ "type": "boolean" }, "priority": { - "description": "An integer indicating the priority of a rule in the list. The priority must be a positive value between 0 and 2147483647. Rules are evaluated in the increasing order of priority.", + "description": "An integer indicating the priority of a rule in the list. The priority must be a positive value between 0 and 2147483647. Rules are evaluated from highest to lowest priority where 0 is the highest priority and 2147483647 is the lowest prority.", "format": "int32", "type": "integer" } @@ -35228,21 +38982,12 @@ "$ref": "Expr", "description": "User defined CEVAL expression. A CEVAL expression is used to specify match criteria such as origin.ip, source.region_code and contents in the request header." }, - "srcIpRanges": { - "description": "CIDR IP address range.", - "items": { - "type": "string" - }, - "type": "array" - }, "versionedExpr": { "description": "Preconfigured versioned expression. If this field is specified, config must also be specified. Available preconfigured expressions along with their requirements are: SRC_IPS_V1 - must specify the corresponding src_ip_range field in config.", "enum": [ - "SRC_IPS_V1", - "VERSIONED_EXPR_UNSPECIFIED" + "SRC_IPS_V1" ], "enumDescriptions": [ - "", "" ], "type": "string" @@ -35316,26 +39061,61 @@ "id": "ShieldedVmConfig", "properties": { "enableIntegrityMonitoring": { - "description": "Defines whether the instance should have integrity monitoring enabled.", + "description": "Defines whether the instance has integrity monitoring enabled.", "type": "boolean" }, "enableSecureBoot": { - "description": "Defines whether the instance should have secure boot enabled.", + "description": "Defines whether the instance has Secure Boot enabled.", "type": "boolean" }, "enableVtpm": { - "description": "Defines whether the instance should have the TPM enabled.", + "description": "Defines whether the instance has the vTPM enabled.", "type": "boolean" } }, "type": "object" }, + "ShieldedVmIdentity": { + "description": "A shielded VM identity entry.", + "id": "ShieldedVmIdentity", + "properties": { + "encryptionKey": { + "$ref": "ShieldedVmIdentityEntry", + "description": "An Endorsement Key (EK) issued to the Shielded VM's vTPM." + }, + "kind": { + "default": "compute#shieldedVmIdentity", + "description": "[Output Only] Type of the resource. Always compute#shieldedVmIdentity for shielded VM identity entry.", + "type": "string" + }, + "signingKey": { + "$ref": "ShieldedVmIdentityEntry", + "description": "An Attestation Key (AK) issued to the Shielded VM's vTPM." + } + }, + "type": "object" + }, + "ShieldedVmIdentityEntry": { + "description": "A Shielded VM Identity Entry.", + "id": "ShieldedVmIdentityEntry", + "properties": { + "ekCert": { + "description": "A PEM-encoded X.509 certificate. This field can be empty.", + "type": "string" + }, + "ekPub": { + "description": "A PEM-encoded public key.", + "type": "string" + } + }, + "type": "object" + }, "ShieldedVmIntegrityPolicy": { - "description": "The policy describes how boot integrity measurements are evaluated.", + "description": "The policy describes the baseline against which VM instance boot integrity is measured.", "id": "ShieldedVmIntegrityPolicy", "properties": { "updateAutoLearnPolicy": { - "description": "Triggers an auto relearn event: the integrity monitoring module copies existing guest measurements to the baseline.", + "description": "Updates the integrity policy baseline using the measurements from the VM instance's most recent boot.", "type": "boolean" } }, @@ -35361,6 +39141,10 @@ "description": "A persistent disk snapshot resource. (== resource_for beta.snapshots ==) (== resource_for v1.snapshots ==)", "id": "Snapshot", "properties": { + "autoCreated": { + "description": "[Output Only] Set to true if snapshots are automatically by applying resource policy on the target disk.", + "type": "boolean" + }, "creationTimestamp": { "description": "[Output Only] Creation timestamp in RFC3339 text format.", "type": "string" @@ -35385,7 +39169,7 @@ "type": "string" }, "labelFingerprint": { - "description": "A fingerprint for the labels being applied to this snapshot, which is essentially a hash of the labels set used for optimistic locking. The fingerprint is initially generated by Compute Engine and changes after every request to modify or update labels. You must always provide an up-to-date fingerprint hash in order to update or change labels.\n\nTo see the latest fingerprint, make a get() request to retrieve a snapshot.", + "description": "A fingerprint for the labels being applied to this snapshot, which is essentially a hash of the labels set used for optimistic locking. The fingerprint is initially generated by Compute Engine and changes after every request to modify or update labels. You must always provide an up-to-date fingerprint hash in order to update or change labels, otherwise the request will fail with error 412 conditionNotMet.\n\nTo see the latest fingerprint, make a get() request to retrieve a snapshot.", "format": "byte", "type": "string" }, @@ -35470,6 +39254,13 @@ "" ], "type": "string" + }, + "storageLocations": { + "description": "GCS bucket storage location of the snapshot (regional or multi-regional).", + "items": { + "type": "string" + }, + "type": "array" } }, "type": "object" @@ -35616,6 +39407,10 @@ "description": "An optional description of this resource. Provide this property when you create the resource.", "type": "string" }, + "expireTime": { + "description": "[Output Only] Expire time of the certificate. RFC3339", + "type": "string" + }, "id": { "description": "[Output Only] The unique identifier for the resource. This identifier is defined by the server.", "format": "uint64", @@ -35626,6 +39421,10 @@ "description": "[Output Only] Type of the resource. Always compute#sslCertificate for SSL certificates.", "type": "string" }, + "managed": { + "$ref": "SslCertificateManagedSslCertificate", + "description": "Configuration and status of a managed SSL certificate." + }, "name": { "description": "Name of the resource. Provided by the client when the resource is created. The name must be 1-63 characters long, and comply with RFC1035. Specifically, the name must be 1-63 characters long and match the regular expression `[a-z]([-a-z0-9]*[a-z0-9])?` which means the first character must be a lowercase letter, and all following characters must be a dash, lowercase letter, or digit, except the last character, which cannot be a dash.", "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", @@ -35638,6 +39437,31 @@ "selfLink": { "description": "[Output only] Server-defined URL for the resource.", "type": "string" + }, + "selfManaged": { + "$ref": "SslCertificateSelfManagedSslCertificate", + "description": "Configuration and status of a self-managed SSL certificate." + }, + "subjectAlternativeNames": { + "description": "[Output Only] Domains associated with the certificate via Subject Alternative Name.", + "items": { + "type": "string" + }, + "type": "array" + }, + "type": { + "description": "(Optional) Specifies the type of SSL certificate, either \"SELF_MANAGED\" or \"MANAGED\". If not specified, the certificate is self-managed and the fields certificate and private_key are used.", + "enum": [ + "MANAGED", + "SELF_MANAGED", + "TYPE_UNSPECIFIED" + ], + "enumDescriptions": [ + "", + "", + "" + ], + "type": "string" } }, "type": "object" @@ -35754,6 +39578,80 @@ }, "type": "object" }, + "SslCertificateManagedSslCertificate": { + "description": "Configuration and status of a managed SSL certificate.", + "id": "SslCertificateManagedSslCertificate", + "properties": { + "domainStatus": { + "additionalProperties": { + "enum": [ + "ACTIVE", + "DOMAIN_STATUS_UNSPECIFIED", + "FAILED_CAA_CHECKING", + "FAILED_CAA_FORBIDDEN", + "FAILED_NOT_VISIBLE", + "FAILED_RATE_LIMITED", + "PROVISIONING" + ], + "enumDescriptions": [ + "", + "", + "", + "", + "", + "", + "" + ], + "type": "string" + }, + "description": "[Output only] Detailed statuses of the domains specified for managed certificate resource.", + "type": "object" + }, + "domains": { + "description": "The domains for which a managed SSL certificate will be generated. Currently only single-domain certs are supported.", + "items": { + "type": "string" + }, + "type": "array" + }, + "status": { + "description": "[Output only] Status of the managed certificate resource.", + "enum": [ + "ACTIVE", + "MANAGED_CERTIFICATE_STATUS_UNSPECIFIED", + "PROVISIONING", + "PROVISIONING_FAILED", + "PROVISIONING_FAILED_PERMANENTLY", + "RENEWAL_FAILED" + ], + "enumDescriptions": [ + "", + "", + "", + "", + "", + "" + ], + "type": "string" + } + }, + "type": "object" + }, + "SslCertificateSelfManagedSslCertificate": { + "description": "Configuration and status of a self-managed SSL certificate.", + "id": "SslCertificateSelfManagedSslCertificate", + "properties": { + "certificate": { + "description": "A local certificate file. The certificate must be in PEM format. The certificate chain must be no greater than 5 certs long. The chain must include at least one intermediate cert.", + "type": "string" + }, + "privateKey": { + "description": "A write-only private key in PEM format. Only insert requests will include this field.", + "type": "string" + } + }, + "type": "object" + }, "SslPoliciesList": { "id": "SslPoliciesList", "properties": { @@ -35904,7 +39802,7 @@ "type": "array" }, "fingerprint": { - "description": "Fingerprint of this resource. A hash of the contents stored in this object. This field is used in optimistic locking. This field will be ignored when inserting a SslPolicy. An up-to-date fingerprint must be provided in order to update the SslPolicy.", + "description": "Fingerprint of this resource. A hash of the contents stored in this object. This field is used in optimistic locking. This field will be ignored when inserting a SslPolicy. An up-to-date fingerprint must be provided in order to update the SslPolicy, otherwise the request will fail with error 412 conditionNotMet.\n\nTo see the latest fingerprint, make a get() request to retrieve an SslPolicy.", "format": "byte", "type": "string" }, @@ -36071,11 +39969,11 @@ "type": "string" }, "enableFlowLogs": { - "description": "Whether to enable flow logging for this subnetwork.", + "description": "Whether to enable flow logging for this subnetwork. If this field is not explicitly set, it will not appear in get listings. If not set the default behavior is to disable flow logging.", "type": "boolean" }, "fingerprint": { - "description": "Fingerprint of this resource. A hash of the contents stored in this object. This field is used in optimistic locking. This field will be ignored when inserting a Subnetwork. An up-to-date fingerprint must be provided in order to update the Subnetwork.", + "description": "Fingerprint of this resource. A hash of the contents stored in this object. This field is used in optimistic locking. This field will be ignored when inserting a Subnetwork. An up-to-date fingerprint must be provided in order to update the Subnetwork, otherwise the request will fail with error 412 conditionNotMet.\n\nTo see the latest fingerprint, make a get() request to retrieve a Subnetwork.", "format": "byte", "type": "string" }, @@ -36115,7 +40013,7 @@ "type": "string" }, "secondaryIpRanges": { - "description": "An array of configurations for secondary IP ranges for VM instances contained in this subnetwork. The primary IP of such VM must belong to the primary ipCidrRange of the subnetwork. The alias IPs may belong to either primary or secondary ranges.", + "description": "An array of configurations for secondary IP ranges for VM instances contained in this subnetwork. The primary IP of such VM must belong to the primary ipCidrRange of the subnetwork. The alias IPs may belong to either primary or secondary ranges. This field can be updated with a patch request.", "items": { "$ref": "SubnetworkSecondaryRange" }, @@ -36492,6 +40390,20 @@ "description": "Port name as defined in InstanceGroup#NamedPort#name. If both port and port_name are defined, port takes precedence.", "type": "string" }, + "portSpecification": { + "description": "Specifies how port is selected for health checking, can be one of following values:\nUSE_FIXED_PORT: The port number in\nport\nis used for health checking.\nUSE_NAMED_PORT: The\nportName\nis used for health checking.\nUSE_SERVING_PORT: For NetworkEndpointGroup, the port specified for each network endpoint is used for health checking. For other backends, the port or named port specified in the Backend Service is used for health checking.\n\n\nIf not specified, TCP health check follows behavior specified in\nport\nand\nportName\nfields.", + "enum": [ + "USE_FIXED_PORT", + "USE_NAMED_PORT", + "USE_SERVING_PORT" + ], + "enumDescriptions": [ + "", + "", + "" + ], + "type": "string" + }, "proxyHeader": { "description": "Specifies the type of proxy header to append before sending data to the backend, either NONE or PROXY_V1. The default is NONE.", "enum": [ @@ -36763,7 +40675,7 @@ "type": "string" }, "sslCertificates": { - "description": "URLs to SslCertificate resources that are used to authenticate connections between users and the load balancer. Currently, exactly one SSL certificate must be specified.", + "description": "URLs to SslCertificate resources that are used to authenticate connections between users and the load balancer. At least one SSL certificate must be specified. Currently, you may specify up to 15 SSL certificates.", "items": { "type": "string" }, @@ -37321,7 +41233,7 @@ "type": "string" }, "sessionAffinity": { - "description": "Sesssion affinity option, must be one of the following values:\nNONE: Connections from the same client IP may go to any instance in the pool.\nCLIENT_IP: Connections from the same client IP will go to the same instance in the pool while that instance remains healthy.\nCLIENT_IP_PROTO: Connections from the same client IP with the same IP protocol will go to the same instance in the pool while that instance remains healthy.", + "description": "Session affinity option, must be one of the following values:\nNONE: Connections from the same client IP may go to any instance in the pool.\nCLIENT_IP: Connections from the same client IP will go to the same instance in the pool while that instance remains healthy.\nCLIENT_IP_PROTO: Connections from the same client IP with the same IP protocol will go to the same instance in the pool while that instance remains healthy.", "enum": [ "CLIENT_IP", "CLIENT_IP_PORT_PROTO", @@ -37826,7 +41738,7 @@ "type": "string" }, "sslCertificates": { - "description": "URLs to SslCertificate resources that are used to authenticate connections to Backends. Currently exactly one SSL certificate must be specified.", + "description": "URLs to SslCertificate resources that are used to authenticate connections to Backends. At least one SSL certificate must be specified. Currently, you may specify up to 15 SSL certificates.", "items": { "type": "string" }, @@ -38171,7 +42083,7 @@ "type": "string" }, "labelFingerprint": { - "description": "A fingerprint for the labels being applied to this TargetVpnGateway, which is essentially a hash of the labels set used for optimistic locking. The fingerprint is initially generated by Compute Engine and changes after every request to modify or update labels. You must always provide an up-to-date fingerprint hash in order to update or change labels.\n\nTo see the latest fingerprint, make a get() request to retrieve an TargetVpnGateway.", + "description": "A fingerprint for the labels being applied to this TargetVpnGateway, which is essentially a hash of the labels set used for optimistic locking. The fingerprint is initially generated by Compute Engine and changes after every request to modify or update labels. You must always provide an up-to-date fingerprint hash in order to update or change labels, otherwise the request will fail with error 412 conditionNotMet.\n\nTo see the latest fingerprint, make a get() request to retrieve a TargetVpnGateway.", "format": "byte", "type": "string" }, @@ -38597,29 +42509,6 @@ }, "type": "object" }, - "UDPHealthCheck": { - "id": "UDPHealthCheck", - "properties": { - "port": { - "description": "The UDP port number for the health check request. Valid values are 1 through 65535.", - "format": "int32", - "type": "integer" - }, - "portName": { - "description": "Port name as defined in InstanceGroup#NamedPort#name. If both port and port_name are defined, port takes precedence.", - "type": "string" - }, - "request": { - "description": "Raw data of request to send in payload of UDP packet. It is an error if this is empty. The request data can only be ASCII.", - "type": "string" - }, - "response": { - "description": "The bytes to match against the beginning of the response data. It is an error if this is empty. The response data can only be ASCII.", - "type": "string" - } - }, - "type": "object" - }, "UrlMap": { "description": "A UrlMap resource. This resource defines the mapping from URL to the BackendService resource, based on the \"longest-match\" of the URL's host and path.", "id": "UrlMap", @@ -38629,7 +42518,7 @@ "type": "string" }, "defaultService": { - "description": "The URL of the BackendService resource if none of the hostRules match.", + "description": "The URL of the backendService resource if none of the hostRules match.\nUse defaultService instead of defaultRouteAction when simple routing to a backendService is desired and other advanced capabilities like traffic splitting and rewrites are not required.\nOnly one of defaultService, defaultRouteAction or defaultUrlRedirect should must be set.", "type": "string" }, "description": { @@ -38637,7 +42526,7 @@ "type": "string" }, "fingerprint": { - "description": "Fingerprint of this resource. A hash of the contents stored in this object. This field is used in optimistic locking. This field will be ignored when inserting a UrlMap. An up-to-date fingerprint must be provided in order to update the UrlMap.", + "description": "Fingerprint of this resource. A hash of the contents stored in this object. This field is used in optimistic locking. This field will be ignored when inserting a UrlMap. An up-to-date fingerprint must be provided in order to update the UrlMap, otherwise the request will fail with error 412 conditionNotMet.\n\nTo see the latest fingerprint, make a get() request to retrieve a UrlMap.", "format": "byte", "type": "string" }, @@ -39041,6 +42930,162 @@ }, "type": "object" }, + "VmEndpointNatMappings": { + "description": "Contain information of Nat mapping for a VM endpoint (i.e., NIC).", + "id": "VmEndpointNatMappings", + "properties": { + "instanceName": { + "description": "Name of the VM instance which the endpoint belongs to", + "type": "string" + }, + "interfaceNatMappings": { + "items": { + "$ref": "VmEndpointNatMappingsInterfaceNatMappings" + }, + "type": "array" + } + }, + "type": "object" + }, + "VmEndpointNatMappingsInterfaceNatMappings": { + "description": "Contain information of Nat mapping for an interface of this endpoint.", + "id": "VmEndpointNatMappingsInterfaceNatMappings", + "properties": { + "natIpPortRanges": { + "description": "A list of all IP:port-range mappings assigned to this interface. These ranges are inclusive, that is, both the first and the last ports can be used for NAT. Example: [\"2.2.2.2:12345-12355\", \"1.1.1.1:2234-2234\"].", + "items": { + "type": "string" + }, + "type": "array" + }, + "numTotalNatPorts": { + "description": "Total number of ports across all NAT IPs allocated to this interface. It equals to the aggregated port number in the field nat_ip_port_ranges.", + "format": "int32", + "type": "integer" + }, + "sourceAliasIpRange": { + "description": "Alias IP range for this interface endpoint. It will be a private (RFC 1918) IP range. Examples: \"10.33.4.55/32\", or \"192.168.5.0/24\".", + "type": "string" + }, + "sourceVirtualIp": { + "description": "Primary IP of the VM for this NIC.", + "type": "string" + } + }, + "type": "object" + }, + "VmEndpointNatMappingsList": { + "description": "Contains a list of VmEndpointNatMappings.", + "id": "VmEndpointNatMappingsList", + "properties": { + "id": { + "description": "[Output Only] The unique identifier for the resource. This identifier is defined by the server.", + "type": "string" + }, + "kind": { + "default": "compute#vmEndpointNatMappingsList", + "description": "[Output Only] Type of resource. Always compute#vmEndpointNatMappingsList for lists of Nat mappings of VM endpoints.", + "type": "string" + }, + "nextPageToken": { + "description": "[Output Only] This token allows you to get the next page of results for list requests. If the number of results is larger than maxResults, use the nextPageToken as a value for the query parameter pageToken in the next list request. Subsequent list requests will have their own nextPageToken to continue paging through the results.", + "type": "string" + }, + "result": { + "description": "[Output Only] A list of Nat mapping information of VM endpoints.", + "items": { + "$ref": "VmEndpointNatMappings" + }, + "type": "array" + }, + "selfLink": { + "description": "[Output Only] Server-defined URL for this resource.", + "type": "string" + }, + "warning": { + "description": "[Output Only] Informational warning message.", + "properties": { + "code": { + "description": "[Output Only] A warning code, if applicable. For example, Compute Engine returns NO_RESULTS_ON_PAGE if there are no results in the response.", + "enum": [ + "CLEANUP_FAILED", + "DEPRECATED_RESOURCE_USED", + "DEPRECATED_TYPE_USED", + "DISK_SIZE_LARGER_THAN_IMAGE_SIZE", + "EXPERIMENTAL_TYPE_USED", + "EXTERNAL_API_WARNING", + "FIELD_VALUE_OVERRIDEN", + "INJECTED_KERNELS_DEPRECATED", + "MISSING_TYPE_DEPENDENCY", + "NEXT_HOP_ADDRESS_NOT_ASSIGNED", + "NEXT_HOP_CANNOT_IP_FORWARD", + "NEXT_HOP_INSTANCE_NOT_FOUND", + "NEXT_HOP_INSTANCE_NOT_ON_NETWORK", + "NEXT_HOP_NOT_RUNNING", + "NOT_CRITICAL_ERROR", + "NO_RESULTS_ON_PAGE", + "REQUIRED_TOS_AGREEMENT", + "RESOURCE_IN_USE_BY_OTHER_RESOURCE_WARNING", + "RESOURCE_NOT_DELETED", + "SCHEMA_VALIDATION_IGNORED", + "SINGLE_INSTANCE_PROPERTY_TEMPLATE", + "UNDECLARED_PROPERTIES", + "UNREACHABLE" + ], + "enumDescriptions": [ + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "" + ], + "type": "string" + }, + "data": { + "description": "[Output Only] Metadata about this warning in key: value format. For example:\n\"data\": [ { \"key\": \"scope\", \"value\": \"zones/us-east1-d\" }", + "items": { + "properties": { + "key": { + "description": "[Output Only] A key that provides more detail on the warning being returned. For example, for warnings where there are no results in a list request for a particular zone, this key might be scope and the key value might be the zone name. Other examples might be a key indicating a deprecated resource and a suggested replacement, or a warning about invalid network settings (for example, if an instance attempts to perform IP forwarding but is not enabled for IP forwarding).", + "type": "string" + }, + "value": { + "description": "[Output Only] A warning data value corresponding to the key.", + "type": "string" + } + }, + "type": "object" + }, + "type": "array" + }, + "message": { + "description": "[Output Only] A human-readable description of the warning code.", + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object" + }, "VpnTunnel": { "description": "VPN tunnel resource. (== resource_for beta.vpnTunnels ==) (== resource_for v1.vpnTunnels ==)", "id": "VpnTunnel", @@ -39073,7 +43118,7 @@ "type": "string" }, "labelFingerprint": { - "description": "A fingerprint for the labels being applied to this VpnTunnel, which is essentially a hash of the labels set used for optimistic locking. The fingerprint is initially generated by Compute Engine and changes after every request to modify or update labels. You must always provide an up-to-date fingerprint hash in order to update or change labels.\n\nTo see the latest fingerprint, make a get() request to retrieve a VpnTunnel.", + "description": "A fingerprint for the labels being applied to this VpnTunnel, which is essentially a hash of the labels set used for optimistic locking. The fingerprint is initially generated by Compute Engine and changes after every request to modify or update labels. You must always provide an up-to-date fingerprint hash in order to update or change labels, otherwise the request will fail with error 412 conditionNotMet.\n\nTo see the latest fingerprint, make a get() request to retrieve a VpnTunnel.", "format": "byte", "type": "string" }, @@ -39639,7 +43684,7 @@ "id": "XpnResourceId", "properties": { "id": { - "description": "The ID of the service resource. In the case of projects, this field matches the project ID (e.g., my-project), not the project number (e.g., 12345678).", + "description": "The ID of the service resource. In the case of projects, this field supports project id (e.g., my-project-123) and project number (e.g. 12345678).", "type": "string" }, "type": { diff --git a/vendor/google.golang.org/api/compute/v0.beta/compute-gen.go b/vendor/google.golang.org/api/compute/v0.beta/compute-gen.go index 49a2415547b..9a58fb1c792 100644 --- a/vendor/google.golang.org/api/compute/v0.beta/compute-gen.go +++ b/vendor/google.golang.org/api/compute/v0.beta/compute-gen.go @@ -1,3 +1,9 @@ +// Copyright 2018 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Code generated file. DO NOT EDIT. + // Package compute provides access to the Compute Engine API. // // See https://developers.google.com/compute/docs/reference/latest/ @@ -11,18 +17,18 @@ package compute import ( "bytes" + "context" "encoding/json" "errors" "fmt" - context "golang.org/x/net/context" - ctxhttp "golang.org/x/net/context/ctxhttp" - gensupport "google.golang.org/api/gensupport" - googleapi "google.golang.org/api/googleapi" "io" "net/http" "net/url" "strconv" "strings" + + gensupport "google.golang.org/api/gensupport" + googleapi "google.golang.org/api/googleapi" ) // Always reference these packages, just in case the auto-generated code @@ -38,7 +44,6 @@ var _ = googleapi.Version var _ = errors.New var _ = strings.Replace var _ = context.Canceled -var _ = ctxhttp.Do const apiId = "compute:beta" const apiName = "compute" @@ -73,6 +78,7 @@ func New(client *http.Client) (*Service, error) { s := &Service{client: client, BasePath: basePath} s.AcceleratorTypes = NewAcceleratorTypesService(s) s.Addresses = NewAddressesService(s) + s.Allocations = NewAllocationsService(s) s.Autoscalers = NewAutoscalersService(s) s.BackendBuckets = NewBackendBucketsService(s) s.BackendServices = NewBackendServicesService(s) @@ -112,6 +118,7 @@ func New(client *http.Client) (*Service, error) { s.RegionInstanceGroups = NewRegionInstanceGroupsService(s) s.RegionOperations = NewRegionOperationsService(s) s.Regions = NewRegionsService(s) + s.ResourcePolicies = NewResourcePoliciesService(s) s.Routers = NewRoutersService(s) s.Routes = NewRoutesService(s) s.SecurityPolicies = NewSecurityPoliciesService(s) @@ -142,6 +149,8 @@ type Service struct { Addresses *AddressesService + Allocations *AllocationsService + Autoscalers *AutoscalersService BackendBuckets *BackendBucketsService @@ -220,6 +229,8 @@ type Service struct { Regions *RegionsService + ResourcePolicies *ResourcePoliciesService + Routers *RoutersService Routes *RoutesService @@ -282,6 +293,15 @@ type AddressesService struct { s *Service } +func NewAllocationsService(s *Service) *AllocationsService { + rs := &AllocationsService{s: s} + return rs +} + +type AllocationsService struct { + s *Service +} + func NewAutoscalersService(s *Service) *AutoscalersService { rs := &AutoscalersService{s: s} return rs @@ -633,6 +653,15 @@ type RegionsService struct { s *Service } +func NewResourcePoliciesService(s *Service) *ResourcePoliciesService { + rs := &ResourcePoliciesService{s: s} + return rs +} + +type ResourcePoliciesService struct { + s *Service +} + func NewRoutersService(s *Service) *RoutersService { rs := &RoutersService{s: s} return rs @@ -1467,7 +1496,8 @@ type Address struct { // optimistic locking. The fingerprint is initially generated by Compute // Engine and changes after every request to modify or update labels. // You must always provide an up-to-date fingerprint hash in order to - // update or change labels. + // update or change labels, otherwise the request will fail with error + // 412 conditionNotMet. // // To see the latest fingerprint, make a get() request to retrieve an // Address. @@ -1492,8 +1522,12 @@ type Address struct { Network string `json:"network,omitempty"` // NetworkTier: This signifies the networking tier used for configuring - // this Address and can only take the following values: PREMIUM , - // STANDARD. + // this Address and can only take the following values: PREMIUM, + // STANDARD. Global forwarding rules can only be Premium Tier. Regional + // forwarding rules can be either Premium or Standard Tier. Standard + // Tier addresses applied to regional forwarding rules can be used with + // any external load balancer. Regional forwarding rules in Premium Tier + // can only be used with a Network load balancer. // // If this field is not specified, it is assumed to be PREMIUM. // @@ -1511,7 +1545,6 @@ type Address struct { // Possible values: // "DNS_RESOLVER" // "GCE_ENDPOINT" - // "UNSPECIFIED_PURPOSE" // "VPC_PEERING" Purpose string `json:"purpose,omitempty"` @@ -2055,6 +2088,671 @@ func (s *AliasIpRange) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +// Allocation: Allocation resource +type Allocation struct { + // CreationTimestamp: [Output Only] Creation timestamp in RFC3339 text + // format. + CreationTimestamp string `json:"creationTimestamp,omitempty"` + + Description string `json:"description,omitempty"` + + // Id: [Output Only] The unique identifier for the resource. This + // identifier is defined by the server. + Id uint64 `json:"id,omitempty,string"` + + // Kind: [Output Only] Type of the resource. Always compute#allocations + // for allocations. + Kind string `json:"kind,omitempty"` + + // Name: The name of the resource, provided by the client when initially + // creating the resource. The resource name must be 1-63 characters + // long, and comply with RFC1035. Specifically, the name must be 1-63 + // characters long and match the regular expression + // `[a-z]([-a-z0-9]*[a-z0-9])?` which means the first character must be + // a lowercase letter, and all following characters must be a dash, + // lowercase letter, or digit, except the last character, which cannot + // be a dash. + Name string `json:"name,omitempty"` + + // SelfLink: [Output Only] Server-defined fully-qualified URL for this + // resource. + SelfLink string `json:"selfLink,omitempty"` + + SpecificAllocation *AllocationSpecificSKUAllocation `json:"specificAllocation,omitempty"` + + // SpecificAllocationRequired: Indicates whether the allocation can be + // consumed by VMs with "any allocation" defined. If the field is set, + // then only VMs that target the allocation by name using + // --allocation-affinity can consume this allocation. + SpecificAllocationRequired bool `json:"specificAllocationRequired,omitempty"` + + Zone string `json:"zone,omitempty"` + + // ServerResponse contains the HTTP response code and headers from the + // server. + googleapi.ServerResponse `json:"-"` + + // ForceSendFields is a list of field names (e.g. "CreationTimestamp") + // to unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "CreationTimestamp") to + // include in API requests with the JSON null value. By default, fields + // with empty values are omitted from API requests. However, any field + // with an empty value appearing in NullFields will be sent to the + // server as null. It is an error if a field in this list has a + // non-empty value. This may be used to include null fields in Patch + // requests. + NullFields []string `json:"-"` +} + +func (s *Allocation) MarshalJSON() ([]byte, error) { + type NoMethod Allocation + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// AllocationAffinity: AllocationAffinity is the configuration of +// desired allocation which this instance could take capacity from. +type AllocationAffinity struct { + // Possible values: + // "ANY_ALLOCATION" + // "NO_ALLOCATION" + // "SPECIFIC_ALLOCATION" + // "UNSPECIFIED" + ConsumeAllocationType string `json:"consumeAllocationType,omitempty"` + + // Key: Corresponds to the label key of allocation resource. + Key string `json:"key,omitempty"` + + // Values: Corresponds to the label values of allocation resource. + Values []string `json:"values,omitempty"` + + // ForceSendFields is a list of field names (e.g. + // "ConsumeAllocationType") to unconditionally include in API requests. + // By default, fields with empty values are omitted from API requests. + // However, any non-pointer, non-interface field appearing in + // ForceSendFields will be sent to the server regardless of whether the + // field is empty or not. This may be used to include empty fields in + // Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "ConsumeAllocationType") to + // include in API requests with the JSON null value. By default, fields + // with empty values are omitted from API requests. However, any field + // with an empty value appearing in NullFields will be sent to the + // server as null. It is an error if a field in this list has a + // non-empty value. This may be used to include null fields in Patch + // requests. + NullFields []string `json:"-"` +} + +func (s *AllocationAffinity) MarshalJSON() ([]byte, error) { + type NoMethod AllocationAffinity + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// AllocationAggregatedList: Contains a list of allocations. +type AllocationAggregatedList struct { + // Id: [Output Only] Unique identifier for the resource; defined by the + // server. + Id string `json:"id,omitempty"` + + // Items: A list of Allocation resources. + Items map[string]AllocationsScopedList `json:"items,omitempty"` + + // Kind: Type of resource. + Kind string `json:"kind,omitempty"` + + // NextPageToken: [Output Only] This token allows you to get the next + // page of results for list requests. If the number of results is larger + // than maxResults, use the nextPageToken as a value for the query + // parameter pageToken in the next list request. Subsequent list + // requests will have their own nextPageToken to continue paging through + // the results. + NextPageToken string `json:"nextPageToken,omitempty"` + + // SelfLink: [Output Only] Server-defined URL for this resource. + SelfLink string `json:"selfLink,omitempty"` + + // Warning: [Output Only] Informational warning message. + Warning *AllocationAggregatedListWarning `json:"warning,omitempty"` + + // ServerResponse contains the HTTP response code and headers from the + // server. + googleapi.ServerResponse `json:"-"` + + // ForceSendFields is a list of field names (e.g. "Id") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Id") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *AllocationAggregatedList) MarshalJSON() ([]byte, error) { + type NoMethod AllocationAggregatedList + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// AllocationAggregatedListWarning: [Output Only] Informational warning +// message. +type AllocationAggregatedListWarning struct { + // Code: [Output Only] A warning code, if applicable. For example, + // Compute Engine returns NO_RESULTS_ON_PAGE if there are no results in + // the response. + // + // Possible values: + // "CLEANUP_FAILED" + // "DEPRECATED_RESOURCE_USED" + // "DEPRECATED_TYPE_USED" + // "DISK_SIZE_LARGER_THAN_IMAGE_SIZE" + // "EXPERIMENTAL_TYPE_USED" + // "EXTERNAL_API_WARNING" + // "FIELD_VALUE_OVERRIDEN" + // "INJECTED_KERNELS_DEPRECATED" + // "MISSING_TYPE_DEPENDENCY" + // "NEXT_HOP_ADDRESS_NOT_ASSIGNED" + // "NEXT_HOP_CANNOT_IP_FORWARD" + // "NEXT_HOP_INSTANCE_NOT_FOUND" + // "NEXT_HOP_INSTANCE_NOT_ON_NETWORK" + // "NEXT_HOP_NOT_RUNNING" + // "NOT_CRITICAL_ERROR" + // "NO_RESULTS_ON_PAGE" + // "REQUIRED_TOS_AGREEMENT" + // "RESOURCE_IN_USE_BY_OTHER_RESOURCE_WARNING" + // "RESOURCE_NOT_DELETED" + // "SCHEMA_VALIDATION_IGNORED" + // "SINGLE_INSTANCE_PROPERTY_TEMPLATE" + // "UNDECLARED_PROPERTIES" + // "UNREACHABLE" + Code string `json:"code,omitempty"` + + // Data: [Output Only] Metadata about this warning in key: value format. + // For example: + // "data": [ { "key": "scope", "value": "zones/us-east1-d" } + Data []*AllocationAggregatedListWarningData `json:"data,omitempty"` + + // Message: [Output Only] A human-readable description of the warning + // code. + Message string `json:"message,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Code") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Code") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *AllocationAggregatedListWarning) MarshalJSON() ([]byte, error) { + type NoMethod AllocationAggregatedListWarning + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type AllocationAggregatedListWarningData struct { + // Key: [Output Only] A key that provides more detail on the warning + // being returned. For example, for warnings where there are no results + // in a list request for a particular zone, this key might be scope and + // the key value might be the zone name. Other examples might be a key + // indicating a deprecated resource and a suggested replacement, or a + // warning about invalid network settings (for example, if an instance + // attempts to perform IP forwarding but is not enabled for IP + // forwarding). + Key string `json:"key,omitempty"` + + // Value: [Output Only] A warning data value corresponding to the key. + Value string `json:"value,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Key") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Key") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *AllocationAggregatedListWarningData) MarshalJSON() ([]byte, error) { + type NoMethod AllocationAggregatedListWarningData + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type AllocationList struct { + // Id: [Output Only] The unique identifier for the resource. This + // identifier is defined by the server. + Id string `json:"id,omitempty"` + + // Items: [Output Only] A list of Allocation resources. + Items []*Allocation `json:"items,omitempty"` + + // Kind: [Output Only] Type of resource.Always compute#allocationsList + // for listsof allocations + Kind string `json:"kind,omitempty"` + + // NextPageToken: [Output Only] This token allows you to get the next + // page of results for list requests. If the number of results is larger + // than maxResults, use the nextPageToken as a value for the query + // parameter pageToken in the next list request. Subsequent list + // requests will have their own nextPageToken to continue paging through + // the results. + NextPageToken string `json:"nextPageToken,omitempty"` + + // SelfLink: [Output Only] Server-defined URL for this resource. + SelfLink string `json:"selfLink,omitempty"` + + // Warning: [Output Only] Informational warning message. + Warning *AllocationListWarning `json:"warning,omitempty"` + + // ServerResponse contains the HTTP response code and headers from the + // server. + googleapi.ServerResponse `json:"-"` + + // ForceSendFields is a list of field names (e.g. "Id") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Id") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *AllocationList) MarshalJSON() ([]byte, error) { + type NoMethod AllocationList + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// AllocationListWarning: [Output Only] Informational warning message. +type AllocationListWarning struct { + // Code: [Output Only] A warning code, if applicable. For example, + // Compute Engine returns NO_RESULTS_ON_PAGE if there are no results in + // the response. + // + // Possible values: + // "CLEANUP_FAILED" + // "DEPRECATED_RESOURCE_USED" + // "DEPRECATED_TYPE_USED" + // "DISK_SIZE_LARGER_THAN_IMAGE_SIZE" + // "EXPERIMENTAL_TYPE_USED" + // "EXTERNAL_API_WARNING" + // "FIELD_VALUE_OVERRIDEN" + // "INJECTED_KERNELS_DEPRECATED" + // "MISSING_TYPE_DEPENDENCY" + // "NEXT_HOP_ADDRESS_NOT_ASSIGNED" + // "NEXT_HOP_CANNOT_IP_FORWARD" + // "NEXT_HOP_INSTANCE_NOT_FOUND" + // "NEXT_HOP_INSTANCE_NOT_ON_NETWORK" + // "NEXT_HOP_NOT_RUNNING" + // "NOT_CRITICAL_ERROR" + // "NO_RESULTS_ON_PAGE" + // "REQUIRED_TOS_AGREEMENT" + // "RESOURCE_IN_USE_BY_OTHER_RESOURCE_WARNING" + // "RESOURCE_NOT_DELETED" + // "SCHEMA_VALIDATION_IGNORED" + // "SINGLE_INSTANCE_PROPERTY_TEMPLATE" + // "UNDECLARED_PROPERTIES" + // "UNREACHABLE" + Code string `json:"code,omitempty"` + + // Data: [Output Only] Metadata about this warning in key: value format. + // For example: + // "data": [ { "key": "scope", "value": "zones/us-east1-d" } + Data []*AllocationListWarningData `json:"data,omitempty"` + + // Message: [Output Only] A human-readable description of the warning + // code. + Message string `json:"message,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Code") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Code") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *AllocationListWarning) MarshalJSON() ([]byte, error) { + type NoMethod AllocationListWarning + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type AllocationListWarningData struct { + // Key: [Output Only] A key that provides more detail on the warning + // being returned. For example, for warnings where there are no results + // in a list request for a particular zone, this key might be scope and + // the key value might be the zone name. Other examples might be a key + // indicating a deprecated resource and a suggested replacement, or a + // warning about invalid network settings (for example, if an instance + // attempts to perform IP forwarding but is not enabled for IP + // forwarding). + Key string `json:"key,omitempty"` + + // Value: [Output Only] A warning data value corresponding to the key. + Value string `json:"value,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Key") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Key") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *AllocationListWarningData) MarshalJSON() ([]byte, error) { + type NoMethod AllocationListWarningData + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// AllocationSpecificSKUAllocation: This allocation type allows to pre +// allocate specific instance configuration. +type AllocationSpecificSKUAllocation struct { + // Count: Specifies number of resources that are allocated. + Count int64 `json:"count,omitempty,string"` + + // InUseCount: [OutputOnly] Indicates how many resource are in use. + InUseCount int64 `json:"inUseCount,omitempty,string"` + + InstanceProperties *AllocationSpecificSKUAllocationAllocatedInstanceProperties `json:"instanceProperties,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Count") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Count") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *AllocationSpecificSKUAllocation) MarshalJSON() ([]byte, error) { + type NoMethod AllocationSpecificSKUAllocation + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// AllocationSpecificSKUAllocationAllocatedInstanceProperties: +// Properties of the SKU instances being reserved. +type AllocationSpecificSKUAllocationAllocatedInstanceProperties struct { + // GuestAccelerators: Specifies accelerator type and count. + GuestAccelerators []*AcceleratorConfig `json:"guestAccelerators,omitempty"` + + // LocalSsds: Specifies amount of local ssd to reserve with each + // instance. The type of disk is local-ssd. + LocalSsds []*AllocationSpecificSKUAllocationAllocatedInstancePropertiesAllocatedDisk `json:"localSsds,omitempty"` + + // MachineType: Specifies type of machine (name only) which has fixed + // number of vCPUs and fixed amount of memory. This also includes + // specifying custom machine type following + // custom-NUMBER_OF_CPUS-AMOUNT_OF_MEMORY pattern. + MachineType string `json:"machineType,omitempty"` + + // MinCpuPlatform: Minimum cpu platform the allocation. + MinCpuPlatform string `json:"minCpuPlatform,omitempty"` + + // ForceSendFields is a list of field names (e.g. "GuestAccelerators") + // to unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "GuestAccelerators") to + // include in API requests with the JSON null value. By default, fields + // with empty values are omitted from API requests. However, any field + // with an empty value appearing in NullFields will be sent to the + // server as null. It is an error if a field in this list has a + // non-empty value. This may be used to include null fields in Patch + // requests. + NullFields []string `json:"-"` +} + +func (s *AllocationSpecificSKUAllocationAllocatedInstanceProperties) MarshalJSON() ([]byte, error) { + type NoMethod AllocationSpecificSKUAllocationAllocatedInstanceProperties + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type AllocationSpecificSKUAllocationAllocatedInstancePropertiesAllocatedDisk struct { + // DiskSizeGb: Specifies the size of the disk in base-2 GB. + DiskSizeGb int64 `json:"diskSizeGb,omitempty,string"` + + // Interface: Specifies the disk interface to use for attaching this + // disk, which is either SCSI or NVME. The default is SCSI. For + // performance characteristics of SCSI over NVMe, see Local SSD + // performance. + // + // Possible values: + // "NVME" + // "SCSI" + Interface string `json:"interface,omitempty"` + + // ForceSendFields is a list of field names (e.g. "DiskSizeGb") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "DiskSizeGb") to include in + // API requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *AllocationSpecificSKUAllocationAllocatedInstancePropertiesAllocatedDisk) MarshalJSON() ([]byte, error) { + type NoMethod AllocationSpecificSKUAllocationAllocatedInstancePropertiesAllocatedDisk + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type AllocationsScopedList struct { + // Allocations: A list of allocations contained in this scope. + Allocations []*Allocation `json:"allocations,omitempty"` + + // Warning: Informational warning which replaces the list of allocations + // when the list is empty. + Warning *AllocationsScopedListWarning `json:"warning,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Allocations") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Allocations") to include + // in API requests with the JSON null value. By default, fields with + // empty values are omitted from API requests. However, any field with + // an empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *AllocationsScopedList) MarshalJSON() ([]byte, error) { + type NoMethod AllocationsScopedList + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// AllocationsScopedListWarning: Informational warning which replaces +// the list of allocations when the list is empty. +type AllocationsScopedListWarning struct { + // Code: [Output Only] A warning code, if applicable. For example, + // Compute Engine returns NO_RESULTS_ON_PAGE if there are no results in + // the response. + // + // Possible values: + // "CLEANUP_FAILED" + // "DEPRECATED_RESOURCE_USED" + // "DEPRECATED_TYPE_USED" + // "DISK_SIZE_LARGER_THAN_IMAGE_SIZE" + // "EXPERIMENTAL_TYPE_USED" + // "EXTERNAL_API_WARNING" + // "FIELD_VALUE_OVERRIDEN" + // "INJECTED_KERNELS_DEPRECATED" + // "MISSING_TYPE_DEPENDENCY" + // "NEXT_HOP_ADDRESS_NOT_ASSIGNED" + // "NEXT_HOP_CANNOT_IP_FORWARD" + // "NEXT_HOP_INSTANCE_NOT_FOUND" + // "NEXT_HOP_INSTANCE_NOT_ON_NETWORK" + // "NEXT_HOP_NOT_RUNNING" + // "NOT_CRITICAL_ERROR" + // "NO_RESULTS_ON_PAGE" + // "REQUIRED_TOS_AGREEMENT" + // "RESOURCE_IN_USE_BY_OTHER_RESOURCE_WARNING" + // "RESOURCE_NOT_DELETED" + // "SCHEMA_VALIDATION_IGNORED" + // "SINGLE_INSTANCE_PROPERTY_TEMPLATE" + // "UNDECLARED_PROPERTIES" + // "UNREACHABLE" + Code string `json:"code,omitempty"` + + // Data: [Output Only] Metadata about this warning in key: value format. + // For example: + // "data": [ { "key": "scope", "value": "zones/us-east1-d" } + Data []*AllocationsScopedListWarningData `json:"data,omitempty"` + + // Message: [Output Only] A human-readable description of the warning + // code. + Message string `json:"message,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Code") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Code") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *AllocationsScopedListWarning) MarshalJSON() ([]byte, error) { + type NoMethod AllocationsScopedListWarning + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type AllocationsScopedListWarningData struct { + // Key: [Output Only] A key that provides more detail on the warning + // being returned. For example, for warnings where there are no results + // in a list request for a particular zone, this key might be scope and + // the key value might be the zone name. Other examples might be a key + // indicating a deprecated resource and a suggested replacement, or a + // warning about invalid network settings (for example, if an instance + // attempts to perform IP forwarding but is not enabled for IP + // forwarding). + Key string `json:"key,omitempty"` + + // Value: [Output Only] A warning data value corresponding to the key. + Value string `json:"value,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Key") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Key") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *AllocationsScopedListWarningData) MarshalJSON() ([]byte, error) { + type NoMethod AllocationsScopedListWarningData + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + // AttachedDisk: An instance-attached disk resource. type AttachedDisk struct { // AutoDelete: Specifies whether the disk will be auto-deleted when the @@ -2200,20 +2898,19 @@ func (s *AttachedDisk) MarshalJSON() ([]byte, error) { // This property is mutually exclusive with the source property; you can // only define one or the other, but not both. type AttachedDiskInitializeParams struct { + // Description: An optional description. Provide this property when + // creating the disk. + Description string `json:"description,omitempty"` + // DiskName: Specifies the disk name. If not specified, the default is - // to use the name of the instance. + // to use the name of the instance. If the disk with the instance name + // exists already in the given zone/region, a new name will be + // automatically generated. DiskName string `json:"diskName,omitempty"` // DiskSizeGb: Specifies the size of the disk in base-2 GB. DiskSizeGb int64 `json:"diskSizeGb,omitempty,string"` - // DiskStorageType: [Deprecated] Storage type of the disk. - // - // Possible values: - // "HDD" - // "SSD" - DiskStorageType string `json:"diskStorageType,omitempty"` - // DiskType: Specifies the disk type to use to create the instance. If // not specified, the default is pd-standard, specified using the full // URL. For @@ -2243,15 +2940,15 @@ type AttachedDiskInitializeParams struct { // // To create a disk with one of the public operating system images, // specify the image by its family name. For example, specify - // family/debian-8 to use the latest Debian 8 + // family/debian-9 to use the latest Debian 9 // image: - // projects/debian-cloud/global/images/family/debian-8 + // projects/debian-cloud/global/images/family/debian-9 // // // Alternati // vely, use a specific version of a public operating system // image: - // projects/debian-cloud/global/images/debian-8-jessie-vYYYYMMDD + // projects/debian-cloud/global/images/debian-9-stretch-vYYYYMMDD // // // @@ -2280,7 +2977,7 @@ type AttachedDiskInitializeParams struct { // the source images are encrypted with your own keys. SourceImageEncryptionKey *CustomerEncryptionKey `json:"sourceImageEncryptionKey,omitempty"` - // ForceSendFields is a list of field names (e.g. "DiskName") to + // ForceSendFields is a list of field names (e.g. "Description") to // unconditionally include in API requests. By default, fields with // empty values are omitted from API requests. However, any non-pointer, // non-interface field appearing in ForceSendFields will be sent to the @@ -2288,10 +2985,10 @@ type AttachedDiskInitializeParams struct { // used to include empty fields in Patch requests. ForceSendFields []string `json:"-"` - // NullFields is a list of field names (e.g. "DiskName") to include in - // API requests with the JSON null value. By default, fields with empty - // values are omitted from API requests. However, any field with an - // empty value appearing in NullFields will be sent to the server as + // NullFields is a list of field names (e.g. "Description") to include + // in API requests with the JSON null value. By default, fields with + // empty values are omitted from API requests. However, any field with + // an empty value appearing in NullFields will be sent to the server as // null. It is an error if a field in this list has a non-empty value. // This may be used to include null fields in Patch requests. NullFields []string `json:"-"` @@ -3229,8 +3926,7 @@ type AutoscalingPolicyCustomMetricUtilization struct { // UtilizationTargetType: Defines how target utilization value is // expressed for a Stackdriver Monitoring metric. Either GAUGE, - // DELTA_PER_SECOND, or DELTA_PER_MINUTE. If not specified, the default - // is GAUGE. + // DELTA_PER_SECOND, or DELTA_PER_MINUTE. // // Possible values: // "DELTA_PER_MINUTE" @@ -3354,18 +4050,28 @@ type Backend struct { // property when you create the resource. Description string `json:"description,omitempty"` - // Group: The fully-qualified URL of a Instance Group resource. This - // instance group defines the list of instances that serve traffic. - // Member virtual machine instances from each instance group must live - // in the same zone as the instance group itself. No two backends in a - // backend service are allowed to use same Instance Group - // resource. + // Group: The fully-qualified URL of an Instance Group or Network + // Endpoint Group resource. In case of instance group this defines the + // list of instances that serve traffic. Member virtual machine + // instances from each instance group must live in the same zone as the + // instance group itself. No two backends in a backend service are + // allowed to use same Instance Group resource. // - // Note that you must specify an Instance Group resource using the - // fully-qualified URL, rather than a partial URL. + // For Network Endpoint Groups this defines list of endpoints. All + // endpoints of Network Endpoint Group must be hosted on instances + // located in the same zone as the Network Endpoint Group. + // + // Backend service can not contain mix of Instance Group and Network + // Endpoint Group backends. + // + // Note that you must specify an Instance Group or Network Endpoint + // Group resource using the fully-qualified URL, rather than a partial + // URL. // // When the BackendService has load balancing scheme INTERNAL, the // instance group must be within the same region as the BackendService. + // Network Endpoint Groups are not supported for INTERNAL load balancing + // scheme. Group string `json:"group,omitempty"` // MaxConnections: The max number of simultaneous connections for the @@ -3474,7 +4180,7 @@ type BackendBucket struct { // BucketName: Cloud Storage bucket name. BucketName string `json:"bucketName,omitempty"` - // CdnPolicy: Cloud CDN Coniguration for this BackendBucket. + // CdnPolicy: Cloud CDN configuration for this BackendBucket. CdnPolicy *BackendBucketCdnPolicy `json:"cdnPolicy,omitempty"` // CreationTimestamp: [Output Only] Creation timestamp in RFC3339 text @@ -3537,18 +4243,18 @@ func (s *BackendBucket) MarshalJSON() ([]byte, error) { // BackendBucketCdnPolicy: Message containing Cloud CDN configuration // for a backend bucket. type BackendBucketCdnPolicy struct { - // SignedUrlCacheMaxAgeSec: Number of seconds up to which the response - // to a signed URL request will be cached in the CDN. After this time - // period, the Signed URL will be revalidated before being served. - // Defaults to 1hr (3600s). If this field is set, Cloud CDN will - // internally act as though all responses from this bucket had a - // ?Cache-Control: public, max-age=[TTL]? header, regardless of any + // SignedUrlCacheMaxAgeSec: Maximum number of seconds the response to a + // signed URL request will be considered fresh. After this time period, + // the response will be revalidated before being served. Defaults to 1hr + // (3600s). When serving responses to signed URL requests, Cloud CDN + // will internally behave as though all responses from this backend had + // a "Cache-Control: public, max-age=[TTL]" header, regardless of any // existing Cache-Control header. The actual headers served in responses // will not be altered. SignedUrlCacheMaxAgeSec int64 `json:"signedUrlCacheMaxAgeSec,omitempty,string"` - // SignedUrlKeyNames: [Output Only] Names of the keys currently - // configured for Cloud CDN Signed URL on this backend bucket. + // SignedUrlKeyNames: [Output Only] Names of the keys for signing + // request URLs. SignedUrlKeyNames []string `json:"signedUrlKeyNames,omitempty"` // ForceSendFields is a list of field names (e.g. @@ -3772,7 +4478,11 @@ type BackendService struct { // Fingerprint: Fingerprint of this resource. A hash of the contents // stored in this object. This field is used in optimistic locking. This // field will be ignored when inserting a BackendService. An up-to-date - // fingerprint must be provided in order to update the BackendService. + // fingerprint must be provided in order to update the BackendService, + // otherwise the request will fail with error 412 conditionNotMet. + // + // To see the latest fingerprint, make a get() request to retrieve a + // BackendService. Fingerprint string `json:"fingerprint,omitempty"` // HealthChecks: The list of URLs to the HttpHealthCheck or @@ -4074,18 +4784,18 @@ type BackendServiceCdnPolicy struct { // CacheKeyPolicy: The CacheKeyPolicy for this CdnPolicy. CacheKeyPolicy *CacheKeyPolicy `json:"cacheKeyPolicy,omitempty"` - // SignedUrlCacheMaxAgeSec: Number of seconds up to which the response - // to a signed URL request will be cached in the CDN. After this time - // period, the Signed URL will be revalidated before being served. - // Defaults to 1hr (3600s). If this field is set, Cloud CDN will - // internally act as though all responses from this backend had a - // ?Cache-Control: public, max-age=[TTL]? header, regardless of any + // SignedUrlCacheMaxAgeSec: Maximum number of seconds the response to a + // signed URL request will be considered fresh. After this time period, + // the response will be revalidated before being served. Defaults to 1hr + // (3600s). When serving responses to signed URL requests, Cloud CDN + // will internally behave as though all responses from this backend had + // a "Cache-Control: public, max-age=[TTL]" header, regardless of any // existing Cache-Control header. The actual headers served in responses // will not be altered. SignedUrlCacheMaxAgeSec int64 `json:"signedUrlCacheMaxAgeSec,omitempty,string"` - // SignedUrlKeyNames: [Output Only] Names of the keys currently - // configured for Cloud CDN Signed URL on this backend service. + // SignedUrlKeyNames: [Output Only] Names of the keys for signing + // request URLs. SignedUrlKeyNames []string `json:"signedUrlKeyNames,omitempty"` // ForceSendFields is a list of field names (e.g. "CacheKeyPolicy") to @@ -4113,6 +4823,9 @@ func (s *BackendServiceCdnPolicy) MarshalJSON() ([]byte, error) { } type BackendServiceGroupHealth struct { + // HealthStatus: Health state of the backend instances or endpoints in + // requested instance or network endpoint group, determined based on + // configured health checks. HealthStatus []*HealthStatus `json:"healthStatus,omitempty"` // Kind: [Output Only] Type of resource. Always @@ -4500,11 +5213,10 @@ func (s *BackendServicesScopedListWarningData) MarshalJSON() ([]byte, error) { // Binding: Associates `members` with a `role`. type Binding struct { - // Condition: The condition that is associated with this binding. NOTE: - // an unsatisfied condition will not allow user access via current - // binding. Different bindings, including their conditions, are examined - // independently. This field is only visible as GOOGLE_INTERNAL or - // CONDITION_TRUSTED_TESTER. + // Condition: Unimplemented. The condition that is associated with this + // binding. NOTE: an unsatisfied condition will not allow user access + // via current binding. Different bindings, including their conditions, + // are examined independently. Condition *Expr `json:"condition,omitempty"` // Members: Specifies the identities requesting access for a Cloud @@ -4657,6 +5369,9 @@ func (s *CacheKeyPolicy) MarshalJSON() ([]byte, error) { // must purchase a new commitment to continue receiving discounts. (== // resource_for beta.commitments ==) (== resource_for v1.commitments ==) type Commitment struct { + // Allocations: List of allocations for this commitment. + Allocations []*Allocation `json:"allocations,omitempty"` + // CreationTimestamp: [Output Only] Creation timestamp in RFC3339 text // format. CreationTimestamp string `json:"creationTimestamp,omitempty"` @@ -4730,21 +5445,20 @@ type Commitment struct { // server. googleapi.ServerResponse `json:"-"` - // ForceSendFields is a list of field names (e.g. "CreationTimestamp") - // to unconditionally include in API requests. By default, fields with + // ForceSendFields is a list of field names (e.g. "Allocations") to + // unconditionally include in API requests. By default, fields with // empty values are omitted from API requests. However, any non-pointer, // non-interface field appearing in ForceSendFields will be sent to the // server regardless of whether the field is empty or not. This may be // used to include empty fields in Patch requests. ForceSendFields []string `json:"-"` - // NullFields is a list of field names (e.g. "CreationTimestamp") to - // include in API requests with the JSON null value. By default, fields - // with empty values are omitted from API requests. However, any field - // with an empty value appearing in NullFields will be sent to the - // server as null. It is an error if a field in this list has a - // non-empty value. This may be used to include null fields in Patch - // requests. + // NullFields is a list of field names (e.g. "Allocations") to include + // in API requests with the JSON null value. By default, fields with + // empty values are omitted from API requests. However, any field with + // an empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. NullFields []string `json:"-"` } @@ -5490,7 +6204,8 @@ type Disk struct { // optimistic locking. The fingerprint is initially generated by Compute // Engine and changes after every request to modify or update labels. // You must always provide an up-to-date fingerprint hash in order to - // update or change labels. + // update or change labels, otherwise the request will fail with error + // 412 conditionNotMet. // // To see the latest fingerprint, make a get() request to retrieve a // disk. @@ -5512,7 +6227,8 @@ type Disk struct { // attached to this disk. LicenseCodes googleapi.Int64s `json:"licenseCodes,omitempty"` - // Licenses: Any applicable publicly visible licenses. + // Licenses: A list of publicly visible licenses. Reserved for Google's + // use. Licenses []string `json:"licenses,omitempty"` // Name: Name of the resource. Provided by the client when the resource @@ -5527,6 +6243,13 @@ type Disk struct { // Options: Internal use only. Options string `json:"options,omitempty"` + // PhysicalBlockSizeBytes: Physical block size of the persistent disk, + // in bytes. If not present in a request, a default value is used. + // Currently supported sizes are 4096 and 16384, other sizes may be + // added in the future. If an unsupported value is requested, the error + // message will list the supported values for the caller's project. + PhysicalBlockSizeBytes int64 `json:"physicalBlockSizeBytes,omitempty,string"` + // Region: [Output Only] URL of the region where the disk resides. Only // applicable for regional resources. You must specify this field as // part of the HTTP request URL. It is not settable as a field in the @@ -5537,6 +6260,10 @@ type Disk struct { // to. Only applicable for regional resources. ReplicaZones []string `json:"replicaZones,omitempty"` + // ResourcePolicies: Resource policies applied to this disk for + // automatic snapshot creations. + ResourcePolicies []string `json:"resourcePolicies,omitempty"` + // SelfLink: [Output Only] Server-defined fully-qualified URL for this // resource. SelfLink string `json:"selfLink,omitempty"` @@ -5557,15 +6284,15 @@ type Disk struct { // // To create a disk with one of the public operating system images, // specify the image by its family name. For example, specify - // family/debian-8 to use the latest Debian 8 + // family/debian-9 to use the latest Debian 9 // image: - // projects/debian-cloud/global/images/family/debian-8 + // projects/debian-cloud/global/images/family/debian-9 // // // Alternati // vely, use a specific version of a public operating system // image: - // projects/debian-cloud/global/images/debian-8-jessie-vYYYYMMDD + // projects/debian-cloud/global/images/debian-9-stretch-vYYYYMMDD // // // @@ -6612,6 +7339,62 @@ func (s *DiskTypesScopedListWarningData) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +type DisksAddResourcePoliciesRequest struct { + // ResourcePolicies: Resource policies to be added to this disk. + ResourcePolicies []string `json:"resourcePolicies,omitempty"` + + // ForceSendFields is a list of field names (e.g. "ResourcePolicies") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "ResourcePolicies") to + // include in API requests with the JSON null value. By default, fields + // with empty values are omitted from API requests. However, any field + // with an empty value appearing in NullFields will be sent to the + // server as null. It is an error if a field in this list has a + // non-empty value. This may be used to include null fields in Patch + // requests. + NullFields []string `json:"-"` +} + +func (s *DisksAddResourcePoliciesRequest) MarshalJSON() ([]byte, error) { + type NoMethod DisksAddResourcePoliciesRequest + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type DisksRemoveResourcePoliciesRequest struct { + // ResourcePolicies: Resource policies to be removed from this disk. + ResourcePolicies []string `json:"resourcePolicies,omitempty"` + + // ForceSendFields is a list of field names (e.g. "ResourcePolicies") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "ResourcePolicies") to + // include in API requests with the JSON null value. By default, fields + // with empty values are omitted from API requests. However, any field + // with an empty value appearing in NullFields will be sent to the + // server as null. It is an error if a field in this list has a + // non-empty value. This may be used to include null fields in Patch + // requests. + NullFields []string `json:"-"` +} + +func (s *DisksRemoveResourcePoliciesRequest) MarshalJSON() ([]byte, error) { + type NoMethod DisksRemoveResourcePoliciesRequest + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + type DisksResizeRequest struct { // SizeGb: The new size of the persistent disk, which is specified in // GB. @@ -6773,7 +7556,37 @@ func (s *DisksScopedListWarningData) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +// DisplayDevice: A set of Display Device options +type DisplayDevice struct { + // EnableDisplay: Defines whether the instance has Display enabled. + EnableDisplay bool `json:"enableDisplay,omitempty"` + + // ForceSendFields is a list of field names (e.g. "EnableDisplay") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "EnableDisplay") to include + // in API requests with the JSON null value. By default, fields with + // empty values are omitted from API requests. However, any field with + // an empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *DisplayDevice) MarshalJSON() ([]byte, error) { + type NoMethod DisplayDevice + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + type DistributionPolicy struct { + // Zones: Zones where the regional managed instance group will create + // and manage instances. Zones []*DistributionPolicyZoneConfiguration `json:"zones,omitempty"` // ForceSendFields is a list of field names (e.g. "Zones") to @@ -6800,9 +7613,8 @@ func (s *DistributionPolicy) MarshalJSON() ([]byte, error) { } type DistributionPolicyZoneConfiguration struct { - // Zone: URL of the zone where managed instance group is spawning - // instances (for regional resources). Zone has to belong to the region - // where managed instance group is located. + // Zone: The URL of the zone. The zone must exist in the region where + // the managed instance group is located. Zone string `json:"zone,omitempty"` // ForceSendFields is a list of field names (e.g. "Zone") to @@ -6828,6 +7640,208 @@ func (s *DistributionPolicyZoneConfiguration) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +type ExchangedPeeringRoute struct { + // DestRange: The destination range of the route. + DestRange string `json:"destRange,omitempty"` + + // Imported: If the peering route is imported if there is no + // confliction. + Imported bool `json:"imported,omitempty"` + + // NextHopRegion: The region of peering route next hop, only applies to + // dynamic routes. + NextHopRegion string `json:"nextHopRegion,omitempty"` + + // Priority: The priority of the peering route. + Priority int64 `json:"priority,omitempty"` + + // Type: The type of the peering route. + // + // Possible values: + // "DYNAMIC_PEERING_ROUTE" + // "STATIC_PEERING_ROUTE" + // "SUBNET_PEERING_ROUTE" + Type string `json:"type,omitempty"` + + // ForceSendFields is a list of field names (e.g. "DestRange") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "DestRange") to include in + // API requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *ExchangedPeeringRoute) MarshalJSON() ([]byte, error) { + type NoMethod ExchangedPeeringRoute + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type ExchangedPeeringRoutesList struct { + // Id: [Output Only] Unique identifier for the resource; defined by the + // server. + Id string `json:"id,omitempty"` + + // Items: A list of ExchangedPeeringRoute resources. + Items []*ExchangedPeeringRoute `json:"items,omitempty"` + + // Kind: [Output Only] Type of resource. Always + // compute#exchangedPeeringRoutesList for exchanged peering routes + // lists. + Kind string `json:"kind,omitempty"` + + // NextPageToken: [Output Only] This token allows you to get the next + // page of results for list requests. If the number of results is larger + // than maxResults, use the nextPageToken as a value for the query + // parameter pageToken in the next list request. Subsequent list + // requests will have their own nextPageToken to continue paging through + // the results. + NextPageToken string `json:"nextPageToken,omitempty"` + + // SelfLink: [Output Only] Server-defined URL for this resource. + SelfLink string `json:"selfLink,omitempty"` + + // Warning: [Output Only] Informational warning message. + Warning *ExchangedPeeringRoutesListWarning `json:"warning,omitempty"` + + // ServerResponse contains the HTTP response code and headers from the + // server. + googleapi.ServerResponse `json:"-"` + + // ForceSendFields is a list of field names (e.g. "Id") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Id") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *ExchangedPeeringRoutesList) MarshalJSON() ([]byte, error) { + type NoMethod ExchangedPeeringRoutesList + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// ExchangedPeeringRoutesListWarning: [Output Only] Informational +// warning message. +type ExchangedPeeringRoutesListWarning struct { + // Code: [Output Only] A warning code, if applicable. For example, + // Compute Engine returns NO_RESULTS_ON_PAGE if there are no results in + // the response. + // + // Possible values: + // "CLEANUP_FAILED" + // "DEPRECATED_RESOURCE_USED" + // "DEPRECATED_TYPE_USED" + // "DISK_SIZE_LARGER_THAN_IMAGE_SIZE" + // "EXPERIMENTAL_TYPE_USED" + // "EXTERNAL_API_WARNING" + // "FIELD_VALUE_OVERRIDEN" + // "INJECTED_KERNELS_DEPRECATED" + // "MISSING_TYPE_DEPENDENCY" + // "NEXT_HOP_ADDRESS_NOT_ASSIGNED" + // "NEXT_HOP_CANNOT_IP_FORWARD" + // "NEXT_HOP_INSTANCE_NOT_FOUND" + // "NEXT_HOP_INSTANCE_NOT_ON_NETWORK" + // "NEXT_HOP_NOT_RUNNING" + // "NOT_CRITICAL_ERROR" + // "NO_RESULTS_ON_PAGE" + // "REQUIRED_TOS_AGREEMENT" + // "RESOURCE_IN_USE_BY_OTHER_RESOURCE_WARNING" + // "RESOURCE_NOT_DELETED" + // "SCHEMA_VALIDATION_IGNORED" + // "SINGLE_INSTANCE_PROPERTY_TEMPLATE" + // "UNDECLARED_PROPERTIES" + // "UNREACHABLE" + Code string `json:"code,omitempty"` + + // Data: [Output Only] Metadata about this warning in key: value format. + // For example: + // "data": [ { "key": "scope", "value": "zones/us-east1-d" } + Data []*ExchangedPeeringRoutesListWarningData `json:"data,omitempty"` + + // Message: [Output Only] A human-readable description of the warning + // code. + Message string `json:"message,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Code") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Code") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *ExchangedPeeringRoutesListWarning) MarshalJSON() ([]byte, error) { + type NoMethod ExchangedPeeringRoutesListWarning + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type ExchangedPeeringRoutesListWarningData struct { + // Key: [Output Only] A key that provides more detail on the warning + // being returned. For example, for warnings where there are no results + // in a list request for a particular zone, this key might be scope and + // the key value might be the zone name. Other examples might be a key + // indicating a deprecated resource and a suggested replacement, or a + // warning about invalid network settings (for example, if an instance + // attempts to perform IP forwarding but is not enabled for IP + // forwarding). + Key string `json:"key,omitempty"` + + // Value: [Output Only] A warning data value corresponding to the key. + Value string `json:"value,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Key") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Key") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *ExchangedPeeringRoutesListWarningData) MarshalJSON() ([]byte, error) { + type NoMethod ExchangedPeeringRoutesListWarningData + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + // Expr: Represents an expression text. Example: // // title: "User account presence" description: "Determines whether the @@ -6920,9 +7934,9 @@ type Firewall struct { // not exist. If this is unspecified, the firewall rule will be enabled. Disabled bool `json:"disabled,omitempty"` - // EnableLogging: This field denotes whether to enable logging for a - // particular firewall rule. If logging is enabled, logs will be - // exported to Stackdriver. + // EnableLogging: Deprecated in favor of enable in LogConfig. This field + // denotes whether to enable logging for a particular firewall rule. If + // logging is enabled, logs will be exported to Stackdriver. EnableLogging bool `json:"enableLogging,omitempty"` // Id: [Output Only] The unique identifier for the resource. This @@ -6933,6 +7947,11 @@ type Firewall struct { // firewall rules. Kind string `json:"kind,omitempty"` + // LogConfig: This field denotes the logging options for a particular + // firewall rule. If logging is enabled, logs will be exported to + // Stackdriver. + LogConfig *FirewallLogConfig `json:"logConfig,omitempty"` + // Name: Name of the resource; provided by the client when the resource // is created. The name must be 1-63 characters long, and comply with // RFC1035. Specifically, the name must be 1-63 characters long and @@ -7277,6 +8296,35 @@ func (s *FirewallListWarningData) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +// FirewallLogConfig: The available logging options for a firewall rule. +type FirewallLogConfig struct { + // Enable: This field denotes whether to enable logging for a particular + // firewall rule. + Enable bool `json:"enable,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Enable") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Enable") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *FirewallLogConfig) MarshalJSON() ([]byte, error) { + type NoMethod FirewallLogConfig + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + // FixedOrPercent: Encapsulates numeric value that can be either // absolute or relative. type FixedOrPercent struct { @@ -7347,6 +8395,11 @@ type ForwardingRule struct { // rule supports IPv4 only. A global forwarding rule supports either // IPv4 or IPv6. // + // When the load balancing scheme is INTERNAL_SELF_MANAGED, this must be + // a URL reference to an existing Address resource ( internal regional + // static IP address), with a purpose of GCE_END_POINT and address_type + // of INTERNAL. + // // When the load balancing scheme is INTERNAL, this can only be an RFC // 1918 IP address belonging to the network/subnet configured for the // forwarding rule. By default, if this field is empty, an ephemeral @@ -7369,7 +8422,8 @@ type ForwardingRule struct { // are TCP, UDP, ESP, AH, SCTP or ICMP. // // When the load balancing scheme is INTERNAL, only TCP and UDP are - // valid. + // valid. When the load balancing scheme is INTERNAL_SELF_MANAGED, only + // TCPis valid. // // Possible values: // "AH" @@ -7380,7 +8434,17 @@ type ForwardingRule struct { // "UDP" IPProtocol string `json:"IPProtocol,omitempty"` - // BackendService: This field is not used for external load + // AllPorts: This field is used along with the backend_service field for + // internal load balancing or with the target field for internal + // TargetInstance. This field cannot be used with port or portRange + // fields. + // + // When the load balancing scheme is INTERNAL and protocol is TCP/UDP, + // specify this field to allow packets addressed to any ports will be + // forwarded to the backends configured with this forwarding rule. + AllPorts bool `json:"allPorts,omitempty"` + + // BackendService: This field is only used for INTERNAL load // balancing. // // For internal load balancing, this field identifies the BackendService @@ -7400,8 +8464,8 @@ type ForwardingRule struct { Id uint64 `json:"id,omitempty,string"` // IpVersion: The IP Version that will be used by this forwarding rule. - // Valid options are IPV4 or IPV6. This can only be specified for a - // global forwarding rule. + // Valid options are IPV4 or IPV6. This can only be specified for an + // external global forwarding rule. // // Possible values: // "IPV4" @@ -7418,7 +8482,8 @@ type ForwardingRule struct { // optimistic locking. The fingerprint is initially generated by Compute // Engine and changes after every request to modify or update labels. // You must always provide an up-to-date fingerprint hash in order to - // update or change labels. + // update or change labels, otherwise the request will fail with error + // 412 conditionNotMet. // // To see the latest fingerprint, make a get() request to retrieve a // ForwardingRule. @@ -7430,10 +8495,12 @@ type ForwardingRule struct { Labels map[string]string `json:"labels,omitempty"` // LoadBalancingScheme: This signifies what the ForwardingRule will be - // used for and can only take the following values: INTERNAL, EXTERNAL - // The value of INTERNAL means that this will be used for Internal - // Network Load Balancing (TCP, UDP). The value of EXTERNAL means that - // this will be used for External Load Balancing (HTTP(S) LB, External + // used for and can only take the following values: INTERNAL, + // INTERNAL_SELF_MANAGED, EXTERNAL. The value of INTERNAL means that + // this will be used for Internal Network Load Balancing (TCP, UDP). The + // value of INTERNAL_SELF_MANAGED means that this will be used for + // Internal Global HTTP(S) LB. The value of EXTERNAL means that this + // will be used for External Load Balancing (HTTP(S) LB, External // TCP/UDP LB, SSL Proxy) // // Possible values: @@ -7453,9 +8520,10 @@ type ForwardingRule struct { // Network: This field is not used for external load balancing. // - // For internal load balancing, this field identifies the network that - // the load balanced IP should belong to for this Forwarding Rule. If - // this field is not specified, the default network will be used. + // For INTERNAL and INTERNAL_SELF_MANAGED load balancing, this field + // identifies the network that the load balanced IP should belong to for + // this Forwarding Rule. If this field is not specified, the default + // network will be used. Network string `json:"network,omitempty"` // NetworkTier: This signifies the networking tier used for configuring @@ -7497,10 +8565,10 @@ type ForwardingRule struct { // Ports: This field is used along with the backend_service field for // internal load balancing. // - // When the load balancing scheme is INTERNAL, a single port or a comma - // separated list of ports can be configured. Only packets addressed to - // these ports will be forwarded to the backends configured with this - // forwarding rule. + // When the load balancing scheme is INTERNAL, a list of ports can be + // configured, for example, ['80'], ['8000','9000'] etc. Only packets + // addressed to these ports will be forwarded to the backends configured + // with this forwarding rule. // // You may specify a maximum of up to 5 ports. Ports []string `json:"ports,omitempty"` @@ -7534,7 +8602,7 @@ type ForwardingRule struct { // This field is only used for internal load balancing. ServiceName string `json:"serviceName,omitempty"` - // Subnetwork: This field is not used for external load balancing. + // Subnetwork: This field is only used for INTERNAL load balancing. // // For internal load balancing, this field identifies the subnetwork // that the load balanced IP should belong to for this Forwarding @@ -7549,7 +8617,9 @@ type ForwardingRule struct { // traffic. For regional forwarding rules, this target must live in the // same region as the forwarding rule. For global forwarding rules, this // target must be a global load balancing resource. The forwarded - // traffic must be of a type appropriate to the target object. + // traffic must be of a type appropriate to the target object. For + // INTERNAL_SELF_MANAGED" load balancing, only HTTP and HTTPS targets + // are valid. Target string `json:"target,omitempty"` // ServerResponse contains the HTTP response code and headers from the @@ -8055,7 +9125,8 @@ type GlobalSetLabelsRequest struct { // this resource, used to detect conflicts. The fingerprint is initially // generated by Compute Engine and changes after every request to modify // or update labels. You must always provide an up-to-date fingerprint - // hash when updating or changing labels. Make a get() request to the + // hash when updating or changing labels, otherwise the request will + // fail with error 412 conditionNotMet. Make a get() request to the // resource to get the latest fingerprint. LabelFingerprint string `json:"labelFingerprint,omitempty"` @@ -8093,6 +9164,155 @@ func (s *GlobalSetLabelsRequest) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +type GlobalSetPolicyRequest struct { + // Bindings: Flatten Policy to create a backward compatible wire-format. + // Deprecated. Use 'policy' to specify bindings. + Bindings []*Binding `json:"bindings,omitempty"` + + // Etag: Flatten Policy to create a backward compatible wire-format. + // Deprecated. Use 'policy' to specify the etag. + Etag string `json:"etag,omitempty"` + + // Policy: REQUIRED: The complete policy to be applied to the + // 'resource'. The size of the policy is limited to a few 10s of KB. An + // empty policy is in general a valid policy but certain services (like + // Projects) might reject them. + Policy *Policy `json:"policy,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Bindings") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Bindings") to include in + // API requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *GlobalSetPolicyRequest) MarshalJSON() ([]byte, error) { + type NoMethod GlobalSetPolicyRequest + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// GuestAttributes: A guest attributes entry. +type GuestAttributes struct { + // Kind: [Output Only] Type of the resource. Always + // compute#guestAttributes for guest attributes entry. + Kind string `json:"kind,omitempty"` + + // QueryPath: The path to be queried. This can be the default namespace + // ('/') or a nested namespace ('//') or a specified key ('//') + QueryPath string `json:"queryPath,omitempty"` + + // QueryValue: [Output Only] The value of the requested queried path. + QueryValue *GuestAttributesValue `json:"queryValue,omitempty"` + + // SelfLink: [Output Only] Server-defined URL for this resource. + SelfLink string `json:"selfLink,omitempty"` + + // VariableKey: The key to search for. + VariableKey string `json:"variableKey,omitempty"` + + // VariableValue: [Output Only] The value found for the requested key. + VariableValue string `json:"variableValue,omitempty"` + + // ServerResponse contains the HTTP response code and headers from the + // server. + googleapi.ServerResponse `json:"-"` + + // ForceSendFields is a list of field names (e.g. "Kind") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Kind") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *GuestAttributes) MarshalJSON() ([]byte, error) { + type NoMethod GuestAttributes + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// GuestAttributesEntry: A guest attributes namespace/key/value entry. +type GuestAttributesEntry struct { + // Key: Key for the guest attribute entry. + Key string `json:"key,omitempty"` + + // Namespace: Namespace for the guest attribute entry. + Namespace string `json:"namespace,omitempty"` + + // Value: Value for the guest attribute entry. + Value string `json:"value,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Key") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Key") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *GuestAttributesEntry) MarshalJSON() ([]byte, error) { + type NoMethod GuestAttributesEntry + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// GuestAttributesValue: Array of guest attribute namespace/key/value +// tuples. +type GuestAttributesValue struct { + Items []*GuestAttributesEntry `json:"items,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Items") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Items") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *GuestAttributesValue) MarshalJSON() ([]byte, error) { + type NoMethod GuestAttributesValue + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + // GuestOsFeature: Guest OS features. type GuestOsFeature struct { // Type: The ID of a supported feature. Read Enabling guest operating @@ -8442,11 +9662,8 @@ type HealthCheck struct { // "INVALID" // "SSL" // "TCP" - // "UDP" Type string `json:"type,omitempty"` - UdpHealthCheck *UDPHealthCheck `json:"udpHealthCheck,omitempty"` - // UnhealthyThreshold: A so-far healthy instance will be marked // unhealthy after this many consecutive failures. The default value is // 2. @@ -9346,7 +10563,8 @@ type Image struct { // locking. The fingerprint is initially generated by Compute Engine and // changes after every request to modify or update labels. You must // always provide an up-to-date fingerprint hash in order to update or - // change labels. + // change labels, otherwise the request will fail with error 412 + // conditionNotMet. // // To see the latest fingerprint, make a get() request to retrieve an // image. @@ -9393,9 +10611,9 @@ type Image struct { // customer-supplied encryption key. SourceDiskEncryptionKey *CustomerEncryptionKey `json:"sourceDiskEncryptionKey,omitempty"` - // SourceDiskId: The ID value of the disk used to create this image. - // This value may be used to determine whether the image was taken from - // the current or a previous instance of a given disk name. + // SourceDiskId: [Output Only] The ID value of the disk used to create + // this image. This value may be used to determine whether the image was + // taken from the current or a previous instance of a given disk name. SourceDiskId string `json:"sourceDiskId,omitempty"` // SourceImage: URL of the source image used to create this image. This @@ -9682,6 +10900,10 @@ func (s *ImageListWarningData) MarshalJSON() ([]byte, error) { // Instance: An Instance resource. (== resource_for beta.instances ==) // (== resource_for v1.instances ==) type Instance struct { + // AllocationAffinity: The configuration of desired allocations which + // this Instance could consume capacity from. + AllocationAffinity *AllocationAffinity `json:"allocationAffinity,omitempty"` + // CanIpForward: Allows this instance to send and receive packets with // non-matching destination or source IPs. This is required if you plan // to use this instance to forward routes. For more information, see @@ -9707,10 +10929,15 @@ type Instance struct { // must be created before you can assign them. Disks []*AttachedDisk `json:"disks,omitempty"` + // DisplayDevice: Enables display device for the instance. + DisplayDevice *DisplayDevice `json:"displayDevice,omitempty"` + // GuestAccelerators: A list of the type and count of accelerator cards // attached to the instance. GuestAccelerators []*AcceleratorConfig `json:"guestAccelerators,omitempty"` + Hostname string `json:"hostname,omitempty"` + // Id: [Output Only] The unique identifier for the resource. This // identifier is defined by the server. Id uint64 `json:"id,omitempty,string"` @@ -9825,11 +11052,11 @@ type Instance struct { // of the status. StatusMessage string `json:"statusMessage,omitempty"` - // Tags: A list of tags to apply to this instance. Tags are used to - // identify valid sources or targets for network firewalls and are - // specified by the client during instance creation. The tags can be - // later modified by the setTags method. Each tag within the list must - // comply with RFC1035. + // Tags: Tags to apply to this instance. Tags are used to identify valid + // sources or targets for network firewalls and are specified by the + // client during instance creation. The tags can be later modified by + // the setTags method. Each tag within the list must comply with + // RFC1035. Multiple tags can be specified via the 'tags.items' field. Tags *Tags `json:"tags,omitempty"` // Zone: [Output Only] URL of the zone where the instance resides. You @@ -9841,20 +11068,21 @@ type Instance struct { // server. googleapi.ServerResponse `json:"-"` - // ForceSendFields is a list of field names (e.g. "CanIpForward") to - // unconditionally include in API requests. By default, fields with + // ForceSendFields is a list of field names (e.g. "AllocationAffinity") + // to unconditionally include in API requests. By default, fields with // empty values are omitted from API requests. However, any non-pointer, // non-interface field appearing in ForceSendFields will be sent to the // server regardless of whether the field is empty or not. This may be // used to include empty fields in Patch requests. ForceSendFields []string `json:"-"` - // NullFields is a list of field names (e.g. "CanIpForward") to include - // in API requests with the JSON null value. By default, fields with - // empty values are omitted from API requests. However, any field with - // an empty value appearing in NullFields will be sent to the server as - // null. It is an error if a field in this list has a non-empty value. - // This may be used to include null fields in Patch requests. + // NullFields is a list of field names (e.g. "AllocationAffinity") to + // include in API requests with the JSON null value. By default, fields + // with empty values are omitted from API requests. However, any field + // with an empty value appearing in NullFields will be sent to the + // server as null. It is an error if a field in this list has a + // non-empty value. This may be used to include null fields in Patch + // requests. NullFields []string `json:"-"` } @@ -10454,8 +11682,8 @@ type InstanceGroupManager struct { // property when you create the resource. Description string `json:"description,omitempty"` - // DistributionPolicy: Policy valid only for regional managed instance - // groups. + // DistributionPolicy: Policy specifying intended distribution of + // instances in regional managed instance group. DistributionPolicy *DistributionPolicy `json:"distributionPolicy,omitempty"` // FailoverAction: The action to perform in case of zone failure. Only @@ -10469,7 +11697,11 @@ type InstanceGroupManager struct { // Fingerprint: Fingerprint of this resource. This field may be used in // optimistic locking. It will be ignored when inserting an // InstanceGroupManager. An up-to-date fingerprint must be provided in - // order to update the InstanceGroupManager. + // order to update the InstanceGroupManager, otherwise the request will + // fail with error 412 conditionNotMet. + // + // To see the latest fingerprint, make a get() request to retrieve an + // InstanceGroupManager. Fingerprint string `json:"fingerprint,omitempty"` // Id: [Output Only] A unique identifier for this resource type. The @@ -10516,6 +11748,9 @@ type InstanceGroupManager struct { // {projectNumber}@cloudservices.gserviceaccount.com is used. ServiceAccount string `json:"serviceAccount,omitempty"` + // Status: [Output Only] The status of this managed instance group. + Status *InstanceGroupManagerStatus `json:"status,omitempty"` + // TargetPools: The URLs for all TargetPool resources to which instances // in the instanceGroup field are added. The target pools automatically // apply to all of the instances in the managed instance group. @@ -11042,6 +12277,38 @@ func (s *InstanceGroupManagerPendingActionsSummary) MarshalJSON() ([]byte, error return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +type InstanceGroupManagerStatus struct { + // IsStable: [Output Only] A bit indicating whether the managed instance + // group is in a stable state. A stable state means that: none of the + // instances in the managed instance group is currently undergoing any + // type of change (for example, creation, restart, or deletion); no + // future changes are scheduled for instances in the managed instance + // group; and the managed instance group itself is not being modified. + IsStable bool `json:"isStable,omitempty"` + + // ForceSendFields is a list of field names (e.g. "IsStable") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "IsStable") to include in + // API requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *InstanceGroupManagerStatus) MarshalJSON() ([]byte, error) { + type NoMethod InstanceGroupManagerStatus + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + type InstanceGroupManagerUpdatePolicy struct { // MaxSurge: The maximum number of instances that can be created above // the specified targetSize during the update process. By default, a @@ -11081,10 +12348,10 @@ type InstanceGroupManagerUpdatePolicy struct { // MinimalAction: Minimal action to be taken on an instance. You can // specify either RESTART to restart existing instances or REPLACE to // delete and create new instances from the target template. If you - // specify a code>RESTART, the Updater will attempt to perform that - // action only. However, if the Updater determines that the minimal - // action you specify is not enough to perform the update, it might - // perform a more disruptive action. + // specify a RESTART, the Updater will attempt to perform that action + // only. However, if the Updater determines that the minimal action you + // specify is not enough to perform the update, it might perform a more + // disruptive action. // // Possible values: // "REPLACE" @@ -11296,7 +12563,7 @@ type InstanceGroupManagersResizeAdvancedRequest struct { // only once. If there is an error during creation, the managed instance // group does not retry create this instance, and we will decrease the // targetSize of the request instead. If the flag is false, the group - // attemps to recreate each instance continuously until it + // attempts to recreate each instance continuously until it // succeeds. // // This flag matters only in the first attempt of creation of an @@ -11963,7 +13230,9 @@ type InstanceGroupsSetNamedPortsRequest struct { // multiple users change the named ports settings concurrently. Obtain // the fingerprint with the instanceGroups.get method. Then, include the // fingerprint in your request to ensure that you do not overwrite - // changes that were applied from another concurrent request. + // changes that were applied from another concurrent request. A request + // with an incorrect fingerprint will fail with error 412 + // conditionNotMet. Fingerprint string `json:"fingerprint,omitempty"` // NamedPorts: The list of named ports to set for this instance group. @@ -12347,6 +13616,10 @@ func (s *InstanceMoveRequest) MarshalJSON() ([]byte, error) { } type InstanceProperties struct { + // AllocationAffinity: The configuration of desired allocations which + // this Instance could consume capacity from. + AllocationAffinity *AllocationAffinity `json:"allocationAffinity,omitempty"` + // CanIpForward: Enables instances created based on this template to // send packets with source IP addresses other than their own and // receive packets with destination IP addresses other than their own. @@ -12414,20 +13687,21 @@ type InstanceProperties struct { // within the list must comply with RFC1035. Tags *Tags `json:"tags,omitempty"` - // ForceSendFields is a list of field names (e.g. "CanIpForward") to - // unconditionally include in API requests. By default, fields with + // ForceSendFields is a list of field names (e.g. "AllocationAffinity") + // to unconditionally include in API requests. By default, fields with // empty values are omitted from API requests. However, any non-pointer, // non-interface field appearing in ForceSendFields will be sent to the // server regardless of whether the field is empty or not. This may be // used to include empty fields in Patch requests. ForceSendFields []string `json:"-"` - // NullFields is a list of field names (e.g. "CanIpForward") to include - // in API requests with the JSON null value. By default, fields with - // empty values are omitted from API requests. However, any field with - // an empty value appearing in NullFields will be sent to the server as - // null. It is an error if a field in this list has a non-empty value. - // This may be used to include null fields in Patch requests. + // NullFields is a list of field names (e.g. "AllocationAffinity") to + // include in API requests with the JSON null value. By default, fields + // with empty values are omitted from API requests. However, any field + // with an empty value appearing in NullFields will be sent to the + // server as null. It is an error if a field in this list has a + // non-empty value. This may be used to include null fields in Patch + // requests. NullFields []string `json:"-"` } @@ -12739,6 +14013,48 @@ func (s *InstanceWithNamedPorts) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +type InstancesResumeRequest struct { + // Disks: Array of disks associated with this instance that are + // protected with a customer-supplied encryption key. + // + // In order to resume the instance, the disk url and its corresponding + // key must be provided. + // + // If the disk is not protected with a customer-supplied encryption key + // it should not be specified. + Disks []*CustomerEncryptionKeyProtectedDisk `json:"disks,omitempty"` + + // InstanceEncryptionKey: Decrypts data associated with an instance that + // is protected with a customer-supplied encryption key. + // + // If the instance you are starting is protected with a + // customer-supplied encryption key, the correct key must be provided + // otherwise the instance resume will not succeed. + InstanceEncryptionKey *CustomerEncryptionKey `json:"instanceEncryptionKey,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Disks") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Disks") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *InstancesResumeRequest) MarshalJSON() ([]byte, error) { + type NoMethod InstancesResumeRequest + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + type InstancesScopedList struct { // Instances: [Output Only] A list of instances contained in this scope. Instances []*Instance `json:"instances,omitempty"` @@ -13124,7 +14440,8 @@ type Interconnect struct { // optimistic locking. The fingerprint is initially generated by Compute // Engine and changes after every request to modify or update labels. // You must always provide an up-to-date fingerprint hash in order to - // update or change labels. + // update or change labels, otherwise the request will fail with error + // 412 conditionNotMet. // // To see the latest fingerprint, make a get() request to retrieve an // Interconnect. @@ -13234,8 +14551,8 @@ type InterconnectAttachment struct { // Bandwidth: Provisioned bandwidth capacity for the // interconnectAttachment. Can be set by the partner to update the - // customer's provisioned bandwidth. Output only for for PARTNER type, - // mutable for PARTNER_PROVIDER, not available for DEDICATED. + // customer's provisioned bandwidth. Output only for PARTNER type, + // mutable for PARTNER_PROVIDER and DEDICATED. // // Possible values: // "BPS_100M" @@ -13313,7 +14630,8 @@ type InterconnectAttachment struct { // used for optimistic locking. The fingerprint is initially generated // by Compute Engine and changes after every request to modify or update // labels. You must always provide an up-to-date fingerprint hash in - // order to update or change labels. + // order to update or change labels, otherwise the request will fail + // with error 412 conditionNotMet. // // To see the latest fingerprint, make a get() request to retrieve an // InterconnectAttachment. @@ -13369,7 +14687,7 @@ type InterconnectAttachment struct { // body. Region string `json:"region,omitempty"` - // Router: URL of the cloud router to be used for dynamic routing. This + // Router: URL of the Cloud Router to be used for dynamic routing. This // router must be in the same region as this InterconnectAttachment. The // InterconnectAttachment will automatically connect the Interconnect to // the network & region within which the Cloud Router is configured. @@ -13397,10 +14715,8 @@ type InterconnectAttachment struct { // "PARTNER_PROVIDER" Type string `json:"type,omitempty"` - // VlanTag8021q: Available only for DEDICATED and PARTNER_PROVIDER. - // Desired VLAN tag for this attachment, in the range 2-4094. This field - // refers to 802.1q VLAN tag, also known as IEEE 802.1Q Only specified - // at creation time. + // VlanTag8021q: The IEEE 802.1Q VLAN tag for this attachment, in the + // range 2-4094. Only specified at creation time. VlanTag8021q int64 `json:"vlanTag8021q,omitempty"` // ServerResponse contains the HTTP response code and headers from the @@ -13751,7 +15067,7 @@ func (s *InterconnectAttachmentListWarningData) MarshalJSON() ([]byte, error) { type InterconnectAttachmentPartnerMetadata struct { // InterconnectName: Plain text name of the Interconnect this attachment // is connected to, as displayed in the Partner?s portal. For instance - // ?Chicago 1?. This value may be validated to match approved Partner + // "Chicago 1". This value may be validated to match approved Partner // values. InterconnectName string `json:"interconnectName,omitempty"` @@ -13996,6 +15312,211 @@ func (s *InterconnectCircuitInfo) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +// InterconnectDiagnostics: Diagnostics information about interconnect, +// contains detailed and current technical information about Google?s +// side of the connection. +type InterconnectDiagnostics struct { + // ArpCaches: A list of InterconnectDiagnostics.ARPEntry objects, + // describing individual neighbors currently seen by the Google router + // in the ARP cache for the Interconnect. This will be empty when the + // Interconnect is not bundled. + ArpCaches []*InterconnectDiagnosticsARPEntry `json:"arpCaches,omitempty"` + + // Links: A list of InterconnectDiagnostics.LinkStatus objects, + // describing the status for each link on the Interconnect. + Links []*InterconnectDiagnosticsLinkStatus `json:"links,omitempty"` + + // MacAddress: The MAC address of the Interconnect's bundle interface. + MacAddress string `json:"macAddress,omitempty"` + + // ForceSendFields is a list of field names (e.g. "ArpCaches") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "ArpCaches") to include in + // API requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *InterconnectDiagnostics) MarshalJSON() ([]byte, error) { + type NoMethod InterconnectDiagnostics + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// InterconnectDiagnosticsARPEntry: Describing the ARP neighbor entries +// seen on this link +type InterconnectDiagnosticsARPEntry struct { + // IpAddress: The IP address of this ARP neighbor. + IpAddress string `json:"ipAddress,omitempty"` + + // MacAddress: The MAC address of this ARP neighbor. + MacAddress string `json:"macAddress,omitempty"` + + // ForceSendFields is a list of field names (e.g. "IpAddress") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "IpAddress") to include in + // API requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *InterconnectDiagnosticsARPEntry) MarshalJSON() ([]byte, error) { + type NoMethod InterconnectDiagnosticsARPEntry + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type InterconnectDiagnosticsLinkLACPStatus struct { + // GoogleSystemId: System ID of the port on Google?s side of the LACP + // exchange. + GoogleSystemId string `json:"googleSystemId,omitempty"` + + // NeighborSystemId: System ID of the port on the neighbor?s side of the + // LACP exchange. + NeighborSystemId string `json:"neighborSystemId,omitempty"` + + // Possible values: + // "ACTIVE" + // "DETACHED" + State string `json:"state,omitempty"` + + // ForceSendFields is a list of field names (e.g. "GoogleSystemId") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "GoogleSystemId") to + // include in API requests with the JSON null value. By default, fields + // with empty values are omitted from API requests. However, any field + // with an empty value appearing in NullFields will be sent to the + // server as null. It is an error if a field in this list has a + // non-empty value. This may be used to include null fields in Patch + // requests. + NullFields []string `json:"-"` +} + +func (s *InterconnectDiagnosticsLinkLACPStatus) MarshalJSON() ([]byte, error) { + type NoMethod InterconnectDiagnosticsLinkLACPStatus + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type InterconnectDiagnosticsLinkOpticalPower struct { + // Possible values: + // "HIGH_ALARM" + // "HIGH_WARNING" + // "LOW_ALARM" + // "LOW_WARNING" + // "OK" + State string `json:"state,omitempty"` + + // Value: Value of the current optical power, read in dBm. Take a known + // good optical value, give it a 10% margin and trigger warnings + // relative to that value. In general, a -7dBm warning and a -11dBm + // alarm are good optical value estimates for most links. + Value float64 `json:"value,omitempty"` + + // ForceSendFields is a list of field names (e.g. "State") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "State") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *InterconnectDiagnosticsLinkOpticalPower) MarshalJSON() ([]byte, error) { + type NoMethod InterconnectDiagnosticsLinkOpticalPower + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +func (s *InterconnectDiagnosticsLinkOpticalPower) UnmarshalJSON(data []byte) error { + type NoMethod InterconnectDiagnosticsLinkOpticalPower + var s1 struct { + Value gensupport.JSONFloat64 `json:"value"` + *NoMethod + } + s1.NoMethod = (*NoMethod)(s) + if err := json.Unmarshal(data, &s1); err != nil { + return err + } + s.Value = float64(s1.Value) + return nil +} + +type InterconnectDiagnosticsLinkStatus struct { + // ArpCaches: A list of InterconnectDiagnostics.ARPEntry objects, + // describing the ARP neighbor entries seen on this link. This will be + // empty if the link is bundled + ArpCaches []*InterconnectDiagnosticsARPEntry `json:"arpCaches,omitempty"` + + // CircuitId: The unique ID for this link assigned during turn up by + // Google. + CircuitId string `json:"circuitId,omitempty"` + + // GoogleDemarc: The Demarc address assigned by Google and provided in + // the LoA. + GoogleDemarc string `json:"googleDemarc,omitempty"` + + LacpStatus *InterconnectDiagnosticsLinkLACPStatus `json:"lacpStatus,omitempty"` + + ReceivingOpticalPower *InterconnectDiagnosticsLinkOpticalPower `json:"receivingOpticalPower,omitempty"` + + TransmittingOpticalPower *InterconnectDiagnosticsLinkOpticalPower `json:"transmittingOpticalPower,omitempty"` + + // ForceSendFields is a list of field names (e.g. "ArpCaches") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "ArpCaches") to include in + // API requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *InterconnectDiagnosticsLinkStatus) MarshalJSON() ([]byte, error) { + type NoMethod InterconnectDiagnosticsLinkStatus + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + // InterconnectList: Response to the list request, and contains a list // of interconnects. type InterconnectList struct { @@ -14161,10 +15682,10 @@ type InterconnectLocation struct { // each line in the address is separated by a newline character. Address string `json:"address,omitempty"` - // AvailabilityZone: [Output Only] Availability zone for this location. - // Within a metropolitan area (metro), maintenance will not be - // simultaneously scheduled in more than one availability zone. Example: - // "zone1" or "zone2". + // AvailabilityZone: [Output Only] Availability zone for this + // InterconnectLocation. Within a metropolitan area (metro), maintenance + // will not be simultaneously scheduled in more than one availability + // zone. Example: "zone1" or "zone2". AvailabilityZone string `json:"availabilityZone,omitempty"` // City: [Output Only] Metropolitan area designator that indicates which @@ -14225,6 +15746,16 @@ type InterconnectLocation struct { // SelfLink: [Output Only] Server-defined URL for the resource. SelfLink string `json:"selfLink,omitempty"` + // Status: [Output Only] The status of this InterconnectLocation. If the + // status is AVAILABLE, new Interconnects may be provisioned in this + // InterconnectLocation. Otherwise, no new Interconnects may be + // provisioned. + // + // Possible values: + // "AVAILABLE" + // "CLOSED" + Status string `json:"status,omitempty"` + // ServerResponse contains the HTTP response code and headers from the // server. googleapi.ServerResponse `json:"-"` @@ -14526,6 +16057,38 @@ func (s *InterconnectOutageNotification) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +// InterconnectsGetDiagnosticsResponse: Response for the +// InterconnectsGetDiagnosticsRequest. +type InterconnectsGetDiagnosticsResponse struct { + Result *InterconnectDiagnostics `json:"result,omitempty"` + + // ServerResponse contains the HTTP response code and headers from the + // server. + googleapi.ServerResponse `json:"-"` + + // ForceSendFields is a list of field names (e.g. "Result") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Result") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *InterconnectsGetDiagnosticsResponse) MarshalJSON() ([]byte, error) { + type NoMethod InterconnectsGetDiagnosticsResponse + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + // License: A license resource. type License struct { // ChargesUseFee: [Output Only] Deprecated. This field no longer @@ -14552,8 +16115,8 @@ type License struct { // license to images, snapshots, and disks. LicenseCode uint64 `json:"licenseCode,omitempty,string"` - // Name: [Output Only] Name of the resource. The name is 1-63 characters - // long and complies with RFC1035. + // Name: Name of the resource. The name must be 1-63 characters long and + // comply with RFC1035. Name string `json:"name,omitempty"` ResourceRequirements *LicenseResourceRequirements `json:"resourceRequirements,omitempty"` @@ -14962,18 +16525,21 @@ func (s *LogConfigCloudAuditOptions) MarshalJSON() ([]byte, error) { // Field names correspond to IAM request parameters and field values are // their respective values. // -// At present the only supported field names are - "iam_principal", -// corresponding to IAMContext.principal; - "" (empty string), resulting -// in one aggretated counter with no field. +// Supported field names: - "authority", which is "[token]" if +// IAMContext.token is present, otherwise the value of +// IAMContext.authority_selector if present, and otherwise a +// representation of IAMContext.principal; or - "iam_principal", a +// representation of IAMContext.principal even if a token or authority +// selector is present; or - "" (empty string), resulting in a counter +// with no fields. // // Examples: counter { metric: "/debug_access_count" field: // "iam_principal" } ==> increment counter // /iam/policy/backend_debug_access_count {iam_principal=[value of // IAMContext.principal]} // -// At this time we do not support: * multiple field names (though this -// may be supported in the future) * decrementing the counter * -// incrementing it by anything other than 1 +// At this time we do not support multiple field names (though this may +// be supported in the future). type LogConfigCounterOptions struct { // Field: The field value to attribute. Field string `json:"field,omitempty"` @@ -15010,6 +16576,12 @@ type LogConfigDataAccessOptions struct { // the caller. This is relevant only in the LocalIAM implementation, for // now. // + // NOTE: Logging to Gin in a fail-closed manner is currently unsupported + // while work is being done to satisfy the requirements of go/345. + // Currently, setting LOG_FAIL_CLOSED mode will have no effect, but + // still exists because there is active work being done to support it + // (b/115874152). + // // Possible values: // "LOG_FAIL_CLOSED" // "LOG_MODE_UNSPECIFIED" @@ -15789,7 +17361,11 @@ type Metadata struct { // locking. The fingerprint is initially generated by Compute Engine and // changes after every request to modify or update metadata. You must // always provide an up-to-date fingerprint hash in order to update or - // change metadata. + // change metadata, otherwise the request will fail with error 412 + // conditionNotMet. + // + // To see the latest fingerprint, make a get() request to retrieve the + // resource. Fingerprint string `json:"fingerprint,omitempty"` // Items: Array of key/value pairs. The total size of all keys and @@ -15892,22 +17468,22 @@ func (s *NamedPort) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } -// Network: Represents a Network resource. Read Networks and Firewalls -// for more information. (== resource_for v1.networks ==) (== -// resource_for beta.networks ==) +// Network: Represents a Network resource. Read Virtual Private Cloud +// (VPC) Network Overview for more information. (== resource_for +// v1.networks ==) (== resource_for beta.networks ==) type Network struct { // IPv4Range: The range of internal addresses that are legal on this // network. This range is a CIDR specification, for example: // 192.168.0.0/16. Provided by the client when the network is created. IPv4Range string `json:"IPv4Range,omitempty"` - // AutoCreateSubnetworks: When set to true, the network is created in - // "auto subnet mode". When set to false, the network is in "custom - // subnet mode". + // AutoCreateSubnetworks: When set to true, the VPC network is created + // in "auto" mode. When set to false, the VPC network is created in + // "custom" mode. // - // In "auto subnet mode", a newly created network is assigned the - // default CIDR of 10.128.0.0/9 and it automatically creates one - // subnetwork per region. + // An auto mode VPC network starts with one subnet per region. Each + // subnet has a predetermined range as described in Auto mode VPC + // network IP ranges. AutoCreateSubnetworks bool `json:"autoCreateSubnetworks,omitempty"` // CreationTimestamp: [Output Only] Creation timestamp in RFC3339 text @@ -15918,9 +17494,8 @@ type Network struct { // property when you create the resource. Description string `json:"description,omitempty"` - // GatewayIPv4: A gateway address for default routing to other networks. - // This value is read only and is selected by the Google Compute Engine, - // typically as the first usable address in the IPv4Range. + // GatewayIPv4: [Output Only] The gateway address for default routing + // out of the network. This value is read only and is selected by GCP. GatewayIPv4 string `json:"gatewayIPv4,omitempty"` // Id: [Output Only] The unique identifier for the resource. This @@ -15952,7 +17527,7 @@ type Network struct { SelfLink string `json:"selfLink,omitempty"` // Subnetworks: [Output Only] Server-defined fully-qualified URLs for - // all subnetworks in this network. + // all subnetworks in this VPC network. Subnetworks []string `json:"subnetworks,omitempty"` // ServerResponse contains the HTTP response code and headers from the @@ -15985,8 +17560,8 @@ func (s *Network) MarshalJSON() ([]byte, error) { // NetworkEndpoint: The network endpoint. type NetworkEndpoint struct { // Instance: The name for a specific VM instance that the IP address - // belongs to. This is required for network endpoints of type GCE_VM_IP - // and GCE_VM_IP_PORT. The instance must be in the same zone of network + // belongs to. This is required for network endpoints of type + // GCE_VM_IP_PORT. The instance must be in the same zone of network // endpoint group. // // The name must be 1-63 characters long, and comply with RFC1035. @@ -16033,6 +17608,10 @@ type NetworkEndpointGroup struct { // format. CreationTimestamp string `json:"creationTimestamp,omitempty"` + // DefaultPort: The default port used if the port number is not + // specified in the network endpoint. + DefaultPort int64 `json:"defaultPort,omitempty"` + // Description: An optional description of this resource. Provide this // property when you create the resource. Description string `json:"description,omitempty"` @@ -16046,7 +17625,8 @@ type NetworkEndpointGroup struct { Kind string `json:"kind,omitempty"` // LoadBalancer: This field is only valid when the network endpoint - // group type is LOAD_BALANCING. + // group is used for load balancing. [Deprecated] This field is + // deprecated. LoadBalancer *NetworkEndpointGroupLbNetworkEndpointGroup `json:"loadBalancer,omitempty"` // Name: Name of the resource; provided by the client when the resource @@ -16058,9 +17638,12 @@ type NetworkEndpointGroup struct { // last character, which cannot be a dash. Name string `json:"name,omitempty"` + // Network: The URL of the network to which all network endpoints in the + // NEG belong. Uses "default" project network if unspecified. + Network string `json:"network,omitempty"` + // NetworkEndpointType: Type of network endpoints in this network - // endpoint group. Only supported values for LOAD_BALANCING are - // GCE_VM_IP or GCE_VM_IP_PORT. + // endpoint group. Currently the only supported value is GCE_VM_IP_PORT. // // Possible values: // "GCE_VM_IP_PORT" @@ -16073,6 +17656,14 @@ type NetworkEndpointGroup struct { // endpoint group. Size int64 `json:"size,omitempty"` + // Subnetwork: Optional URL of the subnetwork to which all network + // endpoints in the NEG belong. + Subnetwork string `json:"subnetwork,omitempty"` + + // Zone: [Output Only] The URL of the zone where the network endpoint + // group is located. + Zone string `json:"zone,omitempty"` + // ServerResponse contains the HTTP response code and headers from the // server. googleapi.ServerResponse `json:"-"` @@ -16258,23 +17849,24 @@ func (s *NetworkEndpointGroupAggregatedListWarningData) MarshalJSON() ([]byte, e } // NetworkEndpointGroupLbNetworkEndpointGroup: Load balancing specific -// fields for network endpoint group of type LOAD_BALANCING. +// fields for network endpoint group. type NetworkEndpointGroupLbNetworkEndpointGroup struct { // DefaultPort: The default port used if the port number is not - // specified in the network endpoint. If the network endpoint type is - // GCE_VM_IP, this field must not be specified. + // specified in the network endpoint. [Deprecated] This field is + // deprecated. DefaultPort int64 `json:"defaultPort,omitempty"` // Network: The URL of the network to which all network endpoints in the // NEG belong. Uses "default" project network if unspecified. + // [Deprecated] This field is deprecated. Network string `json:"network,omitempty"` // Subnetwork: Optional URL of the subnetwork to which all network - // endpoints in the NEG belong. + // endpoints in the NEG belong. [Deprecated] This field is deprecated. Subnetwork string `json:"subnetwork,omitempty"` // Zone: [Output Only] The URL of the zone where the network endpoint - // group is located. + // group is located. [Deprecated] This field is deprecated. Zone string `json:"zone,omitempty"` // ForceSendFields is a list of field names (e.g. "DefaultPort") to @@ -16882,7 +18474,8 @@ type NetworkInterface struct { // Fingerprint: Fingerprint hash of contents stored in this network // interface. This field will be ignored when inserting an Instance or // adding a NetworkInterface. An up-to-date fingerprint must be provided - // in order to update the NetworkInterface. + // in order to update the NetworkInterface, otherwise the request will + // fail with error 412 conditionNotMet. Fingerprint string `json:"fingerprint,omitempty"` // Kind: [Output Only] Type of the resource. Always @@ -17111,12 +18704,27 @@ func (s *NetworkListWarningData) MarshalJSON() ([]byte, error) { // flag indicating whether Google Compute Engine should automatically // create routes for the peering. type NetworkPeering struct { - // AutoCreateRoutes: Whether full mesh connectivity is created and + // AutoCreateRoutes: Indicates whether full mesh connectivity is created + // and managed automatically. When it is set to true, Google Compute + // Engine will automatically create and manage the routes between two + // networks when the state is ACTIVE. Otherwise, user needs to create + // routes manually to route packets to peer network. + AutoCreateRoutes bool `json:"autoCreateRoutes,omitempty"` + + // ExchangeSubnetRoutes: Whether full mesh connectivity is created and // managed automatically. When it is set to true, Google Compute Engine // will automatically create and manage the routes between two networks - // when the state is ACTIVE. Otherwise, user needs to create routes - // manually to route packets to peer network. - AutoCreateRoutes bool `json:"autoCreateRoutes,omitempty"` + // when the peering state is ACTIVE. Otherwise, user needs to create + // routes manually to route packets to peer network. + ExchangeSubnetRoutes bool `json:"exchangeSubnetRoutes,omitempty"` + + // ExportCustomRoutes: Whether to export the custom routes to peer + // network. + ExportCustomRoutes bool `json:"exportCustomRoutes,omitempty"` + + // ImportCustomRoutes: Whether to import the custom routes from peer + // network. + ImportCustomRoutes bool `json:"importCustomRoutes,omitempty"` // Name: Name of this peering. Provided by the client when the peering // is created. The name must comply with RFC1035. Specifically, the name @@ -17175,9 +18783,9 @@ func (s *NetworkPeering) MarshalJSON() ([]byte, error) { type NetworkRoutingConfig struct { // RoutingMode: The network-wide routing mode to use. If set to // REGIONAL, this network's cloud routers will only advertise routes - // with subnetworks of this network in the same region as the router. If - // set to GLOBAL, this network's cloud routers will advertise routes - // with all subnetworks of this network, across regions. + // with subnets of this network in the same region as the router. If set + // to GLOBAL, this network's cloud routers will advertise routes with + // all subnets of this network, across regions. // // Possible values: // "GLOBAL" @@ -17215,6 +18823,13 @@ type NetworksAddPeeringRequest struct { // Name: Name of the peering, which should conform to RFC1035. Name string `json:"name,omitempty"` + // NetworkPeering: Network peering parameters. In order to specify route + // policies for peering using import/export custom routes, you will have + // to fill all peering related parameters (name, peer network, + // exchange_subnet_routes) in network_peeringfield. Corresponding fields + // in NetworksAddPeeringRequest will be deprecated soon. + NetworkPeering *NetworkPeering `json:"networkPeering,omitempty"` + // PeerNetwork: URL of the peer network. It can be either full URL or // partial URL. The peer network may belong to a different project. If // the partial URL does not contain project, it is assumed that the peer @@ -17272,6 +18887,33 @@ func (s *NetworksRemovePeeringRequest) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +type NetworksUpdatePeeringRequest struct { + NetworkPeering *NetworkPeering `json:"networkPeering,omitempty"` + + // ForceSendFields is a list of field names (e.g. "NetworkPeering") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "NetworkPeering") to + // include in API requests with the JSON null value. By default, fields + // with empty values are omitted from API requests. However, any field + // with an empty value appearing in NullFields will be sent to the + // server as null. It is an error if a field in this list has a + // non-empty value. This may be used to include null fields in Patch + // requests. + NullFields []string `json:"-"` +} + +func (s *NetworksUpdatePeeringRequest) MarshalJSON() ([]byte, error) { + type NoMethod NetworksUpdatePeeringRequest + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + // NodeGroup: A NodeGroup resource. type NodeGroup struct { // CreationTimestamp: [Output Only] Creation timestamp in RFC3339 text @@ -17304,12 +18946,12 @@ type NodeGroup struct { // belongs. NodeTemplate string `json:"nodeTemplate,omitempty"` - // Nodes: [Output Only] A list of nodes in this node group. - Nodes []*NodeGroupNode `json:"nodes,omitempty"` - // SelfLink: [Output Only] Server-defined URL for the resource. SelfLink string `json:"selfLink,omitempty"` + // Size: [Output Only] The total number of nodes in the node group. + Size int64 `json:"size,omitempty"` + // Possible values: // "CREATING" // "DELETING" @@ -17674,6 +19316,7 @@ type NodeGroupNode struct { // "DELETING" // "INVALID" // "READY" + // "REPAIRING" Status string `json:"status,omitempty"` // ForceSendFields is a list of field names (e.g. "Instances") to @@ -17754,6 +19397,162 @@ func (s *NodeGroupsDeleteNodesRequest) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +type NodeGroupsListNodes struct { + // Id: [Output Only] Unique identifier for the resource; defined by the + // server. + Id string `json:"id,omitempty"` + + // Items: A list of Node resources. + Items []*NodeGroupNode `json:"items,omitempty"` + + // Kind: [Output Only] The resource type, which is always + // compute.nodeGroupsListNodes for the list of nodes in the specified + // node group. + Kind string `json:"kind,omitempty"` + + // NextPageToken: [Output Only] This token allows you to get the next + // page of results for list requests. If the number of results is larger + // than maxResults, use the nextPageToken as a value for the query + // parameter pageToken in the next list request. Subsequent list + // requests will have their own nextPageToken to continue paging through + // the results. + NextPageToken string `json:"nextPageToken,omitempty"` + + // SelfLink: [Output Only] Server-defined URL for this resource. + SelfLink string `json:"selfLink,omitempty"` + + // Warning: [Output Only] Informational warning message. + Warning *NodeGroupsListNodesWarning `json:"warning,omitempty"` + + // ServerResponse contains the HTTP response code and headers from the + // server. + googleapi.ServerResponse `json:"-"` + + // ForceSendFields is a list of field names (e.g. "Id") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Id") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *NodeGroupsListNodes) MarshalJSON() ([]byte, error) { + type NoMethod NodeGroupsListNodes + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// NodeGroupsListNodesWarning: [Output Only] Informational warning +// message. +type NodeGroupsListNodesWarning struct { + // Code: [Output Only] A warning code, if applicable. For example, + // Compute Engine returns NO_RESULTS_ON_PAGE if there are no results in + // the response. + // + // Possible values: + // "CLEANUP_FAILED" + // "DEPRECATED_RESOURCE_USED" + // "DEPRECATED_TYPE_USED" + // "DISK_SIZE_LARGER_THAN_IMAGE_SIZE" + // "EXPERIMENTAL_TYPE_USED" + // "EXTERNAL_API_WARNING" + // "FIELD_VALUE_OVERRIDEN" + // "INJECTED_KERNELS_DEPRECATED" + // "MISSING_TYPE_DEPENDENCY" + // "NEXT_HOP_ADDRESS_NOT_ASSIGNED" + // "NEXT_HOP_CANNOT_IP_FORWARD" + // "NEXT_HOP_INSTANCE_NOT_FOUND" + // "NEXT_HOP_INSTANCE_NOT_ON_NETWORK" + // "NEXT_HOP_NOT_RUNNING" + // "NOT_CRITICAL_ERROR" + // "NO_RESULTS_ON_PAGE" + // "REQUIRED_TOS_AGREEMENT" + // "RESOURCE_IN_USE_BY_OTHER_RESOURCE_WARNING" + // "RESOURCE_NOT_DELETED" + // "SCHEMA_VALIDATION_IGNORED" + // "SINGLE_INSTANCE_PROPERTY_TEMPLATE" + // "UNDECLARED_PROPERTIES" + // "UNREACHABLE" + Code string `json:"code,omitempty"` + + // Data: [Output Only] Metadata about this warning in key: value format. + // For example: + // "data": [ { "key": "scope", "value": "zones/us-east1-d" } + Data []*NodeGroupsListNodesWarningData `json:"data,omitempty"` + + // Message: [Output Only] A human-readable description of the warning + // code. + Message string `json:"message,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Code") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Code") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *NodeGroupsListNodesWarning) MarshalJSON() ([]byte, error) { + type NoMethod NodeGroupsListNodesWarning + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type NodeGroupsListNodesWarningData struct { + // Key: [Output Only] A key that provides more detail on the warning + // being returned. For example, for warnings where there are no results + // in a list request for a particular zone, this key might be scope and + // the key value might be the zone name. Other examples might be a key + // indicating a deprecated resource and a suggested replacement, or a + // warning about invalid network settings (for example, if an instance + // attempts to perform IP forwarding but is not enabled for IP + // forwarding). + Key string `json:"key,omitempty"` + + // Value: [Output Only] A warning data value corresponding to the key. + Value string `json:"value,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Key") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Key") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *NodeGroupsListNodesWarningData) MarshalJSON() ([]byte, error) { + type NoMethod NodeGroupsListNodesWarningData + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + type NodeGroupsScopedList struct { // NodeGroups: [Output Only] A list of node groups contained in this // scope. @@ -17940,7 +19739,7 @@ type NodeTemplate struct { // characters long and match the regular expression // `[a-z]([-a-z0-9]*[a-z0-9])?` which means the first character must be // a lowercase letter, and all following characters must be a dash, - // lowercase letter, or digit, except the last charaicter, which cannot + // lowercase letter, or digit, except the last character, which cannot // be a dash. Name string `json:"name,omitempty"` @@ -19752,14 +21551,23 @@ func (s *OperationsScopedListWarningData) MarshalJSON() ([]byte, error) { // no rule was matched, the default service will be used. type PathMatcher struct { // DefaultService: The full or partial URL to the BackendService - // resource. This will be used if none of the pathRules defined by this - // PathMatcher is matched by the URL's path portion. For example, the - // following are all valid URLs to a BackendService resource: + // resource. This will be used if none of the pathRules or routeRules + // defined by this PathMatcher are matched. For example, the following + // are all valid URLs to a BackendService resource: // - // https://www.googleapis.com/compute/v1/projects/project/global/backendServices/backendService // - compute/v1/projects/project/global/backendServices/backendService // // - global/backendServices/backendService + // Use defaultService instead of defaultRouteAction when simple routing + // to a backend service is desired and other advanced capabilities like + // traffic splitting and URL rewrites are not required. + // Only one of defaultService, defaultRouteAction or defaultUrlRedirect + // must be set. + // Authorization requires one or more of the following Google IAM + // permissions on the specified resource default_service: + // - compute.backendBuckets.use + // - compute.backendServices.use DefaultService string `json:"defaultService,omitempty"` // Description: An optional description of this resource. Provide this @@ -19769,7 +21577,14 @@ type PathMatcher struct { // Name: The name to which this PathMatcher is referred by the HostRule. Name string `json:"name,omitempty"` - // PathRules: The list of path rules. + // PathRules: The list of path rules. Use this list instead of + // routeRules when routing based on simple path matching is all that's + // required. The order by which path rules are specified does not + // matter. Matches are always done on the longest-path-first basis. + // For example: a pathRule with a path /a/b/c/* will match before /a/b/* + // irrespective of the order in which those paths appear in this + // list. + // Only one of pathRules or routeRules must be set. PathRules []*PathRule `json:"pathRules,omitempty"` // ForceSendFields is a list of field names (e.g. "DefaultService") to @@ -19805,8 +21620,12 @@ type PathRule struct { // or #, and those chars are not allowed here. Paths []string `json:"paths,omitempty"` - // Service: The URL of the BackendService resource if this rule is + // Service: The URL of the backend service resource if this rule is // matched. + // Use service instead of routeAction when simple routing to a backend + // service is desired and other advanced capabilities like traffic + // splitting and rewrites are not required. + // Only one of service, routeAction or urlRedirect should must be set. Service string `json:"service,omitempty"` // ForceSendFields is a list of field names (e.g. "Paths") to @@ -20226,6 +22045,8 @@ type Quota struct { // "DISKS_TOTAL_GB" // "FIREWALLS" // "FORWARDING_RULES" + // "GLOBAL_INTERNAL_ADDRESSES" + // "GPUS_ALL_REGIONS" // "HEALTH_CHECKS" // "IMAGES" // "INSTANCES" @@ -20237,19 +22058,31 @@ type Quota struct { // "INTERCONNECT_ATTACHMENTS_TOTAL_MBPS" // "INTERNAL_ADDRESSES" // "IN_USE_ADDRESSES" + // "IN_USE_BACKUP_SCHEDULES" // "LOCAL_SSD_TOTAL_GB" // "NETWORKS" // "NETWORK_ENDPOINT_GROUPS" // "NVIDIA_K80_GPUS" // "NVIDIA_P100_GPUS" + // "NVIDIA_P100_VWS_GPUS" + // "NVIDIA_P4_GPUS" + // "NVIDIA_P4_VWS_GPUS" + // "NVIDIA_T4_GPUS" + // "NVIDIA_T4_VWS_GPUS" // "NVIDIA_V100_GPUS" // "PREEMPTIBLE_CPUS" // "PREEMPTIBLE_LOCAL_SSD_GB" // "PREEMPTIBLE_NVIDIA_K80_GPUS" // "PREEMPTIBLE_NVIDIA_P100_GPUS" + // "PREEMPTIBLE_NVIDIA_P100_VWS_GPUS" + // "PREEMPTIBLE_NVIDIA_P4_GPUS" + // "PREEMPTIBLE_NVIDIA_P4_VWS_GPUS" + // "PREEMPTIBLE_NVIDIA_T4_GPUS" + // "PREEMPTIBLE_NVIDIA_T4_VWS_GPUS" // "PREEMPTIBLE_NVIDIA_V100_GPUS" // "REGIONAL_AUTOSCALERS" // "REGIONAL_INSTANCE_GROUP_MANAGERS" + // "RESOURCE_POLICIES" // "ROUTERS" // "ROUTES" // "SECURITY_POLICIES" @@ -20267,6 +22100,7 @@ type Quota struct { // "TARGET_TCP_PROXIES" // "TARGET_VPN_GATEWAYS" // "URL_MAPS" + // "VPN_GATEWAYS" // "VPN_TUNNELS" Metric string `json:"metric,omitempty"` @@ -20732,6 +22566,62 @@ func (s *RegionDiskTypeListWarningData) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +type RegionDisksAddResourcePoliciesRequest struct { + // ResourcePolicies: Resource policies to be added to this disk. + ResourcePolicies []string `json:"resourcePolicies,omitempty"` + + // ForceSendFields is a list of field names (e.g. "ResourcePolicies") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "ResourcePolicies") to + // include in API requests with the JSON null value. By default, fields + // with empty values are omitted from API requests. However, any field + // with an empty value appearing in NullFields will be sent to the + // server as null. It is an error if a field in this list has a + // non-empty value. This may be used to include null fields in Patch + // requests. + NullFields []string `json:"-"` +} + +func (s *RegionDisksAddResourcePoliciesRequest) MarshalJSON() ([]byte, error) { + type NoMethod RegionDisksAddResourcePoliciesRequest + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type RegionDisksRemoveResourcePoliciesRequest struct { + // ResourcePolicies: Resource policies to be removed from this disk. + ResourcePolicies []string `json:"resourcePolicies,omitempty"` + + // ForceSendFields is a list of field names (e.g. "ResourcePolicies") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "ResourcePolicies") to + // include in API requests with the JSON null value. By default, fields + // with empty values are omitted from API requests. However, any field + // with an empty value appearing in NullFields will be sent to the + // server as null. It is an error if a field in this list has a + // non-empty value. This may be used to include null fields in Patch + // requests. + NullFields []string `json:"-"` +} + +func (s *RegionDisksRemoveResourcePoliciesRequest) MarshalJSON() ([]byte, error) { + type NoMethod RegionDisksRemoveResourcePoliciesRequest + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + type RegionDisksResizeRequest struct { // SizeGb: The new size of the regional persistent disk, which is // specified in GB. @@ -21788,8 +23678,8 @@ func (s *ResourceCommitment) MarshalJSON() ([]byte, error) { } type ResourceGroupReference struct { - // Group: A URI referencing one of the instance groups listed in the - // backend service. + // Group: A URI referencing one of the instance groups or network + // endpoint groups listed in the backend service. Group string `json:"group,omitempty"` // ForceSendFields is a list of field names (e.g. "Group") to @@ -21815,6 +23705,813 @@ func (s *ResourceGroupReference) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +type ResourcePoliciesScopedList struct { + // ResourcePolicies: A list of resourcePolicies contained in this scope. + ResourcePolicies []*ResourcePolicy `json:"resourcePolicies,omitempty"` + + // Warning: Informational warning which replaces the list of + // resourcePolicies when the list is empty. + Warning *ResourcePoliciesScopedListWarning `json:"warning,omitempty"` + + // ForceSendFields is a list of field names (e.g. "ResourcePolicies") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "ResourcePolicies") to + // include in API requests with the JSON null value. By default, fields + // with empty values are omitted from API requests. However, any field + // with an empty value appearing in NullFields will be sent to the + // server as null. It is an error if a field in this list has a + // non-empty value. This may be used to include null fields in Patch + // requests. + NullFields []string `json:"-"` +} + +func (s *ResourcePoliciesScopedList) MarshalJSON() ([]byte, error) { + type NoMethod ResourcePoliciesScopedList + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// ResourcePoliciesScopedListWarning: Informational warning which +// replaces the list of resourcePolicies when the list is empty. +type ResourcePoliciesScopedListWarning struct { + // Code: [Output Only] A warning code, if applicable. For example, + // Compute Engine returns NO_RESULTS_ON_PAGE if there are no results in + // the response. + // + // Possible values: + // "CLEANUP_FAILED" + // "DEPRECATED_RESOURCE_USED" + // "DEPRECATED_TYPE_USED" + // "DISK_SIZE_LARGER_THAN_IMAGE_SIZE" + // "EXPERIMENTAL_TYPE_USED" + // "EXTERNAL_API_WARNING" + // "FIELD_VALUE_OVERRIDEN" + // "INJECTED_KERNELS_DEPRECATED" + // "MISSING_TYPE_DEPENDENCY" + // "NEXT_HOP_ADDRESS_NOT_ASSIGNED" + // "NEXT_HOP_CANNOT_IP_FORWARD" + // "NEXT_HOP_INSTANCE_NOT_FOUND" + // "NEXT_HOP_INSTANCE_NOT_ON_NETWORK" + // "NEXT_HOP_NOT_RUNNING" + // "NOT_CRITICAL_ERROR" + // "NO_RESULTS_ON_PAGE" + // "REQUIRED_TOS_AGREEMENT" + // "RESOURCE_IN_USE_BY_OTHER_RESOURCE_WARNING" + // "RESOURCE_NOT_DELETED" + // "SCHEMA_VALIDATION_IGNORED" + // "SINGLE_INSTANCE_PROPERTY_TEMPLATE" + // "UNDECLARED_PROPERTIES" + // "UNREACHABLE" + Code string `json:"code,omitempty"` + + // Data: [Output Only] Metadata about this warning in key: value format. + // For example: + // "data": [ { "key": "scope", "value": "zones/us-east1-d" } + Data []*ResourcePoliciesScopedListWarningData `json:"data,omitempty"` + + // Message: [Output Only] A human-readable description of the warning + // code. + Message string `json:"message,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Code") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Code") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *ResourcePoliciesScopedListWarning) MarshalJSON() ([]byte, error) { + type NoMethod ResourcePoliciesScopedListWarning + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type ResourcePoliciesScopedListWarningData struct { + // Key: [Output Only] A key that provides more detail on the warning + // being returned. For example, for warnings where there are no results + // in a list request for a particular zone, this key might be scope and + // the key value might be the zone name. Other examples might be a key + // indicating a deprecated resource and a suggested replacement, or a + // warning about invalid network settings (for example, if an instance + // attempts to perform IP forwarding but is not enabled for IP + // forwarding). + Key string `json:"key,omitempty"` + + // Value: [Output Only] A warning data value corresponding to the key. + Value string `json:"value,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Key") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Key") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *ResourcePoliciesScopedListWarningData) MarshalJSON() ([]byte, error) { + type NoMethod ResourcePoliciesScopedListWarningData + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type ResourcePolicy struct { + // BackupSchedulePolicy: Resource policy for persistent disks for + // creating snapshots. + BackupSchedulePolicy *ResourcePolicyBackupSchedulePolicy `json:"backupSchedulePolicy,omitempty"` + + // CreationTimestamp: [Output Only] Creation timestamp in RFC3339 text + // format. + CreationTimestamp string `json:"creationTimestamp,omitempty"` + + Description string `json:"description,omitempty"` + + // Id: [Output Only] The unique identifier for the resource. This + // identifier is defined by the server. + Id uint64 `json:"id,omitempty,string"` + + // Kind: [Output Only] Type of the resource. Always + // compute#resource_policies for resource policies. + Kind string `json:"kind,omitempty"` + + // Name: The name of the resource, provided by the client when initially + // creating the resource. The resource name must be 1-63 characters + // long, and comply with RFC1035. Specifically, the name must be 1-63 + // characters long and match the regular expression + // `[a-z]([-a-z0-9]*[a-z0-9])?` which means the first character must be + // a lowercase letter, and all following characters must be a dash, + // lowercase letter, or digit, except the last character, which cannot + // be a dash. + Name string `json:"name,omitempty"` + + Region string `json:"region,omitempty"` + + // SelfLink: [Output Only] Server-defined fully-qualified URL for this + // resource. + SelfLink string `json:"selfLink,omitempty"` + + // ServerResponse contains the HTTP response code and headers from the + // server. + googleapi.ServerResponse `json:"-"` + + // ForceSendFields is a list of field names (e.g. + // "BackupSchedulePolicy") to unconditionally include in API requests. + // By default, fields with empty values are omitted from API requests. + // However, any non-pointer, non-interface field appearing in + // ForceSendFields will be sent to the server regardless of whether the + // field is empty or not. This may be used to include empty fields in + // Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "BackupSchedulePolicy") to + // include in API requests with the JSON null value. By default, fields + // with empty values are omitted from API requests. However, any field + // with an empty value appearing in NullFields will be sent to the + // server as null. It is an error if a field in this list has a + // non-empty value. This may be used to include null fields in Patch + // requests. + NullFields []string `json:"-"` +} + +func (s *ResourcePolicy) MarshalJSON() ([]byte, error) { + type NoMethod ResourcePolicy + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// ResourcePolicyAggregatedList: Contains a list of resourcePolicies. +type ResourcePolicyAggregatedList struct { + Etag string `json:"etag,omitempty"` + + // Id: [Output Only] Unique identifier for the resource; defined by the + // server. + Id string `json:"id,omitempty"` + + // Items: A list of ResourcePolicy resources. + Items map[string]ResourcePoliciesScopedList `json:"items,omitempty"` + + // Kind: Type of resource. + Kind string `json:"kind,omitempty"` + + // NextPageToken: [Output Only] This token allows you to get the next + // page of results for list requests. If the number of results is larger + // than maxResults, use the nextPageToken as a value for the query + // parameter pageToken in the next list request. Subsequent list + // requests will have their own nextPageToken to continue paging through + // the results. + NextPageToken string `json:"nextPageToken,omitempty"` + + // SelfLink: [Output Only] Server-defined URL for this resource. + SelfLink string `json:"selfLink,omitempty"` + + // Warning: [Output Only] Informational warning message. + Warning *ResourcePolicyAggregatedListWarning `json:"warning,omitempty"` + + // ServerResponse contains the HTTP response code and headers from the + // server. + googleapi.ServerResponse `json:"-"` + + // ForceSendFields is a list of field names (e.g. "Etag") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Etag") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *ResourcePolicyAggregatedList) MarshalJSON() ([]byte, error) { + type NoMethod ResourcePolicyAggregatedList + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// ResourcePolicyAggregatedListWarning: [Output Only] Informational +// warning message. +type ResourcePolicyAggregatedListWarning struct { + // Code: [Output Only] A warning code, if applicable. For example, + // Compute Engine returns NO_RESULTS_ON_PAGE if there are no results in + // the response. + // + // Possible values: + // "CLEANUP_FAILED" + // "DEPRECATED_RESOURCE_USED" + // "DEPRECATED_TYPE_USED" + // "DISK_SIZE_LARGER_THAN_IMAGE_SIZE" + // "EXPERIMENTAL_TYPE_USED" + // "EXTERNAL_API_WARNING" + // "FIELD_VALUE_OVERRIDEN" + // "INJECTED_KERNELS_DEPRECATED" + // "MISSING_TYPE_DEPENDENCY" + // "NEXT_HOP_ADDRESS_NOT_ASSIGNED" + // "NEXT_HOP_CANNOT_IP_FORWARD" + // "NEXT_HOP_INSTANCE_NOT_FOUND" + // "NEXT_HOP_INSTANCE_NOT_ON_NETWORK" + // "NEXT_HOP_NOT_RUNNING" + // "NOT_CRITICAL_ERROR" + // "NO_RESULTS_ON_PAGE" + // "REQUIRED_TOS_AGREEMENT" + // "RESOURCE_IN_USE_BY_OTHER_RESOURCE_WARNING" + // "RESOURCE_NOT_DELETED" + // "SCHEMA_VALIDATION_IGNORED" + // "SINGLE_INSTANCE_PROPERTY_TEMPLATE" + // "UNDECLARED_PROPERTIES" + // "UNREACHABLE" + Code string `json:"code,omitempty"` + + // Data: [Output Only] Metadata about this warning in key: value format. + // For example: + // "data": [ { "key": "scope", "value": "zones/us-east1-d" } + Data []*ResourcePolicyAggregatedListWarningData `json:"data,omitempty"` + + // Message: [Output Only] A human-readable description of the warning + // code. + Message string `json:"message,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Code") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Code") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *ResourcePolicyAggregatedListWarning) MarshalJSON() ([]byte, error) { + type NoMethod ResourcePolicyAggregatedListWarning + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type ResourcePolicyAggregatedListWarningData struct { + // Key: [Output Only] A key that provides more detail on the warning + // being returned. For example, for warnings where there are no results + // in a list request for a particular zone, this key might be scope and + // the key value might be the zone name. Other examples might be a key + // indicating a deprecated resource and a suggested replacement, or a + // warning about invalid network settings (for example, if an instance + // attempts to perform IP forwarding but is not enabled for IP + // forwarding). + Key string `json:"key,omitempty"` + + // Value: [Output Only] A warning data value corresponding to the key. + Value string `json:"value,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Key") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Key") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *ResourcePolicyAggregatedListWarningData) MarshalJSON() ([]byte, error) { + type NoMethod ResourcePolicyAggregatedListWarningData + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// ResourcePolicyBackupSchedulePolicy: A backup schedule policy +// specifies when and how frequently snapshots are to be created for the +// target disk. Also specifies how many and how long these scheduled +// snapshots should be retained. +type ResourcePolicyBackupSchedulePolicy struct { + // RetentionPolicy: Retention policy applied to snapshots created by + // this resource policy. + RetentionPolicy *ResourcePolicyBackupSchedulePolicyRetentionPolicy `json:"retentionPolicy,omitempty"` + + // Schedule: A Vm Maintenance Policy specifies what kind of + // infrastructure maintenance we are allowed to perform on this VM and + // when. Schedule that is applied to disks covered by this policy. + Schedule *ResourcePolicyBackupSchedulePolicySchedule `json:"schedule,omitempty"` + + // SnapshotProperties: Properties with which snapshots are created such + // as labels, encryption keys. + SnapshotProperties *ResourcePolicyBackupSchedulePolicySnapshotProperties `json:"snapshotProperties,omitempty"` + + // ForceSendFields is a list of field names (e.g. "RetentionPolicy") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "RetentionPolicy") to + // include in API requests with the JSON null value. By default, fields + // with empty values are omitted from API requests. However, any field + // with an empty value appearing in NullFields will be sent to the + // server as null. It is an error if a field in this list has a + // non-empty value. This may be used to include null fields in Patch + // requests. + NullFields []string `json:"-"` +} + +func (s *ResourcePolicyBackupSchedulePolicy) MarshalJSON() ([]byte, error) { + type NoMethod ResourcePolicyBackupSchedulePolicy + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// ResourcePolicyBackupSchedulePolicyRetentionPolicy: Policy for +// retention of scheduled snapshots. +type ResourcePolicyBackupSchedulePolicyRetentionPolicy struct { + // MaxRetentionDays: Maximum age of the snapshot that is allowed to be + // kept. + MaxRetentionDays int64 `json:"maxRetentionDays,omitempty"` + + // OnSourceDiskDelete: Specifies the behavior to apply to scheduled + // snapshots when the source disk is deleted. + // + // Possible values: + // "APPLY_RETENTION_POLICY" + // "KEEP_AUTO_SNAPSHOTS" + // "UNSPECIFIED_ON_SOURCE_DISK_DELETE" + OnSourceDiskDelete string `json:"onSourceDiskDelete,omitempty"` + + // ForceSendFields is a list of field names (e.g. "MaxRetentionDays") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "MaxRetentionDays") to + // include in API requests with the JSON null value. By default, fields + // with empty values are omitted from API requests. However, any field + // with an empty value appearing in NullFields will be sent to the + // server as null. It is an error if a field in this list has a + // non-empty value. This may be used to include null fields in Patch + // requests. + NullFields []string `json:"-"` +} + +func (s *ResourcePolicyBackupSchedulePolicyRetentionPolicy) MarshalJSON() ([]byte, error) { + type NoMethod ResourcePolicyBackupSchedulePolicyRetentionPolicy + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// ResourcePolicyBackupSchedulePolicySchedule: A schedule for disks +// where the schedueled operations are performed. +type ResourcePolicyBackupSchedulePolicySchedule struct { + DailySchedule *ResourcePolicyDailyCycle `json:"dailySchedule,omitempty"` + + HourlySchedule *ResourcePolicyHourlyCycle `json:"hourlySchedule,omitempty"` + + WeeklySchedule *ResourcePolicyWeeklyCycle `json:"weeklySchedule,omitempty"` + + // ForceSendFields is a list of field names (e.g. "DailySchedule") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "DailySchedule") to include + // in API requests with the JSON null value. By default, fields with + // empty values are omitted from API requests. However, any field with + // an empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *ResourcePolicyBackupSchedulePolicySchedule) MarshalJSON() ([]byte, error) { + type NoMethod ResourcePolicyBackupSchedulePolicySchedule + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// ResourcePolicyBackupSchedulePolicySnapshotProperties: Specified +// snapshot properties for scheduled snapshots created by this policy. +type ResourcePolicyBackupSchedulePolicySnapshotProperties struct { + // GuestFlush: Indication to perform a ?guest aware? snapshot. + GuestFlush bool `json:"guestFlush,omitempty"` + + // Labels: Labels to apply to scheduled snapshots. These can be later + // modified by the setLabels method. Label values may be empty. + Labels map[string]string `json:"labels,omitempty"` + + // ForceSendFields is a list of field names (e.g. "GuestFlush") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "GuestFlush") to include in + // API requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *ResourcePolicyBackupSchedulePolicySnapshotProperties) MarshalJSON() ([]byte, error) { + type NoMethod ResourcePolicyBackupSchedulePolicySnapshotProperties + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// ResourcePolicyDailyCycle: Time window specified for daily operations. +type ResourcePolicyDailyCycle struct { + // DaysInCycle: Allows to define schedule that runs every nth day of the + // month. + DaysInCycle int64 `json:"daysInCycle,omitempty"` + + // Duration: [Output only] Duration of the time window, automatically + // chosen to be smallest possible in the given scenario. + Duration string `json:"duration,omitempty"` + + // StartTime: Time within the window to start the operations. It must be + // in format "HH:MM", where HH : [00-23] and MM : [00-00] GMT. + StartTime string `json:"startTime,omitempty"` + + // ForceSendFields is a list of field names (e.g. "DaysInCycle") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "DaysInCycle") to include + // in API requests with the JSON null value. By default, fields with + // empty values are omitted from API requests. However, any field with + // an empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *ResourcePolicyDailyCycle) MarshalJSON() ([]byte, error) { + type NoMethod ResourcePolicyDailyCycle + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// ResourcePolicyHourlyCycle: Time window specified for hourly +// operations. +type ResourcePolicyHourlyCycle struct { + // Duration: [Output only] Duration of the time window, automatically + // chosen to be smallest possible in the given scenario. + Duration string `json:"duration,omitempty"` + + // HoursInCycle: Allows to define schedule that runs every nth hour. + HoursInCycle int64 `json:"hoursInCycle,omitempty"` + + // StartTime: Time within the window to start the operations. It must be + // in format "HH:MM", where HH : [00-23] and MM : [00-00] GMT. + StartTime string `json:"startTime,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Duration") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Duration") to include in + // API requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *ResourcePolicyHourlyCycle) MarshalJSON() ([]byte, error) { + type NoMethod ResourcePolicyHourlyCycle + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type ResourcePolicyList struct { + Etag string `json:"etag,omitempty"` + + // Id: [Output Only] The unique identifier for the resource. This + // identifier is defined by the server. + Id string `json:"id,omitempty"` + + // Items: [Output Only] A list of ResourcePolicy resources. + Items []*ResourcePolicy `json:"items,omitempty"` + + // Kind: [Output Only] Type of resource.Always + // compute#resourcePoliciesList for listsof resourcePolicies + Kind string `json:"kind,omitempty"` + + // NextPageToken: [Output Only] This token allows you to get the next + // page of results for list requests. If the number of results is larger + // than maxResults, use the nextPageToken as a value for the query + // parameter pageToken in the next list request. Subsequent list + // requests will have their own nextPageToken to continue paging through + // the results. + NextPageToken string `json:"nextPageToken,omitempty"` + + // SelfLink: [Output Only] Server-defined URL for this resource. + SelfLink string `json:"selfLink,omitempty"` + + // Warning: [Output Only] Informational warning message. + Warning *ResourcePolicyListWarning `json:"warning,omitempty"` + + // ServerResponse contains the HTTP response code and headers from the + // server. + googleapi.ServerResponse `json:"-"` + + // ForceSendFields is a list of field names (e.g. "Etag") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Etag") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *ResourcePolicyList) MarshalJSON() ([]byte, error) { + type NoMethod ResourcePolicyList + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// ResourcePolicyListWarning: [Output Only] Informational warning +// message. +type ResourcePolicyListWarning struct { + // Code: [Output Only] A warning code, if applicable. For example, + // Compute Engine returns NO_RESULTS_ON_PAGE if there are no results in + // the response. + // + // Possible values: + // "CLEANUP_FAILED" + // "DEPRECATED_RESOURCE_USED" + // "DEPRECATED_TYPE_USED" + // "DISK_SIZE_LARGER_THAN_IMAGE_SIZE" + // "EXPERIMENTAL_TYPE_USED" + // "EXTERNAL_API_WARNING" + // "FIELD_VALUE_OVERRIDEN" + // "INJECTED_KERNELS_DEPRECATED" + // "MISSING_TYPE_DEPENDENCY" + // "NEXT_HOP_ADDRESS_NOT_ASSIGNED" + // "NEXT_HOP_CANNOT_IP_FORWARD" + // "NEXT_HOP_INSTANCE_NOT_FOUND" + // "NEXT_HOP_INSTANCE_NOT_ON_NETWORK" + // "NEXT_HOP_NOT_RUNNING" + // "NOT_CRITICAL_ERROR" + // "NO_RESULTS_ON_PAGE" + // "REQUIRED_TOS_AGREEMENT" + // "RESOURCE_IN_USE_BY_OTHER_RESOURCE_WARNING" + // "RESOURCE_NOT_DELETED" + // "SCHEMA_VALIDATION_IGNORED" + // "SINGLE_INSTANCE_PROPERTY_TEMPLATE" + // "UNDECLARED_PROPERTIES" + // "UNREACHABLE" + Code string `json:"code,omitempty"` + + // Data: [Output Only] Metadata about this warning in key: value format. + // For example: + // "data": [ { "key": "scope", "value": "zones/us-east1-d" } + Data []*ResourcePolicyListWarningData `json:"data,omitempty"` + + // Message: [Output Only] A human-readable description of the warning + // code. + Message string `json:"message,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Code") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Code") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *ResourcePolicyListWarning) MarshalJSON() ([]byte, error) { + type NoMethod ResourcePolicyListWarning + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type ResourcePolicyListWarningData struct { + // Key: [Output Only] A key that provides more detail on the warning + // being returned. For example, for warnings where there are no results + // in a list request for a particular zone, this key might be scope and + // the key value might be the zone name. Other examples might be a key + // indicating a deprecated resource and a suggested replacement, or a + // warning about invalid network settings (for example, if an instance + // attempts to perform IP forwarding but is not enabled for IP + // forwarding). + Key string `json:"key,omitempty"` + + // Value: [Output Only] A warning data value corresponding to the key. + Value string `json:"value,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Key") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Key") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *ResourcePolicyListWarningData) MarshalJSON() ([]byte, error) { + type NoMethod ResourcePolicyListWarningData + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// ResourcePolicyWeeklyCycle: Time window specified for weekly +// operations. +type ResourcePolicyWeeklyCycle struct { + // DayOfWeeks: Up to 7 intervals/windows, one for each day of the week. + DayOfWeeks []*ResourcePolicyWeeklyCycleDayOfWeek `json:"dayOfWeeks,omitempty"` + + // ForceSendFields is a list of field names (e.g. "DayOfWeeks") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "DayOfWeeks") to include in + // API requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *ResourcePolicyWeeklyCycle) MarshalJSON() ([]byte, error) { + type NoMethod ResourcePolicyWeeklyCycle + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type ResourcePolicyWeeklyCycleDayOfWeek struct { + // Day: Allows to define schedule that runs specified day of the week. + // + // Possible values: + // "FRIDAY" + // "INVALID" + // "MONDAY" + // "SATURDAY" + // "SUNDAY" + // "THURSDAY" + // "TUESDAY" + // "WEDNESDAY" + Day string `json:"day,omitempty"` + + // Duration: [Output only] Duration of the time window, automatically + // chosen to be smallest possible in the given scenario. + Duration string `json:"duration,omitempty"` + + // StartTime: Time within the window to start the operations. It must be + // in format "HH:MM", where HH : [00-23] and MM : [00-00] GMT. + StartTime string `json:"startTime,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Day") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Day") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *ResourcePolicyWeeklyCycleDayOfWeek) MarshalJSON() ([]byte, error) { + type NoMethod ResourcePolicyWeeklyCycleDayOfWeek + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + // Route: Represents a Route resource. A route specifies how certain // packets should be handled by the network. Routes are associated with // instances by tags and the set of routes for a particular instance is @@ -21874,6 +24571,17 @@ type Route struct { // projects//global/gateways/default-internet-gateway NextHopGateway string `json:"nextHopGateway,omitempty"` + // NextHopIlb: The URL to a forwarding rule of type + // loadBalancingScheme=INTERNAL that should handle matching packets. You + // can only specify the forwarding rule as a partial or full URL. For + // example, the following are all valid URLs: + // - + // https://www.googleapis.com/compute/v1/projects/project/regions/region/forwardingRules/forwardingRule + // - regions/region/forwardingRules/forwardingRule Note that this can + // only be used when the destination_range is a public (non-RFC 1918) IP + // CIDR range. + NextHopIlb string `json:"nextHopIlb,omitempty"` + // NextHopInstance: The URL to an instance that should handle matching // packets. You can specify this as a full or partial URL. For // example: @@ -22237,6 +24945,9 @@ type Router struct { // last character, which cannot be a dash. Name string `json:"name,omitempty"` + // Nats: A list of Nat services created in this router. + Nats []*RouterNat `json:"nats,omitempty"` + // Network: URI of the network to which this router belongs. Network string `json:"network,omitempty"` @@ -22559,12 +25270,13 @@ type RouterBgpPeer struct { // Only IPv4 is supported. IpAddress string `json:"ipAddress,omitempty"` - // ManagementType: [Output Only] Type of how the resource/configuration - // of the BGP peer is managed. MANAGED_BY_USER is the default value; - // MANAGED_BY_ATTACHMENT represents an BGP peer that is automatically - // created for PARTNER interconnectAttachment, Google will automatically - // create/delete this type of BGP peer when the PARTNER - // interconnectAttachment is created/deleted. + // ManagementType: [Output Only] The resource that configures and + // manages this BGP peer. MANAGED_BY_USER is the default value and can + // be managed by you or other users; MANAGED_BY_ATTACHMENT is a BGP peer + // that is configured and managed by Cloud Interconnect, specifically by + // an InterconnectAttachment of type PARTNER. Google will automatically + // create, update, and delete this type of BGP peer when the PARTNER + // InterconnectAttachment is created, updated, or deleted. // // Possible values: // "MANAGED_BY_ATTACHMENT" @@ -22626,12 +25338,14 @@ type RouterInterface struct { // attachment. LinkedVpnTunnel string `json:"linkedVpnTunnel,omitempty"` - // ManagementType: [Output Only] Type of how the resource/configuration - // of the interface is managed. MANAGED_BY_USER is the default value; - // MANAGED_BY_ATTACHMENT represents an interface that is automatically - // created for PARTNER type interconnectAttachment, Google will - // automatically create/update/delete this type of interface when the - // PARTNER interconnectAttachment is created/provisioned/deleted. + // ManagementType: [Output Only] The resource that configures and + // manages this interface. MANAGED_BY_USER is the default value and can + // be managed by you or other users; MANAGED_BY_ATTACHMENT is an + // interface that is configured and managed by Cloud Interconnect, + // specifically by an InterconnectAttachment of type PARTNER. Google + // will automatically create, update, and delete this type of interface + // when the PARTNER InterconnectAttachment is created, updated, or + // deleted. // // Possible values: // "MANAGED_BY_ATTACHMENT" @@ -22820,6 +25534,140 @@ func (s *RouterListWarningData) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +// RouterNat: Represents a Nat resource. It enables the VMs within the +// specified subnetworks to access Internet without external IP +// addresses. It specifies a list of subnetworks (and the ranges within) +// that want to use NAT. Customers can also provide the external IPs +// that would be used for NAT. GCP would auto-allocate ephemeral IPs if +// no external IPs are provided. +type RouterNat struct { + // IcmpIdleTimeoutSec: Timeout (in seconds) for ICMP connections. + // Defaults to 30s if not set. + IcmpIdleTimeoutSec int64 `json:"icmpIdleTimeoutSec,omitempty"` + + // MinPortsPerVm: Minimum number of ports allocated to a VM from this + // NAT config. If not set, a default number of ports is allocated to a + // VM. This gets rounded up to the nearest power of 2. Eg. if the value + // of this field is 50, at least 64 ports will be allocated to a VM. + MinPortsPerVm int64 `json:"minPortsPerVm,omitempty"` + + // Name: Unique name of this Nat service. The name must be 1-63 + // characters long and comply with RFC1035. + Name string `json:"name,omitempty"` + + // NatIpAllocateOption: Specify the NatIpAllocateOption. If it is + // AUTO_ONLY, then nat_ip should be empty. + // + // Possible values: + // "AUTO_ONLY" + // "MANUAL_ONLY" + NatIpAllocateOption string `json:"natIpAllocateOption,omitempty"` + + // NatIps: A list of URLs of the IP resources used for this Nat service. + // These IPs must be valid static external IP addresses assigned to the + // project. max_length is subject to change post alpha. + NatIps []string `json:"natIps,omitempty"` + + // SourceSubnetworkIpRangesToNat: Specify the Nat option. If this field + // contains ALL_SUBNETWORKS_ALL_IP_RANGES or + // ALL_SUBNETWORKS_ALL_PRIMARY_IP_RANGES, then there should not be any + // other Router.Nat section in any Router for this network in this + // region. + // + // Possible values: + // "ALL_SUBNETWORKS_ALL_IP_RANGES" + // "ALL_SUBNETWORKS_ALL_PRIMARY_IP_RANGES" + // "LIST_OF_SUBNETWORKS" + SourceSubnetworkIpRangesToNat string `json:"sourceSubnetworkIpRangesToNat,omitempty"` + + // Subnetworks: A list of Subnetwork resources whose traffic should be + // translated by NAT Gateway. It is used only when LIST_OF_SUBNETWORKS + // is selected for the SubnetworkIpRangeToNatOption above. + Subnetworks []*RouterNatSubnetworkToNat `json:"subnetworks,omitempty"` + + // TcpEstablishedIdleTimeoutSec: Timeout (in seconds) for TCP + // established connections. Defaults to 1200s if not set. + TcpEstablishedIdleTimeoutSec int64 `json:"tcpEstablishedIdleTimeoutSec,omitempty"` + + // TcpTransitoryIdleTimeoutSec: Timeout (in seconds) for TCP transitory + // connections. Defaults to 30s if not set. + TcpTransitoryIdleTimeoutSec int64 `json:"tcpTransitoryIdleTimeoutSec,omitempty"` + + // UdpIdleTimeoutSec: Timeout (in seconds) for UDP connections. Defaults + // to 30s if not set. + UdpIdleTimeoutSec int64 `json:"udpIdleTimeoutSec,omitempty"` + + // ForceSendFields is a list of field names (e.g. "IcmpIdleTimeoutSec") + // to unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "IcmpIdleTimeoutSec") to + // include in API requests with the JSON null value. By default, fields + // with empty values are omitted from API requests. However, any field + // with an empty value appearing in NullFields will be sent to the + // server as null. It is an error if a field in this list has a + // non-empty value. This may be used to include null fields in Patch + // requests. + NullFields []string `json:"-"` +} + +func (s *RouterNat) MarshalJSON() ([]byte, error) { + type NoMethod RouterNat + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// RouterNatSubnetworkToNat: Defines the IP ranges that want to use NAT +// for a subnetwork. +type RouterNatSubnetworkToNat struct { + // Name: URL for the subnetwork resource to use NAT. + Name string `json:"name,omitempty"` + + // SecondaryIpRangeNames: A list of the secondary ranges of the + // Subnetwork that are allowed to use NAT. This can be populated only if + // "LIST_OF_SECONDARY_IP_RANGES" is one of the values in + // source_ip_ranges_to_nat. + SecondaryIpRangeNames []string `json:"secondaryIpRangeNames,omitempty"` + + // SourceIpRangesToNat: Specify the options for NAT ranges in the + // Subnetwork. All usages of single value are valid except + // NAT_IP_RANGE_OPTION_UNSPECIFIED. The only valid option with multiple + // values is: ["PRIMARY_IP_RANGE", "LIST_OF_SECONDARY_IP_RANGES"] + // Default: [ALL_IP_RANGES] + // + // Possible values: + // "ALL_IP_RANGES" + // "LIST_OF_SECONDARY_IP_RANGES" + // "PRIMARY_IP_RANGE" + SourceIpRangesToNat []string `json:"sourceIpRangesToNat,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Name") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Name") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *RouterNatSubnetworkToNat) MarshalJSON() ([]byte, error) { + type NoMethod RouterNatSubnetworkToNat + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + type RouterStatus struct { // BestRoutes: Best routes for this router's network. BestRoutes []*Route `json:"bestRoutes,omitempty"` @@ -22829,6 +25677,8 @@ type RouterStatus struct { BgpPeerStatus []*RouterStatusBgpPeerStatus `json:"bgpPeerStatus,omitempty"` + NatStatus []*RouterStatusNatStatus `json:"natStatus,omitempty"` + // Network: URI of the network to which this router belongs. Network string `json:"network,omitempty"` @@ -22916,6 +25766,57 @@ func (s *RouterStatusBgpPeerStatus) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +// RouterStatusNatStatus: Status of a NAT contained in this router. +type RouterStatusNatStatus struct { + // AutoAllocatedNatIps: A list of IPs auto-allocated for NAT. Example: + // ["1.1.1.1", "129.2.16.89"] + AutoAllocatedNatIps []string `json:"autoAllocatedNatIps,omitempty"` + + // MinExtraNatIpsNeeded: The number of extra IPs to allocate. This will + // be greater than 0 only if user-specified IPs are NOT enough to allow + // all configured VMs to use NAT. This value is meaningful only when + // auto-allocation of NAT IPs is *not* used. + MinExtraNatIpsNeeded int64 `json:"minExtraNatIpsNeeded,omitempty"` + + // Name: Unique name of this NAT. + Name string `json:"name,omitempty"` + + // NumVmEndpointsWithNatMappings: Number of VM endpoints (i.e., Nics) + // that can use NAT. + NumVmEndpointsWithNatMappings int64 `json:"numVmEndpointsWithNatMappings,omitempty"` + + // UserAllocatedNatIpResources: A list of fully qualified URLs of + // reserved IP address resources. + UserAllocatedNatIpResources []string `json:"userAllocatedNatIpResources,omitempty"` + + // UserAllocatedNatIps: A list of IPs user-allocated for NAT. They will + // be raw IP strings like "179.12.26.133". + UserAllocatedNatIps []string `json:"userAllocatedNatIps,omitempty"` + + // ForceSendFields is a list of field names (e.g. "AutoAllocatedNatIps") + // to unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "AutoAllocatedNatIps") to + // include in API requests with the JSON null value. By default, fields + // with empty values are omitted from API requests. However, any field + // with an empty value appearing in NullFields will be sent to the + // server as null. It is an error if a field in this list has a + // non-empty value. This may be used to include null fields in Patch + // requests. + NullFields []string `json:"-"` +} + +func (s *RouterStatusNatStatus) MarshalJSON() ([]byte, error) { + type NoMethod RouterStatusNatStatus + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + type RouterStatusResponse struct { // Kind: Type of resource. Kind string `json:"kind,omitempty"` @@ -23407,8 +26308,9 @@ func (s *SecurityPoliciesWafConfig) MarshalJSON() ([]byte, error) { } // SecurityPolicy: A security policy is comprised of one or more rules. -// It can also be associated with one or more 'targets'. Next available -// tag: 11 +// It can also be associated with one or more 'targets'. (== +// resource_for v1.securityPolicies ==) (== resource_for +// beta.securityPolicies ==) type SecurityPolicy struct { // CreationTimestamp: [Output Only] Creation timestamp in RFC3339 text // format. @@ -23423,7 +26325,8 @@ type SecurityPolicy struct { // locking. The fingerprint is initially generated by Compute Engine and // changes after every request to modify or update metadata. You must // always provide an up-to-date fingerprint hash in order to update or - // change metadata. + // change metadata, otherwise the request will fail with error 412 + // conditionNotMet. // // To see the latest fingerprint, make get() request to the security // policy. @@ -23437,6 +26340,22 @@ type SecurityPolicy struct { // compute#securityPolicyfor security policies Kind string `json:"kind,omitempty"` + // LabelFingerprint: A fingerprint for the labels being applied to this + // security policy, which is essentially a hash of the labels set used + // for optimistic locking. The fingerprint is initially generated by + // Compute Engine and changes after every request to modify or update + // labels. You must always provide an up-to-date fingerprint hash in + // order to update or change labels. + // + // To see the latest fingerprint, make get() request to the security + // policy. + LabelFingerprint string `json:"labelFingerprint,omitempty"` + + // Labels: Labels to apply to this security policy resource. These can + // be later modified by the setLabels method. Each label key/value must + // comply with RFC1035. Label values may be empty. + Labels map[string]string `json:"labels,omitempty"` + // Name: Name of the resource. Provided by the client when the resource // is created. The name must be 1-63 characters long, and comply with // RFC1035. Specifically, the name must be 1-63 characters long and @@ -23688,7 +26607,8 @@ type SecurityPolicyRule struct { // Priority: An integer indicating the priority of a rule in the list. // The priority must be a positive value between 0 and 2147483647. Rules - // are evaluated in the increasing order of priority. + // are evaluated from highest to lowest priority where 0 is the highest + // priority and 2147483647 is the lowest prority. Priority int64 `json:"priority,omitempty"` // ServerResponse contains the HTTP response code and headers from the @@ -23731,9 +26651,6 @@ type SecurityPolicyRuleMatcher struct { // contents in the request header. Expr *Expr `json:"expr,omitempty"` - // SrcIpRanges: CIDR IP address range. - SrcIpRanges []string `json:"srcIpRanges,omitempty"` - // VersionedExpr: Preconfigured versioned expression. If this field is // specified, config must also be specified. Available preconfigured // expressions along with their requirements are: SRC_IPS_V1 - must @@ -23741,7 +26658,6 @@ type SecurityPolicyRuleMatcher struct { // // Possible values: // "SRC_IPS_V1" - // "VERSIONED_EXPR_UNSPECIFIED" VersionedExpr string `json:"versionedExpr,omitempty"` // ForceSendFields is a list of field names (e.g. "Config") to @@ -23879,15 +26795,15 @@ func (s *ServiceAccount) MarshalJSON() ([]byte, error) { // ShieldedVmConfig: A set of Shielded VM options. type ShieldedVmConfig struct { - // EnableIntegrityMonitoring: Defines whether the instance should have - // integrity monitoring enabled. + // EnableIntegrityMonitoring: Defines whether the instance has integrity + // monitoring enabled. EnableIntegrityMonitoring bool `json:"enableIntegrityMonitoring,omitempty"` - // EnableSecureBoot: Defines whether the instance should have secure - // boot enabled. + // EnableSecureBoot: Defines whether the instance has Secure Boot + // enabled. EnableSecureBoot bool `json:"enableSecureBoot,omitempty"` - // EnableVtpm: Defines whether the instance should have the TPM enabled. + // EnableVtpm: Defines whether the instance has the vTPM enabled. EnableVtpm bool `json:"enableVtpm,omitempty"` // ForceSendFields is a list of field names (e.g. @@ -23915,11 +26831,82 @@ func (s *ShieldedVmConfig) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } -// ShieldedVmIntegrityPolicy: The policy describes how boot integrity -// measurements are evaluated. +// ShieldedVmIdentity: A shielded VM identity entry. +type ShieldedVmIdentity struct { + // EncryptionKey: An Endorsement Key (EK) issued to the Shielded VM's + // vTPM. + EncryptionKey *ShieldedVmIdentityEntry `json:"encryptionKey,omitempty"` + + // Kind: [Output Only] Type of the resource. Always + // compute#shieldedVmIdentity for shielded VM identity entry. + Kind string `json:"kind,omitempty"` + + // SigningKey: An Attestation Key (AK) issued to the Shielded VM's vTPM. + SigningKey *ShieldedVmIdentityEntry `json:"signingKey,omitempty"` + + // ServerResponse contains the HTTP response code and headers from the + // server. + googleapi.ServerResponse `json:"-"` + + // ForceSendFields is a list of field names (e.g. "EncryptionKey") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "EncryptionKey") to include + // in API requests with the JSON null value. By default, fields with + // empty values are omitted from API requests. However, any field with + // an empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *ShieldedVmIdentity) MarshalJSON() ([]byte, error) { + type NoMethod ShieldedVmIdentity + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// ShieldedVmIdentityEntry: A Shielded VM Identity Entry. +type ShieldedVmIdentityEntry struct { + // EkCert: A PEM-encoded X.509 certificate. This field can be empty. + EkCert string `json:"ekCert,omitempty"` + + // EkPub: A PEM-encoded public key. + EkPub string `json:"ekPub,omitempty"` + + // ForceSendFields is a list of field names (e.g. "EkCert") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "EkCert") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *ShieldedVmIdentityEntry) MarshalJSON() ([]byte, error) { + type NoMethod ShieldedVmIdentityEntry + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// ShieldedVmIntegrityPolicy: The policy describes the baseline against +// which VM instance boot integrity is measured. type ShieldedVmIntegrityPolicy struct { - // UpdateAutoLearnPolicy: Triggers an auto relearn event: the integrity - // monitoring module copies existing guest measurements to the baseline. + // UpdateAutoLearnPolicy: Updates the integrity policy baseline using + // the measurements from the VM instance's most recent boot. UpdateAutoLearnPolicy bool `json:"updateAutoLearnPolicy,omitempty"` // ForceSendFields is a list of field names (e.g. @@ -23988,6 +26975,10 @@ func (s *SignedUrlKey) MarshalJSON() ([]byte, error) { // Snapshot: A persistent disk snapshot resource. (== resource_for // beta.snapshots ==) (== resource_for v1.snapshots ==) type Snapshot struct { + // AutoCreated: [Output Only] Set to true if snapshots are automatically + // by applying resource policy on the target disk. + AutoCreated bool `json:"autoCreated,omitempty"` + // CreationTimestamp: [Output Only] Creation timestamp in RFC3339 text // format. CreationTimestamp string `json:"creationTimestamp,omitempty"` @@ -24012,7 +27003,8 @@ type Snapshot struct { // optimistic locking. The fingerprint is initially generated by Compute // Engine and changes after every request to modify or update labels. // You must always provide an up-to-date fingerprint hash in order to - // update or change labels. + // update or change labels, otherwise the request will fail with error + // 412 conditionNotMet. // // To see the latest fingerprint, make a get() request to retrieve a // snapshot. @@ -24101,25 +27093,28 @@ type Snapshot struct { // "UP_TO_DATE" StorageBytesStatus string `json:"storageBytesStatus,omitempty"` + // StorageLocations: GCS bucket storage location of the snapshot + // (regional or multi-regional). + StorageLocations []string `json:"storageLocations,omitempty"` + // ServerResponse contains the HTTP response code and headers from the // server. googleapi.ServerResponse `json:"-"` - // ForceSendFields is a list of field names (e.g. "CreationTimestamp") - // to unconditionally include in API requests. By default, fields with + // ForceSendFields is a list of field names (e.g. "AutoCreated") to + // unconditionally include in API requests. By default, fields with // empty values are omitted from API requests. However, any non-pointer, // non-interface field appearing in ForceSendFields will be sent to the // server regardless of whether the field is empty or not. This may be // used to include empty fields in Patch requests. ForceSendFields []string `json:"-"` - // NullFields is a list of field names (e.g. "CreationTimestamp") to - // include in API requests with the JSON null value. By default, fields - // with empty values are omitted from API requests. However, any field - // with an empty value appearing in NullFields will be sent to the - // server as null. It is an error if a field in this list has a - // non-empty value. This may be used to include null fields in Patch - // requests. + // NullFields is a list of field names (e.g. "AutoCreated") to include + // in API requests with the JSON null value. By default, fields with + // empty values are omitted from API requests. However, any field with + // an empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. NullFields []string `json:"-"` } @@ -24334,6 +27329,9 @@ type SslCertificate struct { // property when you create the resource. Description string `json:"description,omitempty"` + // ExpireTime: [Output Only] Expire time of the certificate. RFC3339 + ExpireTime string `json:"expireTime,omitempty"` + // Id: [Output Only] The unique identifier for the resource. This // identifier is defined by the server. Id uint64 `json:"id,omitempty,string"` @@ -24342,6 +27340,9 @@ type SslCertificate struct { // compute#sslCertificate for SSL certificates. Kind string `json:"kind,omitempty"` + // Managed: Configuration and status of a managed SSL certificate. + Managed *SslCertificateManagedSslCertificate `json:"managed,omitempty"` + // Name: Name of the resource. Provided by the client when the resource // is created. The name must be 1-63 characters long, and comply with // RFC1035. Specifically, the name must be 1-63 characters long and @@ -24358,6 +27359,24 @@ type SslCertificate struct { // SelfLink: [Output only] Server-defined URL for the resource. SelfLink string `json:"selfLink,omitempty"` + // SelfManaged: Configuration and status of a self-managed SSL + // certificate. + SelfManaged *SslCertificateSelfManagedSslCertificate `json:"selfManaged,omitempty"` + + // SubjectAlternativeNames: [Output Only] Domains associated with the + // certificate via Subject Alternative Name. + SubjectAlternativeNames []string `json:"subjectAlternativeNames,omitempty"` + + // Type: (Optional) Specifies the type of SSL certificate, either + // "SELF_MANAGED" or "MANAGED". If not specified, the certificate is + // self-managed and the fields certificate and private_key are used. + // + // Possible values: + // "MANAGED" + // "SELF_MANAGED" + // "TYPE_UNSPECIFIED" + Type string `json:"type,omitempty"` + // ServerResponse contains the HTTP response code and headers from the // server. googleapi.ServerResponse `json:"-"` @@ -24540,6 +27559,86 @@ func (s *SslCertificateListWarningData) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +// SslCertificateManagedSslCertificate: Configuration and status of a +// managed SSL certificate. +type SslCertificateManagedSslCertificate struct { + // DomainStatus: [Output only] Detailed statuses of the domains + // specified for managed certificate resource. + DomainStatus map[string]string `json:"domainStatus,omitempty"` + + // Domains: The domains for which a managed SSL certificate will be + // generated. Currently only single-domain certs are supported. + Domains []string `json:"domains,omitempty"` + + // Status: [Output only] Status of the managed certificate resource. + // + // Possible values: + // "ACTIVE" + // "MANAGED_CERTIFICATE_STATUS_UNSPECIFIED" + // "PROVISIONING" + // "PROVISIONING_FAILED" + // "PROVISIONING_FAILED_PERMANENTLY" + // "RENEWAL_FAILED" + Status string `json:"status,omitempty"` + + // ForceSendFields is a list of field names (e.g. "DomainStatus") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "DomainStatus") to include + // in API requests with the JSON null value. By default, fields with + // empty values are omitted from API requests. However, any field with + // an empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *SslCertificateManagedSslCertificate) MarshalJSON() ([]byte, error) { + type NoMethod SslCertificateManagedSslCertificate + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// SslCertificateSelfManagedSslCertificate: Configuration and status of +// a self-managed SSL certificate. +type SslCertificateSelfManagedSslCertificate struct { + // Certificate: A local certificate file. The certificate must be in PEM + // format. The certificate chain must be no greater than 5 certs long. + // The chain must include at least one intermediate cert. + Certificate string `json:"certificate,omitempty"` + + // PrivateKey: A write-only private key in PEM format. Only insert + // requests will include this field. + PrivateKey string `json:"privateKey,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Certificate") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Certificate") to include + // in API requests with the JSON null value. By default, fields with + // empty values are omitted from API requests. However, any field with + // an empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *SslCertificateSelfManagedSslCertificate) MarshalJSON() ([]byte, error) { + type NoMethod SslCertificateSelfManagedSslCertificate + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + type SslPoliciesList struct { // Id: [Output Only] Unique identifier for the resource; defined by the // server. @@ -24751,7 +27850,11 @@ type SslPolicy struct { // Fingerprint: Fingerprint of this resource. A hash of the contents // stored in this object. This field is used in optimistic locking. This // field will be ignored when inserting a SslPolicy. An up-to-date - // fingerprint must be provided in order to update the SslPolicy. + // fingerprint must be provided in order to update the SslPolicy, + // otherwise the request will fail with error 412 conditionNotMet. + // + // To see the latest fingerprint, make a get() request to retrieve an + // SslPolicy. Fingerprint string `json:"fingerprint,omitempty"` // Id: [Output Only] The unique identifier for the resource. This @@ -24989,12 +28092,18 @@ type Subnetwork struct { Description string `json:"description,omitempty"` // EnableFlowLogs: Whether to enable flow logging for this subnetwork. + // If this field is not explicitly set, it will not appear in get + // listings. If not set the default behavior is to disable flow logging. EnableFlowLogs bool `json:"enableFlowLogs,omitempty"` // Fingerprint: Fingerprint of this resource. A hash of the contents // stored in this object. This field is used in optimistic locking. This // field will be ignored when inserting a Subnetwork. An up-to-date - // fingerprint must be provided in order to update the Subnetwork. + // fingerprint must be provided in order to update the Subnetwork, + // otherwise the request will fail with error 412 conditionNotMet. + // + // To see the latest fingerprint, make a get() request to retrieve a + // Subnetwork. Fingerprint string `json:"fingerprint,omitempty"` // GatewayAddress: [Output Only] The gateway address for default routes @@ -25044,7 +28153,8 @@ type Subnetwork struct { // SecondaryIpRanges: An array of configurations for secondary IP ranges // for VM instances contained in this subnetwork. The primary IP of such // VM must belong to the primary ipCidrRange of the subnetwork. The - // alias IPs may belong to either primary or secondary ranges. + // alias IPs may belong to either primary or secondary ranges. This + // field can be updated with a patch request. SecondaryIpRanges []*SubnetworkSecondaryRange `json:"secondaryIpRanges,omitempty"` // SelfLink: [Output Only] Server-defined URL for the resource. @@ -25629,6 +28739,33 @@ type TCPHealthCheck struct { // both port and port_name are defined, port takes precedence. PortName string `json:"portName,omitempty"` + // PortSpecification: Specifies how port is selected for health + // checking, can be one of following values: + // USE_FIXED_PORT: The port number in + // port + // is used for health checking. + // USE_NAMED_PORT: The + // portName + // is used for health checking. + // USE_SERVING_PORT: For NetworkEndpointGroup, the port specified for + // each network endpoint is used for health checking. For other + // backends, the port or named port specified in the Backend Service is + // used for health checking. + // + // + // If not specified, TCP health check follows behavior specified + // in + // port + // and + // portName + // fields. + // + // Possible values: + // "USE_FIXED_PORT" + // "USE_NAMED_PORT" + // "USE_SERVING_PORT" + PortSpecification string `json:"portSpecification,omitempty"` + // ProxyHeader: Specifies the type of proxy header to append before // sending data to the backend, either NONE or PROXY_V1. The default is // NONE. @@ -26041,8 +29178,9 @@ type TargetHttpsProxy struct { SelfLink string `json:"selfLink,omitempty"` // SslCertificates: URLs to SslCertificate resources that are used to - // authenticate connections between users and the load balancer. - // Currently, exactly one SSL certificate must be specified. + // authenticate connections between users and the load balancer. At + // least one SSL certificate must be specified. Currently, you may + // specify up to 15 SSL certificates. SslCertificates []string `json:"sslCertificates,omitempty"` // SslPolicy: URL of SslPolicy resource that will be associated with the @@ -26853,7 +29991,7 @@ type TargetPool struct { // SelfLink: [Output Only] Server-defined URL for the resource. SelfLink string `json:"selfLink,omitempty"` - // SessionAffinity: Sesssion affinity option, must be one of the + // SessionAffinity: Session affinity option, must be one of the // following values: // NONE: Connections from the same client IP may go to any instance in // the pool. @@ -27672,8 +30810,9 @@ type TargetSslProxy struct { Service string `json:"service,omitempty"` // SslCertificates: URLs to SslCertificate resources that are used to - // authenticate connections to Backends. Currently exactly one SSL - // certificate must be specified. + // authenticate connections to Backends. At least one SSL certificate + // must be specified. Currently, you may specify up to 15 SSL + // certificates. SslCertificates []string `json:"sslCertificates,omitempty"` // SslPolicy: URL of SslPolicy resource that will be associated with the @@ -28181,9 +31320,10 @@ type TargetVpnGateway struct { // for optimistic locking. The fingerprint is initially generated by // Compute Engine and changes after every request to modify or update // labels. You must always provide an up-to-date fingerprint hash in - // order to update or change labels. + // order to update or change labels, otherwise the request will fail + // with error 412 conditionNotMet. // - // To see the latest fingerprint, make a get() request to retrieve an + // To see the latest fingerprint, make a get() request to retrieve a // TargetVpnGateway. LabelFingerprint string `json:"labelFingerprint,omitempty"` @@ -28794,47 +31934,6 @@ func (s *TestPermissionsResponse) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } -type UDPHealthCheck struct { - // Port: The UDP port number for the health check request. Valid values - // are 1 through 65535. - Port int64 `json:"port,omitempty"` - - // PortName: Port name as defined in InstanceGroup#NamedPort#name. If - // both port and port_name are defined, port takes precedence. - PortName string `json:"portName,omitempty"` - - // Request: Raw data of request to send in payload of UDP packet. It is - // an error if this is empty. The request data can only be ASCII. - Request string `json:"request,omitempty"` - - // Response: The bytes to match against the beginning of the response - // data. It is an error if this is empty. The response data can only be - // ASCII. - Response string `json:"response,omitempty"` - - // ForceSendFields is a list of field names (e.g. "Port") to - // unconditionally include in API requests. By default, fields with - // empty values are omitted from API requests. However, any non-pointer, - // non-interface field appearing in ForceSendFields will be sent to the - // server regardless of whether the field is empty or not. This may be - // used to include empty fields in Patch requests. - ForceSendFields []string `json:"-"` - - // NullFields is a list of field names (e.g. "Port") to include in API - // requests with the JSON null value. By default, fields with empty - // values are omitted from API requests. However, any field with an - // empty value appearing in NullFields will be sent to the server as - // null. It is an error if a field in this list has a non-empty value. - // This may be used to include null fields in Patch requests. - NullFields []string `json:"-"` -} - -func (s *UDPHealthCheck) MarshalJSON() ([]byte, error) { - type NoMethod UDPHealthCheck - raw := NoMethod(*s) - return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) -} - // UrlMap: A UrlMap resource. This resource defines the mapping from URL // to the BackendService resource, based on the "longest-match" of the // URL's host and path. @@ -28843,8 +31942,13 @@ type UrlMap struct { // format. CreationTimestamp string `json:"creationTimestamp,omitempty"` - // DefaultService: The URL of the BackendService resource if none of the + // DefaultService: The URL of the backendService resource if none of the // hostRules match. + // Use defaultService instead of defaultRouteAction when simple routing + // to a backendService is desired and other advanced capabilities like + // traffic splitting and rewrites are not required. + // Only one of defaultService, defaultRouteAction or defaultUrlRedirect + // should must be set. DefaultService string `json:"defaultService,omitempty"` // Description: An optional description of this resource. Provide this @@ -28854,7 +31958,11 @@ type UrlMap struct { // Fingerprint: Fingerprint of this resource. A hash of the contents // stored in this object. This field is used in optimistic locking. This // field will be ignored when inserting a UrlMap. An up-to-date - // fingerprint must be provided in order to update the UrlMap. + // fingerprint must be provided in order to update the UrlMap, otherwise + // the request will fail with error 412 conditionNotMet. + // + // To see the latest fingerprint, make a get() request to retrieve a + // UrlMap. Fingerprint string `json:"fingerprint,omitempty"` // HostRules: The list of HostRules to use against the URL. @@ -29504,6 +32612,241 @@ func (s *UsageExportLocation) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +// VmEndpointNatMappings: Contain information of Nat mapping for a VM +// endpoint (i.e., NIC). +type VmEndpointNatMappings struct { + // InstanceName: Name of the VM instance which the endpoint belongs to + InstanceName string `json:"instanceName,omitempty"` + + InterfaceNatMappings []*VmEndpointNatMappingsInterfaceNatMappings `json:"interfaceNatMappings,omitempty"` + + // ForceSendFields is a list of field names (e.g. "InstanceName") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "InstanceName") to include + // in API requests with the JSON null value. By default, fields with + // empty values are omitted from API requests. However, any field with + // an empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *VmEndpointNatMappings) MarshalJSON() ([]byte, error) { + type NoMethod VmEndpointNatMappings + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// VmEndpointNatMappingsInterfaceNatMappings: Contain information of Nat +// mapping for an interface of this endpoint. +type VmEndpointNatMappingsInterfaceNatMappings struct { + // NatIpPortRanges: A list of all IP:port-range mappings assigned to + // this interface. These ranges are inclusive, that is, both the first + // and the last ports can be used for NAT. Example: + // ["2.2.2.2:12345-12355", "1.1.1.1:2234-2234"]. + NatIpPortRanges []string `json:"natIpPortRanges,omitempty"` + + // NumTotalNatPorts: Total number of ports across all NAT IPs allocated + // to this interface. It equals to the aggregated port number in the + // field nat_ip_port_ranges. + NumTotalNatPorts int64 `json:"numTotalNatPorts,omitempty"` + + // SourceAliasIpRange: Alias IP range for this interface endpoint. It + // will be a private (RFC 1918) IP range. Examples: "10.33.4.55/32", or + // "192.168.5.0/24". + SourceAliasIpRange string `json:"sourceAliasIpRange,omitempty"` + + // SourceVirtualIp: Primary IP of the VM for this NIC. + SourceVirtualIp string `json:"sourceVirtualIp,omitempty"` + + // ForceSendFields is a list of field names (e.g. "NatIpPortRanges") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "NatIpPortRanges") to + // include in API requests with the JSON null value. By default, fields + // with empty values are omitted from API requests. However, any field + // with an empty value appearing in NullFields will be sent to the + // server as null. It is an error if a field in this list has a + // non-empty value. This may be used to include null fields in Patch + // requests. + NullFields []string `json:"-"` +} + +func (s *VmEndpointNatMappingsInterfaceNatMappings) MarshalJSON() ([]byte, error) { + type NoMethod VmEndpointNatMappingsInterfaceNatMappings + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// VmEndpointNatMappingsList: Contains a list of VmEndpointNatMappings. +type VmEndpointNatMappingsList struct { + // Id: [Output Only] The unique identifier for the resource. This + // identifier is defined by the server. + Id string `json:"id,omitempty"` + + // Kind: [Output Only] Type of resource. Always + // compute#vmEndpointNatMappingsList for lists of Nat mappings of VM + // endpoints. + Kind string `json:"kind,omitempty"` + + // NextPageToken: [Output Only] This token allows you to get the next + // page of results for list requests. If the number of results is larger + // than maxResults, use the nextPageToken as a value for the query + // parameter pageToken in the next list request. Subsequent list + // requests will have their own nextPageToken to continue paging through + // the results. + NextPageToken string `json:"nextPageToken,omitempty"` + + // Result: [Output Only] A list of Nat mapping information of VM + // endpoints. + Result []*VmEndpointNatMappings `json:"result,omitempty"` + + // SelfLink: [Output Only] Server-defined URL for this resource. + SelfLink string `json:"selfLink,omitempty"` + + // Warning: [Output Only] Informational warning message. + Warning *VmEndpointNatMappingsListWarning `json:"warning,omitempty"` + + // ServerResponse contains the HTTP response code and headers from the + // server. + googleapi.ServerResponse `json:"-"` + + // ForceSendFields is a list of field names (e.g. "Id") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Id") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *VmEndpointNatMappingsList) MarshalJSON() ([]byte, error) { + type NoMethod VmEndpointNatMappingsList + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// VmEndpointNatMappingsListWarning: [Output Only] Informational warning +// message. +type VmEndpointNatMappingsListWarning struct { + // Code: [Output Only] A warning code, if applicable. For example, + // Compute Engine returns NO_RESULTS_ON_PAGE if there are no results in + // the response. + // + // Possible values: + // "CLEANUP_FAILED" + // "DEPRECATED_RESOURCE_USED" + // "DEPRECATED_TYPE_USED" + // "DISK_SIZE_LARGER_THAN_IMAGE_SIZE" + // "EXPERIMENTAL_TYPE_USED" + // "EXTERNAL_API_WARNING" + // "FIELD_VALUE_OVERRIDEN" + // "INJECTED_KERNELS_DEPRECATED" + // "MISSING_TYPE_DEPENDENCY" + // "NEXT_HOP_ADDRESS_NOT_ASSIGNED" + // "NEXT_HOP_CANNOT_IP_FORWARD" + // "NEXT_HOP_INSTANCE_NOT_FOUND" + // "NEXT_HOP_INSTANCE_NOT_ON_NETWORK" + // "NEXT_HOP_NOT_RUNNING" + // "NOT_CRITICAL_ERROR" + // "NO_RESULTS_ON_PAGE" + // "REQUIRED_TOS_AGREEMENT" + // "RESOURCE_IN_USE_BY_OTHER_RESOURCE_WARNING" + // "RESOURCE_NOT_DELETED" + // "SCHEMA_VALIDATION_IGNORED" + // "SINGLE_INSTANCE_PROPERTY_TEMPLATE" + // "UNDECLARED_PROPERTIES" + // "UNREACHABLE" + Code string `json:"code,omitempty"` + + // Data: [Output Only] Metadata about this warning in key: value format. + // For example: + // "data": [ { "key": "scope", "value": "zones/us-east1-d" } + Data []*VmEndpointNatMappingsListWarningData `json:"data,omitempty"` + + // Message: [Output Only] A human-readable description of the warning + // code. + Message string `json:"message,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Code") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Code") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *VmEndpointNatMappingsListWarning) MarshalJSON() ([]byte, error) { + type NoMethod VmEndpointNatMappingsListWarning + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type VmEndpointNatMappingsListWarningData struct { + // Key: [Output Only] A key that provides more detail on the warning + // being returned. For example, for warnings where there are no results + // in a list request for a particular zone, this key might be scope and + // the key value might be the zone name. Other examples might be a key + // indicating a deprecated resource and a suggested replacement, or a + // warning about invalid network settings (for example, if an instance + // attempts to perform IP forwarding but is not enabled for IP + // forwarding). + Key string `json:"key,omitempty"` + + // Value: [Output Only] A warning data value corresponding to the key. + Value string `json:"value,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Key") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Key") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *VmEndpointNatMappingsListWarningData) MarshalJSON() ([]byte, error) { + type NoMethod VmEndpointNatMappingsListWarningData + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + // VpnTunnel: VPN tunnel resource. (== resource_for beta.vpnTunnels ==) // (== resource_for v1.vpnTunnels ==) type VpnTunnel struct { @@ -29537,7 +32880,8 @@ type VpnTunnel struct { // optimistic locking. The fingerprint is initially generated by Compute // Engine and changes after every request to modify or update labels. // You must always provide an up-to-date fingerprint hash in order to - // update or change labels. + // update or change labels, otherwise the request will fail with error + // 412 conditionNotMet. // // To see the latest fingerprint, make a get() request to retrieve a // VpnTunnel. @@ -30310,8 +33654,8 @@ func (s *XpnHostListWarningData) MarshalJSON() ([]byte, error) { // XpnResourceId: Service resource (a.k.a service project) ID. type XpnResourceId struct { // Id: The ID of the service resource. In the case of projects, this - // field matches the project ID (e.g., my-project), not the project - // number (e.g., 12345678). + // field supports project id (e.g., my-project-123) and project number + // (e.g. 12345678). Id string `json:"id,omitempty"` // Type: The type of the service resource. @@ -30771,9 +34115,13 @@ func (c *AcceleratorTypesAggregatedListCall) doRequest(alt string) (*http.Respon } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/aggregated/acceleratorTypes") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -30959,9 +34307,13 @@ func (c *AcceleratorTypesGetCall) doRequest(alt string) (*http.Response, error) } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/acceleratorTypes/{acceleratorType}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -31183,9 +34535,13 @@ func (c *AcceleratorTypesListCall) doRequest(alt string) (*http.Response, error) } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/acceleratorTypes") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -31440,9 +34796,13 @@ func (c *AddressesAggregatedListCall) doRequest(alt string) (*http.Response, err } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/aggregated/addresses") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -31634,9 +34994,13 @@ func (c *AddressesDeleteCall) doRequest(alt string) (*http.Response, error) { reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/addresses/{address}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -31801,9 +35165,13 @@ func (c *AddressesGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/addresses/{address}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -31975,9 +35343,13 @@ func (c *AddressesInsertCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/addresses") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -32198,9 +35570,13 @@ func (c *AddressesListCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/addresses") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -32408,9 +35784,13 @@ func (c *AddressesSetLabelsCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/addresses/{resource}/setLabels") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -32487,9 +35867,9 @@ func (c *AddressesSetLabelsCall) Do(opts ...googleapi.CallOption) (*Operation, e // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -32571,9 +35951,13 @@ func (c *AddressesTestIamPermissionsCall) doRequest(alt string) (*http.Response, } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/addresses/{resource}/testIamPermissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -32645,14 +36029,1535 @@ func (c *AddressesTestIamPermissionsCall) Do(opts ...googleapi.CallOption) (*Tes // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/regions/{region}/addresses/{resource}/testIamPermissions", + // "request": { + // "$ref": "TestPermissionsRequest" + // }, + // "response": { + // "$ref": "TestPermissionsResponse" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute", + // "https://www.googleapis.com/auth/compute.readonly" + // ] + // } + +} + +// method id "compute.allocations.aggregatedList": + +type AllocationsAggregatedListCall struct { + s *Service + project string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// AggregatedList: Retrieves an aggregated list of allocations. +func (r *AllocationsService) AggregatedList(project string) *AllocationsAggregatedListCall { + c := &AllocationsAggregatedListCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + return c +} + +// Filter sets the optional parameter "filter": A filter expression that +// filters resources listed in the response. The expression must specify +// the field name, a comparison operator, and the value that you want to +// use for filtering. The value must be a string, a number, or a +// boolean. The comparison operator must be either =, !=, >, or <. +// +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. +// +// You can also filter nested fields. For example, you could specify +// scheduling.automaticRestart = false to include instances only if they +// are not scheduled for automatic restarts. You can use filtering on +// nested fields to filter based on resource labels. +// +// To filter on multiple expressions, provide each separate expression +// within parentheses. For example, (scheduling.automaticRestart = true) +// (cpuPlatform = "Intel Skylake"). By default, each expression is an +// AND expression. However, you can include AND and OR expressions +// explicitly. For example, (cpuPlatform = "Intel Skylake") OR +// (cpuPlatform = "Intel Broadwell") AND (scheduling.automaticRestart = +// true). +func (c *AllocationsAggregatedListCall) Filter(filter string) *AllocationsAggregatedListCall { + c.urlParams_.Set("filter", filter) + return c +} + +// MaxResults sets the optional parameter "maxResults": The maximum +// number of results per page that should be returned. If the number of +// available results is larger than maxResults, Compute Engine returns a +// nextPageToken that can be used to get the next page of results in +// subsequent list requests. Acceptable values are 0 to 500, inclusive. +// (Default: 500) +func (c *AllocationsAggregatedListCall) MaxResults(maxResults int64) *AllocationsAggregatedListCall { + c.urlParams_.Set("maxResults", fmt.Sprint(maxResults)) + return c +} + +// OrderBy sets the optional parameter "orderBy": Sorts list results by +// a certain order. By default, results are returned in alphanumerical +// order based on the resource name. +// +// You can also sort results in descending order based on the creation +// timestamp using orderBy="creationTimestamp desc". This sorts results +// based on the creationTimestamp field in reverse chronological order +// (newest result first). Use this to sort resources like operations so +// that the newest operation is returned first. +// +// Currently, only sorting by name or creationTimestamp desc is +// supported. +func (c *AllocationsAggregatedListCall) OrderBy(orderBy string) *AllocationsAggregatedListCall { + c.urlParams_.Set("orderBy", orderBy) + return c +} + +// PageToken sets the optional parameter "pageToken": Specifies a page +// token to use. Set pageToken to the nextPageToken returned by a +// previous list request to get the next page of results. +func (c *AllocationsAggregatedListCall) PageToken(pageToken string) *AllocationsAggregatedListCall { + c.urlParams_.Set("pageToken", pageToken) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *AllocationsAggregatedListCall) Fields(s ...googleapi.Field) *AllocationsAggregatedListCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// IfNoneMatch sets the optional parameter which makes the operation +// fail if the object's ETag matches the given value. This is useful for +// getting updates only after the object has changed since the last +// request. Use googleapi.IsNotModified to check whether the response +// error from Do is the result of In-None-Match. +func (c *AllocationsAggregatedListCall) IfNoneMatch(entityTag string) *AllocationsAggregatedListCall { + c.ifNoneMatch_ = entityTag + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *AllocationsAggregatedListCall) Context(ctx context.Context) *AllocationsAggregatedListCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *AllocationsAggregatedListCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *AllocationsAggregatedListCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + if c.ifNoneMatch_ != "" { + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) + } + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/aggregated/allocations") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.allocations.aggregatedList" call. +// Exactly one of *AllocationAggregatedList or error will be non-nil. +// Any non-2xx status code is an error. Response headers are in either +// *AllocationAggregatedList.ServerResponse.Header or (if a response was +// returned at all) in error.(*googleapi.Error).Header. Use +// googleapi.IsNotModified to check whether the returned error was +// because http.StatusNotModified was returned. +func (c *AllocationsAggregatedListCall) Do(opts ...googleapi.CallOption) (*AllocationAggregatedList, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &AllocationAggregatedList{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Retrieves an aggregated list of allocations.", + // "httpMethod": "GET", + // "id": "compute.allocations.aggregatedList", + // "parameterOrder": [ + // "project" + // ], + // "parameters": { + // "filter": { + // "description": "A filter expression that filters resources listed in the response. The expression must specify the field name, a comparison operator, and the value that you want to use for filtering. The value must be a string, a number, or a boolean. The comparison operator must be either =, !=, \u003e, or \u003c.\n\nFor example, if you are filtering Compute Engine instances, you can exclude instances named example-instance by specifying name != example-instance.\n\nYou can also filter nested fields. For example, you could specify scheduling.automaticRestart = false to include instances only if they are not scheduled for automatic restarts. You can use filtering on nested fields to filter based on resource labels.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart = true) (cpuPlatform = \"Intel Skylake\"). By default, each expression is an AND expression. However, you can include AND and OR expressions explicitly. For example, (cpuPlatform = \"Intel Skylake\") OR (cpuPlatform = \"Intel Broadwell\") AND (scheduling.automaticRestart = true).", + // "location": "query", + // "type": "string" + // }, + // "maxResults": { + // "default": "500", + // "description": "The maximum number of results per page that should be returned. If the number of available results is larger than maxResults, Compute Engine returns a nextPageToken that can be used to get the next page of results in subsequent list requests. Acceptable values are 0 to 500, inclusive. (Default: 500)", + // "format": "uint32", + // "location": "query", + // "minimum": "0", + // "type": "integer" + // }, + // "orderBy": { + // "description": "Sorts list results by a certain order. By default, results are returned in alphanumerical order based on the resource name.\n\nYou can also sort results in descending order based on the creation timestamp using orderBy=\"creationTimestamp desc\". This sorts results based on the creationTimestamp field in reverse chronological order (newest result first). Use this to sort resources like operations so that the newest operation is returned first.\n\nCurrently, only sorting by name or creationTimestamp desc is supported.", + // "location": "query", + // "type": "string" + // }, + // "pageToken": { + // "description": "Specifies a page token to use. Set pageToken to the nextPageToken returned by a previous list request to get the next page of results.", + // "location": "query", + // "type": "string" + // }, + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/aggregated/allocations", + // "response": { + // "$ref": "AllocationAggregatedList" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute", + // "https://www.googleapis.com/auth/compute.readonly" + // ] + // } + +} + +// Pages invokes f for each page of results. +// A non-nil error returned from f will halt the iteration. +// The provided context supersedes any context provided to the Context method. +func (c *AllocationsAggregatedListCall) Pages(ctx context.Context, f func(*AllocationAggregatedList) error) error { + c.ctx_ = ctx + defer c.PageToken(c.urlParams_.Get("pageToken")) // reset paging to original point + for { + x, err := c.Do() + if err != nil { + return err + } + if err := f(x); err != nil { + return err + } + if x.NextPageToken == "" { + return nil + } + c.PageToken(x.NextPageToken) + } +} + +// method id "compute.allocations.delete": + +type AllocationsDeleteCall struct { + s *Service + project string + zone string + allocation string + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// Delete: Deletes the specified allocation. +func (r *AllocationsService) Delete(project string, zone string, allocation string) *AllocationsDeleteCall { + c := &AllocationsDeleteCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.zone = zone + c.allocation = allocation + return c +} + +// RequestId sets the optional parameter "requestId": An optional +// request ID to identify requests. Specify a unique request ID so that +// if you must retry your request, the server will know to ignore the +// request if it has already been completed. +// +// For example, consider a situation where you make an initial request +// and the request times out. If you make the request again with the +// same request ID, the server can check if original operation with the +// same request ID was received, and if so, will ignore the second +// request. This prevents clients from accidentally creating duplicate +// commitments. +// +// The request ID must be a valid UUID with the exception that zero UUID +// is not supported (00000000-0000-0000-0000-000000000000). +func (c *AllocationsDeleteCall) RequestId(requestId string) *AllocationsDeleteCall { + c.urlParams_.Set("requestId", requestId) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *AllocationsDeleteCall) Fields(s ...googleapi.Field) *AllocationsDeleteCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *AllocationsDeleteCall) Context(ctx context.Context) *AllocationsDeleteCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *AllocationsDeleteCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *AllocationsDeleteCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/allocations/{allocation}") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "zone": c.zone, + "allocation": c.allocation, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.allocations.delete" call. +// Exactly one of *Operation or error will be non-nil. Any non-2xx +// status code is an error. Response headers are in either +// *Operation.ServerResponse.Header or (if a response was returned at +// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified +// to check whether the returned error was because +// http.StatusNotModified was returned. +func (c *AllocationsDeleteCall) Do(opts ...googleapi.CallOption) (*Operation, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Operation{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Deletes the specified allocation.", + // "httpMethod": "DELETE", + // "id": "compute.allocations.delete", + // "parameterOrder": [ + // "project", + // "zone", + // "allocation" + // ], + // "parameters": { + // "allocation": { + // "description": "Name of the allocation to delete.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // }, + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "requestId": { + // "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", + // "location": "query", + // "type": "string" + // }, + // "zone": { + // "description": "Name of the zone for this request.", // "location": "path", // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", // "required": true, // "type": "string" // } // }, - // "path": "{project}/regions/{region}/addresses/{resource}/testIamPermissions", + // "path": "{project}/zones/{zone}/allocations/{allocation}", + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + +// method id "compute.allocations.get": + +type AllocationsGetCall struct { + s *Service + project string + zone string + allocation string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// Get: Retrieves all information of the specified allocation. +func (r *AllocationsService) Get(project string, zone string, allocation string) *AllocationsGetCall { + c := &AllocationsGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.zone = zone + c.allocation = allocation + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *AllocationsGetCall) Fields(s ...googleapi.Field) *AllocationsGetCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// IfNoneMatch sets the optional parameter which makes the operation +// fail if the object's ETag matches the given value. This is useful for +// getting updates only after the object has changed since the last +// request. Use googleapi.IsNotModified to check whether the response +// error from Do is the result of In-None-Match. +func (c *AllocationsGetCall) IfNoneMatch(entityTag string) *AllocationsGetCall { + c.ifNoneMatch_ = entityTag + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *AllocationsGetCall) Context(ctx context.Context) *AllocationsGetCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *AllocationsGetCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *AllocationsGetCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + if c.ifNoneMatch_ != "" { + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) + } + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/allocations/{allocation}") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "zone": c.zone, + "allocation": c.allocation, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.allocations.get" call. +// Exactly one of *Allocation or error will be non-nil. Any non-2xx +// status code is an error. Response headers are in either +// *Allocation.ServerResponse.Header or (if a response was returned at +// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified +// to check whether the returned error was because +// http.StatusNotModified was returned. +func (c *AllocationsGetCall) Do(opts ...googleapi.CallOption) (*Allocation, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Allocation{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Retrieves all information of the specified allocation.", + // "httpMethod": "GET", + // "id": "compute.allocations.get", + // "parameterOrder": [ + // "project", + // "zone", + // "allocation" + // ], + // "parameters": { + // "allocation": { + // "description": "Name of the allocation to retrieve.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // }, + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "zone": { + // "description": "Name of the zone for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/zones/{zone}/allocations/{allocation}", + // "response": { + // "$ref": "Allocation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute", + // "https://www.googleapis.com/auth/compute.readonly" + // ] + // } + +} + +// method id "compute.allocations.getIamPolicy": + +type AllocationsGetIamPolicyCall struct { + s *Service + project string + zone string + resource string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// GetIamPolicy: Gets the access control policy for a resource. May be +// empty if no such policy or resource exists. +func (r *AllocationsService) GetIamPolicy(project string, zone string, resource string) *AllocationsGetIamPolicyCall { + c := &AllocationsGetIamPolicyCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.zone = zone + c.resource = resource + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *AllocationsGetIamPolicyCall) Fields(s ...googleapi.Field) *AllocationsGetIamPolicyCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// IfNoneMatch sets the optional parameter which makes the operation +// fail if the object's ETag matches the given value. This is useful for +// getting updates only after the object has changed since the last +// request. Use googleapi.IsNotModified to check whether the response +// error from Do is the result of In-None-Match. +func (c *AllocationsGetIamPolicyCall) IfNoneMatch(entityTag string) *AllocationsGetIamPolicyCall { + c.ifNoneMatch_ = entityTag + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *AllocationsGetIamPolicyCall) Context(ctx context.Context) *AllocationsGetIamPolicyCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *AllocationsGetIamPolicyCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *AllocationsGetIamPolicyCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + if c.ifNoneMatch_ != "" { + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) + } + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/allocations/{resource}/getIamPolicy") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "zone": c.zone, + "resource": c.resource, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.allocations.getIamPolicy" call. +// Exactly one of *Policy or error will be non-nil. Any non-2xx status +// code is an error. Response headers are in either +// *Policy.ServerResponse.Header or (if a response was returned at all) +// in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to +// check whether the returned error was because http.StatusNotModified +// was returned. +func (c *AllocationsGetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Policy, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Policy{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Gets the access control policy for a resource. May be empty if no such policy or resource exists.", + // "httpMethod": "GET", + // "id": "compute.allocations.getIamPolicy", + // "parameterOrder": [ + // "project", + // "zone", + // "resource" + // ], + // "parameters": { + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "resource": { + // "description": "Name or id of the resource for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + // "required": true, + // "type": "string" + // }, + // "zone": { + // "description": "The name of the zone for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/zones/{zone}/allocations/{resource}/getIamPolicy", + // "response": { + // "$ref": "Policy" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute", + // "https://www.googleapis.com/auth/compute.readonly" + // ] + // } + +} + +// method id "compute.allocations.insert": + +type AllocationsInsertCall struct { + s *Service + project string + zone string + allocation *Allocation + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// Insert: Creates a new allocation. +func (r *AllocationsService) Insert(project string, zone string, allocation *Allocation) *AllocationsInsertCall { + c := &AllocationsInsertCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.zone = zone + c.allocation = allocation + return c +} + +// RequestId sets the optional parameter "requestId": An optional +// request ID to identify requests. Specify a unique request ID so that +// if you must retry your request, the server will know to ignore the +// request if it has already been completed. +// +// For example, consider a situation where you make an initial request +// and the request times out. If you make the request again with the +// same request ID, the server can check if original operation with the +// same request ID was received, and if so, will ignore the second +// request. This prevents clients from accidentally creating duplicate +// commitments. +// +// The request ID must be a valid UUID with the exception that zero UUID +// is not supported (00000000-0000-0000-0000-000000000000). +func (c *AllocationsInsertCall) RequestId(requestId string) *AllocationsInsertCall { + c.urlParams_.Set("requestId", requestId) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *AllocationsInsertCall) Fields(s ...googleapi.Field) *AllocationsInsertCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *AllocationsInsertCall) Context(ctx context.Context) *AllocationsInsertCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *AllocationsInsertCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *AllocationsInsertCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.allocation) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/allocations") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "zone": c.zone, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.allocations.insert" call. +// Exactly one of *Operation or error will be non-nil. Any non-2xx +// status code is an error. Response headers are in either +// *Operation.ServerResponse.Header or (if a response was returned at +// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified +// to check whether the returned error was because +// http.StatusNotModified was returned. +func (c *AllocationsInsertCall) Do(opts ...googleapi.CallOption) (*Operation, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Operation{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Creates a new allocation.", + // "httpMethod": "POST", + // "id": "compute.allocations.insert", + // "parameterOrder": [ + // "project", + // "zone" + // ], + // "parameters": { + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "requestId": { + // "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", + // "location": "query", + // "type": "string" + // }, + // "zone": { + // "description": "Name of the zone for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/zones/{zone}/allocations", + // "request": { + // "$ref": "Allocation" + // }, + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + +// method id "compute.allocations.list": + +type AllocationsListCall struct { + s *Service + project string + zone string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// List: A list all the allocations that have been configured for the +// specified project in specified zone. +func (r *AllocationsService) List(project string, zone string) *AllocationsListCall { + c := &AllocationsListCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.zone = zone + return c +} + +// Filter sets the optional parameter "filter": A filter expression that +// filters resources listed in the response. The expression must specify +// the field name, a comparison operator, and the value that you want to +// use for filtering. The value must be a string, a number, or a +// boolean. The comparison operator must be either =, !=, >, or <. +// +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. +// +// You can also filter nested fields. For example, you could specify +// scheduling.automaticRestart = false to include instances only if they +// are not scheduled for automatic restarts. You can use filtering on +// nested fields to filter based on resource labels. +// +// To filter on multiple expressions, provide each separate expression +// within parentheses. For example, (scheduling.automaticRestart = true) +// (cpuPlatform = "Intel Skylake"). By default, each expression is an +// AND expression. However, you can include AND and OR expressions +// explicitly. For example, (cpuPlatform = "Intel Skylake") OR +// (cpuPlatform = "Intel Broadwell") AND (scheduling.automaticRestart = +// true). +func (c *AllocationsListCall) Filter(filter string) *AllocationsListCall { + c.urlParams_.Set("filter", filter) + return c +} + +// MaxResults sets the optional parameter "maxResults": The maximum +// number of results per page that should be returned. If the number of +// available results is larger than maxResults, Compute Engine returns a +// nextPageToken that can be used to get the next page of results in +// subsequent list requests. Acceptable values are 0 to 500, inclusive. +// (Default: 500) +func (c *AllocationsListCall) MaxResults(maxResults int64) *AllocationsListCall { + c.urlParams_.Set("maxResults", fmt.Sprint(maxResults)) + return c +} + +// OrderBy sets the optional parameter "orderBy": Sorts list results by +// a certain order. By default, results are returned in alphanumerical +// order based on the resource name. +// +// You can also sort results in descending order based on the creation +// timestamp using orderBy="creationTimestamp desc". This sorts results +// based on the creationTimestamp field in reverse chronological order +// (newest result first). Use this to sort resources like operations so +// that the newest operation is returned first. +// +// Currently, only sorting by name or creationTimestamp desc is +// supported. +func (c *AllocationsListCall) OrderBy(orderBy string) *AllocationsListCall { + c.urlParams_.Set("orderBy", orderBy) + return c +} + +// PageToken sets the optional parameter "pageToken": Specifies a page +// token to use. Set pageToken to the nextPageToken returned by a +// previous list request to get the next page of results. +func (c *AllocationsListCall) PageToken(pageToken string) *AllocationsListCall { + c.urlParams_.Set("pageToken", pageToken) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *AllocationsListCall) Fields(s ...googleapi.Field) *AllocationsListCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// IfNoneMatch sets the optional parameter which makes the operation +// fail if the object's ETag matches the given value. This is useful for +// getting updates only after the object has changed since the last +// request. Use googleapi.IsNotModified to check whether the response +// error from Do is the result of In-None-Match. +func (c *AllocationsListCall) IfNoneMatch(entityTag string) *AllocationsListCall { + c.ifNoneMatch_ = entityTag + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *AllocationsListCall) Context(ctx context.Context) *AllocationsListCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *AllocationsListCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *AllocationsListCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + if c.ifNoneMatch_ != "" { + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) + } + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/allocations") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "zone": c.zone, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.allocations.list" call. +// Exactly one of *AllocationList or error will be non-nil. Any non-2xx +// status code is an error. Response headers are in either +// *AllocationList.ServerResponse.Header or (if a response was returned +// at all) in error.(*googleapi.Error).Header. Use +// googleapi.IsNotModified to check whether the returned error was +// because http.StatusNotModified was returned. +func (c *AllocationsListCall) Do(opts ...googleapi.CallOption) (*AllocationList, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &AllocationList{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "A list all the allocations that have been configured for the specified project in specified zone.", + // "httpMethod": "GET", + // "id": "compute.allocations.list", + // "parameterOrder": [ + // "project", + // "zone" + // ], + // "parameters": { + // "filter": { + // "description": "A filter expression that filters resources listed in the response. The expression must specify the field name, a comparison operator, and the value that you want to use for filtering. The value must be a string, a number, or a boolean. The comparison operator must be either =, !=, \u003e, or \u003c.\n\nFor example, if you are filtering Compute Engine instances, you can exclude instances named example-instance by specifying name != example-instance.\n\nYou can also filter nested fields. For example, you could specify scheduling.automaticRestart = false to include instances only if they are not scheduled for automatic restarts. You can use filtering on nested fields to filter based on resource labels.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart = true) (cpuPlatform = \"Intel Skylake\"). By default, each expression is an AND expression. However, you can include AND and OR expressions explicitly. For example, (cpuPlatform = \"Intel Skylake\") OR (cpuPlatform = \"Intel Broadwell\") AND (scheduling.automaticRestart = true).", + // "location": "query", + // "type": "string" + // }, + // "maxResults": { + // "default": "500", + // "description": "The maximum number of results per page that should be returned. If the number of available results is larger than maxResults, Compute Engine returns a nextPageToken that can be used to get the next page of results in subsequent list requests. Acceptable values are 0 to 500, inclusive. (Default: 500)", + // "format": "uint32", + // "location": "query", + // "minimum": "0", + // "type": "integer" + // }, + // "orderBy": { + // "description": "Sorts list results by a certain order. By default, results are returned in alphanumerical order based on the resource name.\n\nYou can also sort results in descending order based on the creation timestamp using orderBy=\"creationTimestamp desc\". This sorts results based on the creationTimestamp field in reverse chronological order (newest result first). Use this to sort resources like operations so that the newest operation is returned first.\n\nCurrently, only sorting by name or creationTimestamp desc is supported.", + // "location": "query", + // "type": "string" + // }, + // "pageToken": { + // "description": "Specifies a page token to use. Set pageToken to the nextPageToken returned by a previous list request to get the next page of results.", + // "location": "query", + // "type": "string" + // }, + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "zone": { + // "description": "Name of the zone for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/zones/{zone}/allocations", + // "response": { + // "$ref": "AllocationList" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute", + // "https://www.googleapis.com/auth/compute.readonly" + // ] + // } + +} + +// Pages invokes f for each page of results. +// A non-nil error returned from f will halt the iteration. +// The provided context supersedes any context provided to the Context method. +func (c *AllocationsListCall) Pages(ctx context.Context, f func(*AllocationList) error) error { + c.ctx_ = ctx + defer c.PageToken(c.urlParams_.Get("pageToken")) // reset paging to original point + for { + x, err := c.Do() + if err != nil { + return err + } + if err := f(x); err != nil { + return err + } + if x.NextPageToken == "" { + return nil + } + c.PageToken(x.NextPageToken) + } +} + +// method id "compute.allocations.setIamPolicy": + +type AllocationsSetIamPolicyCall struct { + s *Service + project string + zone string + resource string + zonesetpolicyrequest *ZoneSetPolicyRequest + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// SetIamPolicy: Sets the access control policy on the specified +// resource. Replaces any existing policy. +func (r *AllocationsService) SetIamPolicy(project string, zone string, resource string, zonesetpolicyrequest *ZoneSetPolicyRequest) *AllocationsSetIamPolicyCall { + c := &AllocationsSetIamPolicyCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.zone = zone + c.resource = resource + c.zonesetpolicyrequest = zonesetpolicyrequest + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *AllocationsSetIamPolicyCall) Fields(s ...googleapi.Field) *AllocationsSetIamPolicyCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *AllocationsSetIamPolicyCall) Context(ctx context.Context) *AllocationsSetIamPolicyCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *AllocationsSetIamPolicyCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *AllocationsSetIamPolicyCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.zonesetpolicyrequest) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/allocations/{resource}/setIamPolicy") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "zone": c.zone, + "resource": c.resource, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.allocations.setIamPolicy" call. +// Exactly one of *Policy or error will be non-nil. Any non-2xx status +// code is an error. Response headers are in either +// *Policy.ServerResponse.Header or (if a response was returned at all) +// in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to +// check whether the returned error was because http.StatusNotModified +// was returned. +func (c *AllocationsSetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Policy, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Policy{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Sets the access control policy on the specified resource. Replaces any existing policy.", + // "httpMethod": "POST", + // "id": "compute.allocations.setIamPolicy", + // "parameterOrder": [ + // "project", + // "zone", + // "resource" + // ], + // "parameters": { + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "resource": { + // "description": "Name or id of the resource for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + // "required": true, + // "type": "string" + // }, + // "zone": { + // "description": "The name of the zone for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/zones/{zone}/allocations/{resource}/setIamPolicy", + // "request": { + // "$ref": "ZoneSetPolicyRequest" + // }, + // "response": { + // "$ref": "Policy" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + +// method id "compute.allocations.testIamPermissions": + +type AllocationsTestIamPermissionsCall struct { + s *Service + project string + zone string + resource string + testpermissionsrequest *TestPermissionsRequest + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// TestIamPermissions: Returns permissions that a caller has on the +// specified resource. +func (r *AllocationsService) TestIamPermissions(project string, zone string, resource string, testpermissionsrequest *TestPermissionsRequest) *AllocationsTestIamPermissionsCall { + c := &AllocationsTestIamPermissionsCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.zone = zone + c.resource = resource + c.testpermissionsrequest = testpermissionsrequest + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *AllocationsTestIamPermissionsCall) Fields(s ...googleapi.Field) *AllocationsTestIamPermissionsCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *AllocationsTestIamPermissionsCall) Context(ctx context.Context) *AllocationsTestIamPermissionsCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *AllocationsTestIamPermissionsCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *AllocationsTestIamPermissionsCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.testpermissionsrequest) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/allocations/{resource}/testIamPermissions") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "zone": c.zone, + "resource": c.resource, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.allocations.testIamPermissions" call. +// Exactly one of *TestPermissionsResponse or error will be non-nil. Any +// non-2xx status code is an error. Response headers are in either +// *TestPermissionsResponse.ServerResponse.Header or (if a response was +// returned at all) in error.(*googleapi.Error).Header. Use +// googleapi.IsNotModified to check whether the returned error was +// because http.StatusNotModified was returned. +func (c *AllocationsTestIamPermissionsCall) Do(opts ...googleapi.CallOption) (*TestPermissionsResponse, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &TestPermissionsResponse{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Returns permissions that a caller has on the specified resource.", + // "httpMethod": "POST", + // "id": "compute.allocations.testIamPermissions", + // "parameterOrder": [ + // "project", + // "zone", + // "resource" + // ], + // "parameters": { + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "resource": { + // "description": "Name or id of the resource for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + // "required": true, + // "type": "string" + // }, + // "zone": { + // "description": "The name of the zone for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/zones/{zone}/allocations/{resource}/testIamPermissions", // "request": { // "$ref": "TestPermissionsRequest" // }, @@ -32795,9 +37700,13 @@ func (c *AutoscalersAggregatedListCall) doRequest(alt string) (*http.Response, e } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/aggregated/autoscalers") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -32988,9 +37897,13 @@ func (c *AutoscalersDeleteCall) doRequest(alt string) (*http.Response, error) { reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/autoscalers/{autoscaler}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -33155,9 +38068,13 @@ func (c *AutoscalersGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/autoscalers/{autoscaler}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -33328,9 +38245,13 @@ func (c *AutoscalersInsertCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/autoscalers") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -33550,9 +38471,13 @@ func (c *AutoscalersListCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/autoscalers") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -33766,9 +38691,13 @@ func (c *AutoscalersPatchCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/autoscalers") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PATCH", urls, body) + req, err := http.NewRequest("PATCH", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -33926,9 +38855,13 @@ func (c *AutoscalersTestIamPermissionsCall) doRequest(alt string) (*http.Respons } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/autoscalers/{resource}/testIamPermissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -33993,9 +38926,9 @@ func (c *AutoscalersTestIamPermissionsCall) Do(opts ...googleapi.CallOption) (*T // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -34109,9 +39042,13 @@ func (c *AutoscalersUpdateCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/autoscalers") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PUT", urls, body) + req, err := http.NewRequest("PUT", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -34219,7 +39156,8 @@ type BackendBucketsAddSignedUrlKeyCall struct { header_ http.Header } -// AddSignedUrlKey: Adds the given Signed URL Key to the backend bucket. +// AddSignedUrlKey: Adds a key for validating requests with signed URLs +// for this backend bucket. func (r *BackendBucketsService) AddSignedUrlKey(project string, backendBucket string, signedurlkey *SignedUrlKey) *BackendBucketsAddSignedUrlKeyCall { c := &BackendBucketsAddSignedUrlKeyCall{s: r.s, urlParams_: make(gensupport.URLParams)} c.project = project @@ -34285,9 +39223,13 @@ func (c *BackendBucketsAddSignedUrlKeyCall) doRequest(alt string) (*http.Respons } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/backendBuckets/{backendBucket}/addSignedUrlKey") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -34334,7 +39276,7 @@ func (c *BackendBucketsAddSignedUrlKeyCall) Do(opts ...googleapi.CallOption) (*O } return ret, nil // { - // "description": "Adds the given Signed URL Key to the backend bucket.", + // "description": "Adds a key for validating requests with signed URLs for this backend bucket.", // "httpMethod": "POST", // "id": "compute.backendBuckets.addSignedUrlKey", // "parameterOrder": [ @@ -34447,9 +39389,13 @@ func (c *BackendBucketsDeleteCall) doRequest(alt string) (*http.Response, error) reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/backendBuckets/{backendBucket}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -34547,8 +39493,8 @@ type BackendBucketsDeleteSignedUrlKeyCall struct { header_ http.Header } -// DeleteSignedUrlKey: Deletes the given Signed URL Key from the backend -// bucket. +// DeleteSignedUrlKey: Deletes a key for validating requests with signed +// URLs for this backend bucket. func (r *BackendBucketsService) DeleteSignedUrlKey(project string, backendBucket string, keyName string) *BackendBucketsDeleteSignedUrlKeyCall { c := &BackendBucketsDeleteSignedUrlKeyCall{s: r.s, urlParams_: make(gensupport.URLParams)} c.project = project @@ -34609,9 +39555,13 @@ func (c *BackendBucketsDeleteSignedUrlKeyCall) doRequest(alt string) (*http.Resp reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/backendBuckets/{backendBucket}/deleteSignedUrlKey") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -34658,7 +39608,7 @@ func (c *BackendBucketsDeleteSignedUrlKeyCall) Do(opts ...googleapi.CallOption) } return ret, nil // { - // "description": "Deletes the given Signed URL Key from the backend bucket.", + // "description": "Deletes a key for validating requests with signed URLs for this backend bucket.", // "httpMethod": "POST", // "id": "compute.backendBuckets.deleteSignedUrlKey", // "parameterOrder": [ @@ -34771,9 +39721,13 @@ func (c *BackendBucketsGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/backendBuckets/{backendBucket}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -34933,9 +39887,13 @@ func (c *BackendBucketsInsertCall) doRequest(alt string) (*http.Response, error) } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/backendBuckets") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -35144,9 +40102,13 @@ func (c *BackendBucketsListCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/backendBuckets") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -35344,9 +40306,13 @@ func (c *BackendBucketsPatchCall) doRequest(alt string) (*http.Response, error) } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/backendBuckets/{backendBucket}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PATCH", urls, body) + req, err := http.NewRequest("PATCH", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -35515,9 +40481,13 @@ func (c *BackendBucketsUpdateCall) doRequest(alt string) (*http.Response, error) } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/backendBuckets/{backendBucket}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PUT", urls, body) + req, err := http.NewRequest("PUT", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -35619,8 +40589,8 @@ type BackendServicesAddSignedUrlKeyCall struct { header_ http.Header } -// AddSignedUrlKey: Adds the given Signed URL Key to the specified -// backend service. +// AddSignedUrlKey: Adds a key for validating requests with signed URLs +// for this backend service. func (r *BackendServicesService) AddSignedUrlKey(project string, backendService string, signedurlkey *SignedUrlKey) *BackendServicesAddSignedUrlKeyCall { c := &BackendServicesAddSignedUrlKeyCall{s: r.s, urlParams_: make(gensupport.URLParams)} c.project = project @@ -35686,9 +40656,13 @@ func (c *BackendServicesAddSignedUrlKeyCall) doRequest(alt string) (*http.Respon } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/backendServices/{backendService}/addSignedUrlKey") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -35735,7 +40709,7 @@ func (c *BackendServicesAddSignedUrlKeyCall) Do(opts ...googleapi.CallOption) (* } return ret, nil // { - // "description": "Adds the given Signed URL Key to the specified backend service.", + // "description": "Adds a key for validating requests with signed URLs for this backend service.", // "httpMethod": "POST", // "id": "compute.backendServices.addSignedUrlKey", // "parameterOrder": [ @@ -35905,9 +40879,13 @@ func (c *BackendServicesAggregatedListCall) doRequest(alt string) (*http.Respons } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/aggregated/backendServices") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -36097,9 +41075,13 @@ func (c *BackendServicesDeleteCall) doRequest(alt string) (*http.Response, error reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/backendServices/{backendService}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -36197,8 +41179,8 @@ type BackendServicesDeleteSignedUrlKeyCall struct { header_ http.Header } -// DeleteSignedUrlKey: Deletes the given Signed URL Key from the -// specified backend service. +// DeleteSignedUrlKey: Deletes a key for validating requests with signed +// URLs for this backend service. func (r *BackendServicesService) DeleteSignedUrlKey(project string, backendService string, keyName string) *BackendServicesDeleteSignedUrlKeyCall { c := &BackendServicesDeleteSignedUrlKeyCall{s: r.s, urlParams_: make(gensupport.URLParams)} c.project = project @@ -36259,9 +41241,13 @@ func (c *BackendServicesDeleteSignedUrlKeyCall) doRequest(alt string) (*http.Res reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/backendServices/{backendService}/deleteSignedUrlKey") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -36308,7 +41294,7 @@ func (c *BackendServicesDeleteSignedUrlKeyCall) Do(opts ...googleapi.CallOption) } return ret, nil // { - // "description": "Deletes the given Signed URL Key from the specified backend service.", + // "description": "Deletes a key for validating requests with signed URLs for this backend service.", // "httpMethod": "POST", // "id": "compute.backendServices.deleteSignedUrlKey", // "parameterOrder": [ @@ -36367,7 +41353,7 @@ type BackendServicesGetCall struct { } // Get: Returns the specified BackendService resource. Gets a list of -// available backend services by making a list() request. +// available backend services. // For details, see https://cloud.google.com/compute/docs/reference/latest/backendServices/get func (r *BackendServicesService) Get(project string, backendService string) *BackendServicesGetCall { c := &BackendServicesGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} @@ -36422,9 +41408,13 @@ func (c *BackendServicesGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/backendServices/{backendService}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -36471,7 +41461,7 @@ func (c *BackendServicesGetCall) Do(opts ...googleapi.CallOption) (*BackendServi } return ret, nil // { - // "description": "Returns the specified BackendService resource. Gets a list of available backend services by making a list() request.", + // "description": "Returns the specified BackendService resource. Gets a list of available backend services.", // "httpMethod": "GET", // "id": "compute.backendServices.get", // "parameterOrder": [ @@ -36568,9 +41558,13 @@ func (c *BackendServicesGetHealthCall) doRequest(alt string) (*http.Response, er } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/backendServices/{backendService}/getHealth") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -36735,9 +41729,13 @@ func (c *BackendServicesInsertCall) doRequest(alt string) (*http.Response, error } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/backendServices") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -36947,9 +41945,13 @@ func (c *BackendServicesListCall) doRequest(alt string) (*http.Response, error) } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/backendServices") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -37151,9 +42153,13 @@ func (c *BackendServicesPatchCall) doRequest(alt string) (*http.Response, error) } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/backendServices/{backendService}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PATCH", urls, body) + req, err := http.NewRequest("PATCH", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -37211,7 +42217,7 @@ func (c *BackendServicesPatchCall) Do(opts ...googleapi.CallOption) (*Operation, // "backendService": { // "description": "Name of the BackendService resource to patch.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -37322,9 +42328,13 @@ func (c *BackendServicesSetSecurityPolicyCall) doRequest(alt string) (*http.Resp } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/backendServices/{backendService}/setSecurityPolicy") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -37473,9 +42483,13 @@ func (c *BackendServicesTestIamPermissionsCall) doRequest(alt string) (*http.Res } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/backendServices/{resource}/testIamPermissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -37538,9 +42552,9 @@ func (c *BackendServicesTestIamPermissionsCall) Do(opts ...googleapi.CallOption) // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "(?:[-a-z0-9_]{0,62}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -37643,9 +42657,13 @@ func (c *BackendServicesUpdateCall) doRequest(alt string) (*http.Response, error } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/backendServices/{backendService}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PUT", urls, body) + req, err := http.NewRequest("PUT", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -37863,9 +42881,13 @@ func (c *DiskTypesAggregatedListCall) doRequest(alt string) (*http.Response, err } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/aggregated/diskTypes") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -38053,9 +43075,13 @@ func (c *DiskTypesGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/diskTypes/{diskType}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -38278,9 +43304,13 @@ func (c *DiskTypesListCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/diskTypes") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -38407,6 +43437,193 @@ func (c *DiskTypesListCall) Pages(ctx context.Context, f func(*DiskTypeList) err } } +// method id "compute.disks.addResourcePolicies": + +type DisksAddResourcePoliciesCall struct { + s *Service + project string + zone string + disk string + disksaddresourcepoliciesrequest *DisksAddResourcePoliciesRequest + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// AddResourcePolicies: Adds existing resource policies to a disk. You +// can only add one policy which will be applied to this disk for +// scheduling snapshot creation. +func (r *DisksService) AddResourcePolicies(project string, zone string, disk string, disksaddresourcepoliciesrequest *DisksAddResourcePoliciesRequest) *DisksAddResourcePoliciesCall { + c := &DisksAddResourcePoliciesCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.zone = zone + c.disk = disk + c.disksaddresourcepoliciesrequest = disksaddresourcepoliciesrequest + return c +} + +// RequestId sets the optional parameter "requestId": An optional +// request ID to identify requests. Specify a unique request ID so that +// if you must retry your request, the server will know to ignore the +// request if it has already been completed. +// +// For example, consider a situation where you make an initial request +// and the request times out. If you make the request again with the +// same request ID, the server can check if original operation with the +// same request ID was received, and if so, will ignore the second +// request. This prevents clients from accidentally creating duplicate +// commitments. +// +// The request ID must be a valid UUID with the exception that zero UUID +// is not supported (00000000-0000-0000-0000-000000000000). +func (c *DisksAddResourcePoliciesCall) RequestId(requestId string) *DisksAddResourcePoliciesCall { + c.urlParams_.Set("requestId", requestId) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *DisksAddResourcePoliciesCall) Fields(s ...googleapi.Field) *DisksAddResourcePoliciesCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *DisksAddResourcePoliciesCall) Context(ctx context.Context) *DisksAddResourcePoliciesCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *DisksAddResourcePoliciesCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *DisksAddResourcePoliciesCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.disksaddresourcepoliciesrequest) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/disks/{disk}/addResourcePolicies") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "zone": c.zone, + "disk": c.disk, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.disks.addResourcePolicies" call. +// Exactly one of *Operation or error will be non-nil. Any non-2xx +// status code is an error. Response headers are in either +// *Operation.ServerResponse.Header or (if a response was returned at +// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified +// to check whether the returned error was because +// http.StatusNotModified was returned. +func (c *DisksAddResourcePoliciesCall) Do(opts ...googleapi.CallOption) (*Operation, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Operation{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Adds existing resource policies to a disk. You can only add one policy which will be applied to this disk for scheduling snapshot creation.", + // "httpMethod": "POST", + // "id": "compute.disks.addResourcePolicies", + // "parameterOrder": [ + // "project", + // "zone", + // "disk" + // ], + // "parameters": { + // "disk": { + // "description": "The disk name for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + // "required": true, + // "type": "string" + // }, + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "requestId": { + // "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", + // "location": "query", + // "type": "string" + // }, + // "zone": { + // "description": "The name of the zone for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/zones/{zone}/disks/{disk}/addResourcePolicies", + // "request": { + // "$ref": "DisksAddResourcePoliciesRequest" + // }, + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + // method id "compute.disks.aggregatedList": type DisksAggregatedListCall struct { @@ -38535,9 +43752,13 @@ func (c *DisksAggregatedListCall) doRequest(alt string) (*http.Response, error) } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/aggregated/disks") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -38742,9 +43963,13 @@ func (c *DisksCreateSnapshotCall) doRequest(alt string) (*http.Response, error) } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/disks/{disk}/createSnapshot") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -38804,7 +44029,7 @@ func (c *DisksCreateSnapshotCall) Do(opts ...googleapi.CallOption) (*Operation, // "disk": { // "description": "Name of the persistent disk to snapshot.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -38924,9 +44149,13 @@ func (c *DisksDeleteCall) doRequest(alt string) (*http.Response, error) { reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/disks/{disk}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -39091,9 +44320,13 @@ func (c *DisksGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/disks/{disk}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -39153,7 +44386,7 @@ func (c *DisksGetCall) Do(opts ...googleapi.CallOption) (*Disk, error) { // "disk": { // "description": "Name of the persistent disk to return.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -39185,6 +44418,173 @@ func (c *DisksGetCall) Do(opts ...googleapi.CallOption) (*Disk, error) { } +// method id "compute.disks.getIamPolicy": + +type DisksGetIamPolicyCall struct { + s *Service + project string + zone string + resource string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// GetIamPolicy: Gets the access control policy for a resource. May be +// empty if no such policy or resource exists. +func (r *DisksService) GetIamPolicy(project string, zone string, resource string) *DisksGetIamPolicyCall { + c := &DisksGetIamPolicyCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.zone = zone + c.resource = resource + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *DisksGetIamPolicyCall) Fields(s ...googleapi.Field) *DisksGetIamPolicyCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// IfNoneMatch sets the optional parameter which makes the operation +// fail if the object's ETag matches the given value. This is useful for +// getting updates only after the object has changed since the last +// request. Use googleapi.IsNotModified to check whether the response +// error from Do is the result of In-None-Match. +func (c *DisksGetIamPolicyCall) IfNoneMatch(entityTag string) *DisksGetIamPolicyCall { + c.ifNoneMatch_ = entityTag + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *DisksGetIamPolicyCall) Context(ctx context.Context) *DisksGetIamPolicyCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *DisksGetIamPolicyCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *DisksGetIamPolicyCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + if c.ifNoneMatch_ != "" { + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) + } + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/disks/{resource}/getIamPolicy") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "zone": c.zone, + "resource": c.resource, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.disks.getIamPolicy" call. +// Exactly one of *Policy or error will be non-nil. Any non-2xx status +// code is an error. Response headers are in either +// *Policy.ServerResponse.Header or (if a response was returned at all) +// in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to +// check whether the returned error was because http.StatusNotModified +// was returned. +func (c *DisksGetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Policy, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Policy{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Gets the access control policy for a resource. May be empty if no such policy or resource exists.", + // "httpMethod": "GET", + // "id": "compute.disks.getIamPolicy", + // "parameterOrder": [ + // "project", + // "zone", + // "resource" + // ], + // "parameters": { + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "resource": { + // "description": "Name or id of the resource for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + // "required": true, + // "type": "string" + // }, + // "zone": { + // "description": "The name of the zone for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/zones/{zone}/disks/{resource}/getIamPolicy", + // "response": { + // "$ref": "Policy" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute", + // "https://www.googleapis.com/auth/compute.readonly" + // ] + // } + +} + // method id "compute.disks.insert": type DisksInsertCall struct { @@ -39275,9 +44675,13 @@ func (c *DisksInsertCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/disks") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -39503,9 +44907,13 @@ func (c *DisksListCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/disks") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -39632,6 +45040,191 @@ func (c *DisksListCall) Pages(ctx context.Context, f func(*DiskList) error) erro } } +// method id "compute.disks.removeResourcePolicies": + +type DisksRemoveResourcePoliciesCall struct { + s *Service + project string + zone string + disk string + disksremoveresourcepoliciesrequest *DisksRemoveResourcePoliciesRequest + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// RemoveResourcePolicies: Removes resource policies from a disk. +func (r *DisksService) RemoveResourcePolicies(project string, zone string, disk string, disksremoveresourcepoliciesrequest *DisksRemoveResourcePoliciesRequest) *DisksRemoveResourcePoliciesCall { + c := &DisksRemoveResourcePoliciesCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.zone = zone + c.disk = disk + c.disksremoveresourcepoliciesrequest = disksremoveresourcepoliciesrequest + return c +} + +// RequestId sets the optional parameter "requestId": An optional +// request ID to identify requests. Specify a unique request ID so that +// if you must retry your request, the server will know to ignore the +// request if it has already been completed. +// +// For example, consider a situation where you make an initial request +// and the request times out. If you make the request again with the +// same request ID, the server can check if original operation with the +// same request ID was received, and if so, will ignore the second +// request. This prevents clients from accidentally creating duplicate +// commitments. +// +// The request ID must be a valid UUID with the exception that zero UUID +// is not supported (00000000-0000-0000-0000-000000000000). +func (c *DisksRemoveResourcePoliciesCall) RequestId(requestId string) *DisksRemoveResourcePoliciesCall { + c.urlParams_.Set("requestId", requestId) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *DisksRemoveResourcePoliciesCall) Fields(s ...googleapi.Field) *DisksRemoveResourcePoliciesCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *DisksRemoveResourcePoliciesCall) Context(ctx context.Context) *DisksRemoveResourcePoliciesCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *DisksRemoveResourcePoliciesCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *DisksRemoveResourcePoliciesCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.disksremoveresourcepoliciesrequest) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/disks/{disk}/removeResourcePolicies") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "zone": c.zone, + "disk": c.disk, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.disks.removeResourcePolicies" call. +// Exactly one of *Operation or error will be non-nil. Any non-2xx +// status code is an error. Response headers are in either +// *Operation.ServerResponse.Header or (if a response was returned at +// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified +// to check whether the returned error was because +// http.StatusNotModified was returned. +func (c *DisksRemoveResourcePoliciesCall) Do(opts ...googleapi.CallOption) (*Operation, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Operation{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Removes resource policies from a disk.", + // "httpMethod": "POST", + // "id": "compute.disks.removeResourcePolicies", + // "parameterOrder": [ + // "project", + // "zone", + // "disk" + // ], + // "parameters": { + // "disk": { + // "description": "The disk name for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + // "required": true, + // "type": "string" + // }, + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "requestId": { + // "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", + // "location": "query", + // "type": "string" + // }, + // "zone": { + // "description": "The name of the zone for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/zones/{zone}/disks/{disk}/removeResourcePolicies", + // "request": { + // "$ref": "DisksRemoveResourcePoliciesRequest" + // }, + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + // method id "compute.disks.resize": type DisksResizeCall struct { @@ -39713,9 +45306,13 @@ func (c *DisksResizeCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/disks/{disk}/resize") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -39775,7 +45372,7 @@ func (c *DisksResizeCall) Do(opts ...googleapi.CallOption) (*Operation, error) { // "disk": { // "description": "The name of the persistent disk.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -39814,6 +45411,168 @@ func (c *DisksResizeCall) Do(opts ...googleapi.CallOption) (*Operation, error) { } +// method id "compute.disks.setIamPolicy": + +type DisksSetIamPolicyCall struct { + s *Service + project string + zone string + resource string + zonesetpolicyrequest *ZoneSetPolicyRequest + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// SetIamPolicy: Sets the access control policy on the specified +// resource. Replaces any existing policy. +func (r *DisksService) SetIamPolicy(project string, zone string, resource string, zonesetpolicyrequest *ZoneSetPolicyRequest) *DisksSetIamPolicyCall { + c := &DisksSetIamPolicyCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.zone = zone + c.resource = resource + c.zonesetpolicyrequest = zonesetpolicyrequest + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *DisksSetIamPolicyCall) Fields(s ...googleapi.Field) *DisksSetIamPolicyCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *DisksSetIamPolicyCall) Context(ctx context.Context) *DisksSetIamPolicyCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *DisksSetIamPolicyCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *DisksSetIamPolicyCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.zonesetpolicyrequest) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/disks/{resource}/setIamPolicy") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "zone": c.zone, + "resource": c.resource, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.disks.setIamPolicy" call. +// Exactly one of *Policy or error will be non-nil. Any non-2xx status +// code is an error. Response headers are in either +// *Policy.ServerResponse.Header or (if a response was returned at all) +// in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to +// check whether the returned error was because http.StatusNotModified +// was returned. +func (c *DisksSetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Policy, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Policy{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Sets the access control policy on the specified resource. Replaces any existing policy.", + // "httpMethod": "POST", + // "id": "compute.disks.setIamPolicy", + // "parameterOrder": [ + // "project", + // "zone", + // "resource" + // ], + // "parameters": { + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "resource": { + // "description": "Name or id of the resource for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + // "required": true, + // "type": "string" + // }, + // "zone": { + // "description": "The name of the zone for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/zones/{zone}/disks/{resource}/setIamPolicy", + // "request": { + // "$ref": "ZoneSetPolicyRequest" + // }, + // "response": { + // "$ref": "Policy" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + // method id "compute.disks.setLabels": type DisksSetLabelsCall struct { @@ -39895,9 +45654,13 @@ func (c *DisksSetLabelsCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/disks/{resource}/setLabels") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -39967,9 +45730,9 @@ func (c *DisksSetLabelsCall) Do(opts ...googleapi.CallOption) (*Operation, error // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -40058,9 +45821,13 @@ func (c *DisksTestIamPermissionsCall) doRequest(alt string) (*http.Response, err } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/disks/{resource}/testIamPermissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -40125,9 +45892,9 @@ func (c *DisksTestIamPermissionsCall) Do(opts ...googleapi.CallOption) (*TestPer // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -40227,9 +45994,13 @@ func (c *FirewallsDeleteCall) doRequest(alt string) (*http.Response, error) { reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/firewalls/{firewall}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -40287,7 +46058,7 @@ func (c *FirewallsDeleteCall) Do(opts ...googleapi.CallOption) (*Operation, erro // "firewall": { // "description": "Name of the firewall rule to delete.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -40383,9 +46154,13 @@ func (c *FirewallsGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/firewalls/{firewall}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -40443,7 +46218,7 @@ func (c *FirewallsGetCall) Do(opts ...googleapi.CallOption) (*Firewall, error) { // "firewall": { // "description": "Name of the firewall rule to return.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -40546,9 +46321,13 @@ func (c *FirewallsInsertCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/firewalls") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -40758,9 +46537,13 @@ func (c *FirewallsListCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/firewalls") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -40959,9 +46742,13 @@ func (c *FirewallsPatchCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/firewalls/{firewall}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PATCH", urls, body) + req, err := http.NewRequest("PATCH", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -41019,7 +46806,7 @@ func (c *FirewallsPatchCall) Do(opts ...googleapi.CallOption) (*Operation, error // "firewall": { // "description": "Name of the firewall rule to patch.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -41111,9 +46898,13 @@ func (c *FirewallsTestIamPermissionsCall) doRequest(alt string) (*http.Response, } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/firewalls/{resource}/testIamPermissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -41176,9 +46967,9 @@ func (c *FirewallsTestIamPermissionsCall) Do(opts ...googleapi.CallOption) (*Tes // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "(?:[-a-z0-9_]{0,62}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -41281,9 +47072,13 @@ func (c *FirewallsUpdateCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/firewalls/{firewall}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PUT", urls, body) + req, err := http.NewRequest("PUT", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -41341,7 +47136,7 @@ func (c *FirewallsUpdateCall) Do(opts ...googleapi.CallOption) (*Operation, erro // "firewall": { // "description": "Name of the firewall rule to update.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -41501,9 +47296,13 @@ func (c *ForwardingRulesAggregatedListCall) doRequest(alt string) (*http.Respons } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/aggregated/forwardingRules") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -41695,9 +47494,13 @@ func (c *ForwardingRulesDeleteCall) doRequest(alt string) (*http.Response, error reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/forwardingRules/{forwardingRule}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -41862,9 +47665,13 @@ func (c *ForwardingRulesGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/forwardingRules/{forwardingRule}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -42036,9 +47843,13 @@ func (c *ForwardingRulesInsertCall) doRequest(alt string) (*http.Response, error } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/forwardingRules") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -42259,9 +48070,13 @@ func (c *ForwardingRulesListCall) doRequest(alt string) (*http.Response, error) } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/forwardingRules") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -42469,9 +48284,13 @@ func (c *ForwardingRulesSetLabelsCall) doRequest(alt string) (*http.Response, er } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/forwardingRules/{resource}/setLabels") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -42548,9 +48367,9 @@ func (c *ForwardingRulesSetLabelsCall) Do(opts ...googleapi.CallOption) (*Operat // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -42652,9 +48471,13 @@ func (c *ForwardingRulesSetTargetCall) doRequest(alt string) (*http.Response, er } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/forwardingRules/{forwardingRule}/setTarget") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -42815,9 +48638,13 @@ func (c *ForwardingRulesTestIamPermissionsCall) doRequest(alt string) (*http.Res } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/forwardingRules/{resource}/testIamPermissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -42889,9 +48716,9 @@ func (c *ForwardingRulesTestIamPermissionsCall) Do(opts ...googleapi.CallOption) // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -42984,9 +48811,13 @@ func (c *GlobalAddressesDeleteCall) doRequest(alt string) (*http.Response, error reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/addresses/{address}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -43141,9 +48972,13 @@ func (c *GlobalAddressesGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/addresses/{address}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -43304,9 +49139,13 @@ func (c *GlobalAddressesInsertCall) doRequest(alt string) (*http.Response, error } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/addresses") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -43515,9 +49354,13 @@ func (c *GlobalAddressesListCall) doRequest(alt string) (*http.Response, error) } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/addresses") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -43695,9 +49538,13 @@ func (c *GlobalAddressesSetLabelsCall) doRequest(alt string) (*http.Response, er } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/addresses/{resource}/setLabels") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -43760,9 +49607,9 @@ func (c *GlobalAddressesSetLabelsCall) Do(opts ...googleapi.CallOption) (*Operat // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -43842,9 +49689,13 @@ func (c *GlobalAddressesTestIamPermissionsCall) doRequest(alt string) (*http.Res } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/addresses/{resource}/testIamPermissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -43907,9 +49758,9 @@ func (c *GlobalAddressesTestIamPermissionsCall) Do(opts ...googleapi.CallOption) // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "(?:[-a-z0-9_]{0,62}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -44002,9 +49853,13 @@ func (c *GlobalForwardingRulesDeleteCall) doRequest(alt string) (*http.Response, reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/forwardingRules/{forwardingRule}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -44159,9 +50014,13 @@ func (c *GlobalForwardingRulesGetCall) doRequest(alt string) (*http.Response, er } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/forwardingRules/{forwardingRule}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -44322,9 +50181,13 @@ func (c *GlobalForwardingRulesInsertCall) doRequest(alt string) (*http.Response, } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/forwardingRules") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -44534,9 +50397,13 @@ func (c *GlobalForwardingRulesListCall) doRequest(alt string) (*http.Response, e } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/forwardingRules") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -44714,9 +50581,13 @@ func (c *GlobalForwardingRulesSetLabelsCall) doRequest(alt string) (*http.Respon } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/forwardingRules/{resource}/setLabels") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -44779,9 +50650,9 @@ func (c *GlobalForwardingRulesSetLabelsCall) Do(opts ...googleapi.CallOption) (* // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -44881,9 +50752,13 @@ func (c *GlobalForwardingRulesSetTargetCall) doRequest(alt string) (*http.Respon } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/forwardingRules/{forwardingRule}/setTarget") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -45033,9 +50908,13 @@ func (c *GlobalForwardingRulesTestIamPermissionsCall) doRequest(alt string) (*ht } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/forwardingRules/{resource}/testIamPermissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -45098,9 +50977,9 @@ func (c *GlobalForwardingRulesTestIamPermissionsCall) Do(opts ...googleapi.CallO // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "(?:[-a-z0-9_]{0,62}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -45249,9 +51128,13 @@ func (c *GlobalOperationsAggregatedListCall) doRequest(alt string) (*http.Respon } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/aggregated/operations") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -45422,9 +51305,13 @@ func (c *GlobalOperationsDeleteCall) doRequest(alt string) (*http.Response, erro reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/operations/{operation}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -45546,9 +51433,13 @@ func (c *GlobalOperationsGetCall) doRequest(alt string) (*http.Response, error) } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/operations/{operation}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -45760,9 +51651,13 @@ func (c *GlobalOperationsListCall) doRequest(alt string) (*http.Response, error) } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/operations") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -45951,9 +51846,13 @@ func (c *HealthChecksDeleteCall) doRequest(alt string) (*http.Response, error) { reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/healthChecks/{healthCheck}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -46107,9 +52006,13 @@ func (c *HealthChecksGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/healthChecks/{healthCheck}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -46269,9 +52172,13 @@ func (c *HealthChecksInsertCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/healthChecks") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -46480,9 +52387,13 @@ func (c *HealthChecksListCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/healthChecks") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -46680,9 +52591,13 @@ func (c *HealthChecksPatchCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/healthChecks/{healthCheck}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PATCH", urls, body) + req, err := http.NewRequest("PATCH", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -46832,9 +52747,13 @@ func (c *HealthChecksTestIamPermissionsCall) doRequest(alt string) (*http.Respon } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/healthChecks/{resource}/testIamPermissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -46897,9 +52816,9 @@ func (c *HealthChecksTestIamPermissionsCall) Do(opts ...googleapi.CallOption) (* // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "(?:[-a-z0-9_]{0,62}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -46999,9 +52918,13 @@ func (c *HealthChecksUpdateCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/healthChecks/{healthCheck}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PUT", urls, body) + req, err := http.NewRequest("PUT", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -47163,9 +53086,13 @@ func (c *HttpHealthChecksDeleteCall) doRequest(alt string) (*http.Response, erro reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/httpHealthChecks/{httpHealthCheck}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -47320,9 +53247,13 @@ func (c *HttpHealthChecksGetCall) doRequest(alt string) (*http.Response, error) } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/httpHealthChecks/{httpHealthCheck}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -47483,9 +53414,13 @@ func (c *HttpHealthChecksInsertCall) doRequest(alt string) (*http.Response, erro } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/httpHealthChecks") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -47695,9 +53630,13 @@ func (c *HttpHealthChecksListCall) doRequest(alt string) (*http.Response, error) } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/httpHealthChecks") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -47896,9 +53835,13 @@ func (c *HttpHealthChecksPatchCall) doRequest(alt string) (*http.Response, error } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/httpHealthChecks/{httpHealthCheck}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PATCH", urls, body) + req, err := http.NewRequest("PATCH", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -48048,9 +53991,13 @@ func (c *HttpHealthChecksTestIamPermissionsCall) doRequest(alt string) (*http.Re } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/httpHealthChecks/{resource}/testIamPermissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -48113,9 +54060,9 @@ func (c *HttpHealthChecksTestIamPermissionsCall) Do(opts ...googleapi.CallOption // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "(?:[-a-z0-9_]{0,62}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -48216,9 +54163,13 @@ func (c *HttpHealthChecksUpdateCall) doRequest(alt string) (*http.Response, erro } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/httpHealthChecks/{httpHealthCheck}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PUT", urls, body) + req, err := http.NewRequest("PUT", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -48379,9 +54330,13 @@ func (c *HttpsHealthChecksDeleteCall) doRequest(alt string) (*http.Response, err reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/httpsHealthChecks/{httpsHealthCheck}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -48535,9 +54490,13 @@ func (c *HttpsHealthChecksGetCall) doRequest(alt string) (*http.Response, error) } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/httpsHealthChecks/{httpsHealthCheck}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -48697,9 +54656,13 @@ func (c *HttpsHealthChecksInsertCall) doRequest(alt string) (*http.Response, err } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/httpsHealthChecks") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -48908,9 +54871,13 @@ func (c *HttpsHealthChecksListCall) doRequest(alt string) (*http.Response, error } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/httpsHealthChecks") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -49108,9 +55075,13 @@ func (c *HttpsHealthChecksPatchCall) doRequest(alt string) (*http.Response, erro } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/httpsHealthChecks/{httpsHealthCheck}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PATCH", urls, body) + req, err := http.NewRequest("PATCH", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -49260,9 +55231,13 @@ func (c *HttpsHealthChecksTestIamPermissionsCall) doRequest(alt string) (*http.R } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/httpsHealthChecks/{resource}/testIamPermissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -49325,9 +55300,9 @@ func (c *HttpsHealthChecksTestIamPermissionsCall) Do(opts ...googleapi.CallOptio // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "(?:[-a-z0-9_]{0,62}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -49427,9 +55402,13 @@ func (c *HttpsHealthChecksUpdateCall) doRequest(alt string) (*http.Response, err } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/httpsHealthChecks/{httpsHealthCheck}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PUT", urls, body) + req, err := http.NewRequest("PUT", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -49591,9 +55570,13 @@ func (c *ImagesDeleteCall) doRequest(alt string) (*http.Response, error) { reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/images/{image}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -49651,7 +55634,7 @@ func (c *ImagesDeleteCall) Do(opts ...googleapi.CallOption) (*Operation, error) // "image": { // "description": "Name of the image resource to delete.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -49762,9 +55745,13 @@ func (c *ImagesDeprecateCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/images/{image}/deprecate") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -49822,7 +55809,7 @@ func (c *ImagesDeprecateCall) Do(opts ...googleapi.CallOption) (*Operation, erro // "image": { // "description": "Image name.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -49922,9 +55909,13 @@ func (c *ImagesGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/images/{image}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -49982,7 +55973,7 @@ func (c *ImagesGetCall) Do(opts ...googleapi.CallOption) (*Image, error) { // "image": { // "description": "Name of the image resource to return.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -50074,9 +56065,13 @@ func (c *ImagesGetFromFamilyCall) doRequest(alt string) (*http.Response, error) } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/images/family/{family}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -50134,7 +56129,7 @@ func (c *ImagesGetFromFamilyCall) Do(opts ...googleapi.CallOption) (*Image, erro // "family": { // "description": "Name of the image family to search for.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -50159,6 +56154,162 @@ func (c *ImagesGetFromFamilyCall) Do(opts ...googleapi.CallOption) (*Image, erro } +// method id "compute.images.getIamPolicy": + +type ImagesGetIamPolicyCall struct { + s *Service + project string + resource string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// GetIamPolicy: Gets the access control policy for a resource. May be +// empty if no such policy or resource exists. +func (r *ImagesService) GetIamPolicy(project string, resource string) *ImagesGetIamPolicyCall { + c := &ImagesGetIamPolicyCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.resource = resource + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *ImagesGetIamPolicyCall) Fields(s ...googleapi.Field) *ImagesGetIamPolicyCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// IfNoneMatch sets the optional parameter which makes the operation +// fail if the object's ETag matches the given value. This is useful for +// getting updates only after the object has changed since the last +// request. Use googleapi.IsNotModified to check whether the response +// error from Do is the result of In-None-Match. +func (c *ImagesGetIamPolicyCall) IfNoneMatch(entityTag string) *ImagesGetIamPolicyCall { + c.ifNoneMatch_ = entityTag + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *ImagesGetIamPolicyCall) Context(ctx context.Context) *ImagesGetIamPolicyCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *ImagesGetIamPolicyCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *ImagesGetIamPolicyCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + if c.ifNoneMatch_ != "" { + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) + } + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/images/{resource}/getIamPolicy") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "resource": c.resource, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.images.getIamPolicy" call. +// Exactly one of *Policy or error will be non-nil. Any non-2xx status +// code is an error. Response headers are in either +// *Policy.ServerResponse.Header or (if a response was returned at all) +// in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to +// check whether the returned error was because http.StatusNotModified +// was returned. +func (c *ImagesGetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Policy, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Policy{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Gets the access control policy for a resource. May be empty if no such policy or resource exists.", + // "httpMethod": "GET", + // "id": "compute.images.getIamPolicy", + // "parameterOrder": [ + // "project", + // "resource" + // ], + // "parameters": { + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "resource": { + // "description": "Name or id of the resource for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/global/images/{resource}/getIamPolicy", + // "response": { + // "$ref": "Policy" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute", + // "https://www.googleapis.com/auth/compute.readonly" + // ] + // } + +} + // method id "compute.images.insert": type ImagesInsertCall struct { @@ -50244,9 +56395,13 @@ func (c *ImagesInsertCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/images") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -50469,9 +56624,13 @@ func (c *ImagesListCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/images") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -50589,6 +56748,157 @@ func (c *ImagesListCall) Pages(ctx context.Context, f func(*ImageList) error) er } } +// method id "compute.images.setIamPolicy": + +type ImagesSetIamPolicyCall struct { + s *Service + project string + resource string + globalsetpolicyrequest *GlobalSetPolicyRequest + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// SetIamPolicy: Sets the access control policy on the specified +// resource. Replaces any existing policy. +func (r *ImagesService) SetIamPolicy(project string, resource string, globalsetpolicyrequest *GlobalSetPolicyRequest) *ImagesSetIamPolicyCall { + c := &ImagesSetIamPolicyCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.resource = resource + c.globalsetpolicyrequest = globalsetpolicyrequest + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *ImagesSetIamPolicyCall) Fields(s ...googleapi.Field) *ImagesSetIamPolicyCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *ImagesSetIamPolicyCall) Context(ctx context.Context) *ImagesSetIamPolicyCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *ImagesSetIamPolicyCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *ImagesSetIamPolicyCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.globalsetpolicyrequest) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/images/{resource}/setIamPolicy") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "resource": c.resource, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.images.setIamPolicy" call. +// Exactly one of *Policy or error will be non-nil. Any non-2xx status +// code is an error. Response headers are in either +// *Policy.ServerResponse.Header or (if a response was returned at all) +// in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to +// check whether the returned error was because http.StatusNotModified +// was returned. +func (c *ImagesSetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Policy, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Policy{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Sets the access control policy on the specified resource. Replaces any existing policy.", + // "httpMethod": "POST", + // "id": "compute.images.setIamPolicy", + // "parameterOrder": [ + // "project", + // "resource" + // ], + // "parameters": { + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "resource": { + // "description": "Name or id of the resource for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/global/images/{resource}/setIamPolicy", + // "request": { + // "$ref": "GlobalSetPolicyRequest" + // }, + // "response": { + // "$ref": "Policy" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + // method id "compute.images.setLabels": type ImagesSetLabelsCall struct { @@ -50649,9 +56959,13 @@ func (c *ImagesSetLabelsCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/images/{resource}/setLabels") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -50714,9 +57028,9 @@ func (c *ImagesSetLabelsCall) Do(opts ...googleapi.CallOption) (*Operation, erro // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -50796,9 +57110,13 @@ func (c *ImagesTestIamPermissionsCall) doRequest(alt string) (*http.Response, er } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/images/{resource}/testIamPermissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -50861,9 +57179,9 @@ func (c *ImagesTestIamPermissionsCall) Do(opts ...googleapi.CallOption) (*TestPe // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "(?:[-a-z0-9_]{0,62}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -50897,15 +57215,15 @@ type InstanceGroupManagersAbandonInstancesCall struct { header_ http.Header } -// AbandonInstances: Schedules a group action to remove the specified -// instances from the managed instance group. Abandoning an instance -// does not delete the instance, but it does remove the instance from -// any target pools that are applied by the managed instance group. This -// method reduces the targetSize of the managed instance group by the -// number of instances that you abandon. This operation is marked as -// DONE when the action is scheduled even if the instances have not yet -// been removed from the group. You must separately verify the status of -// the abandoning action with the listmanagedinstances method. +// AbandonInstances: Flags the specified instances to be removed from +// the managed instance group. Abandoning an instance does not delete +// the instance, but it does remove the instance from any target pools +// that are applied by the managed instance group. This method reduces +// the targetSize of the managed instance group by the number of +// instances that you abandon. This operation is marked as DONE when the +// action is scheduled even if the instances have not yet been removed +// from the group. You must separately verify the status of the +// abandoning action with the listmanagedinstances method. // // If the group is part of a backend service that has enabled connection // draining, it can take up to 60 seconds after the connection draining @@ -50980,9 +57298,13 @@ func (c *InstanceGroupManagersAbandonInstancesCall) doRequest(alt string) (*http } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instanceGroupManagers/{instanceGroupManager}/abandonInstances") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -51030,7 +57352,7 @@ func (c *InstanceGroupManagersAbandonInstancesCall) Do(opts ...googleapi.CallOpt } return ret, nil // { - // "description": "Schedules a group action to remove the specified instances from the managed instance group. Abandoning an instance does not delete the instance, but it does remove the instance from any target pools that are applied by the managed instance group. This method reduces the targetSize of the managed instance group by the number of instances that you abandon. This operation is marked as DONE when the action is scheduled even if the instances have not yet been removed from the group. You must separately verify the status of the abandoning action with the listmanagedinstances method.\n\nIf the group is part of a backend service that has enabled connection draining, it can take up to 60 seconds after the connection draining duration has elapsed before the VM instance is removed or deleted.\n\nYou can specify a maximum of 1000 instances with this method per request.", + // "description": "Flags the specified instances to be removed from the managed instance group. Abandoning an instance does not delete the instance, but it does remove the instance from any target pools that are applied by the managed instance group. This method reduces the targetSize of the managed instance group by the number of instances that you abandon. This operation is marked as DONE when the action is scheduled even if the instances have not yet been removed from the group. You must separately verify the status of the abandoning action with the listmanagedinstances method.\n\nIf the group is part of a backend service that has enabled connection draining, it can take up to 60 seconds after the connection draining duration has elapsed before the VM instance is removed or deleted.\n\nYou can specify a maximum of 1000 instances with this method per request.", // "httpMethod": "POST", // "id": "compute.instanceGroupManagers.abandonInstances", // "parameterOrder": [ @@ -51207,9 +57529,13 @@ func (c *InstanceGroupManagersAggregatedListCall) doRequest(alt string) (*http.R } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/aggregated/instanceGroupManagers") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -51404,9 +57730,13 @@ func (c *InstanceGroupManagersDeleteCall) doRequest(alt string) (*http.Response, reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instanceGroupManagers/{instanceGroupManager}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -51513,14 +57843,14 @@ type InstanceGroupManagersDeleteInstancesCall struct { header_ http.Header } -// DeleteInstances: Schedules a group action to delete the specified -// instances in the managed instance group. The instances are also -// removed from any target pools of which they were a member. This -// method reduces the targetSize of the managed instance group by the -// number of instances that you delete. This operation is marked as DONE -// when the action is scheduled even if the instances are still being -// deleted. You must separately verify the status of the deleting action -// with the listmanagedinstances method. +// DeleteInstances: Flags the specified instances in the managed +// instance group for immediate deletion. The instances are also removed +// from any target pools of which they were a member. This method +// reduces the targetSize of the managed instance group by the number of +// instances that you delete. This operation is marked as DONE when the +// action is scheduled even if the instances are still being deleted. +// You must separately verify the status of the deleting action with the +// listmanagedinstances method. // // If the group is part of a backend service that has enabled connection // draining, it can take up to 60 seconds after the connection draining @@ -51595,9 +57925,13 @@ func (c *InstanceGroupManagersDeleteInstancesCall) doRequest(alt string) (*http. } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instanceGroupManagers/{instanceGroupManager}/deleteInstances") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -51645,7 +57979,7 @@ func (c *InstanceGroupManagersDeleteInstancesCall) Do(opts ...googleapi.CallOpti } return ret, nil // { - // "description": "Schedules a group action to delete the specified instances in the managed instance group. The instances are also removed from any target pools of which they were a member. This method reduces the targetSize of the managed instance group by the number of instances that you delete. This operation is marked as DONE when the action is scheduled even if the instances are still being deleted. You must separately verify the status of the deleting action with the listmanagedinstances method.\n\nIf the group is part of a backend service that has enabled connection draining, it can take up to 60 seconds after the connection draining duration has elapsed before the VM instance is removed or deleted.\n\nYou can specify a maximum of 1000 instances with this method per request.", + // "description": "Flags the specified instances in the managed instance group for immediate deletion. The instances are also removed from any target pools of which they were a member. This method reduces the targetSize of the managed instance group by the number of instances that you delete. This operation is marked as DONE when the action is scheduled even if the instances are still being deleted. You must separately verify the status of the deleting action with the listmanagedinstances method.\n\nIf the group is part of a backend service that has enabled connection draining, it can take up to 60 seconds after the connection draining duration has elapsed before the VM instance is removed or deleted.\n\nYou can specify a maximum of 1000 instances with this method per request.", // "httpMethod": "POST", // "id": "compute.instanceGroupManagers.deleteInstances", // "parameterOrder": [ @@ -51764,9 +58098,13 @@ func (c *InstanceGroupManagersGetCall) doRequest(alt string) (*http.Response, er } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instanceGroupManagers/{instanceGroupManager}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -51869,12 +58207,12 @@ type InstanceGroupManagersInsertCall struct { } // Insert: Creates a managed instance group using the information that -// you specify in the request. After the group is created, it schedules -// an action to create instances in the group using the specified -// instance template. This operation is marked as DONE when the group is -// created even if the instances in the group have not yet been created. -// You must separately verify the status of the individual instances -// with the listmanagedinstances method. +// you specify in the request. After the group is created, instances in +// the group are created using the specified instance template. This +// operation is marked as DONE when the group is created even if the +// instances in the group have not yet been created. You must separately +// verify the status of the individual instances with the +// listmanagedinstances method. // // A managed instance group can have up to 1000 VM instances per group. // Please contact Cloud Support if you need an increase in this limit. @@ -51943,9 +58281,13 @@ func (c *InstanceGroupManagersInsertCall) doRequest(alt string) (*http.Response, } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instanceGroupManagers") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -51992,7 +58334,7 @@ func (c *InstanceGroupManagersInsertCall) Do(opts ...googleapi.CallOption) (*Ope } return ret, nil // { - // "description": "Creates a managed instance group using the information that you specify in the request. After the group is created, it schedules an action to create instances in the group using the specified instance template. This operation is marked as DONE when the group is created even if the instances in the group have not yet been created. You must separately verify the status of the individual instances with the listmanagedinstances method.\n\nA managed instance group can have up to 1000 VM instances per group. Please contact Cloud Support if you need an increase in this limit.", + // "description": "Creates a managed instance group using the information that you specify in the request. After the group is created, instances in the group are created using the specified instance template. This operation is marked as DONE when the group is created even if the instances in the group have not yet been created. You must separately verify the status of the individual instances with the listmanagedinstances method.\n\nA managed instance group can have up to 1000 VM instances per group. Please contact Cloud Support if you need an increase in this limit.", // "httpMethod": "POST", // "id": "compute.instanceGroupManagers.insert", // "parameterOrder": [ @@ -52164,9 +58506,13 @@ func (c *InstanceGroupManagersListCall) doRequest(alt string) (*http.Response, e } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instanceGroupManagers") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -52318,25 +58664,64 @@ func (r *InstanceGroupManagersService) ListManagedInstances(project string, zone return c } -// Filter sets the optional parameter "filter": +// Filter sets the optional parameter "filter": A filter expression that +// filters resources listed in the response. The expression must specify +// the field name, a comparison operator, and the value that you want to +// use for filtering. The value must be a string, a number, or a +// boolean. The comparison operator must be either =, !=, >, or <. +// +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. +// +// You can also filter nested fields. For example, you could specify +// scheduling.automaticRestart = false to include instances only if they +// are not scheduled for automatic restarts. You can use filtering on +// nested fields to filter based on resource labels. +// +// To filter on multiple expressions, provide each separate expression +// within parentheses. For example, (scheduling.automaticRestart = true) +// (cpuPlatform = "Intel Skylake"). By default, each expression is an +// AND expression. However, you can include AND and OR expressions +// explicitly. For example, (cpuPlatform = "Intel Skylake") OR +// (cpuPlatform = "Intel Broadwell") AND (scheduling.automaticRestart = +// true). func (c *InstanceGroupManagersListManagedInstancesCall) Filter(filter string) *InstanceGroupManagersListManagedInstancesCall { c.urlParams_.Set("filter", filter) return c } -// MaxResults sets the optional parameter "maxResults": +// MaxResults sets the optional parameter "maxResults": The maximum +// number of results per page that should be returned. If the number of +// available results is larger than maxResults, Compute Engine returns a +// nextPageToken that can be used to get the next page of results in +// subsequent list requests. Acceptable values are 0 to 500, inclusive. +// (Default: 500) func (c *InstanceGroupManagersListManagedInstancesCall) MaxResults(maxResults int64) *InstanceGroupManagersListManagedInstancesCall { c.urlParams_.Set("maxResults", fmt.Sprint(maxResults)) return c } -// OrderBy sets the optional parameter "order_by": +// OrderBy sets the optional parameter "order_by": Sorts list results by +// a certain order. By default, results are returned in alphanumerical +// order based on the resource name. +// +// You can also sort results in descending order based on the creation +// timestamp using orderBy="creationTimestamp desc". This sorts results +// based on the creationTimestamp field in reverse chronological order +// (newest result first). Use this to sort resources like operations so +// that the newest operation is returned first. +// +// Currently, only sorting by name or creationTimestamp desc is +// supported. func (c *InstanceGroupManagersListManagedInstancesCall) OrderBy(orderBy string) *InstanceGroupManagersListManagedInstancesCall { c.urlParams_.Set("order_by", orderBy) return c } -// PageToken sets the optional parameter "pageToken": +// PageToken sets the optional parameter "pageToken": Specifies a page +// token to use. Set pageToken to the nextPageToken returned by a +// previous list request to get the next page of results. func (c *InstanceGroupManagersListManagedInstancesCall) PageToken(pageToken string) *InstanceGroupManagersListManagedInstancesCall { c.urlParams_.Set("pageToken", pageToken) return c @@ -52375,9 +58760,13 @@ func (c *InstanceGroupManagersListManagedInstancesCall) doRequest(alt string) (* reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instanceGroupManagers/{instanceGroupManager}/listManagedInstances") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -52437,6 +58826,7 @@ func (c *InstanceGroupManagersListManagedInstancesCall) Do(opts ...googleapi.Cal // ], // "parameters": { // "filter": { + // "description": "A filter expression that filters resources listed in the response. The expression must specify the field name, a comparison operator, and the value that you want to use for filtering. The value must be a string, a number, or a boolean. The comparison operator must be either =, !=, \u003e, or \u003c.\n\nFor example, if you are filtering Compute Engine instances, you can exclude instances named example-instance by specifying name != example-instance.\n\nYou can also filter nested fields. For example, you could specify scheduling.automaticRestart = false to include instances only if they are not scheduled for automatic restarts. You can use filtering on nested fields to filter based on resource labels.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart = true) (cpuPlatform = \"Intel Skylake\"). By default, each expression is an AND expression. However, you can include AND and OR expressions explicitly. For example, (cpuPlatform = \"Intel Skylake\") OR (cpuPlatform = \"Intel Broadwell\") AND (scheduling.automaticRestart = true).", // "location": "query", // "type": "string" // }, @@ -52448,16 +58838,19 @@ func (c *InstanceGroupManagersListManagedInstancesCall) Do(opts ...googleapi.Cal // }, // "maxResults": { // "default": "500", + // "description": "The maximum number of results per page that should be returned. If the number of available results is larger than maxResults, Compute Engine returns a nextPageToken that can be used to get the next page of results in subsequent list requests. Acceptable values are 0 to 500, inclusive. (Default: 500)", // "format": "uint32", // "location": "query", // "minimum": "0", // "type": "integer" // }, // "order_by": { + // "description": "Sorts list results by a certain order. By default, results are returned in alphanumerical order based on the resource name.\n\nYou can also sort results in descending order based on the creation timestamp using orderBy=\"creationTimestamp desc\". This sorts results based on the creationTimestamp field in reverse chronological order (newest result first). Use this to sort resources like operations so that the newest operation is returned first.\n\nCurrently, only sorting by name or creationTimestamp desc is supported.", // "location": "query", // "type": "string" // }, // "pageToken": { + // "description": "Specifies a page token to use. Set pageToken to the nextPageToken returned by a previous list request to get the next page of results.", // "location": "query", // "type": "string" // }, @@ -52595,9 +58988,13 @@ func (c *InstanceGroupManagersPatchCall) doRequest(alt string) (*http.Response, } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instanceGroupManagers/{instanceGroupManager}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PATCH", urls, body) + req, err := http.NewRequest("PATCH", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -52707,11 +59104,11 @@ type InstanceGroupManagersRecreateInstancesCall struct { header_ http.Header } -// RecreateInstances: Schedules a group action to recreate the specified -// instances in the managed instance group. The instances are deleted +// RecreateInstances: Flags the specified instances in the managed +// instance group to be immediately recreated. The instances are deleted // and recreated using the current instance template for the managed -// instance group. This operation is marked as DONE when the action is -// scheduled even if the instances have not yet been recreated. You must +// instance group. This operation is marked as DONE when the flag is set +// even if the instances have not yet been recreated. You must // separately verify the status of the recreating action with the // listmanagedinstances method. // @@ -52788,9 +59185,13 @@ func (c *InstanceGroupManagersRecreateInstancesCall) doRequest(alt string) (*htt } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instanceGroupManagers/{instanceGroupManager}/recreateInstances") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -52838,7 +59239,7 @@ func (c *InstanceGroupManagersRecreateInstancesCall) Do(opts ...googleapi.CallOp } return ret, nil // { - // "description": "Schedules a group action to recreate the specified instances in the managed instance group. The instances are deleted and recreated using the current instance template for the managed instance group. This operation is marked as DONE when the action is scheduled even if the instances have not yet been recreated. You must separately verify the status of the recreating action with the listmanagedinstances method.\n\nIf the group is part of a backend service that has enabled connection draining, it can take up to 60 seconds after the connection draining duration has elapsed before the VM instance is removed or deleted.\n\nYou can specify a maximum of 1000 instances with this method per request.", + // "description": "Flags the specified instances in the managed instance group to be immediately recreated. The instances are deleted and recreated using the current instance template for the managed instance group. This operation is marked as DONE when the flag is set even if the instances have not yet been recreated. You must separately verify the status of the recreating action with the listmanagedinstances method.\n\nIf the group is part of a backend service that has enabled connection draining, it can take up to 60 seconds after the connection draining duration has elapsed before the VM instance is removed or deleted.\n\nYou can specify a maximum of 1000 instances with this method per request.", // "httpMethod": "POST", // "id": "compute.instanceGroupManagers.recreateInstances", // "parameterOrder": [ @@ -52907,6 +59308,16 @@ type InstanceGroupManagersResizeCall struct { // separately verify the status of the creating or deleting actions with // the listmanagedinstances method. // +// When resizing down, the instance group arbitrarily chooses the order +// in which VMs are deleted. The group takes into account some VM +// attributes when making the selection including: +// +// + The status of the VM instance. + The health of the VM instance. + +// The instance template version the VM is based on. + For regional +// managed instance groups, the location of the VM instance. +// +// This list is subject to change. +// // If the group is part of a backend service that has enabled connection // draining, it can take up to 60 seconds after the connection draining // duration has elapsed before the VM instance is removed or deleted. @@ -52971,9 +59382,13 @@ func (c *InstanceGroupManagersResizeCall) doRequest(alt string) (*http.Response, reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instanceGroupManagers/{instanceGroupManager}/resize") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -53021,7 +59436,7 @@ func (c *InstanceGroupManagersResizeCall) Do(opts ...googleapi.CallOption) (*Ope } return ret, nil // { - // "description": "Resizes the managed instance group. If you increase the size, the group creates new instances using the current instance template. If you decrease the size, the group deletes instances. The resize operation is marked DONE when the resize actions are scheduled even if the group has not yet added or deleted any instances. You must separately verify the status of the creating or deleting actions with the listmanagedinstances method.\n\nIf the group is part of a backend service that has enabled connection draining, it can take up to 60 seconds after the connection draining duration has elapsed before the VM instance is removed or deleted.", + // "description": "Resizes the managed instance group. If you increase the size, the group creates new instances using the current instance template. If you decrease the size, the group deletes instances. The resize operation is marked DONE when the resize actions are scheduled even if the group has not yet added or deleted any instances. You must separately verify the status of the creating or deleting actions with the listmanagedinstances method.\n\nWhen resizing down, the instance group arbitrarily chooses the order in which VMs are deleted. The group takes into account some VM attributes when making the selection including:\n\n+ The status of the VM instance. + The health of the VM instance. + The instance template version the VM is based on. + For regional managed instance groups, the location of the VM instance.\n\nThis list is subject to change.\n\nIf the group is part of a backend service that has enabled connection draining, it can take up to 60 seconds after the connection draining duration has elapsed before the VM instance is removed or deleted.", // "httpMethod": "POST", // "id": "compute.instanceGroupManagers.resize", // "parameterOrder": [ @@ -53169,9 +59584,13 @@ func (c *InstanceGroupManagersResizeAdvancedCall) doRequest(alt string) (*http.R } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instanceGroupManagers/{instanceGroupManager}/resizeAdvanced") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -53282,6 +59701,7 @@ type InstanceGroupManagersSetAutoHealingPoliciesCall struct { } // SetAutoHealingPolicies: Modifies the autohealing policies. +// [Deprecated] This method is deprecated. Please use Patch instead. func (r *InstanceGroupManagersService) SetAutoHealingPolicies(project string, zone string, instanceGroupManager string, instancegroupmanagerssetautohealingrequest *InstanceGroupManagersSetAutoHealingRequest) *InstanceGroupManagersSetAutoHealingPoliciesCall { c := &InstanceGroupManagersSetAutoHealingPoliciesCall{s: r.s, urlParams_: make(gensupport.URLParams)} c.project = project @@ -53348,9 +59768,13 @@ func (c *InstanceGroupManagersSetAutoHealingPoliciesCall) doRequest(alt string) } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instanceGroupManagers/{instanceGroupManager}/setAutoHealingPolicies") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -53398,7 +59822,7 @@ func (c *InstanceGroupManagersSetAutoHealingPoliciesCall) Do(opts ...googleapi.C } return ret, nil // { - // "description": "Modifies the autohealing policies.", + // "description": "Modifies the autohealing policies. [Deprecated] This method is deprecated. Please use Patch instead.", // "httpMethod": "POST", // "id": "compute.instanceGroupManagers.setAutoHealingPolicies", // "parameterOrder": [ @@ -53529,9 +59953,13 @@ func (c *InstanceGroupManagersSetInstanceTemplateCall) doRequest(alt string) (*h } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instanceGroupManagers/{instanceGroupManager}/setInstanceTemplate") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -53714,9 +60142,13 @@ func (c *InstanceGroupManagersSetTargetPoolsCall) doRequest(alt string) (*http.R } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instanceGroupManagers/{instanceGroupManager}/setTargetPools") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -53875,9 +60307,13 @@ func (c *InstanceGroupManagersTestIamPermissionsCall) doRequest(alt string) (*ht } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instanceGroupManagers/{resource}/testIamPermissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -53942,9 +60378,9 @@ func (c *InstanceGroupManagersTestIamPermissionsCall) Do(opts ...googleapi.CallO // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -54056,9 +60492,13 @@ func (c *InstanceGroupManagersUpdateCall) doRequest(alt string) (*http.Response, } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instanceGroupManagers/{instanceGroupManager}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PUT", urls, body) + req, err := http.NewRequest("PUT", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -54237,9 +60677,13 @@ func (c *InstanceGroupsAddInstancesCall) doRequest(alt string) (*http.Response, } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instanceGroups/{instanceGroup}/addInstances") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -54464,9 +60908,13 @@ func (c *InstanceGroupsAggregatedListCall) doRequest(alt string) (*http.Response } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/aggregated/instanceGroups") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -54660,9 +61108,13 @@ func (c *InstanceGroupsDeleteCall) doRequest(alt string) (*http.Response, error) reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instanceGroups/{instanceGroup}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -54825,9 +61277,13 @@ func (c *InstanceGroupsGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instanceGroups/{instanceGroup}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -54996,9 +61452,13 @@ func (c *InstanceGroupsInsertCall) doRequest(alt string) (*http.Response, error) } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instanceGroups") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -55217,9 +61677,13 @@ func (c *InstanceGroupsListCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instanceGroups") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -55469,9 +61933,13 @@ func (c *InstanceGroupsListInstancesCall) doRequest(alt string) (*http.Response, } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instanceGroups/{instanceGroup}/listInstances") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -55693,9 +62161,13 @@ func (c *InstanceGroupsRemoveInstancesCall) doRequest(alt string) (*http.Respons } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instanceGroups/{instanceGroup}/removeInstances") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -55872,9 +62344,13 @@ func (c *InstanceGroupsSetNamedPortsCall) doRequest(alt string) (*http.Response, } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instanceGroups/{instanceGroup}/setNamedPorts") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -56033,9 +62509,13 @@ func (c *InstanceGroupsTestIamPermissionsCall) doRequest(alt string) (*http.Resp } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instanceGroups/{resource}/testIamPermissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -56100,9 +62580,9 @@ func (c *InstanceGroupsTestIamPermissionsCall) Do(opts ...googleapi.CallOption) // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -56204,9 +62684,13 @@ func (c *InstanceTemplatesDeleteCall) doRequest(alt string) (*http.Response, err reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/instanceTemplates/{instanceTemplate}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -56361,9 +62845,13 @@ func (c *InstanceTemplatesGetCall) doRequest(alt string) (*http.Response, error) } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/instanceTemplates/{instanceTemplate}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -56446,6 +62934,162 @@ func (c *InstanceTemplatesGetCall) Do(opts ...googleapi.CallOption) (*InstanceTe } +// method id "compute.instanceTemplates.getIamPolicy": + +type InstanceTemplatesGetIamPolicyCall struct { + s *Service + project string + resource string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// GetIamPolicy: Gets the access control policy for a resource. May be +// empty if no such policy or resource exists. +func (r *InstanceTemplatesService) GetIamPolicy(project string, resource string) *InstanceTemplatesGetIamPolicyCall { + c := &InstanceTemplatesGetIamPolicyCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.resource = resource + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *InstanceTemplatesGetIamPolicyCall) Fields(s ...googleapi.Field) *InstanceTemplatesGetIamPolicyCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// IfNoneMatch sets the optional parameter which makes the operation +// fail if the object's ETag matches the given value. This is useful for +// getting updates only after the object has changed since the last +// request. Use googleapi.IsNotModified to check whether the response +// error from Do is the result of In-None-Match. +func (c *InstanceTemplatesGetIamPolicyCall) IfNoneMatch(entityTag string) *InstanceTemplatesGetIamPolicyCall { + c.ifNoneMatch_ = entityTag + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *InstanceTemplatesGetIamPolicyCall) Context(ctx context.Context) *InstanceTemplatesGetIamPolicyCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *InstanceTemplatesGetIamPolicyCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *InstanceTemplatesGetIamPolicyCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + if c.ifNoneMatch_ != "" { + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) + } + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/instanceTemplates/{resource}/getIamPolicy") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "resource": c.resource, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.instanceTemplates.getIamPolicy" call. +// Exactly one of *Policy or error will be non-nil. Any non-2xx status +// code is an error. Response headers are in either +// *Policy.ServerResponse.Header or (if a response was returned at all) +// in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to +// check whether the returned error was because http.StatusNotModified +// was returned. +func (c *InstanceTemplatesGetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Policy, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Policy{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Gets the access control policy for a resource. May be empty if no such policy or resource exists.", + // "httpMethod": "GET", + // "id": "compute.instanceTemplates.getIamPolicy", + // "parameterOrder": [ + // "project", + // "resource" + // ], + // "parameters": { + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "resource": { + // "description": "Name or id of the resource for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/global/instanceTemplates/{resource}/getIamPolicy", + // "response": { + // "$ref": "Policy" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute", + // "https://www.googleapis.com/auth/compute.readonly" + // ] + // } + +} + // method id "compute.instanceTemplates.insert": type InstanceTemplatesInsertCall struct { @@ -56527,9 +63171,13 @@ func (c *InstanceTemplatesInsertCall) doRequest(alt string) (*http.Response, err } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/instanceTemplates") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -56739,9 +63387,13 @@ func (c *InstanceTemplatesListCall) doRequest(alt string) (*http.Response, error } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/instanceTemplates") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -56859,6 +63511,157 @@ func (c *InstanceTemplatesListCall) Pages(ctx context.Context, f func(*InstanceT } } +// method id "compute.instanceTemplates.setIamPolicy": + +type InstanceTemplatesSetIamPolicyCall struct { + s *Service + project string + resource string + globalsetpolicyrequest *GlobalSetPolicyRequest + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// SetIamPolicy: Sets the access control policy on the specified +// resource. Replaces any existing policy. +func (r *InstanceTemplatesService) SetIamPolicy(project string, resource string, globalsetpolicyrequest *GlobalSetPolicyRequest) *InstanceTemplatesSetIamPolicyCall { + c := &InstanceTemplatesSetIamPolicyCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.resource = resource + c.globalsetpolicyrequest = globalsetpolicyrequest + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *InstanceTemplatesSetIamPolicyCall) Fields(s ...googleapi.Field) *InstanceTemplatesSetIamPolicyCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *InstanceTemplatesSetIamPolicyCall) Context(ctx context.Context) *InstanceTemplatesSetIamPolicyCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *InstanceTemplatesSetIamPolicyCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *InstanceTemplatesSetIamPolicyCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.globalsetpolicyrequest) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/instanceTemplates/{resource}/setIamPolicy") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "resource": c.resource, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.instanceTemplates.setIamPolicy" call. +// Exactly one of *Policy or error will be non-nil. Any non-2xx status +// code is an error. Response headers are in either +// *Policy.ServerResponse.Header or (if a response was returned at all) +// in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to +// check whether the returned error was because http.StatusNotModified +// was returned. +func (c *InstanceTemplatesSetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Policy, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Policy{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Sets the access control policy on the specified resource. Replaces any existing policy.", + // "httpMethod": "POST", + // "id": "compute.instanceTemplates.setIamPolicy", + // "parameterOrder": [ + // "project", + // "resource" + // ], + // "parameters": { + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "resource": { + // "description": "Name or id of the resource for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/global/instanceTemplates/{resource}/setIamPolicy", + // "request": { + // "$ref": "GlobalSetPolicyRequest" + // }, + // "response": { + // "$ref": "Policy" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + // method id "compute.instanceTemplates.testIamPermissions": type InstanceTemplatesTestIamPermissionsCall struct { @@ -56919,9 +63722,13 @@ func (c *InstanceTemplatesTestIamPermissionsCall) doRequest(alt string) (*http.R } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/instanceTemplates/{resource}/testIamPermissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -56984,9 +63791,9 @@ func (c *InstanceTemplatesTestIamPermissionsCall) Do(opts ...googleapi.CallOptio // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "(?:[-a-z0-9_]{0,62}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -57090,9 +63897,13 @@ func (c *InstancesAddAccessConfigCall) doRequest(alt string) (*http.Response, er } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{instance}/addAccessConfig") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -57153,7 +63964,7 @@ func (c *InstancesAddAccessConfigCall) Do(opts ...googleapi.CallOption) (*Operat // "instance": { // "description": "The instance name for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -57209,7 +64020,8 @@ type InstancesAggregatedListCall struct { header_ http.Header } -// AggregatedList: Retrieves aggregated list of instances. +// AggregatedList: Retrieves aggregated list of all of the instances in +// your project across all regions and zones. // For details, see https://cloud.google.com/compute/docs/reference/latest/instances/aggregatedList func (r *InstancesService) AggregatedList(project string) *InstancesAggregatedListCall { c := &InstancesAggregatedListCall{s: r.s, urlParams_: make(gensupport.URLParams)} @@ -57326,9 +64138,13 @@ func (c *InstancesAggregatedListCall) doRequest(alt string) (*http.Response, err } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/aggregated/instances") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -57374,7 +64190,7 @@ func (c *InstancesAggregatedListCall) Do(opts ...googleapi.CallOption) (*Instanc } return ret, nil // { - // "description": "Retrieves aggregated list of instances.", + // "description": "Retrieves aggregated list of all of the instances in your project across all regions and zones.", // "httpMethod": "GET", // "id": "compute.instances.aggregatedList", // "parameterOrder": [ @@ -57538,9 +64354,13 @@ func (c *InstancesAttachDiskCall) doRequest(alt string) (*http.Response, error) } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{instance}/attachDisk") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -57605,7 +64425,7 @@ func (c *InstancesAttachDiskCall) Do(opts ...googleapi.CallOption) (*Operation, // "instance": { // "description": "The instance name for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -57719,9 +64539,13 @@ func (c *InstancesDeleteCall) doRequest(alt string) (*http.Response, error) { reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{instance}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -57781,7 +64605,7 @@ func (c *InstancesDeleteCall) Do(opts ...googleapi.CallOption) (*Operation, erro // "instance": { // "description": "Name of the instance resource to delete.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -57894,9 +64718,13 @@ func (c *InstancesDeleteAccessConfigCall) doRequest(alt string) (*http.Response, reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{instance}/deleteAccessConfig") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -57964,7 +64792,7 @@ func (c *InstancesDeleteAccessConfigCall) Do(opts ...googleapi.CallOption) (*Ope // "instance": { // "description": "The instance name for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -58081,9 +64909,13 @@ func (c *InstancesDetachDiskCall) doRequest(alt string) (*http.Response, error) reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{instance}/detachDisk") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -58142,15 +64974,15 @@ func (c *InstancesDetachDiskCall) Do(opts ...googleapi.CallOption) (*Operation, // ], // "parameters": { // "deviceName": { - // "description": "Disk device name to detach.", + // "description": "The device name of the disk to detach. Make a get() request on the instance to view currently attached disks and device names.", // "location": "query", // "required": true, // "type": "string" // }, // "instance": { - // "description": "Instance name.", + // "description": "Instance name for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -58256,9 +65088,13 @@ func (c *InstancesGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{instance}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -58318,7 +65154,7 @@ func (c *InstancesGetCall) Do(opts ...googleapi.CallOption) (*Instance, error) { // "instance": { // "description": "Name of the instance resource to return.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -58350,6 +65186,363 @@ func (c *InstancesGetCall) Do(opts ...googleapi.CallOption) (*Instance, error) { } +// method id "compute.instances.getGuestAttributes": + +type InstancesGetGuestAttributesCall struct { + s *Service + project string + zone string + instance string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// GetGuestAttributes: Returns the specified guest attributes entry. +func (r *InstancesService) GetGuestAttributes(project string, zone string, instance string) *InstancesGetGuestAttributesCall { + c := &InstancesGetGuestAttributesCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.zone = zone + c.instance = instance + return c +} + +// QueryPath sets the optional parameter "queryPath": Specifies the +// guest attributes path to be queried. +func (c *InstancesGetGuestAttributesCall) QueryPath(queryPath string) *InstancesGetGuestAttributesCall { + c.urlParams_.Set("queryPath", queryPath) + return c +} + +// VariableKey sets the optional parameter "variableKey": Specifies the +// key for the guest attributes entry. +func (c *InstancesGetGuestAttributesCall) VariableKey(variableKey string) *InstancesGetGuestAttributesCall { + c.urlParams_.Set("variableKey", variableKey) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *InstancesGetGuestAttributesCall) Fields(s ...googleapi.Field) *InstancesGetGuestAttributesCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// IfNoneMatch sets the optional parameter which makes the operation +// fail if the object's ETag matches the given value. This is useful for +// getting updates only after the object has changed since the last +// request. Use googleapi.IsNotModified to check whether the response +// error from Do is the result of In-None-Match. +func (c *InstancesGetGuestAttributesCall) IfNoneMatch(entityTag string) *InstancesGetGuestAttributesCall { + c.ifNoneMatch_ = entityTag + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *InstancesGetGuestAttributesCall) Context(ctx context.Context) *InstancesGetGuestAttributesCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *InstancesGetGuestAttributesCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *InstancesGetGuestAttributesCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + if c.ifNoneMatch_ != "" { + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) + } + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{instance}/getGuestAttributes") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "zone": c.zone, + "instance": c.instance, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.instances.getGuestAttributes" call. +// Exactly one of *GuestAttributes or error will be non-nil. Any non-2xx +// status code is an error. Response headers are in either +// *GuestAttributes.ServerResponse.Header or (if a response was returned +// at all) in error.(*googleapi.Error).Header. Use +// googleapi.IsNotModified to check whether the returned error was +// because http.StatusNotModified was returned. +func (c *InstancesGetGuestAttributesCall) Do(opts ...googleapi.CallOption) (*GuestAttributes, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &GuestAttributes{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Returns the specified guest attributes entry.", + // "httpMethod": "GET", + // "id": "compute.instances.getGuestAttributes", + // "parameterOrder": [ + // "project", + // "zone", + // "instance" + // ], + // "parameters": { + // "instance": { + // "description": "Name of the instance scoping this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + // "required": true, + // "type": "string" + // }, + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "queryPath": { + // "description": "Specifies the guest attributes path to be queried.", + // "location": "query", + // "type": "string" + // }, + // "variableKey": { + // "description": "Specifies the key for the guest attributes entry.", + // "location": "query", + // "type": "string" + // }, + // "zone": { + // "description": "The name of the zone for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/zones/{zone}/instances/{instance}/getGuestAttributes", + // "response": { + // "$ref": "GuestAttributes" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute", + // "https://www.googleapis.com/auth/compute.readonly" + // ] + // } + +} + +// method id "compute.instances.getIamPolicy": + +type InstancesGetIamPolicyCall struct { + s *Service + project string + zone string + resource string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// GetIamPolicy: Gets the access control policy for a resource. May be +// empty if no such policy or resource exists. +func (r *InstancesService) GetIamPolicy(project string, zone string, resource string) *InstancesGetIamPolicyCall { + c := &InstancesGetIamPolicyCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.zone = zone + c.resource = resource + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *InstancesGetIamPolicyCall) Fields(s ...googleapi.Field) *InstancesGetIamPolicyCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// IfNoneMatch sets the optional parameter which makes the operation +// fail if the object's ETag matches the given value. This is useful for +// getting updates only after the object has changed since the last +// request. Use googleapi.IsNotModified to check whether the response +// error from Do is the result of In-None-Match. +func (c *InstancesGetIamPolicyCall) IfNoneMatch(entityTag string) *InstancesGetIamPolicyCall { + c.ifNoneMatch_ = entityTag + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *InstancesGetIamPolicyCall) Context(ctx context.Context) *InstancesGetIamPolicyCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *InstancesGetIamPolicyCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *InstancesGetIamPolicyCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + if c.ifNoneMatch_ != "" { + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) + } + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{resource}/getIamPolicy") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "zone": c.zone, + "resource": c.resource, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.instances.getIamPolicy" call. +// Exactly one of *Policy or error will be non-nil. Any non-2xx status +// code is an error. Response headers are in either +// *Policy.ServerResponse.Header or (if a response was returned at all) +// in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to +// check whether the returned error was because http.StatusNotModified +// was returned. +func (c *InstancesGetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Policy, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Policy{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Gets the access control policy for a resource. May be empty if no such policy or resource exists.", + // "httpMethod": "GET", + // "id": "compute.instances.getIamPolicy", + // "parameterOrder": [ + // "project", + // "zone", + // "resource" + // ], + // "parameters": { + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "resource": { + // "description": "Name or id of the resource for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + // "required": true, + // "type": "string" + // }, + // "zone": { + // "description": "The name of the zone for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/zones/{zone}/instances/{resource}/getIamPolicy", + // "response": { + // "$ref": "Policy" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute", + // "https://www.googleapis.com/auth/compute.readonly" + // ] + // } + +} + // method id "compute.instances.getSerialPortOutput": type InstancesGetSerialPortOutputCall struct { @@ -58363,8 +65556,8 @@ type InstancesGetSerialPortOutputCall struct { header_ http.Header } -// GetSerialPortOutput: Returns the specified instance's serial port -// output. +// GetSerialPortOutput: Returns the last 1 MB of serial port output from +// the specified instance. // For details, see https://cloud.google.com/compute/docs/reference/latest/instances/getSerialPortOutput func (r *InstancesService) GetSerialPortOutput(project string, zone string, instance string) *InstancesGetSerialPortOutputCall { c := &InstancesGetSerialPortOutputCall{s: r.s, urlParams_: make(gensupport.URLParams)} @@ -58438,9 +65631,13 @@ func (c *InstancesGetSerialPortOutputCall) doRequest(alt string) (*http.Response } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{instance}/serialPort") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -58488,7 +65685,7 @@ func (c *InstancesGetSerialPortOutputCall) Do(opts ...googleapi.CallOption) (*Se } return ret, nil // { - // "description": "Returns the specified instance's serial port output.", + // "description": "Returns the last 1 MB of serial port output from the specified instance.", // "httpMethod": "GET", // "id": "compute.instances.getSerialPortOutput", // "parameterOrder": [ @@ -58500,7 +65697,7 @@ func (c *InstancesGetSerialPortOutputCall) Do(opts ...googleapi.CallOption) (*Se // "instance": { // "description": "Name of the instance scoping this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -58547,6 +65744,173 @@ func (c *InstancesGetSerialPortOutputCall) Do(opts ...googleapi.CallOption) (*Se } +// method id "compute.instances.getShieldedVmIdentity": + +type InstancesGetShieldedVmIdentityCall struct { + s *Service + project string + zone string + instance string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// GetShieldedVmIdentity: Returns the Shielded VM Identity of an +// instance +func (r *InstancesService) GetShieldedVmIdentity(project string, zone string, instance string) *InstancesGetShieldedVmIdentityCall { + c := &InstancesGetShieldedVmIdentityCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.zone = zone + c.instance = instance + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *InstancesGetShieldedVmIdentityCall) Fields(s ...googleapi.Field) *InstancesGetShieldedVmIdentityCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// IfNoneMatch sets the optional parameter which makes the operation +// fail if the object's ETag matches the given value. This is useful for +// getting updates only after the object has changed since the last +// request. Use googleapi.IsNotModified to check whether the response +// error from Do is the result of In-None-Match. +func (c *InstancesGetShieldedVmIdentityCall) IfNoneMatch(entityTag string) *InstancesGetShieldedVmIdentityCall { + c.ifNoneMatch_ = entityTag + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *InstancesGetShieldedVmIdentityCall) Context(ctx context.Context) *InstancesGetShieldedVmIdentityCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *InstancesGetShieldedVmIdentityCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *InstancesGetShieldedVmIdentityCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + if c.ifNoneMatch_ != "" { + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) + } + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{instance}/getShieldedVmIdentity") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "zone": c.zone, + "instance": c.instance, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.instances.getShieldedVmIdentity" call. +// Exactly one of *ShieldedVmIdentity or error will be non-nil. Any +// non-2xx status code is an error. Response headers are in either +// *ShieldedVmIdentity.ServerResponse.Header or (if a response was +// returned at all) in error.(*googleapi.Error).Header. Use +// googleapi.IsNotModified to check whether the returned error was +// because http.StatusNotModified was returned. +func (c *InstancesGetShieldedVmIdentityCall) Do(opts ...googleapi.CallOption) (*ShieldedVmIdentity, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &ShieldedVmIdentity{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Returns the Shielded VM Identity of an instance", + // "httpMethod": "GET", + // "id": "compute.instances.getShieldedVmIdentity", + // "parameterOrder": [ + // "project", + // "zone", + // "instance" + // ], + // "parameters": { + // "instance": { + // "description": "Name of the instance scoping this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + // "required": true, + // "type": "string" + // }, + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "zone": { + // "description": "The name of the zone for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/zones/{zone}/instances/{instance}/getShieldedVmIdentity", + // "response": { + // "$ref": "ShieldedVmIdentity" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute", + // "https://www.googleapis.com/auth/compute.readonly" + // ] + // } + +} + // method id "compute.instances.insert": type InstancesInsertCall struct { @@ -58596,10 +65960,9 @@ func (c *InstancesInsertCall) RequestId(requestId string) *InstancesInsertCall { // This field is optional. It can be a full or partial URL. For example, // the following are all valid URLs to an instance template: // - -// https://www.googleapis.com/compute/v1/projects/project/global/global/instanceTemplates/instanceTemplate -// - projects/project/global/global/instanceTemplates/instanceTemplate -// -// - global/instancesTemplates/instanceTemplate +// https://www.googleapis.com/compute/v1/projects/project/global/instanceTemplates/instanceTemplate +// - projects/project/global/instanceTemplates/instanceTemplate +// - global/instanceTemplates/instanceTemplate func (c *InstancesInsertCall) SourceInstanceTemplate(sourceInstanceTemplate string) *InstancesInsertCall { c.urlParams_.Set("sourceInstanceTemplate", sourceInstanceTemplate) return c @@ -58643,9 +66006,13 @@ func (c *InstancesInsertCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -58713,7 +66080,7 @@ func (c *InstancesInsertCall) Do(opts ...googleapi.CallOption) (*Operation, erro // "type": "string" // }, // "sourceInstanceTemplate": { - // "description": "Specifies instance template to create the instance.\n\nThis field is optional. It can be a full or partial URL. For example, the following are all valid URLs to an instance template: \n- https://www.googleapis.com/compute/v1/projects/project/global/global/instanceTemplates/instanceTemplate \n- projects/project/global/global/instanceTemplates/instanceTemplate \n- global/instancesTemplates/instanceTemplate", + // "description": "Specifies instance template to create the instance.\n\nThis field is optional. It can be a full or partial URL. For example, the following are all valid URLs to an instance template: \n- https://www.googleapis.com/compute/v1/projects/project/global/instanceTemplates/instanceTemplate \n- projects/project/global/instanceTemplates/instanceTemplate \n- global/instanceTemplates/instanceTemplate", // "location": "query", // "type": "string" // }, @@ -58871,9 +66238,13 @@ func (c *InstancesListCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -59014,7 +66385,8 @@ type InstancesListReferrersCall struct { } // ListReferrers: Retrieves the list of referrers to instances contained -// within the specified zone. +// within the specified zone. For more information, read Viewing +// Referrers to VM Instances. func (r *InstancesService) ListReferrers(project string, zone string, instance string) *InstancesListReferrersCall { c := &InstancesListReferrersCall{s: r.s, urlParams_: make(gensupport.URLParams)} c.project = project @@ -59132,9 +66504,13 @@ func (c *InstancesListReferrersCall) doRequest(alt string) (*http.Response, erro } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{instance}/referrers") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -59182,7 +66558,7 @@ func (c *InstancesListReferrersCall) Do(opts ...googleapi.CallOption) (*Instance } return ret, nil // { - // "description": "Retrieves the list of referrers to instances contained within the specified zone.", + // "description": "Retrieves the list of referrers to instances contained within the specified zone. For more information, read Viewing Referrers to VM Instances.", // "httpMethod": "GET", // "id": "compute.instances.listReferrers", // "parameterOrder": [ @@ -59199,7 +66575,7 @@ func (c *InstancesListReferrersCall) Do(opts ...googleapi.CallOption) (*Instance // "instance": { // "description": "Name of the target instance scoping this request, or '-' if the request should span over all instances in the container.", // "location": "path", - // "pattern": "-|[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "-|[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -59345,9 +66721,13 @@ func (c *InstancesResetCall) doRequest(alt string) (*http.Response, error) { reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{instance}/reset") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -59407,7 +66787,7 @@ func (c *InstancesResetCall) Do(opts ...googleapi.CallOption) (*Operation, error // "instance": { // "description": "Name of the instance scoping this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -59443,6 +66823,192 @@ func (c *InstancesResetCall) Do(opts ...googleapi.CallOption) (*Operation, error } +// method id "compute.instances.resume": + +type InstancesResumeCall struct { + s *Service + project string + zone string + instance string + instancesresumerequest *InstancesResumeRequest + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// Resume: Resumes an instance that was suspended using the +// instances().suspend method. +func (r *InstancesService) Resume(project string, zone string, instance string, instancesresumerequest *InstancesResumeRequest) *InstancesResumeCall { + c := &InstancesResumeCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.zone = zone + c.instance = instance + c.instancesresumerequest = instancesresumerequest + return c +} + +// RequestId sets the optional parameter "requestId": An optional +// request ID to identify requests. Specify a unique request ID so that +// if you must retry your request, the server will know to ignore the +// request if it has already been completed. +// +// For example, consider a situation where you make an initial request +// and the request times out. If you make the request again with the +// same request ID, the server can check if original operation with the +// same request ID was received, and if so, will ignore the second +// request. This prevents clients from accidentally creating duplicate +// commitments. +// +// The request ID must be a valid UUID with the exception that zero UUID +// is not supported (00000000-0000-0000-0000-000000000000). +func (c *InstancesResumeCall) RequestId(requestId string) *InstancesResumeCall { + c.urlParams_.Set("requestId", requestId) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *InstancesResumeCall) Fields(s ...googleapi.Field) *InstancesResumeCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *InstancesResumeCall) Context(ctx context.Context) *InstancesResumeCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *InstancesResumeCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *InstancesResumeCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.instancesresumerequest) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{instance}/resume") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "zone": c.zone, + "instance": c.instance, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.instances.resume" call. +// Exactly one of *Operation or error will be non-nil. Any non-2xx +// status code is an error. Response headers are in either +// *Operation.ServerResponse.Header or (if a response was returned at +// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified +// to check whether the returned error was because +// http.StatusNotModified was returned. +func (c *InstancesResumeCall) Do(opts ...googleapi.CallOption) (*Operation, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Operation{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Resumes an instance that was suspended using the instances().suspend method.", + // "httpMethod": "POST", + // "id": "compute.instances.resume", + // "parameterOrder": [ + // "project", + // "zone", + // "instance" + // ], + // "parameters": { + // "instance": { + // "description": "Name of the instance resource to resume.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + // "required": true, + // "type": "string" + // }, + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "requestId": { + // "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", + // "location": "query", + // "type": "string" + // }, + // "zone": { + // "description": "The name of the zone for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/zones/{zone}/instances/{instance}/resume", + // "request": { + // "$ref": "InstancesResumeRequest" + // }, + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + // method id "compute.instances.setDeletionProtection": type InstancesSetDeletionProtectionCall struct { @@ -59523,9 +67089,13 @@ func (c *InstancesSetDeletionProtectionCall) doRequest(alt string) (*http.Respon reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{resource}/setDeletionProtection") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -59601,9 +67171,9 @@ func (c *InstancesSetDeletionProtectionCall) Do(opts ...googleapi.CallOption) (* // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -59704,9 +67274,13 @@ func (c *InstancesSetDiskAutoDeleteCall) doRequest(alt string) (*http.Response, reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{instance}/setDiskAutoDelete") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -59772,16 +67346,16 @@ func (c *InstancesSetDiskAutoDeleteCall) Do(opts ...googleapi.CallOption) (*Oper // "type": "boolean" // }, // "deviceName": { - // "description": "The device name of the disk to modify.", + // "description": "The device name of the disk to modify. Make a get() request on the instance to view currently attached disks and device names.", // "location": "query", // "pattern": "\\w[\\w.-]{0,254}", // "required": true, // "type": "string" // }, // "instance": { - // "description": "The instance name.", + // "description": "The instance name for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -59817,6 +67391,168 @@ func (c *InstancesSetDiskAutoDeleteCall) Do(opts ...googleapi.CallOption) (*Oper } +// method id "compute.instances.setIamPolicy": + +type InstancesSetIamPolicyCall struct { + s *Service + project string + zone string + resource string + zonesetpolicyrequest *ZoneSetPolicyRequest + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// SetIamPolicy: Sets the access control policy on the specified +// resource. Replaces any existing policy. +func (r *InstancesService) SetIamPolicy(project string, zone string, resource string, zonesetpolicyrequest *ZoneSetPolicyRequest) *InstancesSetIamPolicyCall { + c := &InstancesSetIamPolicyCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.zone = zone + c.resource = resource + c.zonesetpolicyrequest = zonesetpolicyrequest + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *InstancesSetIamPolicyCall) Fields(s ...googleapi.Field) *InstancesSetIamPolicyCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *InstancesSetIamPolicyCall) Context(ctx context.Context) *InstancesSetIamPolicyCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *InstancesSetIamPolicyCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *InstancesSetIamPolicyCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.zonesetpolicyrequest) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{resource}/setIamPolicy") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "zone": c.zone, + "resource": c.resource, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.instances.setIamPolicy" call. +// Exactly one of *Policy or error will be non-nil. Any non-2xx status +// code is an error. Response headers are in either +// *Policy.ServerResponse.Header or (if a response was returned at all) +// in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to +// check whether the returned error was because http.StatusNotModified +// was returned. +func (c *InstancesSetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Policy, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Policy{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Sets the access control policy on the specified resource. Replaces any existing policy.", + // "httpMethod": "POST", + // "id": "compute.instances.setIamPolicy", + // "parameterOrder": [ + // "project", + // "zone", + // "resource" + // ], + // "parameters": { + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "resource": { + // "description": "Name or id of the resource for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + // "required": true, + // "type": "string" + // }, + // "zone": { + // "description": "The name of the zone for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/zones/{zone}/instances/{resource}/setIamPolicy", + // "request": { + // "$ref": "ZoneSetPolicyRequest" + // }, + // "response": { + // "$ref": "Policy" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + // method id "compute.instances.setLabels": type InstancesSetLabelsCall struct { @@ -59898,9 +67634,13 @@ func (c *InstancesSetLabelsCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{instance}/setLabels") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -59960,7 +67700,7 @@ func (c *InstancesSetLabelsCall) Do(opts ...googleapi.CallOption) (*Operation, e // "instance": { // "description": "Name of the instance scoping this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -60080,9 +67820,13 @@ func (c *InstancesSetMachineResourcesCall) doRequest(alt string) (*http.Response } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{instance}/setMachineResources") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -60142,7 +67886,7 @@ func (c *InstancesSetMachineResourcesCall) Do(opts ...googleapi.CallOption) (*Op // "instance": { // "description": "Name of the instance scoping this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -60262,9 +68006,13 @@ func (c *InstancesSetMachineTypeCall) doRequest(alt string) (*http.Response, err } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{instance}/setMachineType") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -60324,7 +68072,7 @@ func (c *InstancesSetMachineTypeCall) Do(opts ...googleapi.CallOption) (*Operati // "instance": { // "description": "Name of the instance scoping this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -60445,9 +68193,13 @@ func (c *InstancesSetMetadataCall) doRequest(alt string) (*http.Response, error) } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{instance}/setMetadata") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -60507,7 +68259,7 @@ func (c *InstancesSetMetadataCall) Do(opts ...googleapi.CallOption) (*Operation, // "instance": { // "description": "Name of the instance scoping this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -60629,9 +68381,13 @@ func (c *InstancesSetMinCpuPlatformCall) doRequest(alt string) (*http.Response, } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{instance}/setMinCpuPlatform") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -60691,7 +68447,7 @@ func (c *InstancesSetMinCpuPlatformCall) Do(opts ...googleapi.CallOption) (*Oper // "instance": { // "description": "Name of the instance scoping this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -60811,9 +68567,13 @@ func (c *InstancesSetSchedulingCall) doRequest(alt string) (*http.Response, erro } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{instance}/setScheduling") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -60871,9 +68631,9 @@ func (c *InstancesSetSchedulingCall) Do(opts ...googleapi.CallOption) (*Operatio // ], // "parameters": { // "instance": { - // "description": "Instance name.", + // "description": "Instance name for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -60994,9 +68754,13 @@ func (c *InstancesSetServiceAccountCall) doRequest(alt string) (*http.Response, } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{instance}/setServiceAccount") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -61056,7 +68820,7 @@ func (c *InstancesSetServiceAccountCall) Do(opts ...googleapi.CallOption) (*Oper // "instance": { // "description": "Name of the instance resource to start.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -61109,8 +68873,9 @@ type InstancesSetShieldedVmIntegrityPolicyCall struct { } // SetShieldedVmIntegrityPolicy: Sets the Shielded VM integrity policy -// for an instance. This method supports PATCH semantics and uses the -// JSON merge patch format and processing rules. +// for a VM instance. You can only use this method on a running VM +// instance. This method supports PATCH semantics and uses the JSON +// merge patch format and processing rules. func (r *InstancesService) SetShieldedVmIntegrityPolicy(project string, zone string, instance string, shieldedvmintegritypolicy *ShieldedVmIntegrityPolicy) *InstancesSetShieldedVmIntegrityPolicyCall { c := &InstancesSetShieldedVmIntegrityPolicyCall{s: r.s, urlParams_: make(gensupport.URLParams)} c.project = project @@ -61177,9 +68942,13 @@ func (c *InstancesSetShieldedVmIntegrityPolicyCall) doRequest(alt string) (*http } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{instance}/setShieldedVmIntegrityPolicy") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PATCH", urls, body) + req, err := http.NewRequest("PATCH", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -61227,7 +68996,7 @@ func (c *InstancesSetShieldedVmIntegrityPolicyCall) Do(opts ...googleapi.CallOpt } return ret, nil // { - // "description": "Sets the Shielded VM integrity policy for an instance. This method supports PATCH semantics and uses the JSON merge patch format and processing rules.", + // "description": "Sets the Shielded VM integrity policy for a VM instance. You can only use this method on a running VM instance. This method supports PATCH semantics and uses the JSON merge patch format and processing rules.", // "httpMethod": "PATCH", // "id": "compute.instances.setShieldedVmIntegrityPolicy", // "parameterOrder": [ @@ -61239,7 +69008,7 @@ func (c *InstancesSetShieldedVmIntegrityPolicyCall) Do(opts ...googleapi.CallOpt // "instance": { // "description": "Name of the instance scoping this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -61291,8 +69060,8 @@ type InstancesSetTagsCall struct { header_ http.Header } -// SetTags: Sets tags for the specified instance to the data included in -// the request. +// SetTags: Sets network tags for the specified instance to the data +// included in the request. // For details, see https://cloud.google.com/compute/docs/reference/latest/instances/setTags func (r *InstancesService) SetTags(project string, zone string, instance string, tags *Tags) *InstancesSetTagsCall { c := &InstancesSetTagsCall{s: r.s, urlParams_: make(gensupport.URLParams)} @@ -61360,9 +69129,13 @@ func (c *InstancesSetTagsCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{instance}/setTags") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -61410,7 +69183,7 @@ func (c *InstancesSetTagsCall) Do(opts ...googleapi.CallOption) (*Operation, err } return ret, nil // { - // "description": "Sets tags for the specified instance to the data included in the request.", + // "description": "Sets network tags for the specified instance to the data included in the request.", // "httpMethod": "POST", // "id": "compute.instances.setTags", // "parameterOrder": [ @@ -61422,7 +69195,7 @@ func (c *InstancesSetTagsCall) Do(opts ...googleapi.CallOption) (*Operation, err // "instance": { // "description": "Name of the instance scoping this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -61516,9 +69289,13 @@ func (c *InstancesSimulateMaintenanceEventCall) doRequest(alt string) (*http.Res reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{instance}/simulateMaintenanceEvent") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -61578,7 +69355,7 @@ func (c *InstancesSimulateMaintenanceEventCall) Do(opts ...googleapi.CallOption) // "instance": { // "description": "Name of the instance scoping this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -61684,9 +69461,13 @@ func (c *InstancesStartCall) doRequest(alt string) (*http.Response, error) { reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{instance}/start") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -61746,7 +69527,7 @@ func (c *InstancesStartCall) Do(opts ...googleapi.CallOption) (*Operation, error // "instance": { // "description": "Name of the instance resource to start.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -61864,9 +69645,13 @@ func (c *InstancesStartWithEncryptionKeyCall) doRequest(alt string) (*http.Respo } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{instance}/startWithEncryptionKey") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -61926,7 +69711,7 @@ func (c *InstancesStartWithEncryptionKeyCall) Do(opts ...googleapi.CallOption) ( // "instance": { // "description": "Name of the instance resource to start.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -62044,9 +69829,13 @@ func (c *InstancesStopCall) doRequest(alt string) (*http.Response, error) { reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{instance}/stop") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -62106,7 +69895,7 @@ func (c *InstancesStopCall) Do(opts ...googleapi.CallOption) (*Operation, error) // "instance": { // "description": "Name of the instance resource to stop.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -62142,6 +69931,199 @@ func (c *InstancesStopCall) Do(opts ...googleapi.CallOption) (*Operation, error) } +// method id "compute.instances.suspend": + +type InstancesSuspendCall struct { + s *Service + project string + zone string + instance string + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// Suspend: This method suspends a running instance, saving its state to +// persistent storage, and allows you to resume the instance at a later +// time. Suspended instances incur reduced per-minute, virtual machine +// usage charges while they are suspended. Any resources the virtual +// machine is using, such as persistent disks and static IP addresses, +// will continue to be charged until they are deleted. +func (r *InstancesService) Suspend(project string, zone string, instance string) *InstancesSuspendCall { + c := &InstancesSuspendCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.zone = zone + c.instance = instance + return c +} + +// DiscardLocalSsd sets the optional parameter "discardLocalSsd": If +// true, discard the contents of any attached localSSD partitions. +// Default value is false (== preserve localSSD data). +func (c *InstancesSuspendCall) DiscardLocalSsd(discardLocalSsd bool) *InstancesSuspendCall { + c.urlParams_.Set("discardLocalSsd", fmt.Sprint(discardLocalSsd)) + return c +} + +// RequestId sets the optional parameter "requestId": An optional +// request ID to identify requests. Specify a unique request ID so that +// if you must retry your request, the server will know to ignore the +// request if it has already been completed. +// +// For example, consider a situation where you make an initial request +// and the request times out. If you make the request again with the +// same request ID, the server can check if original operation with the +// same request ID was received, and if so, will ignore the second +// request. This prevents clients from accidentally creating duplicate +// commitments. +// +// The request ID must be a valid UUID with the exception that zero UUID +// is not supported (00000000-0000-0000-0000-000000000000). +func (c *InstancesSuspendCall) RequestId(requestId string) *InstancesSuspendCall { + c.urlParams_.Set("requestId", requestId) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *InstancesSuspendCall) Fields(s ...googleapi.Field) *InstancesSuspendCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *InstancesSuspendCall) Context(ctx context.Context) *InstancesSuspendCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *InstancesSuspendCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *InstancesSuspendCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{instance}/suspend") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "zone": c.zone, + "instance": c.instance, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.instances.suspend" call. +// Exactly one of *Operation or error will be non-nil. Any non-2xx +// status code is an error. Response headers are in either +// *Operation.ServerResponse.Header or (if a response was returned at +// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified +// to check whether the returned error was because +// http.StatusNotModified was returned. +func (c *InstancesSuspendCall) Do(opts ...googleapi.CallOption) (*Operation, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Operation{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "This method suspends a running instance, saving its state to persistent storage, and allows you to resume the instance at a later time. Suspended instances incur reduced per-minute, virtual machine usage charges while they are suspended. Any resources the virtual machine is using, such as persistent disks and static IP addresses, will continue to be charged until they are deleted.", + // "httpMethod": "POST", + // "id": "compute.instances.suspend", + // "parameterOrder": [ + // "project", + // "zone", + // "instance" + // ], + // "parameters": { + // "discardLocalSsd": { + // "description": "If true, discard the contents of any attached localSSD partitions. Default value is false (== preserve localSSD data).", + // "location": "query", + // "type": "boolean" + // }, + // "instance": { + // "description": "Name of the instance resource to suspend.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + // "required": true, + // "type": "string" + // }, + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "requestId": { + // "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", + // "location": "query", + // "type": "string" + // }, + // "zone": { + // "description": "The name of the zone for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/zones/{zone}/instances/{instance}/suspend", + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + // method id "compute.instances.testIamPermissions": type InstancesTestIamPermissionsCall struct { @@ -62204,9 +70186,13 @@ func (c *InstancesTestIamPermissionsCall) doRequest(alt string) (*http.Response, } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{resource}/testIamPermissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -62271,9 +70257,9 @@ func (c *InstancesTestIamPermissionsCall) Do(opts ...googleapi.CallOption) (*Tes // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -62385,9 +70371,13 @@ func (c *InstancesUpdateAccessConfigCall) doRequest(alt string) (*http.Response, } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{instance}/updateAccessConfig") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -62448,7 +70438,7 @@ func (c *InstancesUpdateAccessConfigCall) Do(opts ...googleapi.CallOption) (*Ope // "instance": { // "description": "The instance name for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -62493,6 +70483,194 @@ func (c *InstancesUpdateAccessConfigCall) Do(opts ...googleapi.CallOption) (*Ope } +// method id "compute.instances.updateDisplayDevice": + +type InstancesUpdateDisplayDeviceCall struct { + s *Service + project string + zone string + instance string + displaydevice *DisplayDevice + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// UpdateDisplayDevice: Updates the Display config for a VM instance. +// You can only use this method on a stopped VM instance. This method +// supports PATCH semantics and uses the JSON merge patch format and +// processing rules. +func (r *InstancesService) UpdateDisplayDevice(project string, zone string, instance string, displaydevice *DisplayDevice) *InstancesUpdateDisplayDeviceCall { + c := &InstancesUpdateDisplayDeviceCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.zone = zone + c.instance = instance + c.displaydevice = displaydevice + return c +} + +// RequestId sets the optional parameter "requestId": An optional +// request ID to identify requests. Specify a unique request ID so that +// if you must retry your request, the server will know to ignore the +// request if it has already been completed. +// +// For example, consider a situation where you make an initial request +// and the request times out. If you make the request again with the +// same request ID, the server can check if original operation with the +// same request ID was received, and if so, will ignore the second +// request. This prevents clients from accidentally creating duplicate +// commitments. +// +// The request ID must be a valid UUID with the exception that zero UUID +// is not supported (00000000-0000-0000-0000-000000000000). +func (c *InstancesUpdateDisplayDeviceCall) RequestId(requestId string) *InstancesUpdateDisplayDeviceCall { + c.urlParams_.Set("requestId", requestId) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *InstancesUpdateDisplayDeviceCall) Fields(s ...googleapi.Field) *InstancesUpdateDisplayDeviceCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *InstancesUpdateDisplayDeviceCall) Context(ctx context.Context) *InstancesUpdateDisplayDeviceCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *InstancesUpdateDisplayDeviceCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *InstancesUpdateDisplayDeviceCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.displaydevice) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{instance}/updateDisplayDevice") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("PATCH", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "zone": c.zone, + "instance": c.instance, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.instances.updateDisplayDevice" call. +// Exactly one of *Operation or error will be non-nil. Any non-2xx +// status code is an error. Response headers are in either +// *Operation.ServerResponse.Header or (if a response was returned at +// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified +// to check whether the returned error was because +// http.StatusNotModified was returned. +func (c *InstancesUpdateDisplayDeviceCall) Do(opts ...googleapi.CallOption) (*Operation, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Operation{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Updates the Display config for a VM instance. You can only use this method on a stopped VM instance. This method supports PATCH semantics and uses the JSON merge patch format and processing rules.", + // "httpMethod": "PATCH", + // "id": "compute.instances.updateDisplayDevice", + // "parameterOrder": [ + // "project", + // "zone", + // "instance" + // ], + // "parameters": { + // "instance": { + // "description": "Name of the instance scoping this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // }, + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "requestId": { + // "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", + // "location": "query", + // "type": "string" + // }, + // "zone": { + // "description": "The name of the zone for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/zones/{zone}/instances/{instance}/updateDisplayDevice", + // "request": { + // "$ref": "DisplayDevice" + // }, + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + // method id "compute.instances.updateNetworkInterface": type InstancesUpdateNetworkInterfaceCall struct { @@ -62575,9 +70753,13 @@ func (c *InstancesUpdateNetworkInterfaceCall) doRequest(alt string) (*http.Respo } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{instance}/updateNetworkInterface") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PATCH", urls, body) + req, err := http.NewRequest("PATCH", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -62638,7 +70820,7 @@ func (c *InstancesUpdateNetworkInterfaceCall) Do(opts ...googleapi.CallOption) ( // "instance": { // "description": "The instance name for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -62696,9 +70878,10 @@ type InstancesUpdateShieldedVmConfigCall struct { header_ http.Header } -// UpdateShieldedVmConfig: Updates the Shielded VM config for an -// instance. This method supports PATCH semantics and uses the JSON -// merge patch format and processing rules. +// UpdateShieldedVmConfig: Updates the Shielded VM config for a VM +// instance. You can only use this method on a stopped VM instance. This +// method supports PATCH semantics and uses the JSON merge patch format +// and processing rules. func (r *InstancesService) UpdateShieldedVmConfig(project string, zone string, instance string, shieldedvmconfig *ShieldedVmConfig) *InstancesUpdateShieldedVmConfigCall { c := &InstancesUpdateShieldedVmConfigCall{s: r.s, urlParams_: make(gensupport.URLParams)} c.project = project @@ -62765,9 +70948,13 @@ func (c *InstancesUpdateShieldedVmConfigCall) doRequest(alt string) (*http.Respo } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{instance}/updateShieldedVmConfig") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PATCH", urls, body) + req, err := http.NewRequest("PATCH", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -62815,7 +71002,7 @@ func (c *InstancesUpdateShieldedVmConfigCall) Do(opts ...googleapi.CallOption) ( } return ret, nil // { - // "description": "Updates the Shielded VM config for an instance. This method supports PATCH semantics and uses the JSON merge patch format and processing rules.", + // "description": "Updates the Shielded VM config for a VM instance. You can only use this method on a stopped VM instance. This method supports PATCH semantics and uses the JSON merge patch format and processing rules.", // "httpMethod": "PATCH", // "id": "compute.instances.updateShieldedVmConfig", // "parameterOrder": [ @@ -62827,7 +71014,7 @@ func (c *InstancesUpdateShieldedVmConfigCall) Do(opts ...googleapi.CallOption) ( // "instance": { // "description": "Name of the instance scoping this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -62994,9 +71181,13 @@ func (c *InterconnectAttachmentsAggregatedListCall) doRequest(alt string) (*http } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/aggregated/interconnectAttachments") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -63188,9 +71379,13 @@ func (c *InterconnectAttachmentsDeleteCall) doRequest(alt string) (*http.Respons reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/interconnectAttachments/{interconnectAttachment}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -63354,9 +71549,13 @@ func (c *InterconnectAttachmentsGetCall) doRequest(alt string) (*http.Response, } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/interconnectAttachments/{interconnectAttachment}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -63527,9 +71726,13 @@ func (c *InterconnectAttachmentsInsertCall) doRequest(alt string) (*http.Respons } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/interconnectAttachments") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -63749,9 +71952,13 @@ func (c *InterconnectAttachmentsListCall) doRequest(alt string) (*http.Response, } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/interconnectAttachments") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -63960,9 +72167,13 @@ func (c *InterconnectAttachmentsPatchCall) doRequest(alt string) (*http.Response } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/interconnectAttachments/{interconnectAttachment}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PATCH", urls, body) + req, err := http.NewRequest("PATCH", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -64142,9 +72353,13 @@ func (c *InterconnectAttachmentsSetLabelsCall) doRequest(alt string) (*http.Resp } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/interconnectAttachments/{resource}/setLabels") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -64221,9 +72436,9 @@ func (c *InterconnectAttachmentsSetLabelsCall) Do(opts ...googleapi.CallOption) // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -64305,9 +72520,13 @@ func (c *InterconnectAttachmentsTestIamPermissionsCall) doRequest(alt string) (* } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/interconnectAttachments/{resource}/testIamPermissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -64379,9 +72598,9 @@ func (c *InterconnectAttachmentsTestIamPermissionsCall) Do(opts ...googleapi.Cal // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -64470,9 +72689,13 @@ func (c *InterconnectLocationsGetCall) doRequest(alt string) (*http.Response, er } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/interconnectLocations/{interconnectLocation}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -64683,9 +72906,13 @@ func (c *InterconnectLocationsListCall) doRequest(alt string) (*http.Response, e } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/interconnectLocations") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -64874,9 +73101,13 @@ func (c *InterconnectsDeleteCall) doRequest(alt string) (*http.Response, error) reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/interconnects/{interconnect}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -65030,9 +73261,13 @@ func (c *InterconnectsGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/interconnects/{interconnect}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -65115,6 +73350,163 @@ func (c *InterconnectsGetCall) Do(opts ...googleapi.CallOption) (*Interconnect, } +// method id "compute.interconnects.getDiagnostics": + +type InterconnectsGetDiagnosticsCall struct { + s *Service + project string + interconnect string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// GetDiagnostics: Returns the interconnectDiagnostics for the specified +// interconnect. +func (r *InterconnectsService) GetDiagnostics(project string, interconnect string) *InterconnectsGetDiagnosticsCall { + c := &InterconnectsGetDiagnosticsCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.interconnect = interconnect + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *InterconnectsGetDiagnosticsCall) Fields(s ...googleapi.Field) *InterconnectsGetDiagnosticsCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// IfNoneMatch sets the optional parameter which makes the operation +// fail if the object's ETag matches the given value. This is useful for +// getting updates only after the object has changed since the last +// request. Use googleapi.IsNotModified to check whether the response +// error from Do is the result of In-None-Match. +func (c *InterconnectsGetDiagnosticsCall) IfNoneMatch(entityTag string) *InterconnectsGetDiagnosticsCall { + c.ifNoneMatch_ = entityTag + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *InterconnectsGetDiagnosticsCall) Context(ctx context.Context) *InterconnectsGetDiagnosticsCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *InterconnectsGetDiagnosticsCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *InterconnectsGetDiagnosticsCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + if c.ifNoneMatch_ != "" { + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) + } + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/interconnects/{interconnect}/getDiagnostics") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "interconnect": c.interconnect, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.interconnects.getDiagnostics" call. +// Exactly one of *InterconnectsGetDiagnosticsResponse or error will be +// non-nil. Any non-2xx status code is an error. Response headers are in +// either *InterconnectsGetDiagnosticsResponse.ServerResponse.Header or +// (if a response was returned at all) in +// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check +// whether the returned error was because http.StatusNotModified was +// returned. +func (c *InterconnectsGetDiagnosticsCall) Do(opts ...googleapi.CallOption) (*InterconnectsGetDiagnosticsResponse, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &InterconnectsGetDiagnosticsResponse{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Returns the interconnectDiagnostics for the specified interconnect.", + // "httpMethod": "GET", + // "id": "compute.interconnects.getDiagnostics", + // "parameterOrder": [ + // "project", + // "interconnect" + // ], + // "parameters": { + // "interconnect": { + // "description": "Name of the interconnect resource to query.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // }, + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/global/interconnects/{interconnect}/getDiagnostics", + // "response": { + // "$ref": "InterconnectsGetDiagnosticsResponse" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute", + // "https://www.googleapis.com/auth/compute.readonly" + // ] + // } + +} + // method id "compute.interconnects.insert": type InterconnectsInsertCall struct { @@ -65192,9 +73584,13 @@ func (c *InterconnectsInsertCall) doRequest(alt string) (*http.Response, error) } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/interconnects") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -65403,9 +73799,13 @@ func (c *InterconnectsListCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/interconnects") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -65603,9 +74003,13 @@ func (c *InterconnectsPatchCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/interconnects/{interconnect}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PATCH", urls, body) + req, err := http.NewRequest("PATCH", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -65755,9 +74159,13 @@ func (c *InterconnectsSetLabelsCall) doRequest(alt string) (*http.Response, erro } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/interconnects/{resource}/setLabels") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -65820,9 +74228,9 @@ func (c *InterconnectsSetLabelsCall) Do(opts ...googleapi.CallOption) (*Operatio // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -65902,9 +74310,13 @@ func (c *InterconnectsTestIamPermissionsCall) doRequest(alt string) (*http.Respo } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/interconnects/{resource}/testIamPermissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -65967,9 +74379,9 @@ func (c *InterconnectsTestIamPermissionsCall) Do(opts ...googleapi.CallOption) ( // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "(?:[-a-z0-9_]{0,62}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -66057,9 +74469,13 @@ func (c *LicenseCodesGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/licenseCodes/{licenseCode}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -66213,9 +74629,13 @@ func (c *LicensesDeleteCall) doRequest(alt string) (*http.Response, error) { reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/licenses/{license}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -66369,9 +74789,13 @@ func (c *LicensesGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/licenses/{license}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -66530,9 +74954,13 @@ func (c *LicensesInsertCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/licenses") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -66748,9 +75176,13 @@ func (c *LicensesListCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/licenses") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -66868,6 +75300,157 @@ func (c *LicensesListCall) Pages(ctx context.Context, f func(*LicensesListRespon } } +// method id "compute.licenses.setIamPolicy": + +type LicensesSetIamPolicyCall struct { + s *Service + project string + resource string + globalsetpolicyrequest *GlobalSetPolicyRequest + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// SetIamPolicy: Sets the access control policy on the specified +// resource. Replaces any existing policy. +func (r *LicensesService) SetIamPolicy(project string, resource string, globalsetpolicyrequest *GlobalSetPolicyRequest) *LicensesSetIamPolicyCall { + c := &LicensesSetIamPolicyCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.resource = resource + c.globalsetpolicyrequest = globalsetpolicyrequest + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *LicensesSetIamPolicyCall) Fields(s ...googleapi.Field) *LicensesSetIamPolicyCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *LicensesSetIamPolicyCall) Context(ctx context.Context) *LicensesSetIamPolicyCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *LicensesSetIamPolicyCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *LicensesSetIamPolicyCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.globalsetpolicyrequest) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/licenses/{resource}/setIamPolicy") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "resource": c.resource, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.licenses.setIamPolicy" call. +// Exactly one of *Policy or error will be non-nil. Any non-2xx status +// code is an error. Response headers are in either +// *Policy.ServerResponse.Header or (if a response was returned at all) +// in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to +// check whether the returned error was because http.StatusNotModified +// was returned. +func (c *LicensesSetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Policy, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Policy{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Sets the access control policy on the specified resource. Replaces any existing policy.", + // "httpMethod": "POST", + // "id": "compute.licenses.setIamPolicy", + // "parameterOrder": [ + // "project", + // "resource" + // ], + // "parameters": { + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "resource": { + // "description": "Name or id of the resource for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/global/licenses/{resource}/setIamPolicy", + // "request": { + // "$ref": "GlobalSetPolicyRequest" + // }, + // "response": { + // "$ref": "Policy" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + // method id "compute.machineTypes.aggregatedList": type MachineTypesAggregatedListCall struct { @@ -66996,9 +75579,13 @@ func (c *MachineTypesAggregatedListCall) doRequest(alt string) (*http.Response, } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/aggregated/machineTypes") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -67186,9 +75773,13 @@ func (c *MachineTypesGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/machineTypes/{machineType}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -67411,9 +76002,13 @@ func (c *MachineTypesListCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/machineTypes") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -67668,9 +76263,13 @@ func (c *NetworkEndpointGroupsAggregatedListCall) doRequest(alt string) (*http.R } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/aggregated/networkEndpointGroups") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -67870,9 +76469,13 @@ func (c *NetworkEndpointGroupsAttachNetworkEndpointsCall) doRequest(alt string) } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/networkEndpointGroups/{networkEndpointGroup}/attachNetworkEndpoints") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -68045,9 +76648,13 @@ func (c *NetworkEndpointGroupsDeleteCall) doRequest(alt string) (*http.Response, reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/networkEndpointGroups/{networkEndpointGroup}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -68222,9 +76829,13 @@ func (c *NetworkEndpointGroupsDetachNetworkEndpointsCall) doRequest(alt string) } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/networkEndpointGroups/{networkEndpointGroup}/detachNetworkEndpoints") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -68390,9 +77001,13 @@ func (c *NetworkEndpointGroupsGetCall) doRequest(alt string) (*http.Response, er } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/networkEndpointGroups/{networkEndpointGroup}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -68561,9 +77176,13 @@ func (c *NetworkEndpointGroupsInsertCall) doRequest(alt string) (*http.Response, } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/networkEndpointGroups") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -68782,9 +77401,13 @@ func (c *NetworkEndpointGroupsListCall) doRequest(alt string) (*http.Response, e } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/networkEndpointGroups") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -69035,9 +77658,13 @@ func (c *NetworkEndpointGroupsListNetworkEndpointsCall) doRequest(alt string) (* } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/networkEndpointGroups/{networkEndpointGroup}/listNetworkEndpoints") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -69238,9 +77865,13 @@ func (c *NetworkEndpointGroupsTestIamPermissionsCall) doRequest(alt string) (*ht } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/networkEndpointGroups/{resource}/testIamPermissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -69305,9 +77936,9 @@ func (c *NetworkEndpointGroupsTestIamPermissionsCall) Do(opts ...googleapi.CallO // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -69413,9 +78044,13 @@ func (c *NetworksAddPeeringCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/networks/{network}/addPeering") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -69473,7 +78108,7 @@ func (c *NetworksAddPeeringCall) Do(opts ...googleapi.CallOption) (*Operation, e // "network": { // "description": "Name of the network resource to add peering to.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -69577,9 +78212,13 @@ func (c *NetworksDeleteCall) doRequest(alt string) (*http.Response, error) { reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/networks/{network}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -69637,7 +78276,7 @@ func (c *NetworksDeleteCall) Do(opts ...googleapi.CallOption) (*Operation, error // "network": { // "description": "Name of the network to delete.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -69734,9 +78373,13 @@ func (c *NetworksGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/networks/{network}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -69794,7 +78437,7 @@ func (c *NetworksGetCall) Do(opts ...googleapi.CallOption) (*Network, error) { // "network": { // "description": "Name of the network to return.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -69897,9 +78540,13 @@ func (c *NetworksInsertCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/networks") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -70109,9 +78756,13 @@ func (c *NetworksListCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/networks") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -70229,6 +78880,318 @@ func (c *NetworksListCall) Pages(ctx context.Context, f func(*NetworkList) error } } +// method id "compute.networks.listPeeringRoutes": + +type NetworksListPeeringRoutesCall struct { + s *Service + project string + network string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// ListPeeringRoutes: Lists the peering routes exchanged over peering +// connection. +func (r *NetworksService) ListPeeringRoutes(project string, network string) *NetworksListPeeringRoutesCall { + c := &NetworksListPeeringRoutesCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.network = network + return c +} + +// Direction sets the optional parameter "direction": The direction of +// the exchanged routes. +// +// Possible values: +// "INCOMING" +// "OUTGOING" +func (c *NetworksListPeeringRoutesCall) Direction(direction string) *NetworksListPeeringRoutesCall { + c.urlParams_.Set("direction", direction) + return c +} + +// Filter sets the optional parameter "filter": A filter expression that +// filters resources listed in the response. The expression must specify +// the field name, a comparison operator, and the value that you want to +// use for filtering. The value must be a string, a number, or a +// boolean. The comparison operator must be either =, !=, >, or <. +// +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. +// +// You can also filter nested fields. For example, you could specify +// scheduling.automaticRestart = false to include instances only if they +// are not scheduled for automatic restarts. You can use filtering on +// nested fields to filter based on resource labels. +// +// To filter on multiple expressions, provide each separate expression +// within parentheses. For example, (scheduling.automaticRestart = true) +// (cpuPlatform = "Intel Skylake"). By default, each expression is an +// AND expression. However, you can include AND and OR expressions +// explicitly. For example, (cpuPlatform = "Intel Skylake") OR +// (cpuPlatform = "Intel Broadwell") AND (scheduling.automaticRestart = +// true). +func (c *NetworksListPeeringRoutesCall) Filter(filter string) *NetworksListPeeringRoutesCall { + c.urlParams_.Set("filter", filter) + return c +} + +// MaxResults sets the optional parameter "maxResults": The maximum +// number of results per page that should be returned. If the number of +// available results is larger than maxResults, Compute Engine returns a +// nextPageToken that can be used to get the next page of results in +// subsequent list requests. Acceptable values are 0 to 500, inclusive. +// (Default: 500) +func (c *NetworksListPeeringRoutesCall) MaxResults(maxResults int64) *NetworksListPeeringRoutesCall { + c.urlParams_.Set("maxResults", fmt.Sprint(maxResults)) + return c +} + +// OrderBy sets the optional parameter "orderBy": Sorts list results by +// a certain order. By default, results are returned in alphanumerical +// order based on the resource name. +// +// You can also sort results in descending order based on the creation +// timestamp using orderBy="creationTimestamp desc". This sorts results +// based on the creationTimestamp field in reverse chronological order +// (newest result first). Use this to sort resources like operations so +// that the newest operation is returned first. +// +// Currently, only sorting by name or creationTimestamp desc is +// supported. +func (c *NetworksListPeeringRoutesCall) OrderBy(orderBy string) *NetworksListPeeringRoutesCall { + c.urlParams_.Set("orderBy", orderBy) + return c +} + +// PageToken sets the optional parameter "pageToken": Specifies a page +// token to use. Set pageToken to the nextPageToken returned by a +// previous list request to get the next page of results. +func (c *NetworksListPeeringRoutesCall) PageToken(pageToken string) *NetworksListPeeringRoutesCall { + c.urlParams_.Set("pageToken", pageToken) + return c +} + +// PeeringName sets the optional parameter "peeringName": The response +// will show routes exchanged over the given peering connection. +func (c *NetworksListPeeringRoutesCall) PeeringName(peeringName string) *NetworksListPeeringRoutesCall { + c.urlParams_.Set("peeringName", peeringName) + return c +} + +// Region sets the optional parameter "region": The region of the +// request. The response will include all subnet routes, static routes +// and dynamic routes in the region. +func (c *NetworksListPeeringRoutesCall) Region(region string) *NetworksListPeeringRoutesCall { + c.urlParams_.Set("region", region) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *NetworksListPeeringRoutesCall) Fields(s ...googleapi.Field) *NetworksListPeeringRoutesCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// IfNoneMatch sets the optional parameter which makes the operation +// fail if the object's ETag matches the given value. This is useful for +// getting updates only after the object has changed since the last +// request. Use googleapi.IsNotModified to check whether the response +// error from Do is the result of In-None-Match. +func (c *NetworksListPeeringRoutesCall) IfNoneMatch(entityTag string) *NetworksListPeeringRoutesCall { + c.ifNoneMatch_ = entityTag + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *NetworksListPeeringRoutesCall) Context(ctx context.Context) *NetworksListPeeringRoutesCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *NetworksListPeeringRoutesCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *NetworksListPeeringRoutesCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + if c.ifNoneMatch_ != "" { + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) + } + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/networks/{network}/listPeeringRoutes") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "network": c.network, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.networks.listPeeringRoutes" call. +// Exactly one of *ExchangedPeeringRoutesList or error will be non-nil. +// Any non-2xx status code is an error. Response headers are in either +// *ExchangedPeeringRoutesList.ServerResponse.Header or (if a response +// was returned at all) in error.(*googleapi.Error).Header. Use +// googleapi.IsNotModified to check whether the returned error was +// because http.StatusNotModified was returned. +func (c *NetworksListPeeringRoutesCall) Do(opts ...googleapi.CallOption) (*ExchangedPeeringRoutesList, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &ExchangedPeeringRoutesList{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Lists the peering routes exchanged over peering connection.", + // "httpMethod": "GET", + // "id": "compute.networks.listPeeringRoutes", + // "parameterOrder": [ + // "project", + // "network" + // ], + // "parameters": { + // "direction": { + // "description": "The direction of the exchanged routes.", + // "enum": [ + // "INCOMING", + // "OUTGOING" + // ], + // "enumDescriptions": [ + // "", + // "" + // ], + // "location": "query", + // "type": "string" + // }, + // "filter": { + // "description": "A filter expression that filters resources listed in the response. The expression must specify the field name, a comparison operator, and the value that you want to use for filtering. The value must be a string, a number, or a boolean. The comparison operator must be either =, !=, \u003e, or \u003c.\n\nFor example, if you are filtering Compute Engine instances, you can exclude instances named example-instance by specifying name != example-instance.\n\nYou can also filter nested fields. For example, you could specify scheduling.automaticRestart = false to include instances only if they are not scheduled for automatic restarts. You can use filtering on nested fields to filter based on resource labels.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart = true) (cpuPlatform = \"Intel Skylake\"). By default, each expression is an AND expression. However, you can include AND and OR expressions explicitly. For example, (cpuPlatform = \"Intel Skylake\") OR (cpuPlatform = \"Intel Broadwell\") AND (scheduling.automaticRestart = true).", + // "location": "query", + // "type": "string" + // }, + // "maxResults": { + // "default": "500", + // "description": "The maximum number of results per page that should be returned. If the number of available results is larger than maxResults, Compute Engine returns a nextPageToken that can be used to get the next page of results in subsequent list requests. Acceptable values are 0 to 500, inclusive. (Default: 500)", + // "format": "uint32", + // "location": "query", + // "minimum": "0", + // "type": "integer" + // }, + // "network": { + // "description": "Name of the network for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + // "required": true, + // "type": "string" + // }, + // "orderBy": { + // "description": "Sorts list results by a certain order. By default, results are returned in alphanumerical order based on the resource name.\n\nYou can also sort results in descending order based on the creation timestamp using orderBy=\"creationTimestamp desc\". This sorts results based on the creationTimestamp field in reverse chronological order (newest result first). Use this to sort resources like operations so that the newest operation is returned first.\n\nCurrently, only sorting by name or creationTimestamp desc is supported.", + // "location": "query", + // "type": "string" + // }, + // "pageToken": { + // "description": "Specifies a page token to use. Set pageToken to the nextPageToken returned by a previous list request to get the next page of results.", + // "location": "query", + // "type": "string" + // }, + // "peeringName": { + // "description": "The response will show routes exchanged over the given peering connection.", + // "location": "query", + // "type": "string" + // }, + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "region": { + // "description": "The region of the request. The response will include all subnet routes, static routes and dynamic routes in the region.", + // "location": "query", + // "type": "string" + // } + // }, + // "path": "{project}/global/networks/{network}/listPeeringRoutes", + // "response": { + // "$ref": "ExchangedPeeringRoutesList" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute", + // "https://www.googleapis.com/auth/compute.readonly" + // ] + // } + +} + +// Pages invokes f for each page of results. +// A non-nil error returned from f will halt the iteration. +// The provided context supersedes any context provided to the Context method. +func (c *NetworksListPeeringRoutesCall) Pages(ctx context.Context, f func(*ExchangedPeeringRoutesList) error) error { + c.ctx_ = ctx + defer c.PageToken(c.urlParams_.Get("pageToken")) // reset paging to original point + for { + x, err := c.Do() + if err != nil { + return err + } + if err := f(x); err != nil { + return err + } + if x.NextPageToken == "" { + return nil + } + c.PageToken(x.NextPageToken) + } +} + // method id "compute.networks.patch": type NetworksPatchCall struct { @@ -70309,9 +79272,13 @@ func (c *NetworksPatchCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/networks/{network}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PATCH", urls, body) + req, err := http.NewRequest("PATCH", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -70369,7 +79336,7 @@ func (c *NetworksPatchCall) Do(opts ...googleapi.CallOption) (*Operation, error) // "network": { // "description": "Name of the network to update.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -70479,9 +79446,13 @@ func (c *NetworksRemovePeeringCall) doRequest(alt string) (*http.Response, error } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/networks/{network}/removePeering") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -70539,7 +79510,7 @@ func (c *NetworksRemovePeeringCall) Do(opts ...googleapi.CallOption) (*Operation // "network": { // "description": "Name of the network resource to remove peering from.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -70643,9 +79614,13 @@ func (c *NetworksSwitchToCustomModeCall) doRequest(alt string) (*http.Response, reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/networks/{network}/switchToCustomMode") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -70703,7 +79678,7 @@ func (c *NetworksSwitchToCustomModeCall) Do(opts ...googleapi.CallOption) (*Oper // "network": { // "description": "Name of the network to be updated.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -70792,9 +79767,13 @@ func (c *NetworksTestIamPermissionsCall) doRequest(alt string) (*http.Response, } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/networks/{resource}/testIamPermissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -70857,9 +79836,9 @@ func (c *NetworksTestIamPermissionsCall) Do(opts ...googleapi.CallOption) (*Test // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "(?:[-a-z0-9_]{0,62}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -70880,6 +79859,183 @@ func (c *NetworksTestIamPermissionsCall) Do(opts ...googleapi.CallOption) (*Test } +// method id "compute.networks.updatePeering": + +type NetworksUpdatePeeringCall struct { + s *Service + project string + network string + networksupdatepeeringrequest *NetworksUpdatePeeringRequest + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// UpdatePeering: Updates the specified network peering with the data +// included in the request Only the following fields can be modified: +// NetworkPeering.export_custom_routes, and +// NetworkPeering.import_custom_routes +func (r *NetworksService) UpdatePeering(project string, network string, networksupdatepeeringrequest *NetworksUpdatePeeringRequest) *NetworksUpdatePeeringCall { + c := &NetworksUpdatePeeringCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.network = network + c.networksupdatepeeringrequest = networksupdatepeeringrequest + return c +} + +// RequestId sets the optional parameter "requestId": An optional +// request ID to identify requests. Specify a unique request ID so that +// if you must retry your request, the server will know to ignore the +// request if it has already been completed. +// +// For example, consider a situation where you make an initial request +// and the request times out. If you make the request again with the +// same request ID, the server can check if original operation with the +// same request ID was received, and if so, will ignore the second +// request. This prevents clients from accidentally creating duplicate +// commitments. +// +// The request ID must be a valid UUID with the exception that zero UUID +// is not supported (00000000-0000-0000-0000-000000000000). +func (c *NetworksUpdatePeeringCall) RequestId(requestId string) *NetworksUpdatePeeringCall { + c.urlParams_.Set("requestId", requestId) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *NetworksUpdatePeeringCall) Fields(s ...googleapi.Field) *NetworksUpdatePeeringCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *NetworksUpdatePeeringCall) Context(ctx context.Context) *NetworksUpdatePeeringCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *NetworksUpdatePeeringCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *NetworksUpdatePeeringCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.networksupdatepeeringrequest) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/networks/{network}/updatePeering") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("PATCH", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "network": c.network, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.networks.updatePeering" call. +// Exactly one of *Operation or error will be non-nil. Any non-2xx +// status code is an error. Response headers are in either +// *Operation.ServerResponse.Header or (if a response was returned at +// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified +// to check whether the returned error was because +// http.StatusNotModified was returned. +func (c *NetworksUpdatePeeringCall) Do(opts ...googleapi.CallOption) (*Operation, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Operation{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Updates the specified network peering with the data included in the request Only the following fields can be modified: NetworkPeering.export_custom_routes, and NetworkPeering.import_custom_routes", + // "httpMethod": "PATCH", + // "id": "compute.networks.updatePeering", + // "parameterOrder": [ + // "project", + // "network" + // ], + // "parameters": { + // "network": { + // "description": "Name of the network resource which the updated peering is belonging to.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + // "required": true, + // "type": "string" + // }, + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "requestId": { + // "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", + // "location": "query", + // "type": "string" + // } + // }, + // "path": "{project}/global/networks/{network}/updatePeering", + // "request": { + // "$ref": "NetworksUpdatePeeringRequest" + // }, + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + // method id "compute.nodeGroups.addNodes": type NodeGroupsAddNodesCall struct { @@ -70960,9 +80116,13 @@ func (c *NodeGroupsAddNodesCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/nodeGroups/{nodeGroup}/addNodes") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -71020,7 +80180,7 @@ func (c *NodeGroupsAddNodesCall) Do(opts ...googleapi.CallOption) (*Operation, e // ], // "parameters": { // "nodeGroup": { - // "description": "Name of the NodeGroup resource to delete.", + // "description": "Name of the NodeGroup resource.", // "location": "path", // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", // "required": true, @@ -71072,7 +80232,8 @@ type NodeGroupsAggregatedListCall struct { header_ http.Header } -// AggregatedList: Retrieves an aggregated list of node groups. +// AggregatedList: Retrieves an aggregated list of node groups. Note: +// use nodeGroups.listNodes for more details about each group. func (r *NodeGroupsService) AggregatedList(project string) *NodeGroupsAggregatedListCall { c := &NodeGroupsAggregatedListCall{s: r.s, urlParams_: make(gensupport.URLParams)} c.project = project @@ -71188,9 +80349,13 @@ func (c *NodeGroupsAggregatedListCall) doRequest(alt string) (*http.Response, er } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/aggregated/nodeGroups") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -71236,7 +80401,7 @@ func (c *NodeGroupsAggregatedListCall) Do(opts ...googleapi.CallOption) (*NodeGr } return ret, nil // { - // "description": "Retrieves an aggregated list of node groups.", + // "description": "Retrieves an aggregated list of node groups. Note: use nodeGroups.listNodes for more details about each group.", // "httpMethod": "GET", // "id": "compute.nodeGroups.aggregatedList", // "parameterOrder": [ @@ -71381,9 +80546,13 @@ func (c *NodeGroupsDeleteCall) doRequest(alt string) (*http.Response, error) { reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/nodeGroups/{nodeGroup}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -71559,9 +80728,13 @@ func (c *NodeGroupsDeleteNodesCall) doRequest(alt string) (*http.Response, error } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/nodeGroups/{nodeGroup}/deleteNodes") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -71674,7 +80847,8 @@ type NodeGroupsGetCall struct { } // Get: Returns the specified NodeGroup. Get a list of available -// NodeGroups by making a list() request. +// NodeGroups by making a list() request. Note: the "nodes" field should +// not be used. Use nodeGroups.listNodes instead. func (r *NodeGroupsService) Get(project string, zone string, nodeGroup string) *NodeGroupsGetCall { c := &NodeGroupsGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} c.project = project @@ -71729,9 +80903,13 @@ func (c *NodeGroupsGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/nodeGroups/{nodeGroup}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -71779,7 +80957,7 @@ func (c *NodeGroupsGetCall) Do(opts ...googleapi.CallOption) (*NodeGroup, error) } return ret, nil // { - // "description": "Returns the specified NodeGroup. Get a list of available NodeGroups by making a list() request.", + // "description": "Returns the specified NodeGroup. Get a list of available NodeGroups by making a list() request. Note: the \"nodes\" field should not be used. Use nodeGroups.listNodes instead.", // "httpMethod": "GET", // "id": "compute.nodeGroups.get", // "parameterOrder": [ @@ -71892,9 +81070,13 @@ func (c *NodeGroupsGetIamPolicyCall) doRequest(alt string) (*http.Response, erro } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/nodeGroups/{resource}/getIamPolicy") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -71959,9 +81141,9 @@ func (c *NodeGroupsGetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Policy, // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -72066,9 +81248,13 @@ func (c *NodeGroupsInsertCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/nodeGroups") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -72179,7 +81365,8 @@ type NodeGroupsListCall struct { } // List: Retrieves a list of node groups available to the specified -// project. +// project. Note: use nodeGroups.listNodes for more details about each +// group. func (r *NodeGroupsService) List(project string, zone string) *NodeGroupsListCall { c := &NodeGroupsListCall{s: r.s, urlParams_: make(gensupport.URLParams)} c.project = project @@ -72296,9 +81483,13 @@ func (c *NodeGroupsListCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/nodeGroups") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -72345,7 +81536,7 @@ func (c *NodeGroupsListCall) Do(opts ...googleapi.CallOption) (*NodeGroupList, e } return ret, nil // { - // "description": "Retrieves a list of node groups available to the specified project.", + // "description": "Retrieves a list of node groups available to the specified project. Note: use nodeGroups.listNodes for more details about each group.", // "httpMethod": "GET", // "id": "compute.nodeGroups.list", // "parameterOrder": [ @@ -72425,6 +81616,265 @@ func (c *NodeGroupsListCall) Pages(ctx context.Context, f func(*NodeGroupList) e } } +// method id "compute.nodeGroups.listNodes": + +type NodeGroupsListNodesCall struct { + s *Service + project string + zone string + nodeGroup string + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// ListNodes: Lists nodes in the node group. +func (r *NodeGroupsService) ListNodes(project string, zone string, nodeGroup string) *NodeGroupsListNodesCall { + c := &NodeGroupsListNodesCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.zone = zone + c.nodeGroup = nodeGroup + return c +} + +// Filter sets the optional parameter "filter": A filter expression that +// filters resources listed in the response. The expression must specify +// the field name, a comparison operator, and the value that you want to +// use for filtering. The value must be a string, a number, or a +// boolean. The comparison operator must be either =, !=, >, or <. +// +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. +// +// You can also filter nested fields. For example, you could specify +// scheduling.automaticRestart = false to include instances only if they +// are not scheduled for automatic restarts. You can use filtering on +// nested fields to filter based on resource labels. +// +// To filter on multiple expressions, provide each separate expression +// within parentheses. For example, (scheduling.automaticRestart = true) +// (cpuPlatform = "Intel Skylake"). By default, each expression is an +// AND expression. However, you can include AND and OR expressions +// explicitly. For example, (cpuPlatform = "Intel Skylake") OR +// (cpuPlatform = "Intel Broadwell") AND (scheduling.automaticRestart = +// true). +func (c *NodeGroupsListNodesCall) Filter(filter string) *NodeGroupsListNodesCall { + c.urlParams_.Set("filter", filter) + return c +} + +// MaxResults sets the optional parameter "maxResults": The maximum +// number of results per page that should be returned. If the number of +// available results is larger than maxResults, Compute Engine returns a +// nextPageToken that can be used to get the next page of results in +// subsequent list requests. Acceptable values are 0 to 500, inclusive. +// (Default: 500) +func (c *NodeGroupsListNodesCall) MaxResults(maxResults int64) *NodeGroupsListNodesCall { + c.urlParams_.Set("maxResults", fmt.Sprint(maxResults)) + return c +} + +// OrderBy sets the optional parameter "orderBy": Sorts list results by +// a certain order. By default, results are returned in alphanumerical +// order based on the resource name. +// +// You can also sort results in descending order based on the creation +// timestamp using orderBy="creationTimestamp desc". This sorts results +// based on the creationTimestamp field in reverse chronological order +// (newest result first). Use this to sort resources like operations so +// that the newest operation is returned first. +// +// Currently, only sorting by name or creationTimestamp desc is +// supported. +func (c *NodeGroupsListNodesCall) OrderBy(orderBy string) *NodeGroupsListNodesCall { + c.urlParams_.Set("orderBy", orderBy) + return c +} + +// PageToken sets the optional parameter "pageToken": Specifies a page +// token to use. Set pageToken to the nextPageToken returned by a +// previous list request to get the next page of results. +func (c *NodeGroupsListNodesCall) PageToken(pageToken string) *NodeGroupsListNodesCall { + c.urlParams_.Set("pageToken", pageToken) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *NodeGroupsListNodesCall) Fields(s ...googleapi.Field) *NodeGroupsListNodesCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *NodeGroupsListNodesCall) Context(ctx context.Context) *NodeGroupsListNodesCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *NodeGroupsListNodesCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *NodeGroupsListNodesCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/nodeGroups/{nodeGroup}/listNodes") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "zone": c.zone, + "nodeGroup": c.nodeGroup, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.nodeGroups.listNodes" call. +// Exactly one of *NodeGroupsListNodes or error will be non-nil. Any +// non-2xx status code is an error. Response headers are in either +// *NodeGroupsListNodes.ServerResponse.Header or (if a response was +// returned at all) in error.(*googleapi.Error).Header. Use +// googleapi.IsNotModified to check whether the returned error was +// because http.StatusNotModified was returned. +func (c *NodeGroupsListNodesCall) Do(opts ...googleapi.CallOption) (*NodeGroupsListNodes, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &NodeGroupsListNodes{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Lists nodes in the node group.", + // "httpMethod": "POST", + // "id": "compute.nodeGroups.listNodes", + // "parameterOrder": [ + // "project", + // "zone", + // "nodeGroup" + // ], + // "parameters": { + // "filter": { + // "description": "A filter expression that filters resources listed in the response. The expression must specify the field name, a comparison operator, and the value that you want to use for filtering. The value must be a string, a number, or a boolean. The comparison operator must be either =, !=, \u003e, or \u003c.\n\nFor example, if you are filtering Compute Engine instances, you can exclude instances named example-instance by specifying name != example-instance.\n\nYou can also filter nested fields. For example, you could specify scheduling.automaticRestart = false to include instances only if they are not scheduled for automatic restarts. You can use filtering on nested fields to filter based on resource labels.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart = true) (cpuPlatform = \"Intel Skylake\"). By default, each expression is an AND expression. However, you can include AND and OR expressions explicitly. For example, (cpuPlatform = \"Intel Skylake\") OR (cpuPlatform = \"Intel Broadwell\") AND (scheduling.automaticRestart = true).", + // "location": "query", + // "type": "string" + // }, + // "maxResults": { + // "default": "500", + // "description": "The maximum number of results per page that should be returned. If the number of available results is larger than maxResults, Compute Engine returns a nextPageToken that can be used to get the next page of results in subsequent list requests. Acceptable values are 0 to 500, inclusive. (Default: 500)", + // "format": "uint32", + // "location": "query", + // "minimum": "0", + // "type": "integer" + // }, + // "nodeGroup": { + // "description": "Name of the NodeGroup resource whose nodes you want to list.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // }, + // "orderBy": { + // "description": "Sorts list results by a certain order. By default, results are returned in alphanumerical order based on the resource name.\n\nYou can also sort results in descending order based on the creation timestamp using orderBy=\"creationTimestamp desc\". This sorts results based on the creationTimestamp field in reverse chronological order (newest result first). Use this to sort resources like operations so that the newest operation is returned first.\n\nCurrently, only sorting by name or creationTimestamp desc is supported.", + // "location": "query", + // "type": "string" + // }, + // "pageToken": { + // "description": "Specifies a page token to use. Set pageToken to the nextPageToken returned by a previous list request to get the next page of results.", + // "location": "query", + // "type": "string" + // }, + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "zone": { + // "description": "The name of the zone for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/zones/{zone}/nodeGroups/{nodeGroup}/listNodes", + // "response": { + // "$ref": "NodeGroupsListNodes" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute", + // "https://www.googleapis.com/auth/compute.readonly" + // ] + // } + +} + +// Pages invokes f for each page of results. +// A non-nil error returned from f will halt the iteration. +// The provided context supersedes any context provided to the Context method. +func (c *NodeGroupsListNodesCall) Pages(ctx context.Context, f func(*NodeGroupsListNodes) error) error { + c.ctx_ = ctx + defer c.PageToken(c.urlParams_.Get("pageToken")) // reset paging to original point + for { + x, err := c.Do() + if err != nil { + return err + } + if err := f(x); err != nil { + return err + } + if x.NextPageToken == "" { + return nil + } + c.PageToken(x.NextPageToken) + } +} + // method id "compute.nodeGroups.setIamPolicy": type NodeGroupsSetIamPolicyCall struct { @@ -72487,9 +81937,13 @@ func (c *NodeGroupsSetIamPolicyCall) doRequest(alt string) (*http.Response, erro } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/nodeGroups/{resource}/setIamPolicy") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -72554,9 +82008,9 @@ func (c *NodeGroupsSetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Policy, // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -72663,9 +82117,13 @@ func (c *NodeGroupsSetNodeTemplateCall) doRequest(alt string) (*http.Response, e } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/nodeGroups/{nodeGroup}/setNodeTemplate") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -72826,9 +82284,13 @@ func (c *NodeGroupsTestIamPermissionsCall) doRequest(alt string) (*http.Response } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/nodeGroups/{resource}/testIamPermissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -72893,9 +82355,9 @@ func (c *NodeGroupsTestIamPermissionsCall) Do(opts ...googleapi.CallOption) (*Te // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -73050,9 +82512,13 @@ func (c *NodeTemplatesAggregatedListCall) doRequest(alt string) (*http.Response, } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/aggregated/nodeTemplates") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -73243,9 +82709,13 @@ func (c *NodeTemplatesDeleteCall) doRequest(alt string) (*http.Response, error) reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/nodeTemplates/{nodeTemplate}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -73410,9 +82880,13 @@ func (c *NodeTemplatesGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/nodeTemplates/{nodeTemplate}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -73573,9 +83047,13 @@ func (c *NodeTemplatesGetIamPolicyCall) doRequest(alt string) (*http.Response, e } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/nodeTemplates/{resource}/getIamPolicy") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -73647,9 +83125,9 @@ func (c *NodeTemplatesGetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Polic // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -73746,9 +83224,13 @@ func (c *NodeTemplatesInsertCall) doRequest(alt string) (*http.Response, error) } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/nodeTemplates") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -73968,9 +83450,13 @@ func (c *NodeTemplatesListCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/nodeTemplates") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -74159,9 +83645,13 @@ func (c *NodeTemplatesSetIamPolicyCall) doRequest(alt string) (*http.Response, e } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/nodeTemplates/{resource}/setIamPolicy") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -74233,9 +83723,9 @@ func (c *NodeTemplatesSetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Polic // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -74317,9 +83807,13 @@ func (c *NodeTemplatesTestIamPermissionsCall) doRequest(alt string) (*http.Respo } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/nodeTemplates/{resource}/testIamPermissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -74391,9 +83885,9 @@ func (c *NodeTemplatesTestIamPermissionsCall) Do(opts ...googleapi.CallOption) ( // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -74541,9 +84035,13 @@ func (c *NodeTypesAggregatedListCall) doRequest(alt string) (*http.Response, err } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/aggregated/nodeTypes") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -74730,9 +84228,13 @@ func (c *NodeTypesGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/nodeTypes/{nodeType}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -74954,9 +84456,13 @@ func (c *NodeTypesListCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/nodeTypes") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -75152,9 +84658,13 @@ func (c *ProjectsDisableXpnHostCall) doRequest(alt string) (*http.Response, erro reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/disableXpnHost") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -75309,9 +84819,13 @@ func (c *ProjectsDisableXpnResourceCall) doRequest(alt string) (*http.Response, } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/disableXpnResource") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -75461,9 +84975,13 @@ func (c *ProjectsEnableXpnHostCall) doRequest(alt string) (*http.Response, error reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/enableXpnHost") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -75619,9 +85137,13 @@ func (c *ProjectsEnableXpnResourceCall) doRequest(alt string) (*http.Response, e } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/enableXpnResource") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -75767,9 +85289,13 @@ func (c *ProjectsGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -75908,9 +85434,13 @@ func (c *ProjectsGetXpnHostCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/getXpnHost") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -76002,25 +85532,64 @@ func (r *ProjectsService) GetXpnResources(project string) *ProjectsGetXpnResourc return c } -// Filter sets the optional parameter "filter": +// Filter sets the optional parameter "filter": A filter expression that +// filters resources listed in the response. The expression must specify +// the field name, a comparison operator, and the value that you want to +// use for filtering. The value must be a string, a number, or a +// boolean. The comparison operator must be either =, !=, >, or <. +// +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. +// +// You can also filter nested fields. For example, you could specify +// scheduling.automaticRestart = false to include instances only if they +// are not scheduled for automatic restarts. You can use filtering on +// nested fields to filter based on resource labels. +// +// To filter on multiple expressions, provide each separate expression +// within parentheses. For example, (scheduling.automaticRestart = true) +// (cpuPlatform = "Intel Skylake"). By default, each expression is an +// AND expression. However, you can include AND and OR expressions +// explicitly. For example, (cpuPlatform = "Intel Skylake") OR +// (cpuPlatform = "Intel Broadwell") AND (scheduling.automaticRestart = +// true). func (c *ProjectsGetXpnResourcesCall) Filter(filter string) *ProjectsGetXpnResourcesCall { c.urlParams_.Set("filter", filter) return c } -// MaxResults sets the optional parameter "maxResults": +// MaxResults sets the optional parameter "maxResults": The maximum +// number of results per page that should be returned. If the number of +// available results is larger than maxResults, Compute Engine returns a +// nextPageToken that can be used to get the next page of results in +// subsequent list requests. Acceptable values are 0 to 500, inclusive. +// (Default: 500) func (c *ProjectsGetXpnResourcesCall) MaxResults(maxResults int64) *ProjectsGetXpnResourcesCall { c.urlParams_.Set("maxResults", fmt.Sprint(maxResults)) return c } -// OrderBy sets the optional parameter "order_by": +// OrderBy sets the optional parameter "order_by": Sorts list results by +// a certain order. By default, results are returned in alphanumerical +// order based on the resource name. +// +// You can also sort results in descending order based on the creation +// timestamp using orderBy="creationTimestamp desc". This sorts results +// based on the creationTimestamp field in reverse chronological order +// (newest result first). Use this to sort resources like operations so +// that the newest operation is returned first. +// +// Currently, only sorting by name or creationTimestamp desc is +// supported. func (c *ProjectsGetXpnResourcesCall) OrderBy(orderBy string) *ProjectsGetXpnResourcesCall { c.urlParams_.Set("order_by", orderBy) return c } -// PageToken sets the optional parameter "pageToken": +// PageToken sets the optional parameter "pageToken": Specifies a page +// token to use. Set pageToken to the nextPageToken returned by a +// previous list request to get the next page of results. func (c *ProjectsGetXpnResourcesCall) PageToken(pageToken string) *ProjectsGetXpnResourcesCall { c.urlParams_.Set("pageToken", pageToken) return c @@ -76072,9 +85641,13 @@ func (c *ProjectsGetXpnResourcesCall) doRequest(alt string) (*http.Response, err } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/getXpnResources") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -76128,21 +85701,25 @@ func (c *ProjectsGetXpnResourcesCall) Do(opts ...googleapi.CallOption) (*Project // ], // "parameters": { // "filter": { + // "description": "A filter expression that filters resources listed in the response. The expression must specify the field name, a comparison operator, and the value that you want to use for filtering. The value must be a string, a number, or a boolean. The comparison operator must be either =, !=, \u003e, or \u003c.\n\nFor example, if you are filtering Compute Engine instances, you can exclude instances named example-instance by specifying name != example-instance.\n\nYou can also filter nested fields. For example, you could specify scheduling.automaticRestart = false to include instances only if they are not scheduled for automatic restarts. You can use filtering on nested fields to filter based on resource labels.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart = true) (cpuPlatform = \"Intel Skylake\"). By default, each expression is an AND expression. However, you can include AND and OR expressions explicitly. For example, (cpuPlatform = \"Intel Skylake\") OR (cpuPlatform = \"Intel Broadwell\") AND (scheduling.automaticRestart = true).", // "location": "query", // "type": "string" // }, // "maxResults": { // "default": "500", + // "description": "The maximum number of results per page that should be returned. If the number of available results is larger than maxResults, Compute Engine returns a nextPageToken that can be used to get the next page of results in subsequent list requests. Acceptable values are 0 to 500, inclusive. (Default: 500)", // "format": "uint32", // "location": "query", // "minimum": "0", // "type": "integer" // }, // "order_by": { + // "description": "Sorts list results by a certain order. By default, results are returned in alphanumerical order based on the resource name.\n\nYou can also sort results in descending order based on the creation timestamp using orderBy=\"creationTimestamp desc\". This sorts results based on the creationTimestamp field in reverse chronological order (newest result first). Use this to sort resources like operations so that the newest operation is returned first.\n\nCurrently, only sorting by name or creationTimestamp desc is supported.", // "location": "query", // "type": "string" // }, // "pageToken": { + // "description": "Specifies a page token to use. Set pageToken to the nextPageToken returned by a previous list request to get the next page of results.", // "location": "query", // "type": "string" // }, @@ -76207,25 +85784,64 @@ func (r *ProjectsService) ListXpnHosts(project string, projectslistxpnhostsreque return c } -// Filter sets the optional parameter "filter": +// Filter sets the optional parameter "filter": A filter expression that +// filters resources listed in the response. The expression must specify +// the field name, a comparison operator, and the value that you want to +// use for filtering. The value must be a string, a number, or a +// boolean. The comparison operator must be either =, !=, >, or <. +// +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. +// +// You can also filter nested fields. For example, you could specify +// scheduling.automaticRestart = false to include instances only if they +// are not scheduled for automatic restarts. You can use filtering on +// nested fields to filter based on resource labels. +// +// To filter on multiple expressions, provide each separate expression +// within parentheses. For example, (scheduling.automaticRestart = true) +// (cpuPlatform = "Intel Skylake"). By default, each expression is an +// AND expression. However, you can include AND and OR expressions +// explicitly. For example, (cpuPlatform = "Intel Skylake") OR +// (cpuPlatform = "Intel Broadwell") AND (scheduling.automaticRestart = +// true). func (c *ProjectsListXpnHostsCall) Filter(filter string) *ProjectsListXpnHostsCall { c.urlParams_.Set("filter", filter) return c } -// MaxResults sets the optional parameter "maxResults": +// MaxResults sets the optional parameter "maxResults": The maximum +// number of results per page that should be returned. If the number of +// available results is larger than maxResults, Compute Engine returns a +// nextPageToken that can be used to get the next page of results in +// subsequent list requests. Acceptable values are 0 to 500, inclusive. +// (Default: 500) func (c *ProjectsListXpnHostsCall) MaxResults(maxResults int64) *ProjectsListXpnHostsCall { c.urlParams_.Set("maxResults", fmt.Sprint(maxResults)) return c } -// OrderBy sets the optional parameter "order_by": +// OrderBy sets the optional parameter "order_by": Sorts list results by +// a certain order. By default, results are returned in alphanumerical +// order based on the resource name. +// +// You can also sort results in descending order based on the creation +// timestamp using orderBy="creationTimestamp desc". This sorts results +// based on the creationTimestamp field in reverse chronological order +// (newest result first). Use this to sort resources like operations so +// that the newest operation is returned first. +// +// Currently, only sorting by name or creationTimestamp desc is +// supported. func (c *ProjectsListXpnHostsCall) OrderBy(orderBy string) *ProjectsListXpnHostsCall { c.urlParams_.Set("order_by", orderBy) return c } -// PageToken sets the optional parameter "pageToken": +// PageToken sets the optional parameter "pageToken": Specifies a page +// token to use. Set pageToken to the nextPageToken returned by a +// previous list request to get the next page of results. func (c *ProjectsListXpnHostsCall) PageToken(pageToken string) *ProjectsListXpnHostsCall { c.urlParams_.Set("pageToken", pageToken) return c @@ -76269,9 +85885,13 @@ func (c *ProjectsListXpnHostsCall) doRequest(alt string) (*http.Response, error) } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/listXpnHosts") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -76325,21 +85945,25 @@ func (c *ProjectsListXpnHostsCall) Do(opts ...googleapi.CallOption) (*XpnHostLis // ], // "parameters": { // "filter": { + // "description": "A filter expression that filters resources listed in the response. The expression must specify the field name, a comparison operator, and the value that you want to use for filtering. The value must be a string, a number, or a boolean. The comparison operator must be either =, !=, \u003e, or \u003c.\n\nFor example, if you are filtering Compute Engine instances, you can exclude instances named example-instance by specifying name != example-instance.\n\nYou can also filter nested fields. For example, you could specify scheduling.automaticRestart = false to include instances only if they are not scheduled for automatic restarts. You can use filtering on nested fields to filter based on resource labels.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart = true) (cpuPlatform = \"Intel Skylake\"). By default, each expression is an AND expression. However, you can include AND and OR expressions explicitly. For example, (cpuPlatform = \"Intel Skylake\") OR (cpuPlatform = \"Intel Broadwell\") AND (scheduling.automaticRestart = true).", // "location": "query", // "type": "string" // }, // "maxResults": { // "default": "500", + // "description": "The maximum number of results per page that should be returned. If the number of available results is larger than maxResults, Compute Engine returns a nextPageToken that can be used to get the next page of results in subsequent list requests. Acceptable values are 0 to 500, inclusive. (Default: 500)", // "format": "uint32", // "location": "query", // "minimum": "0", // "type": "integer" // }, // "order_by": { + // "description": "Sorts list results by a certain order. By default, results are returned in alphanumerical order based on the resource name.\n\nYou can also sort results in descending order based on the creation timestamp using orderBy=\"creationTimestamp desc\". This sorts results based on the creationTimestamp field in reverse chronological order (newest result first). Use this to sort resources like operations so that the newest operation is returned first.\n\nCurrently, only sorting by name or creationTimestamp desc is supported.", // "location": "query", // "type": "string" // }, // "pageToken": { + // "description": "Specifies a page token to use. Set pageToken to the nextPageToken returned by a previous list request to get the next page of results.", // "location": "query", // "type": "string" // }, @@ -76463,9 +86087,13 @@ func (c *ProjectsMoveDiskCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/moveDisk") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -76623,9 +86251,13 @@ func (c *ProjectsMoveInstanceCall) doRequest(alt string) (*http.Response, error) } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/moveInstance") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -76784,9 +86416,13 @@ func (c *ProjectsSetCommonInstanceMetadataCall) doRequest(alt string) (*http.Res } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/setCommonInstanceMetadata") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -76946,9 +86582,13 @@ func (c *ProjectsSetDefaultNetworkTierCall) doRequest(alt string) (*http.Respons } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/setDefaultNetworkTier") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -77109,9 +86749,13 @@ func (c *ProjectsSetUsageExportBucketCall) doRequest(alt string) (*http.Response } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/setUsageExportBucket") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -77268,9 +86912,13 @@ func (c *RegionAutoscalersDeleteCall) doRequest(alt string) (*http.Response, err reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/autoscalers/{autoscaler}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -77434,9 +87082,13 @@ func (c *RegionAutoscalersGetCall) doRequest(alt string) (*http.Response, error) } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/autoscalers/{autoscaler}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -77607,9 +87259,13 @@ func (c *RegionAutoscalersInsertCall) doRequest(alt string) (*http.Response, err } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/autoscalers") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -77829,9 +87485,13 @@ func (c *RegionAutoscalersListCall) doRequest(alt string) (*http.Response, error } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/autoscalers") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -78045,9 +87705,13 @@ func (c *RegionAutoscalersPatchCall) doRequest(alt string) (*http.Response, erro } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/autoscalers") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PATCH", urls, body) + req, err := http.NewRequest("PATCH", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -78205,9 +87869,13 @@ func (c *RegionAutoscalersTestIamPermissionsCall) doRequest(alt string) (*http.R } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/autoscalers/{resource}/testIamPermissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -78279,9 +87947,9 @@ func (c *RegionAutoscalersTestIamPermissionsCall) Do(opts ...googleapi.CallOptio // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -78388,9 +88056,13 @@ func (c *RegionAutoscalersUpdateCall) doRequest(alt string) (*http.Response, err } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/autoscalers") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PUT", urls, body) + req, err := http.NewRequest("PUT", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -78559,9 +88231,13 @@ func (c *RegionBackendServicesDeleteCall) doRequest(alt string) (*http.Response, reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/backendServices/{backendService}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -78725,9 +88401,13 @@ func (c *RegionBackendServicesGetCall) doRequest(alt string) (*http.Response, er } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/backendServices/{backendService}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -78881,9 +88561,13 @@ func (c *RegionBackendServicesGetHealthCall) doRequest(alt string) (*http.Respon } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/backendServices/{backendService}/getHealth") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -79059,9 +88743,13 @@ func (c *RegionBackendServicesInsertCall) doRequest(alt string) (*http.Response, } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/backendServices") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -79281,9 +88969,13 @@ func (c *RegionBackendServicesListCall) doRequest(alt string) (*http.Response, e } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/backendServices") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -79495,9 +89187,13 @@ func (c *RegionBackendServicesPatchCall) doRequest(alt string) (*http.Response, } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/backendServices/{backendService}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PATCH", urls, body) + req, err := http.NewRequest("PATCH", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -79557,7 +89253,7 @@ func (c *RegionBackendServicesPatchCall) Do(opts ...googleapi.CallOption) (*Oper // "backendService": { // "description": "Name of the BackendService resource to patch.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -79658,9 +89354,13 @@ func (c *RegionBackendServicesTestIamPermissionsCall) doRequest(alt string) (*ht } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/backendServices/{resource}/testIamPermissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -79732,9 +89432,9 @@ func (c *RegionBackendServicesTestIamPermissionsCall) Do(opts ...googleapi.CallO // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -79838,9 +89538,13 @@ func (c *RegionBackendServicesUpdateCall) doRequest(alt string) (*http.Response, } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/backendServices/{backendService}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PUT", urls, body) + req, err := http.NewRequest("PUT", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -80066,9 +89770,13 @@ func (c *RegionCommitmentsAggregatedListCall) doRequest(alt string) (*http.Respo } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/aggregated/commitments") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -80255,9 +89963,13 @@ func (c *RegionCommitmentsGetCall) doRequest(alt string) (*http.Response, error) } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/commitments/{commitment}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -80428,9 +90140,13 @@ func (c *RegionCommitmentsInsertCall) doRequest(alt string) (*http.Response, err } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/commitments") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -80650,9 +90366,13 @@ func (c *RegionCommitmentsListCall) doRequest(alt string) (*http.Response, error } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/commitments") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -80848,9 +90568,13 @@ func (c *RegionDiskTypesGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/diskTypes/{diskType}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -81072,9 +90796,13 @@ func (c *RegionDiskTypesListCall) doRequest(alt string) (*http.Response, error) } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/diskTypes") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -81201,6 +90929,193 @@ func (c *RegionDiskTypesListCall) Pages(ctx context.Context, f func(*RegionDiskT } } +// method id "compute.regionDisks.addResourcePolicies": + +type RegionDisksAddResourcePoliciesCall struct { + s *Service + project string + region string + disk string + regiondisksaddresourcepoliciesrequest *RegionDisksAddResourcePoliciesRequest + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// AddResourcePolicies: Adds existing resource policies to a regional +// disk. You can only add one policy which will be applied to this disk +// for scheduling snapshot creation. +func (r *RegionDisksService) AddResourcePolicies(project string, region string, disk string, regiondisksaddresourcepoliciesrequest *RegionDisksAddResourcePoliciesRequest) *RegionDisksAddResourcePoliciesCall { + c := &RegionDisksAddResourcePoliciesCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.region = region + c.disk = disk + c.regiondisksaddresourcepoliciesrequest = regiondisksaddresourcepoliciesrequest + return c +} + +// RequestId sets the optional parameter "requestId": An optional +// request ID to identify requests. Specify a unique request ID so that +// if you must retry your request, the server will know to ignore the +// request if it has already been completed. +// +// For example, consider a situation where you make an initial request +// and the request times out. If you make the request again with the +// same request ID, the server can check if original operation with the +// same request ID was received, and if so, will ignore the second +// request. This prevents clients from accidentally creating duplicate +// commitments. +// +// The request ID must be a valid UUID with the exception that zero UUID +// is not supported (00000000-0000-0000-0000-000000000000). +func (c *RegionDisksAddResourcePoliciesCall) RequestId(requestId string) *RegionDisksAddResourcePoliciesCall { + c.urlParams_.Set("requestId", requestId) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *RegionDisksAddResourcePoliciesCall) Fields(s ...googleapi.Field) *RegionDisksAddResourcePoliciesCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *RegionDisksAddResourcePoliciesCall) Context(ctx context.Context) *RegionDisksAddResourcePoliciesCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *RegionDisksAddResourcePoliciesCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *RegionDisksAddResourcePoliciesCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.regiondisksaddresourcepoliciesrequest) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/disks/{disk}/addResourcePolicies") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "region": c.region, + "disk": c.disk, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.regionDisks.addResourcePolicies" call. +// Exactly one of *Operation or error will be non-nil. Any non-2xx +// status code is an error. Response headers are in either +// *Operation.ServerResponse.Header or (if a response was returned at +// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified +// to check whether the returned error was because +// http.StatusNotModified was returned. +func (c *RegionDisksAddResourcePoliciesCall) Do(opts ...googleapi.CallOption) (*Operation, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Operation{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Adds existing resource policies to a regional disk. You can only add one policy which will be applied to this disk for scheduling snapshot creation.", + // "httpMethod": "POST", + // "id": "compute.regionDisks.addResourcePolicies", + // "parameterOrder": [ + // "project", + // "region", + // "disk" + // ], + // "parameters": { + // "disk": { + // "description": "The disk name for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + // "required": true, + // "type": "string" + // }, + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "region": { + // "description": "The name of the region for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // }, + // "requestId": { + // "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", + // "location": "query", + // "type": "string" + // } + // }, + // "path": "{project}/regions/{region}/disks/{disk}/addResourcePolicies", + // "request": { + // "$ref": "RegionDisksAddResourcePoliciesRequest" + // }, + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + // method id "compute.regionDisks.createSnapshot": type RegionDisksCreateSnapshotCall struct { @@ -81281,9 +91196,13 @@ func (c *RegionDisksCreateSnapshotCall) doRequest(alt string) (*http.Response, e } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/disks/{disk}/createSnapshot") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -81343,7 +91262,7 @@ func (c *RegionDisksCreateSnapshotCall) Do(opts ...googleapi.CallOption) (*Opera // "disk": { // "description": "Name of the regional persistent disk to snapshot.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -81458,9 +91377,13 @@ func (c *RegionDisksDeleteCall) doRequest(alt string) (*http.Response, error) { reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/disks/{disk}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -81623,9 +91546,13 @@ func (c *RegionDisksGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/disks/{disk}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -81685,7 +91612,7 @@ func (c *RegionDisksGetCall) Do(opts ...googleapi.CallOption) (*Disk, error) { // "disk": { // "description": "Name of the regional persistent disk to return.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -81803,9 +91730,13 @@ func (c *RegionDisksInsertCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/disks") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -82030,9 +91961,13 @@ func (c *RegionDisksListCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/disks") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -82159,6 +92094,192 @@ func (c *RegionDisksListCall) Pages(ctx context.Context, f func(*DiskList) error } } +// method id "compute.regionDisks.removeResourcePolicies": + +type RegionDisksRemoveResourcePoliciesCall struct { + s *Service + project string + region string + disk string + regiondisksremoveresourcepoliciesrequest *RegionDisksRemoveResourcePoliciesRequest + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// RemoveResourcePolicies: Removes resource policies from a regional +// disk. +func (r *RegionDisksService) RemoveResourcePolicies(project string, region string, disk string, regiondisksremoveresourcepoliciesrequest *RegionDisksRemoveResourcePoliciesRequest) *RegionDisksRemoveResourcePoliciesCall { + c := &RegionDisksRemoveResourcePoliciesCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.region = region + c.disk = disk + c.regiondisksremoveresourcepoliciesrequest = regiondisksremoveresourcepoliciesrequest + return c +} + +// RequestId sets the optional parameter "requestId": An optional +// request ID to identify requests. Specify a unique request ID so that +// if you must retry your request, the server will know to ignore the +// request if it has already been completed. +// +// For example, consider a situation where you make an initial request +// and the request times out. If you make the request again with the +// same request ID, the server can check if original operation with the +// same request ID was received, and if so, will ignore the second +// request. This prevents clients from accidentally creating duplicate +// commitments. +// +// The request ID must be a valid UUID with the exception that zero UUID +// is not supported (00000000-0000-0000-0000-000000000000). +func (c *RegionDisksRemoveResourcePoliciesCall) RequestId(requestId string) *RegionDisksRemoveResourcePoliciesCall { + c.urlParams_.Set("requestId", requestId) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *RegionDisksRemoveResourcePoliciesCall) Fields(s ...googleapi.Field) *RegionDisksRemoveResourcePoliciesCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *RegionDisksRemoveResourcePoliciesCall) Context(ctx context.Context) *RegionDisksRemoveResourcePoliciesCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *RegionDisksRemoveResourcePoliciesCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *RegionDisksRemoveResourcePoliciesCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.regiondisksremoveresourcepoliciesrequest) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/disks/{disk}/removeResourcePolicies") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "region": c.region, + "disk": c.disk, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.regionDisks.removeResourcePolicies" call. +// Exactly one of *Operation or error will be non-nil. Any non-2xx +// status code is an error. Response headers are in either +// *Operation.ServerResponse.Header or (if a response was returned at +// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified +// to check whether the returned error was because +// http.StatusNotModified was returned. +func (c *RegionDisksRemoveResourcePoliciesCall) Do(opts ...googleapi.CallOption) (*Operation, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Operation{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Removes resource policies from a regional disk.", + // "httpMethod": "POST", + // "id": "compute.regionDisks.removeResourcePolicies", + // "parameterOrder": [ + // "project", + // "region", + // "disk" + // ], + // "parameters": { + // "disk": { + // "description": "The disk name for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + // "required": true, + // "type": "string" + // }, + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "region": { + // "description": "The name of the region for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // }, + // "requestId": { + // "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", + // "location": "query", + // "type": "string" + // } + // }, + // "path": "{project}/regions/{region}/disks/{disk}/removeResourcePolicies", + // "request": { + // "$ref": "RegionDisksRemoveResourcePoliciesRequest" + // }, + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + // method id "compute.regionDisks.resize": type RegionDisksResizeCall struct { @@ -82239,9 +92360,13 @@ func (c *RegionDisksResizeCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/disks/{disk}/resize") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -82301,7 +92426,7 @@ func (c *RegionDisksResizeCall) Do(opts ...googleapi.CallOption) (*Operation, er // "disk": { // "description": "Name of the regional persistent disk.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -82420,9 +92545,13 @@ func (c *RegionDisksSetLabelsCall) doRequest(alt string) (*http.Response, error) } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/disks/{resource}/setLabels") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -82499,9 +92628,9 @@ func (c *RegionDisksSetLabelsCall) Do(opts ...googleapi.CallOption) (*Operation, // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -82583,9 +92712,13 @@ func (c *RegionDisksTestIamPermissionsCall) doRequest(alt string) (*http.Respons } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/disks/{resource}/testIamPermissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -82657,9 +92790,9 @@ func (c *RegionDisksTestIamPermissionsCall) Do(opts ...googleapi.CallOption) (*T // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -82693,10 +92826,10 @@ type RegionInstanceGroupManagersAbandonInstancesCall struct { header_ http.Header } -// AbandonInstances: Schedules a group action to remove the specified -// instances from the managed instance group. Abandoning an instance -// does not delete the instance, but it does remove the instance from -// any target pools that are applied by the managed instance group. This +// AbandonInstances: Flags the specified instances to be immediately +// removed from the managed instance group. Abandoning an instance does +// not delete the instance, but it does remove the instance from any +// target pools that are applied by the managed instance group. This // method reduces the targetSize of the managed instance group by the // number of instances that you abandon. This operation is marked as // DONE when the action is scheduled even if the instances have not yet @@ -82776,9 +92909,13 @@ func (c *RegionInstanceGroupManagersAbandonInstancesCall) doRequest(alt string) } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/instanceGroupManagers/{instanceGroupManager}/abandonInstances") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -82826,7 +92963,7 @@ func (c *RegionInstanceGroupManagersAbandonInstancesCall) Do(opts ...googleapi.C } return ret, nil // { - // "description": "Schedules a group action to remove the specified instances from the managed instance group. Abandoning an instance does not delete the instance, but it does remove the instance from any target pools that are applied by the managed instance group. This method reduces the targetSize of the managed instance group by the number of instances that you abandon. This operation is marked as DONE when the action is scheduled even if the instances have not yet been removed from the group. You must separately verify the status of the abandoning action with the listmanagedinstances method.\n\nIf the group is part of a backend service that has enabled connection draining, it can take up to 60 seconds after the connection draining duration has elapsed before the VM instance is removed or deleted.\n\nYou can specify a maximum of 1000 instances with this method per request.", + // "description": "Flags the specified instances to be immediately removed from the managed instance group. Abandoning an instance does not delete the instance, but it does remove the instance from any target pools that are applied by the managed instance group. This method reduces the targetSize of the managed instance group by the number of instances that you abandon. This operation is marked as DONE when the action is scheduled even if the instances have not yet been removed from the group. You must separately verify the status of the abandoning action with the listmanagedinstances method.\n\nIf the group is part of a backend service that has enabled connection draining, it can take up to 60 seconds after the connection draining duration has elapsed before the VM instance is removed or deleted.\n\nYou can specify a maximum of 1000 instances with this method per request.", // "httpMethod": "POST", // "id": "compute.regionInstanceGroupManagers.abandonInstances", // "parameterOrder": [ @@ -82949,9 +93086,13 @@ func (c *RegionInstanceGroupManagersDeleteCall) doRequest(alt string) (*http.Res reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/instanceGroupManagers/{instanceGroupManager}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -83058,14 +93199,15 @@ type RegionInstanceGroupManagersDeleteInstancesCall struct { header_ http.Header } -// DeleteInstances: Schedules a group action to delete the specified -// instances in the managed instance group. The instances are also +// DeleteInstances: Flags the specified instances in the managed +// instance group to be immediately deleted. The instances are also // removed from any target pools of which they were a member. This // method reduces the targetSize of the managed instance group by the -// number of instances that you delete. This operation is marked as DONE -// when the action is scheduled even if the instances are still being -// deleted. You must separately verify the status of the deleting action -// with the listmanagedinstances method. +// number of instances that you delete. The deleteInstances operation is +// marked DONE if the deleteInstances request is successful. The +// underlying actions take additional time. You must separately verify +// the status of the deleting action with the listmanagedinstances +// method. // // If the group is part of a backend service that has enabled connection // draining, it can take up to 60 seconds after the connection draining @@ -83140,9 +93282,13 @@ func (c *RegionInstanceGroupManagersDeleteInstancesCall) doRequest(alt string) ( } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/instanceGroupManagers/{instanceGroupManager}/deleteInstances") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -83190,7 +93336,7 @@ func (c *RegionInstanceGroupManagersDeleteInstancesCall) Do(opts ...googleapi.Ca } return ret, nil // { - // "description": "Schedules a group action to delete the specified instances in the managed instance group. The instances are also removed from any target pools of which they were a member. This method reduces the targetSize of the managed instance group by the number of instances that you delete. This operation is marked as DONE when the action is scheduled even if the instances are still being deleted. You must separately verify the status of the deleting action with the listmanagedinstances method.\n\nIf the group is part of a backend service that has enabled connection draining, it can take up to 60 seconds after the connection draining duration has elapsed before the VM instance is removed or deleted.\n\nYou can specify a maximum of 1000 instances with this method per request.", + // "description": "Flags the specified instances in the managed instance group to be immediately deleted. The instances are also removed from any target pools of which they were a member. This method reduces the targetSize of the managed instance group by the number of instances that you delete. The deleteInstances operation is marked DONE if the deleteInstances request is successful. The underlying actions take additional time. You must separately verify the status of the deleting action with the listmanagedinstances method.\n\nIf the group is part of a backend service that has enabled connection draining, it can take up to 60 seconds after the connection draining duration has elapsed before the VM instance is removed or deleted.\n\nYou can specify a maximum of 1000 instances with this method per request.", // "httpMethod": "POST", // "id": "compute.regionInstanceGroupManagers.deleteInstances", // "parameterOrder": [ @@ -83308,9 +93454,13 @@ func (c *RegionInstanceGroupManagersGetCall) doRequest(alt string) (*http.Respon } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/instanceGroupManagers/{instanceGroupManager}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -83413,12 +93563,12 @@ type RegionInstanceGroupManagersInsertCall struct { } // Insert: Creates a managed instance group using the information that -// you specify in the request. After the group is created, it schedules -// an action to create instances in the group using the specified -// instance template. This operation is marked as DONE when the group is -// created even if the instances in the group have not yet been created. -// You must separately verify the status of the individual instances -// with the listmanagedinstances method. +// you specify in the request. After the group is created, instances in +// the group are created using the specified instance template. This +// operation is marked as DONE when the group is created even if the +// instances in the group have not yet been created. You must separately +// verify the status of the individual instances with the +// listmanagedinstances method. // // A regional managed instance group can contain up to 2000 instances. func (r *RegionInstanceGroupManagersService) Insert(project string, region string, instancegroupmanager *InstanceGroupManager) *RegionInstanceGroupManagersInsertCall { @@ -83486,9 +93636,13 @@ func (c *RegionInstanceGroupManagersInsertCall) doRequest(alt string) (*http.Res } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/instanceGroupManagers") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -83535,7 +93689,7 @@ func (c *RegionInstanceGroupManagersInsertCall) Do(opts ...googleapi.CallOption) } return ret, nil // { - // "description": "Creates a managed instance group using the information that you specify in the request. After the group is created, it schedules an action to create instances in the group using the specified instance template. This operation is marked as DONE when the group is created even if the instances in the group have not yet been created. You must separately verify the status of the individual instances with the listmanagedinstances method.\n\nA regional managed instance group can contain up to 2000 instances.", + // "description": "Creates a managed instance group using the information that you specify in the request. After the group is created, instances in the group are created using the specified instance template. This operation is marked as DONE when the group is created even if the instances in the group have not yet been created. You must separately verify the status of the individual instances with the listmanagedinstances method.\n\nA regional managed instance group can contain up to 2000 instances.", // "httpMethod": "POST", // "id": "compute.regionInstanceGroupManagers.insert", // "parameterOrder": [ @@ -83707,9 +93861,13 @@ func (c *RegionInstanceGroupManagersListCall) doRequest(alt string) (*http.Respo } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/instanceGroupManagers") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -83859,25 +94017,64 @@ func (r *RegionInstanceGroupManagersService) ListManagedInstances(project string return c } -// Filter sets the optional parameter "filter": +// Filter sets the optional parameter "filter": A filter expression that +// filters resources listed in the response. The expression must specify +// the field name, a comparison operator, and the value that you want to +// use for filtering. The value must be a string, a number, or a +// boolean. The comparison operator must be either =, !=, >, or <. +// +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. +// +// You can also filter nested fields. For example, you could specify +// scheduling.automaticRestart = false to include instances only if they +// are not scheduled for automatic restarts. You can use filtering on +// nested fields to filter based on resource labels. +// +// To filter on multiple expressions, provide each separate expression +// within parentheses. For example, (scheduling.automaticRestart = true) +// (cpuPlatform = "Intel Skylake"). By default, each expression is an +// AND expression. However, you can include AND and OR expressions +// explicitly. For example, (cpuPlatform = "Intel Skylake") OR +// (cpuPlatform = "Intel Broadwell") AND (scheduling.automaticRestart = +// true). func (c *RegionInstanceGroupManagersListManagedInstancesCall) Filter(filter string) *RegionInstanceGroupManagersListManagedInstancesCall { c.urlParams_.Set("filter", filter) return c } -// MaxResults sets the optional parameter "maxResults": +// MaxResults sets the optional parameter "maxResults": The maximum +// number of results per page that should be returned. If the number of +// available results is larger than maxResults, Compute Engine returns a +// nextPageToken that can be used to get the next page of results in +// subsequent list requests. Acceptable values are 0 to 500, inclusive. +// (Default: 500) func (c *RegionInstanceGroupManagersListManagedInstancesCall) MaxResults(maxResults int64) *RegionInstanceGroupManagersListManagedInstancesCall { c.urlParams_.Set("maxResults", fmt.Sprint(maxResults)) return c } -// OrderBy sets the optional parameter "order_by": +// OrderBy sets the optional parameter "order_by": Sorts list results by +// a certain order. By default, results are returned in alphanumerical +// order based on the resource name. +// +// You can also sort results in descending order based on the creation +// timestamp using orderBy="creationTimestamp desc". This sorts results +// based on the creationTimestamp field in reverse chronological order +// (newest result first). Use this to sort resources like operations so +// that the newest operation is returned first. +// +// Currently, only sorting by name or creationTimestamp desc is +// supported. func (c *RegionInstanceGroupManagersListManagedInstancesCall) OrderBy(orderBy string) *RegionInstanceGroupManagersListManagedInstancesCall { c.urlParams_.Set("order_by", orderBy) return c } -// PageToken sets the optional parameter "pageToken": +// PageToken sets the optional parameter "pageToken": Specifies a page +// token to use. Set pageToken to the nextPageToken returned by a +// previous list request to get the next page of results. func (c *RegionInstanceGroupManagersListManagedInstancesCall) PageToken(pageToken string) *RegionInstanceGroupManagersListManagedInstancesCall { c.urlParams_.Set("pageToken", pageToken) return c @@ -83916,9 +94113,13 @@ func (c *RegionInstanceGroupManagersListManagedInstancesCall) doRequest(alt stri reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/instanceGroupManagers/{instanceGroupManager}/listManagedInstances") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -83978,6 +94179,7 @@ func (c *RegionInstanceGroupManagersListManagedInstancesCall) Do(opts ...googlea // ], // "parameters": { // "filter": { + // "description": "A filter expression that filters resources listed in the response. The expression must specify the field name, a comparison operator, and the value that you want to use for filtering. The value must be a string, a number, or a boolean. The comparison operator must be either =, !=, \u003e, or \u003c.\n\nFor example, if you are filtering Compute Engine instances, you can exclude instances named example-instance by specifying name != example-instance.\n\nYou can also filter nested fields. For example, you could specify scheduling.automaticRestart = false to include instances only if they are not scheduled for automatic restarts. You can use filtering on nested fields to filter based on resource labels.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart = true) (cpuPlatform = \"Intel Skylake\"). By default, each expression is an AND expression. However, you can include AND and OR expressions explicitly. For example, (cpuPlatform = \"Intel Skylake\") OR (cpuPlatform = \"Intel Broadwell\") AND (scheduling.automaticRestart = true).", // "location": "query", // "type": "string" // }, @@ -83989,16 +94191,19 @@ func (c *RegionInstanceGroupManagersListManagedInstancesCall) Do(opts ...googlea // }, // "maxResults": { // "default": "500", + // "description": "The maximum number of results per page that should be returned. If the number of available results is larger than maxResults, Compute Engine returns a nextPageToken that can be used to get the next page of results in subsequent list requests. Acceptable values are 0 to 500, inclusive. (Default: 500)", // "format": "uint32", // "location": "query", // "minimum": "0", // "type": "integer" // }, // "order_by": { + // "description": "Sorts list results by a certain order. By default, results are returned in alphanumerical order based on the resource name.\n\nYou can also sort results in descending order based on the creation timestamp using orderBy=\"creationTimestamp desc\". This sorts results based on the creationTimestamp field in reverse chronological order (newest result first). Use this to sort resources like operations so that the newest operation is returned first.\n\nCurrently, only sorting by name or creationTimestamp desc is supported.", // "location": "query", // "type": "string" // }, // "pageToken": { + // "description": "Specifies a page token to use. Set pageToken to the nextPageToken returned by a previous list request to get the next page of results.", // "location": "query", // "type": "string" // }, @@ -84136,9 +94341,13 @@ func (c *RegionInstanceGroupManagersPatchCall) doRequest(alt string) (*http.Resp } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/instanceGroupManagers/{instanceGroupManager}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PATCH", urls, body) + req, err := http.NewRequest("PATCH", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -84248,11 +94457,11 @@ type RegionInstanceGroupManagersRecreateInstancesCall struct { header_ http.Header } -// RecreateInstances: Schedules a group action to recreate the specified -// instances in the managed instance group. The instances are deleted +// RecreateInstances: Flags the specified instances in the managed +// instance group to be immediately recreated. The instances are deleted // and recreated using the current instance template for the managed -// instance group. This operation is marked as DONE when the action is -// scheduled even if the instances have not yet been recreated. You must +// instance group. This operation is marked as DONE when the flag is set +// even if the instances have not yet been recreated. You must // separately verify the status of the recreating action with the // listmanagedinstances method. // @@ -84329,9 +94538,13 @@ func (c *RegionInstanceGroupManagersRecreateInstancesCall) doRequest(alt string) } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/instanceGroupManagers/{instanceGroupManager}/recreateInstances") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -84379,7 +94592,7 @@ func (c *RegionInstanceGroupManagersRecreateInstancesCall) Do(opts ...googleapi. } return ret, nil // { - // "description": "Schedules a group action to recreate the specified instances in the managed instance group. The instances are deleted and recreated using the current instance template for the managed instance group. This operation is marked as DONE when the action is scheduled even if the instances have not yet been recreated. You must separately verify the status of the recreating action with the listmanagedinstances method.\n\nIf the group is part of a backend service that has enabled connection draining, it can take up to 60 seconds after the connection draining duration has elapsed before the VM instance is removed or deleted.\n\nYou can specify a maximum of 1000 instances with this method per request.", + // "description": "Flags the specified instances in the managed instance group to be immediately recreated. The instances are deleted and recreated using the current instance template for the managed instance group. This operation is marked as DONE when the flag is set even if the instances have not yet been recreated. You must separately verify the status of the recreating action with the listmanagedinstances method.\n\nIf the group is part of a backend service that has enabled connection draining, it can take up to 60 seconds after the connection draining duration has elapsed before the VM instance is removed or deleted.\n\nYou can specify a maximum of 1000 instances with this method per request.", // "httpMethod": "POST", // "id": "compute.regionInstanceGroupManagers.recreateInstances", // "parameterOrder": [ @@ -84440,14 +94653,15 @@ type RegionInstanceGroupManagersResizeCall struct { header_ http.Header } -// Resize: Changes the intended size for the managed instance group. If -// you increase the size, the group schedules actions to create new -// instances using the current instance template. If you decrease the -// size, the group schedules delete actions on one or more instances. -// The resize operation is marked DONE when the resize actions are -// scheduled even if the group has not yet added or deleted any -// instances. You must separately verify the status of the creating or -// deleting actions with the listmanagedinstances method. +// Resize: Changes the intended size of the managed instance group. If +// you increase the size, the group creates new instances using the +// current instance template. If you decrease the size, the group +// deletes one or more instances. +// +// The resize operation is marked DONE if the resize request is +// successful. The underlying actions take additional time. You must +// separately verify the status of the creating or deleting actions with +// the listmanagedinstances method. // // If the group is part of a backend service that has enabled connection // draining, it can take up to 60 seconds after the connection draining @@ -84513,9 +94727,13 @@ func (c *RegionInstanceGroupManagersResizeCall) doRequest(alt string) (*http.Res reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/instanceGroupManagers/{instanceGroupManager}/resize") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -84563,7 +94781,7 @@ func (c *RegionInstanceGroupManagersResizeCall) Do(opts ...googleapi.CallOption) } return ret, nil // { - // "description": "Changes the intended size for the managed instance group. If you increase the size, the group schedules actions to create new instances using the current instance template. If you decrease the size, the group schedules delete actions on one or more instances. The resize operation is marked DONE when the resize actions are scheduled even if the group has not yet added or deleted any instances. You must separately verify the status of the creating or deleting actions with the listmanagedinstances method.\n\nIf the group is part of a backend service that has enabled connection draining, it can take up to 60 seconds after the connection draining duration has elapsed before the VM instance is removed or deleted.", + // "description": "Changes the intended size of the managed instance group. If you increase the size, the group creates new instances using the current instance template. If you decrease the size, the group deletes one or more instances.\n\nThe resize operation is marked DONE if the resize request is successful. The underlying actions take additional time. You must separately verify the status of the creating or deleting actions with the listmanagedinstances method.\n\nIf the group is part of a backend service that has enabled connection draining, it can take up to 60 seconds after the connection draining duration has elapsed before the VM instance is removed or deleted.", // "httpMethod": "POST", // "id": "compute.regionInstanceGroupManagers.resize", // "parameterOrder": [ @@ -84632,7 +94850,8 @@ type RegionInstanceGroupManagersSetAutoHealingPoliciesCall struct { } // SetAutoHealingPolicies: Modifies the autohealing policy for the -// instances in this managed instance group. +// instances in this managed instance group. [Deprecated] This method is +// deprecated. Please use Patch instead. func (r *RegionInstanceGroupManagersService) SetAutoHealingPolicies(project string, region string, instanceGroupManager string, regioninstancegroupmanagerssetautohealingrequest *RegionInstanceGroupManagersSetAutoHealingRequest) *RegionInstanceGroupManagersSetAutoHealingPoliciesCall { c := &RegionInstanceGroupManagersSetAutoHealingPoliciesCall{s: r.s, urlParams_: make(gensupport.URLParams)} c.project = project @@ -84699,9 +94918,13 @@ func (c *RegionInstanceGroupManagersSetAutoHealingPoliciesCall) doRequest(alt st } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/instanceGroupManagers/{instanceGroupManager}/setAutoHealingPolicies") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -84749,7 +94972,7 @@ func (c *RegionInstanceGroupManagersSetAutoHealingPoliciesCall) Do(opts ...googl } return ret, nil // { - // "description": "Modifies the autohealing policy for the instances in this managed instance group.", + // "description": "Modifies the autohealing policy for the instances in this managed instance group. [Deprecated] This method is deprecated. Please use Patch instead.", // "httpMethod": "POST", // "id": "compute.regionInstanceGroupManagers.setAutoHealingPolicies", // "parameterOrder": [ @@ -84880,9 +95103,13 @@ func (c *RegionInstanceGroupManagersSetInstanceTemplateCall) doRequest(alt strin } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/instanceGroupManagers/{instanceGroupManager}/setInstanceTemplate") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -85061,9 +95288,13 @@ func (c *RegionInstanceGroupManagersSetTargetPoolsCall) doRequest(alt string) (* } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/instanceGroupManagers/{instanceGroupManager}/setTargetPools") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -85222,9 +95453,13 @@ func (c *RegionInstanceGroupManagersTestIamPermissionsCall) doRequest(alt string } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/instanceGroupManagers/{resource}/testIamPermissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -85296,9 +95531,9 @@ func (c *RegionInstanceGroupManagersTestIamPermissionsCall) Do(opts ...googleapi // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -85403,9 +95638,13 @@ func (c *RegionInstanceGroupManagersUpdateCall) doRequest(alt string) (*http.Res } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/instanceGroupManagers/{instanceGroupManager}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PUT", urls, body) + req, err := http.NewRequest("PUT", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -85570,9 +95809,13 @@ func (c *RegionInstanceGroupsGetCall) doRequest(alt string) (*http.Response, err } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/instanceGroups/{instanceGroup}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -85792,9 +96035,13 @@ func (c *RegionInstanceGroupsListCall) doRequest(alt string) (*http.Response, er } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/instanceGroups") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -86047,9 +96294,13 @@ func (c *RegionInstanceGroupsListInstancesCall) doRequest(alt string) (*http.Res } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/instanceGroups/{instanceGroup}/listInstances") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -86268,9 +96519,13 @@ func (c *RegionInstanceGroupsSetNamedPortsCall) doRequest(alt string) (*http.Res } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/instanceGroups/{instanceGroup}/setNamedPorts") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -86429,9 +96684,13 @@ func (c *RegionInstanceGroupsTestIamPermissionsCall) doRequest(alt string) (*htt } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/instanceGroups/{resource}/testIamPermissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -86503,9 +96762,9 @@ func (c *RegionInstanceGroupsTestIamPermissionsCall) Do(opts ...googleapi.CallOp // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -86581,9 +96840,13 @@ func (c *RegionOperationsDeleteCall) doRequest(alt string) (*http.Response, erro reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/operations/{operation}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -86715,9 +96978,13 @@ func (c *RegionOperationsGetCall) doRequest(alt string) (*http.Response, error) } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/operations/{operation}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -86940,9 +97207,13 @@ func (c *RegionOperationsListCall) doRequest(alt string) (*http.Response, error) } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/operations") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -87137,9 +97408,13 @@ func (c *RegionsGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -87351,9 +97626,13 @@ func (c *RegionsListCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -87471,6 +97750,1198 @@ func (c *RegionsListCall) Pages(ctx context.Context, f func(*RegionList) error) } } +// method id "compute.resourcePolicies.aggregatedList": + +type ResourcePoliciesAggregatedListCall struct { + s *Service + project string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// AggregatedList: Retrieves an aggregated list of resource policies. +func (r *ResourcePoliciesService) AggregatedList(project string) *ResourcePoliciesAggregatedListCall { + c := &ResourcePoliciesAggregatedListCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + return c +} + +// Filter sets the optional parameter "filter": A filter expression that +// filters resources listed in the response. The expression must specify +// the field name, a comparison operator, and the value that you want to +// use for filtering. The value must be a string, a number, or a +// boolean. The comparison operator must be either =, !=, >, or <. +// +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. +// +// You can also filter nested fields. For example, you could specify +// scheduling.automaticRestart = false to include instances only if they +// are not scheduled for automatic restarts. You can use filtering on +// nested fields to filter based on resource labels. +// +// To filter on multiple expressions, provide each separate expression +// within parentheses. For example, (scheduling.automaticRestart = true) +// (cpuPlatform = "Intel Skylake"). By default, each expression is an +// AND expression. However, you can include AND and OR expressions +// explicitly. For example, (cpuPlatform = "Intel Skylake") OR +// (cpuPlatform = "Intel Broadwell") AND (scheduling.automaticRestart = +// true). +func (c *ResourcePoliciesAggregatedListCall) Filter(filter string) *ResourcePoliciesAggregatedListCall { + c.urlParams_.Set("filter", filter) + return c +} + +// MaxResults sets the optional parameter "maxResults": The maximum +// number of results per page that should be returned. If the number of +// available results is larger than maxResults, Compute Engine returns a +// nextPageToken that can be used to get the next page of results in +// subsequent list requests. Acceptable values are 0 to 500, inclusive. +// (Default: 500) +func (c *ResourcePoliciesAggregatedListCall) MaxResults(maxResults int64) *ResourcePoliciesAggregatedListCall { + c.urlParams_.Set("maxResults", fmt.Sprint(maxResults)) + return c +} + +// OrderBy sets the optional parameter "orderBy": Sorts list results by +// a certain order. By default, results are returned in alphanumerical +// order based on the resource name. +// +// You can also sort results in descending order based on the creation +// timestamp using orderBy="creationTimestamp desc". This sorts results +// based on the creationTimestamp field in reverse chronological order +// (newest result first). Use this to sort resources like operations so +// that the newest operation is returned first. +// +// Currently, only sorting by name or creationTimestamp desc is +// supported. +func (c *ResourcePoliciesAggregatedListCall) OrderBy(orderBy string) *ResourcePoliciesAggregatedListCall { + c.urlParams_.Set("orderBy", orderBy) + return c +} + +// PageToken sets the optional parameter "pageToken": Specifies a page +// token to use. Set pageToken to the nextPageToken returned by a +// previous list request to get the next page of results. +func (c *ResourcePoliciesAggregatedListCall) PageToken(pageToken string) *ResourcePoliciesAggregatedListCall { + c.urlParams_.Set("pageToken", pageToken) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *ResourcePoliciesAggregatedListCall) Fields(s ...googleapi.Field) *ResourcePoliciesAggregatedListCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// IfNoneMatch sets the optional parameter which makes the operation +// fail if the object's ETag matches the given value. This is useful for +// getting updates only after the object has changed since the last +// request. Use googleapi.IsNotModified to check whether the response +// error from Do is the result of In-None-Match. +func (c *ResourcePoliciesAggregatedListCall) IfNoneMatch(entityTag string) *ResourcePoliciesAggregatedListCall { + c.ifNoneMatch_ = entityTag + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *ResourcePoliciesAggregatedListCall) Context(ctx context.Context) *ResourcePoliciesAggregatedListCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *ResourcePoliciesAggregatedListCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *ResourcePoliciesAggregatedListCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + if c.ifNoneMatch_ != "" { + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) + } + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/aggregated/resourcePolicies") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.resourcePolicies.aggregatedList" call. +// Exactly one of *ResourcePolicyAggregatedList or error will be +// non-nil. Any non-2xx status code is an error. Response headers are in +// either *ResourcePolicyAggregatedList.ServerResponse.Header or (if a +// response was returned at all) in error.(*googleapi.Error).Header. Use +// googleapi.IsNotModified to check whether the returned error was +// because http.StatusNotModified was returned. +func (c *ResourcePoliciesAggregatedListCall) Do(opts ...googleapi.CallOption) (*ResourcePolicyAggregatedList, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &ResourcePolicyAggregatedList{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Retrieves an aggregated list of resource policies.", + // "httpMethod": "GET", + // "id": "compute.resourcePolicies.aggregatedList", + // "parameterOrder": [ + // "project" + // ], + // "parameters": { + // "filter": { + // "description": "A filter expression that filters resources listed in the response. The expression must specify the field name, a comparison operator, and the value that you want to use for filtering. The value must be a string, a number, or a boolean. The comparison operator must be either =, !=, \u003e, or \u003c.\n\nFor example, if you are filtering Compute Engine instances, you can exclude instances named example-instance by specifying name != example-instance.\n\nYou can also filter nested fields. For example, you could specify scheduling.automaticRestart = false to include instances only if they are not scheduled for automatic restarts. You can use filtering on nested fields to filter based on resource labels.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart = true) (cpuPlatform = \"Intel Skylake\"). By default, each expression is an AND expression. However, you can include AND and OR expressions explicitly. For example, (cpuPlatform = \"Intel Skylake\") OR (cpuPlatform = \"Intel Broadwell\") AND (scheduling.automaticRestart = true).", + // "location": "query", + // "type": "string" + // }, + // "maxResults": { + // "default": "500", + // "description": "The maximum number of results per page that should be returned. If the number of available results is larger than maxResults, Compute Engine returns a nextPageToken that can be used to get the next page of results in subsequent list requests. Acceptable values are 0 to 500, inclusive. (Default: 500)", + // "format": "uint32", + // "location": "query", + // "minimum": "0", + // "type": "integer" + // }, + // "orderBy": { + // "description": "Sorts list results by a certain order. By default, results are returned in alphanumerical order based on the resource name.\n\nYou can also sort results in descending order based on the creation timestamp using orderBy=\"creationTimestamp desc\". This sorts results based on the creationTimestamp field in reverse chronological order (newest result first). Use this to sort resources like operations so that the newest operation is returned first.\n\nCurrently, only sorting by name or creationTimestamp desc is supported.", + // "location": "query", + // "type": "string" + // }, + // "pageToken": { + // "description": "Specifies a page token to use. Set pageToken to the nextPageToken returned by a previous list request to get the next page of results.", + // "location": "query", + // "type": "string" + // }, + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/aggregated/resourcePolicies", + // "response": { + // "$ref": "ResourcePolicyAggregatedList" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute", + // "https://www.googleapis.com/auth/compute.readonly" + // ] + // } + +} + +// Pages invokes f for each page of results. +// A non-nil error returned from f will halt the iteration. +// The provided context supersedes any context provided to the Context method. +func (c *ResourcePoliciesAggregatedListCall) Pages(ctx context.Context, f func(*ResourcePolicyAggregatedList) error) error { + c.ctx_ = ctx + defer c.PageToken(c.urlParams_.Get("pageToken")) // reset paging to original point + for { + x, err := c.Do() + if err != nil { + return err + } + if err := f(x); err != nil { + return err + } + if x.NextPageToken == "" { + return nil + } + c.PageToken(x.NextPageToken) + } +} + +// method id "compute.resourcePolicies.delete": + +type ResourcePoliciesDeleteCall struct { + s *Service + project string + region string + resourcePolicy string + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// Delete: Deletes the specified resource policy. +func (r *ResourcePoliciesService) Delete(project string, region string, resourcePolicy string) *ResourcePoliciesDeleteCall { + c := &ResourcePoliciesDeleteCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.region = region + c.resourcePolicy = resourcePolicy + return c +} + +// RequestId sets the optional parameter "requestId": An optional +// request ID to identify requests. Specify a unique request ID so that +// if you must retry your request, the server will know to ignore the +// request if it has already been completed. +// +// For example, consider a situation where you make an initial request +// and the request times out. If you make the request again with the +// same request ID, the server can check if original operation with the +// same request ID was received, and if so, will ignore the second +// request. This prevents clients from accidentally creating duplicate +// commitments. +// +// The request ID must be a valid UUID with the exception that zero UUID +// is not supported (00000000-0000-0000-0000-000000000000). +func (c *ResourcePoliciesDeleteCall) RequestId(requestId string) *ResourcePoliciesDeleteCall { + c.urlParams_.Set("requestId", requestId) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *ResourcePoliciesDeleteCall) Fields(s ...googleapi.Field) *ResourcePoliciesDeleteCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *ResourcePoliciesDeleteCall) Context(ctx context.Context) *ResourcePoliciesDeleteCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *ResourcePoliciesDeleteCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *ResourcePoliciesDeleteCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/resourcePolicies/{resourcePolicy}") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "region": c.region, + "resourcePolicy": c.resourcePolicy, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.resourcePolicies.delete" call. +// Exactly one of *Operation or error will be non-nil. Any non-2xx +// status code is an error. Response headers are in either +// *Operation.ServerResponse.Header or (if a response was returned at +// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified +// to check whether the returned error was because +// http.StatusNotModified was returned. +func (c *ResourcePoliciesDeleteCall) Do(opts ...googleapi.CallOption) (*Operation, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Operation{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Deletes the specified resource policy.", + // "httpMethod": "DELETE", + // "id": "compute.resourcePolicies.delete", + // "parameterOrder": [ + // "project", + // "region", + // "resourcePolicy" + // ], + // "parameters": { + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "region": { + // "description": "Name of the region for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // }, + // "requestId": { + // "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", + // "location": "query", + // "type": "string" + // }, + // "resourcePolicy": { + // "description": "Name of the resource policy to delete.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/regions/{region}/resourcePolicies/{resourcePolicy}", + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + +// method id "compute.resourcePolicies.get": + +type ResourcePoliciesGetCall struct { + s *Service + project string + region string + resourcePolicy string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// Get: Retrieves all information of the specified resource policy. +func (r *ResourcePoliciesService) Get(project string, region string, resourcePolicy string) *ResourcePoliciesGetCall { + c := &ResourcePoliciesGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.region = region + c.resourcePolicy = resourcePolicy + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *ResourcePoliciesGetCall) Fields(s ...googleapi.Field) *ResourcePoliciesGetCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// IfNoneMatch sets the optional parameter which makes the operation +// fail if the object's ETag matches the given value. This is useful for +// getting updates only after the object has changed since the last +// request. Use googleapi.IsNotModified to check whether the response +// error from Do is the result of In-None-Match. +func (c *ResourcePoliciesGetCall) IfNoneMatch(entityTag string) *ResourcePoliciesGetCall { + c.ifNoneMatch_ = entityTag + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *ResourcePoliciesGetCall) Context(ctx context.Context) *ResourcePoliciesGetCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *ResourcePoliciesGetCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *ResourcePoliciesGetCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + if c.ifNoneMatch_ != "" { + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) + } + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/resourcePolicies/{resourcePolicy}") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "region": c.region, + "resourcePolicy": c.resourcePolicy, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.resourcePolicies.get" call. +// Exactly one of *ResourcePolicy or error will be non-nil. Any non-2xx +// status code is an error. Response headers are in either +// *ResourcePolicy.ServerResponse.Header or (if a response was returned +// at all) in error.(*googleapi.Error).Header. Use +// googleapi.IsNotModified to check whether the returned error was +// because http.StatusNotModified was returned. +func (c *ResourcePoliciesGetCall) Do(opts ...googleapi.CallOption) (*ResourcePolicy, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &ResourcePolicy{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Retrieves all information of the specified resource policy.", + // "httpMethod": "GET", + // "id": "compute.resourcePolicies.get", + // "parameterOrder": [ + // "project", + // "region", + // "resourcePolicy" + // ], + // "parameters": { + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "region": { + // "description": "Name of the region for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // }, + // "resourcePolicy": { + // "description": "Name of the resource policy to retrieve.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/regions/{region}/resourcePolicies/{resourcePolicy}", + // "response": { + // "$ref": "ResourcePolicy" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute", + // "https://www.googleapis.com/auth/compute.readonly" + // ] + // } + +} + +// method id "compute.resourcePolicies.insert": + +type ResourcePoliciesInsertCall struct { + s *Service + project string + region string + resourcepolicy *ResourcePolicy + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// Insert: Creates a new resource policy. +func (r *ResourcePoliciesService) Insert(project string, region string, resourcepolicy *ResourcePolicy) *ResourcePoliciesInsertCall { + c := &ResourcePoliciesInsertCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.region = region + c.resourcepolicy = resourcepolicy + return c +} + +// RequestId sets the optional parameter "requestId": An optional +// request ID to identify requests. Specify a unique request ID so that +// if you must retry your request, the server will know to ignore the +// request if it has already been completed. +// +// For example, consider a situation where you make an initial request +// and the request times out. If you make the request again with the +// same request ID, the server can check if original operation with the +// same request ID was received, and if so, will ignore the second +// request. This prevents clients from accidentally creating duplicate +// commitments. +// +// The request ID must be a valid UUID with the exception that zero UUID +// is not supported (00000000-0000-0000-0000-000000000000). +func (c *ResourcePoliciesInsertCall) RequestId(requestId string) *ResourcePoliciesInsertCall { + c.urlParams_.Set("requestId", requestId) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *ResourcePoliciesInsertCall) Fields(s ...googleapi.Field) *ResourcePoliciesInsertCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *ResourcePoliciesInsertCall) Context(ctx context.Context) *ResourcePoliciesInsertCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *ResourcePoliciesInsertCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *ResourcePoliciesInsertCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.resourcepolicy) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/resourcePolicies") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "region": c.region, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.resourcePolicies.insert" call. +// Exactly one of *Operation or error will be non-nil. Any non-2xx +// status code is an error. Response headers are in either +// *Operation.ServerResponse.Header or (if a response was returned at +// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified +// to check whether the returned error was because +// http.StatusNotModified was returned. +func (c *ResourcePoliciesInsertCall) Do(opts ...googleapi.CallOption) (*Operation, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Operation{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Creates a new resource policy.", + // "httpMethod": "POST", + // "id": "compute.resourcePolicies.insert", + // "parameterOrder": [ + // "project", + // "region" + // ], + // "parameters": { + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "region": { + // "description": "Name of the region for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // }, + // "requestId": { + // "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", + // "location": "query", + // "type": "string" + // } + // }, + // "path": "{project}/regions/{region}/resourcePolicies", + // "request": { + // "$ref": "ResourcePolicy" + // }, + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + +// method id "compute.resourcePolicies.list": + +type ResourcePoliciesListCall struct { + s *Service + project string + region string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// List: A list all the resource policies that have been configured for +// the specified project in specified region. +func (r *ResourcePoliciesService) List(project string, region string) *ResourcePoliciesListCall { + c := &ResourcePoliciesListCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.region = region + return c +} + +// Filter sets the optional parameter "filter": A filter expression that +// filters resources listed in the response. The expression must specify +// the field name, a comparison operator, and the value that you want to +// use for filtering. The value must be a string, a number, or a +// boolean. The comparison operator must be either =, !=, >, or <. +// +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. +// +// You can also filter nested fields. For example, you could specify +// scheduling.automaticRestart = false to include instances only if they +// are not scheduled for automatic restarts. You can use filtering on +// nested fields to filter based on resource labels. +// +// To filter on multiple expressions, provide each separate expression +// within parentheses. For example, (scheduling.automaticRestart = true) +// (cpuPlatform = "Intel Skylake"). By default, each expression is an +// AND expression. However, you can include AND and OR expressions +// explicitly. For example, (cpuPlatform = "Intel Skylake") OR +// (cpuPlatform = "Intel Broadwell") AND (scheduling.automaticRestart = +// true). +func (c *ResourcePoliciesListCall) Filter(filter string) *ResourcePoliciesListCall { + c.urlParams_.Set("filter", filter) + return c +} + +// MaxResults sets the optional parameter "maxResults": The maximum +// number of results per page that should be returned. If the number of +// available results is larger than maxResults, Compute Engine returns a +// nextPageToken that can be used to get the next page of results in +// subsequent list requests. Acceptable values are 0 to 500, inclusive. +// (Default: 500) +func (c *ResourcePoliciesListCall) MaxResults(maxResults int64) *ResourcePoliciesListCall { + c.urlParams_.Set("maxResults", fmt.Sprint(maxResults)) + return c +} + +// OrderBy sets the optional parameter "orderBy": Sorts list results by +// a certain order. By default, results are returned in alphanumerical +// order based on the resource name. +// +// You can also sort results in descending order based on the creation +// timestamp using orderBy="creationTimestamp desc". This sorts results +// based on the creationTimestamp field in reverse chronological order +// (newest result first). Use this to sort resources like operations so +// that the newest operation is returned first. +// +// Currently, only sorting by name or creationTimestamp desc is +// supported. +func (c *ResourcePoliciesListCall) OrderBy(orderBy string) *ResourcePoliciesListCall { + c.urlParams_.Set("orderBy", orderBy) + return c +} + +// PageToken sets the optional parameter "pageToken": Specifies a page +// token to use. Set pageToken to the nextPageToken returned by a +// previous list request to get the next page of results. +func (c *ResourcePoliciesListCall) PageToken(pageToken string) *ResourcePoliciesListCall { + c.urlParams_.Set("pageToken", pageToken) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *ResourcePoliciesListCall) Fields(s ...googleapi.Field) *ResourcePoliciesListCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// IfNoneMatch sets the optional parameter which makes the operation +// fail if the object's ETag matches the given value. This is useful for +// getting updates only after the object has changed since the last +// request. Use googleapi.IsNotModified to check whether the response +// error from Do is the result of In-None-Match. +func (c *ResourcePoliciesListCall) IfNoneMatch(entityTag string) *ResourcePoliciesListCall { + c.ifNoneMatch_ = entityTag + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *ResourcePoliciesListCall) Context(ctx context.Context) *ResourcePoliciesListCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *ResourcePoliciesListCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *ResourcePoliciesListCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + if c.ifNoneMatch_ != "" { + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) + } + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/resourcePolicies") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "region": c.region, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.resourcePolicies.list" call. +// Exactly one of *ResourcePolicyList or error will be non-nil. Any +// non-2xx status code is an error. Response headers are in either +// *ResourcePolicyList.ServerResponse.Header or (if a response was +// returned at all) in error.(*googleapi.Error).Header. Use +// googleapi.IsNotModified to check whether the returned error was +// because http.StatusNotModified was returned. +func (c *ResourcePoliciesListCall) Do(opts ...googleapi.CallOption) (*ResourcePolicyList, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &ResourcePolicyList{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "A list all the resource policies that have been configured for the specified project in specified region.", + // "httpMethod": "GET", + // "id": "compute.resourcePolicies.list", + // "parameterOrder": [ + // "project", + // "region" + // ], + // "parameters": { + // "filter": { + // "description": "A filter expression that filters resources listed in the response. The expression must specify the field name, a comparison operator, and the value that you want to use for filtering. The value must be a string, a number, or a boolean. The comparison operator must be either =, !=, \u003e, or \u003c.\n\nFor example, if you are filtering Compute Engine instances, you can exclude instances named example-instance by specifying name != example-instance.\n\nYou can also filter nested fields. For example, you could specify scheduling.automaticRestart = false to include instances only if they are not scheduled for automatic restarts. You can use filtering on nested fields to filter based on resource labels.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart = true) (cpuPlatform = \"Intel Skylake\"). By default, each expression is an AND expression. However, you can include AND and OR expressions explicitly. For example, (cpuPlatform = \"Intel Skylake\") OR (cpuPlatform = \"Intel Broadwell\") AND (scheduling.automaticRestart = true).", + // "location": "query", + // "type": "string" + // }, + // "maxResults": { + // "default": "500", + // "description": "The maximum number of results per page that should be returned. If the number of available results is larger than maxResults, Compute Engine returns a nextPageToken that can be used to get the next page of results in subsequent list requests. Acceptable values are 0 to 500, inclusive. (Default: 500)", + // "format": "uint32", + // "location": "query", + // "minimum": "0", + // "type": "integer" + // }, + // "orderBy": { + // "description": "Sorts list results by a certain order. By default, results are returned in alphanumerical order based on the resource name.\n\nYou can also sort results in descending order based on the creation timestamp using orderBy=\"creationTimestamp desc\". This sorts results based on the creationTimestamp field in reverse chronological order (newest result first). Use this to sort resources like operations so that the newest operation is returned first.\n\nCurrently, only sorting by name or creationTimestamp desc is supported.", + // "location": "query", + // "type": "string" + // }, + // "pageToken": { + // "description": "Specifies a page token to use. Set pageToken to the nextPageToken returned by a previous list request to get the next page of results.", + // "location": "query", + // "type": "string" + // }, + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "region": { + // "description": "Name of the region for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/regions/{region}/resourcePolicies", + // "response": { + // "$ref": "ResourcePolicyList" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute", + // "https://www.googleapis.com/auth/compute.readonly" + // ] + // } + +} + +// Pages invokes f for each page of results. +// A non-nil error returned from f will halt the iteration. +// The provided context supersedes any context provided to the Context method. +func (c *ResourcePoliciesListCall) Pages(ctx context.Context, f func(*ResourcePolicyList) error) error { + c.ctx_ = ctx + defer c.PageToken(c.urlParams_.Get("pageToken")) // reset paging to original point + for { + x, err := c.Do() + if err != nil { + return err + } + if err := f(x); err != nil { + return err + } + if x.NextPageToken == "" { + return nil + } + c.PageToken(x.NextPageToken) + } +} + +// method id "compute.resourcePolicies.testIamPermissions": + +type ResourcePoliciesTestIamPermissionsCall struct { + s *Service + project string + region string + resource string + testpermissionsrequest *TestPermissionsRequest + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// TestIamPermissions: Returns permissions that a caller has on the +// specified resource. +func (r *ResourcePoliciesService) TestIamPermissions(project string, region string, resource string, testpermissionsrequest *TestPermissionsRequest) *ResourcePoliciesTestIamPermissionsCall { + c := &ResourcePoliciesTestIamPermissionsCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.region = region + c.resource = resource + c.testpermissionsrequest = testpermissionsrequest + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *ResourcePoliciesTestIamPermissionsCall) Fields(s ...googleapi.Field) *ResourcePoliciesTestIamPermissionsCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *ResourcePoliciesTestIamPermissionsCall) Context(ctx context.Context) *ResourcePoliciesTestIamPermissionsCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *ResourcePoliciesTestIamPermissionsCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *ResourcePoliciesTestIamPermissionsCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.testpermissionsrequest) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/resourcePolicies/{resource}/testIamPermissions") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "region": c.region, + "resource": c.resource, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.resourcePolicies.testIamPermissions" call. +// Exactly one of *TestPermissionsResponse or error will be non-nil. Any +// non-2xx status code is an error. Response headers are in either +// *TestPermissionsResponse.ServerResponse.Header or (if a response was +// returned at all) in error.(*googleapi.Error).Header. Use +// googleapi.IsNotModified to check whether the returned error was +// because http.StatusNotModified was returned. +func (c *ResourcePoliciesTestIamPermissionsCall) Do(opts ...googleapi.CallOption) (*TestPermissionsResponse, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &TestPermissionsResponse{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Returns permissions that a caller has on the specified resource.", + // "httpMethod": "POST", + // "id": "compute.resourcePolicies.testIamPermissions", + // "parameterOrder": [ + // "project", + // "region", + // "resource" + // ], + // "parameters": { + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "region": { + // "description": "The name of the region for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // }, + // "resource": { + // "description": "Name or id of the resource for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/regions/{region}/resourcePolicies/{resource}/testIamPermissions", + // "request": { + // "$ref": "TestPermissionsRequest" + // }, + // "response": { + // "$ref": "TestPermissionsResponse" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute", + // "https://www.googleapis.com/auth/compute.readonly" + // ] + // } + +} + // method id "compute.routers.aggregatedList": type RoutersAggregatedListCall struct { @@ -87598,9 +99069,13 @@ func (c *RoutersAggregatedListCall) doRequest(alt string) (*http.Response, error } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/aggregated/routers") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -87791,9 +99266,13 @@ func (c *RoutersDeleteCall) doRequest(alt string) (*http.Response, error) { reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/routers/{router}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -87958,9 +99437,13 @@ func (c *RoutersGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/routers/{router}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -88052,6 +99535,280 @@ func (c *RoutersGetCall) Do(opts ...googleapi.CallOption) (*Router, error) { } +// method id "compute.routers.getNatMappingInfo": + +type RoutersGetNatMappingInfoCall struct { + s *Service + project string + region string + router string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// GetNatMappingInfo: Retrieves runtime Nat mapping information of VM +// endpoints. +func (r *RoutersService) GetNatMappingInfo(project string, region string, router string) *RoutersGetNatMappingInfoCall { + c := &RoutersGetNatMappingInfoCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.region = region + c.router = router + return c +} + +// Filter sets the optional parameter "filter": A filter expression that +// filters resources listed in the response. The expression must specify +// the field name, a comparison operator, and the value that you want to +// use for filtering. The value must be a string, a number, or a +// boolean. The comparison operator must be either =, !=, >, or <. +// +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. +// +// You can also filter nested fields. For example, you could specify +// scheduling.automaticRestart = false to include instances only if they +// are not scheduled for automatic restarts. You can use filtering on +// nested fields to filter based on resource labels. +// +// To filter on multiple expressions, provide each separate expression +// within parentheses. For example, (scheduling.automaticRestart = true) +// (cpuPlatform = "Intel Skylake"). By default, each expression is an +// AND expression. However, you can include AND and OR expressions +// explicitly. For example, (cpuPlatform = "Intel Skylake") OR +// (cpuPlatform = "Intel Broadwell") AND (scheduling.automaticRestart = +// true). +func (c *RoutersGetNatMappingInfoCall) Filter(filter string) *RoutersGetNatMappingInfoCall { + c.urlParams_.Set("filter", filter) + return c +} + +// MaxResults sets the optional parameter "maxResults": The maximum +// number of results per page that should be returned. If the number of +// available results is larger than maxResults, Compute Engine returns a +// nextPageToken that can be used to get the next page of results in +// subsequent list requests. Acceptable values are 0 to 500, inclusive. +// (Default: 500) +func (c *RoutersGetNatMappingInfoCall) MaxResults(maxResults int64) *RoutersGetNatMappingInfoCall { + c.urlParams_.Set("maxResults", fmt.Sprint(maxResults)) + return c +} + +// OrderBy sets the optional parameter "orderBy": Sorts list results by +// a certain order. By default, results are returned in alphanumerical +// order based on the resource name. +// +// You can also sort results in descending order based on the creation +// timestamp using orderBy="creationTimestamp desc". This sorts results +// based on the creationTimestamp field in reverse chronological order +// (newest result first). Use this to sort resources like operations so +// that the newest operation is returned first. +// +// Currently, only sorting by name or creationTimestamp desc is +// supported. +func (c *RoutersGetNatMappingInfoCall) OrderBy(orderBy string) *RoutersGetNatMappingInfoCall { + c.urlParams_.Set("orderBy", orderBy) + return c +} + +// PageToken sets the optional parameter "pageToken": Specifies a page +// token to use. Set pageToken to the nextPageToken returned by a +// previous list request to get the next page of results. +func (c *RoutersGetNatMappingInfoCall) PageToken(pageToken string) *RoutersGetNatMappingInfoCall { + c.urlParams_.Set("pageToken", pageToken) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *RoutersGetNatMappingInfoCall) Fields(s ...googleapi.Field) *RoutersGetNatMappingInfoCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// IfNoneMatch sets the optional parameter which makes the operation +// fail if the object's ETag matches the given value. This is useful for +// getting updates only after the object has changed since the last +// request. Use googleapi.IsNotModified to check whether the response +// error from Do is the result of In-None-Match. +func (c *RoutersGetNatMappingInfoCall) IfNoneMatch(entityTag string) *RoutersGetNatMappingInfoCall { + c.ifNoneMatch_ = entityTag + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *RoutersGetNatMappingInfoCall) Context(ctx context.Context) *RoutersGetNatMappingInfoCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *RoutersGetNatMappingInfoCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *RoutersGetNatMappingInfoCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + if c.ifNoneMatch_ != "" { + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) + } + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/routers/{router}/getNatMappingInfo") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "region": c.region, + "router": c.router, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.routers.getNatMappingInfo" call. +// Exactly one of *VmEndpointNatMappingsList or error will be non-nil. +// Any non-2xx status code is an error. Response headers are in either +// *VmEndpointNatMappingsList.ServerResponse.Header or (if a response +// was returned at all) in error.(*googleapi.Error).Header. Use +// googleapi.IsNotModified to check whether the returned error was +// because http.StatusNotModified was returned. +func (c *RoutersGetNatMappingInfoCall) Do(opts ...googleapi.CallOption) (*VmEndpointNatMappingsList, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &VmEndpointNatMappingsList{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Retrieves runtime Nat mapping information of VM endpoints.", + // "httpMethod": "GET", + // "id": "compute.routers.getNatMappingInfo", + // "parameterOrder": [ + // "project", + // "region", + // "router" + // ], + // "parameters": { + // "filter": { + // "description": "A filter expression that filters resources listed in the response. The expression must specify the field name, a comparison operator, and the value that you want to use for filtering. The value must be a string, a number, or a boolean. The comparison operator must be either =, !=, \u003e, or \u003c.\n\nFor example, if you are filtering Compute Engine instances, you can exclude instances named example-instance by specifying name != example-instance.\n\nYou can also filter nested fields. For example, you could specify scheduling.automaticRestart = false to include instances only if they are not scheduled for automatic restarts. You can use filtering on nested fields to filter based on resource labels.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart = true) (cpuPlatform = \"Intel Skylake\"). By default, each expression is an AND expression. However, you can include AND and OR expressions explicitly. For example, (cpuPlatform = \"Intel Skylake\") OR (cpuPlatform = \"Intel Broadwell\") AND (scheduling.automaticRestart = true).", + // "location": "query", + // "type": "string" + // }, + // "maxResults": { + // "default": "500", + // "description": "The maximum number of results per page that should be returned. If the number of available results is larger than maxResults, Compute Engine returns a nextPageToken that can be used to get the next page of results in subsequent list requests. Acceptable values are 0 to 500, inclusive. (Default: 500)", + // "format": "uint32", + // "location": "query", + // "minimum": "0", + // "type": "integer" + // }, + // "orderBy": { + // "description": "Sorts list results by a certain order. By default, results are returned in alphanumerical order based on the resource name.\n\nYou can also sort results in descending order based on the creation timestamp using orderBy=\"creationTimestamp desc\". This sorts results based on the creationTimestamp field in reverse chronological order (newest result first). Use this to sort resources like operations so that the newest operation is returned first.\n\nCurrently, only sorting by name or creationTimestamp desc is supported.", + // "location": "query", + // "type": "string" + // }, + // "pageToken": { + // "description": "Specifies a page token to use. Set pageToken to the nextPageToken returned by a previous list request to get the next page of results.", + // "location": "query", + // "type": "string" + // }, + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "region": { + // "description": "Name of the region for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // }, + // "router": { + // "description": "Name of the Router resource to query for Nat Mapping information of VM endpoints.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/regions/{region}/routers/{router}/getNatMappingInfo", + // "response": { + // "$ref": "VmEndpointNatMappingsList" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute", + // "https://www.googleapis.com/auth/compute.readonly" + // ] + // } + +} + +// Pages invokes f for each page of results. +// A non-nil error returned from f will halt the iteration. +// The provided context supersedes any context provided to the Context method. +func (c *RoutersGetNatMappingInfoCall) Pages(ctx context.Context, f func(*VmEndpointNatMappingsList) error) error { + c.ctx_ = ctx + defer c.PageToken(c.urlParams_.Get("pageToken")) // reset paging to original point + for { + x, err := c.Do() + if err != nil { + return err + } + if err := f(x); err != nil { + return err + } + if x.NextPageToken == "" { + return nil + } + c.PageToken(x.NextPageToken) + } +} + // method id "compute.routers.getRouterStatus": type RoutersGetRouterStatusCall struct { @@ -88121,9 +99878,13 @@ func (c *RoutersGetRouterStatusCall) doRequest(alt string) (*http.Response, erro } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/routers/{router}/getRouterStatus") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -88294,9 +100055,13 @@ func (c *RoutersInsertCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/routers") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -88516,9 +100281,13 @@ func (c *RoutersListCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/routers") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -88727,9 +100496,13 @@ func (c *RoutersPatchCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/routers/{router}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PATCH", urls, body) + req, err := http.NewRequest("PATCH", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -88891,9 +100664,13 @@ func (c *RoutersPreviewCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/routers/{router}/preview") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -89050,9 +100827,13 @@ func (c *RoutersTestIamPermissionsCall) doRequest(alt string) (*http.Response, e } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/routers/{resource}/testIamPermissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -89124,9 +100905,9 @@ func (c *RoutersTestIamPermissionsCall) Do(opts ...googleapi.CallOption) (*TestP // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -89228,9 +101009,13 @@ func (c *RoutersUpdateCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/routers/{router}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PUT", urls, body) + req, err := http.NewRequest("PUT", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -89401,9 +101186,13 @@ func (c *RoutesDeleteCall) doRequest(alt string) (*http.Response, error) { reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/routes/{route}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -89473,7 +101262,7 @@ func (c *RoutesDeleteCall) Do(opts ...googleapi.CallOption) (*Operation, error) // "route": { // "description": "Name of the Route resource to delete.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -89558,9 +101347,13 @@ func (c *RoutesGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/routes/{route}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -89625,7 +101418,7 @@ func (c *RoutesGetCall) Do(opts ...googleapi.CallOption) (*Route, error) { // "route": { // "description": "Name of the Route resource to return.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -89721,9 +101514,13 @@ func (c *RoutesInsertCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/routes") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -89933,9 +101730,13 @@ func (c *RoutesListCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/routes") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -90113,9 +101914,13 @@ func (c *RoutesTestIamPermissionsCall) doRequest(alt string) (*http.Response, er } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/routes/{resource}/testIamPermissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -90178,9 +101983,9 @@ func (c *RoutesTestIamPermissionsCall) Do(opts ...googleapi.CallOption) (*TestPe // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "(?:[-a-z0-9_]{0,62}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -90222,6 +102027,13 @@ func (r *SecurityPoliciesService) AddRule(project string, securityPolicy string, return c } +// ValidateOnly sets the optional parameter "validateOnly": If true, the +// request will not be committed. +func (c *SecurityPoliciesAddRuleCall) ValidateOnly(validateOnly bool) *SecurityPoliciesAddRuleCall { + c.urlParams_.Set("validateOnly", fmt.Sprint(validateOnly)) + return c +} + // Fields allows partial responses to be retrieved. See // https://developers.google.com/gdata/docs/2.0/basics#PartialResponse // for more information. @@ -90260,9 +102072,13 @@ func (c *SecurityPoliciesAddRuleCall) doRequest(alt string) (*http.Response, err } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/securityPolicies/{securityPolicy}/addRule") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -90330,6 +102146,11 @@ func (c *SecurityPoliciesAddRuleCall) Do(opts ...googleapi.CallOption) (*Operati // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", // "required": true, // "type": "string" + // }, + // "validateOnly": { + // "description": "If true, the request will not be committed.", + // "location": "query", + // "type": "boolean" // } // }, // "path": "{project}/global/securityPolicies/{securityPolicy}/addRule", @@ -90418,9 +102239,13 @@ func (c *SecurityPoliciesDeleteCall) doRequest(alt string) (*http.Response, erro reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/securityPolicies/{securityPolicy}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -90574,9 +102399,13 @@ func (c *SecurityPoliciesGetCall) doRequest(alt string) (*http.Response, error) } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/securityPolicies/{securityPolicy}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -90732,9 +102561,13 @@ func (c *SecurityPoliciesGetRuleCall) doRequest(alt string) (*http.Response, err } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/securityPolicies/{securityPolicy}/getRule") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -90862,6 +102695,13 @@ func (c *SecurityPoliciesInsertCall) RequestId(requestId string) *SecurityPolici return c } +// ValidateOnly sets the optional parameter "validateOnly": If true, the +// request will not be committed. +func (c *SecurityPoliciesInsertCall) ValidateOnly(validateOnly bool) *SecurityPoliciesInsertCall { + c.urlParams_.Set("validateOnly", fmt.Sprint(validateOnly)) + return c +} + // Fields allows partial responses to be retrieved. See // https://developers.google.com/gdata/docs/2.0/basics#PartialResponse // for more information. @@ -90900,9 +102740,13 @@ func (c *SecurityPoliciesInsertCall) doRequest(alt string) (*http.Response, erro } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/securityPolicies") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -90966,6 +102810,11 @@ func (c *SecurityPoliciesInsertCall) Do(opts ...googleapi.CallOption) (*Operatio // "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", // "location": "query", // "type": "string" + // }, + // "validateOnly": { + // "description": "If true, the request will not be committed.", + // "location": "query", + // "type": "boolean" // } // }, // "path": "{project}/global/securityPolicies", @@ -91111,9 +102960,13 @@ func (c *SecurityPoliciesListCall) doRequest(alt string) (*http.Response, error) } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/securityPolicies") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -91359,9 +103212,13 @@ func (c *SecurityPoliciesListPreconfiguredExpressionSetsCall) doRequest(alt stri } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/securityPolicies/listPreconfiguredExpressionSets") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -91539,9 +103396,13 @@ func (c *SecurityPoliciesPatchCall) doRequest(alt string) (*http.Response, error } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/securityPolicies/{securityPolicy}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PATCH", urls, body) + req, err := http.NewRequest("PATCH", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -91659,6 +103520,13 @@ func (c *SecurityPoliciesPatchRuleCall) Priority(priority int64) *SecurityPolici return c } +// ValidateOnly sets the optional parameter "validateOnly": If true, the +// request will not be committed. +func (c *SecurityPoliciesPatchRuleCall) ValidateOnly(validateOnly bool) *SecurityPoliciesPatchRuleCall { + c.urlParams_.Set("validateOnly", fmt.Sprint(validateOnly)) + return c +} + // Fields allows partial responses to be retrieved. See // https://developers.google.com/gdata/docs/2.0/basics#PartialResponse // for more information. @@ -91697,9 +103565,13 @@ func (c *SecurityPoliciesPatchRuleCall) doRequest(alt string) (*http.Response, e } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/securityPolicies/{securityPolicy}/patchRule") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -91773,6 +103645,11 @@ func (c *SecurityPoliciesPatchRuleCall) Do(opts ...googleapi.CallOption) (*Opera // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", // "required": true, // "type": "string" + // }, + // "validateOnly": { + // "description": "If true, the request will not be committed.", + // "location": "query", + // "type": "boolean" // } // }, // "path": "{project}/global/securityPolicies/{securityPolicy}/patchRule", @@ -91849,9 +103726,13 @@ func (c *SecurityPoliciesRemoveRuleCall) doRequest(alt string) (*http.Response, reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/securityPolicies/{securityPolicy}/removeRule") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -91939,6 +103820,157 @@ func (c *SecurityPoliciesRemoveRuleCall) Do(opts ...googleapi.CallOption) (*Oper } +// method id "compute.securityPolicies.setLabels": + +type SecurityPoliciesSetLabelsCall struct { + s *Service + project string + resource string + globalsetlabelsrequest *GlobalSetLabelsRequest + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// SetLabels: Sets the labels on a security policy. To learn more about +// labels, read the Labeling Resources documentation. +func (r *SecurityPoliciesService) SetLabels(project string, resource string, globalsetlabelsrequest *GlobalSetLabelsRequest) *SecurityPoliciesSetLabelsCall { + c := &SecurityPoliciesSetLabelsCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.resource = resource + c.globalsetlabelsrequest = globalsetlabelsrequest + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *SecurityPoliciesSetLabelsCall) Fields(s ...googleapi.Field) *SecurityPoliciesSetLabelsCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *SecurityPoliciesSetLabelsCall) Context(ctx context.Context) *SecurityPoliciesSetLabelsCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *SecurityPoliciesSetLabelsCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *SecurityPoliciesSetLabelsCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.globalsetlabelsrequest) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/securityPolicies/{resource}/setLabels") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "resource": c.resource, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.securityPolicies.setLabels" call. +// Exactly one of *Operation or error will be non-nil. Any non-2xx +// status code is an error. Response headers are in either +// *Operation.ServerResponse.Header or (if a response was returned at +// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified +// to check whether the returned error was because +// http.StatusNotModified was returned. +func (c *SecurityPoliciesSetLabelsCall) Do(opts ...googleapi.CallOption) (*Operation, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Operation{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Sets the labels on a security policy. To learn more about labels, read the Labeling Resources documentation.", + // "httpMethod": "POST", + // "id": "compute.securityPolicies.setLabels", + // "parameterOrder": [ + // "project", + // "resource" + // ], + // "parameters": { + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "resource": { + // "description": "Name or id of the resource for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/global/securityPolicies/{resource}/setLabels", + // "request": { + // "$ref": "GlobalSetLabelsRequest" + // }, + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + // method id "compute.securityPolicies.testIamPermissions": type SecurityPoliciesTestIamPermissionsCall struct { @@ -91999,9 +104031,13 @@ func (c *SecurityPoliciesTestIamPermissionsCall) doRequest(alt string) (*http.Re } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/securityPolicies/{resource}/testIamPermissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -92064,9 +104100,9 @@ func (c *SecurityPoliciesTestIamPermissionsCall) Do(opts ...googleapi.CallOption // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "(?:[-a-z0-9_]{0,62}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -92104,7 +104140,7 @@ type SnapshotsDeleteCall struct { // deletion is needed for subsequent snapshots, the data will be moved // to the next corresponding snapshot. // -// For more information, see Deleting snaphots. +// For more information, see Deleting snapshots. // For details, see https://cloud.google.com/compute/docs/reference/latest/snapshots/delete func (r *SnapshotsService) Delete(project string, snapshot string) *SnapshotsDeleteCall { c := &SnapshotsDeleteCall{s: r.s, urlParams_: make(gensupport.URLParams)} @@ -92165,9 +104201,13 @@ func (c *SnapshotsDeleteCall) doRequest(alt string) (*http.Response, error) { reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/snapshots/{snapshot}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -92214,7 +104254,7 @@ func (c *SnapshotsDeleteCall) Do(opts ...googleapi.CallOption) (*Operation, erro } return ret, nil // { - // "description": "Deletes the specified Snapshot resource. Keep in mind that deleting a single snapshot might not necessarily delete all the data on that snapshot. If any data on the snapshot that is marked for deletion is needed for subsequent snapshots, the data will be moved to the next corresponding snapshot.\n\nFor more information, see Deleting snaphots.", + // "description": "Deletes the specified Snapshot resource. Keep in mind that deleting a single snapshot might not necessarily delete all the data on that snapshot. If any data on the snapshot that is marked for deletion is needed for subsequent snapshots, the data will be moved to the next corresponding snapshot.\n\nFor more information, see Deleting snapshots.", // "httpMethod": "DELETE", // "id": "compute.snapshots.delete", // "parameterOrder": [ @@ -92237,7 +104277,7 @@ func (c *SnapshotsDeleteCall) Do(opts ...googleapi.CallOption) (*Operation, erro // "snapshot": { // "description": "Name of the Snapshot resource to delete.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -92322,9 +104362,13 @@ func (c *SnapshotsGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/snapshots/{snapshot}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -92389,7 +104433,7 @@ func (c *SnapshotsGetCall) Do(opts ...googleapi.CallOption) (*Snapshot, error) { // "snapshot": { // "description": "Name of the Snapshot resource to return.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -92407,6 +104451,162 @@ func (c *SnapshotsGetCall) Do(opts ...googleapi.CallOption) (*Snapshot, error) { } +// method id "compute.snapshots.getIamPolicy": + +type SnapshotsGetIamPolicyCall struct { + s *Service + project string + resource string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// GetIamPolicy: Gets the access control policy for a resource. May be +// empty if no such policy or resource exists. +func (r *SnapshotsService) GetIamPolicy(project string, resource string) *SnapshotsGetIamPolicyCall { + c := &SnapshotsGetIamPolicyCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.resource = resource + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *SnapshotsGetIamPolicyCall) Fields(s ...googleapi.Field) *SnapshotsGetIamPolicyCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// IfNoneMatch sets the optional parameter which makes the operation +// fail if the object's ETag matches the given value. This is useful for +// getting updates only after the object has changed since the last +// request. Use googleapi.IsNotModified to check whether the response +// error from Do is the result of In-None-Match. +func (c *SnapshotsGetIamPolicyCall) IfNoneMatch(entityTag string) *SnapshotsGetIamPolicyCall { + c.ifNoneMatch_ = entityTag + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *SnapshotsGetIamPolicyCall) Context(ctx context.Context) *SnapshotsGetIamPolicyCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *SnapshotsGetIamPolicyCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *SnapshotsGetIamPolicyCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + if c.ifNoneMatch_ != "" { + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) + } + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/snapshots/{resource}/getIamPolicy") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "resource": c.resource, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.snapshots.getIamPolicy" call. +// Exactly one of *Policy or error will be non-nil. Any non-2xx status +// code is an error. Response headers are in either +// *Policy.ServerResponse.Header or (if a response was returned at all) +// in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to +// check whether the returned error was because http.StatusNotModified +// was returned. +func (c *SnapshotsGetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Policy, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Policy{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Gets the access control policy for a resource. May be empty if no such policy or resource exists.", + // "httpMethod": "GET", + // "id": "compute.snapshots.getIamPolicy", + // "parameterOrder": [ + // "project", + // "resource" + // ], + // "parameters": { + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "resource": { + // "description": "Name or id of the resource for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/global/snapshots/{resource}/getIamPolicy", + // "response": { + // "$ref": "Policy" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute", + // "https://www.googleapis.com/auth/compute.readonly" + // ] + // } + +} + // method id "compute.snapshots.list": type SnapshotsListCall struct { @@ -92536,9 +104736,13 @@ func (c *SnapshotsListCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/snapshots") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -92656,6 +104860,157 @@ func (c *SnapshotsListCall) Pages(ctx context.Context, f func(*SnapshotList) err } } +// method id "compute.snapshots.setIamPolicy": + +type SnapshotsSetIamPolicyCall struct { + s *Service + project string + resource string + globalsetpolicyrequest *GlobalSetPolicyRequest + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// SetIamPolicy: Sets the access control policy on the specified +// resource. Replaces any existing policy. +func (r *SnapshotsService) SetIamPolicy(project string, resource string, globalsetpolicyrequest *GlobalSetPolicyRequest) *SnapshotsSetIamPolicyCall { + c := &SnapshotsSetIamPolicyCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.resource = resource + c.globalsetpolicyrequest = globalsetpolicyrequest + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *SnapshotsSetIamPolicyCall) Fields(s ...googleapi.Field) *SnapshotsSetIamPolicyCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *SnapshotsSetIamPolicyCall) Context(ctx context.Context) *SnapshotsSetIamPolicyCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *SnapshotsSetIamPolicyCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *SnapshotsSetIamPolicyCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.globalsetpolicyrequest) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/snapshots/{resource}/setIamPolicy") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "resource": c.resource, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.snapshots.setIamPolicy" call. +// Exactly one of *Policy or error will be non-nil. Any non-2xx status +// code is an error. Response headers are in either +// *Policy.ServerResponse.Header or (if a response was returned at all) +// in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to +// check whether the returned error was because http.StatusNotModified +// was returned. +func (c *SnapshotsSetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Policy, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Policy{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Sets the access control policy on the specified resource. Replaces any existing policy.", + // "httpMethod": "POST", + // "id": "compute.snapshots.setIamPolicy", + // "parameterOrder": [ + // "project", + // "resource" + // ], + // "parameters": { + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "resource": { + // "description": "Name or id of the resource for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/global/snapshots/{resource}/setIamPolicy", + // "request": { + // "$ref": "GlobalSetPolicyRequest" + // }, + // "response": { + // "$ref": "Policy" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + // method id "compute.snapshots.setLabels": type SnapshotsSetLabelsCall struct { @@ -92716,9 +105071,13 @@ func (c *SnapshotsSetLabelsCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/snapshots/{resource}/setLabels") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -92781,9 +105140,9 @@ func (c *SnapshotsSetLabelsCall) Do(opts ...googleapi.CallOption) (*Operation, e // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -92863,9 +105222,13 @@ func (c *SnapshotsTestIamPermissionsCall) doRequest(alt string) (*http.Response, } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/snapshots/{resource}/testIamPermissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -92928,9 +105291,9 @@ func (c *SnapshotsTestIamPermissionsCall) Do(opts ...googleapi.CallOption) (*Tes // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "(?:[-a-z0-9_]{0,62}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -93022,9 +105385,13 @@ func (c *SslCertificatesDeleteCall) doRequest(alt string) (*http.Response, error reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/sslCertificates/{sslCertificate}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -93178,9 +105545,13 @@ func (c *SslCertificatesGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/sslCertificates/{sslCertificate}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -93340,9 +105711,13 @@ func (c *SslCertificatesInsertCall) doRequest(alt string) (*http.Response, error } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/sslCertificates") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -93551,9 +105926,13 @@ func (c *SslCertificatesListCall) doRequest(alt string) (*http.Response, error) } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/sslCertificates") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -93731,9 +106110,13 @@ func (c *SslCertificatesTestIamPermissionsCall) doRequest(alt string) (*http.Res } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/sslCertificates/{resource}/testIamPermissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -93796,9 +106179,9 @@ func (c *SslCertificatesTestIamPermissionsCall) Do(opts ...googleapi.CallOption) // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "(?:[-a-z0-9_]{0,62}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -93892,9 +106275,13 @@ func (c *SslPoliciesDeleteCall) doRequest(alt string) (*http.Response, error) { reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/sslPolicies/{sslPolicy}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -94047,9 +106434,13 @@ func (c *SslPoliciesGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/sslPolicies/{sslPolicy}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -94208,9 +106599,13 @@ func (c *SslPoliciesInsertCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/sslPolicies") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -94419,9 +106814,13 @@ func (c *SslPoliciesListCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/sslPolicies") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -94667,9 +107066,13 @@ func (c *SslPoliciesListAvailableFeaturesCall) doRequest(alt string) (*http.Resp } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/sslPolicies/listAvailableFeatures") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -94847,9 +107250,13 @@ func (c *SslPoliciesPatchCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/sslPolicies/{sslPolicy}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PATCH", urls, body) + req, err := http.NewRequest("PATCH", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -94998,9 +107405,13 @@ func (c *SslPoliciesTestIamPermissionsCall) doRequest(alt string) (*http.Respons } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/sslPolicies/{resource}/testIamPermissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -95063,9 +107474,9 @@ func (c *SslPoliciesTestIamPermissionsCall) Do(opts ...googleapi.CallOption) (*T // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "(?:[-a-z0-9_]{0,62}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -95213,9 +107624,13 @@ func (c *SubnetworksAggregatedListCall) doRequest(alt string) (*http.Response, e } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/aggregated/subnetworks") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -95406,9 +107821,13 @@ func (c *SubnetworksDeleteCall) doRequest(alt string) (*http.Response, error) { reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/subnetworks/{subnetwork}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -95585,9 +108004,13 @@ func (c *SubnetworksExpandIpCidrRangeCall) doRequest(alt string) (*http.Response } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/subnetworks/{subnetwork}/expandIpCidrRange") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -95755,9 +108178,13 @@ func (c *SubnetworksGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/subnetworks/{subnetwork}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -95918,9 +108345,13 @@ func (c *SubnetworksGetIamPolicyCall) doRequest(alt string) (*http.Response, err } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/subnetworks/{resource}/getIamPolicy") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -95992,9 +108423,9 @@ func (c *SubnetworksGetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Policy, // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -96091,9 +108522,13 @@ func (c *SubnetworksInsertCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/subnetworks") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -96313,9 +108748,13 @@ func (c *SubnetworksListCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/subnetworks") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -96569,9 +109008,13 @@ func (c *SubnetworksListUsableCall) doRequest(alt string) (*http.Response, error } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/aggregated/subnetworks/listUsable") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -96703,11 +109146,9 @@ type SubnetworksPatchCall struct { } // Patch: Patches the specified subnetwork with the data included in the -// request. Only the following fields within the subnetwork resource can -// be specified in the request: secondary_ip_range, -// allow_subnet_cidr_routes_overlap and role. It is also mandatory to -// specify the current fingeprint of the subnetwork resource being -// patched. +// request. Only certain fields can up updated with a patch request as +// indicated in the field descriptions. You must specify the current +// fingeprint of the subnetwork resource being patched. func (r *SubnetworksService) Patch(project string, region string, subnetwork string, subnetwork2 *Subnetwork) *SubnetworksPatchCall { c := &SubnetworksPatchCall{s: r.s, urlParams_: make(gensupport.URLParams)} c.project = project @@ -96774,9 +109215,13 @@ func (c *SubnetworksPatchCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/subnetworks/{subnetwork}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PATCH", urls, body) + req, err := http.NewRequest("PATCH", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -96824,7 +109269,7 @@ func (c *SubnetworksPatchCall) Do(opts ...googleapi.CallOption) (*Operation, err } return ret, nil // { - // "description": "Patches the specified subnetwork with the data included in the request. Only the following fields within the subnetwork resource can be specified in the request: secondary_ip_range, allow_subnet_cidr_routes_overlap and role. It is also mandatory to specify the current fingeprint of the subnetwork resource being patched.", + // "description": "Patches the specified subnetwork with the data included in the request. Only certain fields can up updated with a patch request as indicated in the field descriptions. You must specify the current fingeprint of the subnetwork resource being patched.", // "httpMethod": "PATCH", // "id": "compute.subnetworks.patch", // "parameterOrder": [ @@ -96937,9 +109382,13 @@ func (c *SubnetworksSetIamPolicyCall) doRequest(alt string) (*http.Response, err } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/subnetworks/{resource}/setIamPolicy") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -97011,9 +109460,9 @@ func (c *SubnetworksSetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Policy, // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -97115,9 +109564,13 @@ func (c *SubnetworksSetPrivateIpGoogleAccessCall) doRequest(alt string) (*http.R } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/subnetworks/{subnetwork}/setPrivateIpGoogleAccess") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -97278,9 +109731,13 @@ func (c *SubnetworksTestIamPermissionsCall) doRequest(alt string) (*http.Respons } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/subnetworks/{resource}/testIamPermissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -97352,9 +109809,9 @@ func (c *SubnetworksTestIamPermissionsCall) Do(opts ...googleapi.CallOption) (*T // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -97447,9 +109904,13 @@ func (c *TargetHttpProxiesDeleteCall) doRequest(alt string) (*http.Response, err reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/targetHttpProxies/{targetHttpProxy}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -97604,9 +110065,13 @@ func (c *TargetHttpProxiesGetCall) doRequest(alt string) (*http.Response, error) } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/targetHttpProxies/{targetHttpProxy}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -97767,9 +110232,13 @@ func (c *TargetHttpProxiesInsertCall) doRequest(alt string) (*http.Response, err } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/targetHttpProxies") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -97979,9 +110448,13 @@ func (c *TargetHttpProxiesListCall) doRequest(alt string) (*http.Response, error } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/targetHttpProxies") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -98178,9 +110651,13 @@ func (c *TargetHttpProxiesSetUrlMapCall) doRequest(alt string) (*http.Response, } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/targetHttpProxies/{targetHttpProxy}/setUrlMap") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -98330,9 +110807,13 @@ func (c *TargetHttpProxiesTestIamPermissionsCall) doRequest(alt string) (*http.R } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/targetHttpProxies/{resource}/testIamPermissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -98395,9 +110876,9 @@ func (c *TargetHttpProxiesTestIamPermissionsCall) Do(opts ...googleapi.CallOptio // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "(?:[-a-z0-9_]{0,62}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -98489,9 +110970,13 @@ func (c *TargetHttpsProxiesDeleteCall) doRequest(alt string) (*http.Response, er reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/targetHttpsProxies/{targetHttpsProxy}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -98645,9 +111130,13 @@ func (c *TargetHttpsProxiesGetCall) doRequest(alt string) (*http.Response, error } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/targetHttpsProxies/{targetHttpsProxy}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -98807,9 +111296,13 @@ func (c *TargetHttpsProxiesInsertCall) doRequest(alt string) (*http.Response, er } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/targetHttpsProxies") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -99018,9 +111511,13 @@ func (c *TargetHttpsProxiesListCall) doRequest(alt string) (*http.Response, erro } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/targetHttpsProxies") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -99216,9 +111713,13 @@ func (c *TargetHttpsProxiesSetQuicOverrideCall) doRequest(alt string) (*http.Res } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/targetHttpsProxies/{targetHttpsProxy}/setQuicOverride") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -99385,9 +111886,13 @@ func (c *TargetHttpsProxiesSetSslCertificatesCall) doRequest(alt string) (*http. } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/targetHttpsProxies/{targetHttpsProxy}/setSslCertificates") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -99559,9 +112064,13 @@ func (c *TargetHttpsProxiesSetSslPolicyCall) doRequest(alt string) (*http.Respon } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/targetHttpsProxies/{targetHttpsProxy}/setSslPolicy") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -99728,9 +112237,13 @@ func (c *TargetHttpsProxiesSetUrlMapCall) doRequest(alt string) (*http.Response, } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/targetHttpsProxies/{targetHttpsProxy}/setUrlMap") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -99880,9 +112393,13 @@ func (c *TargetHttpsProxiesTestIamPermissionsCall) doRequest(alt string) (*http. } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/targetHttpsProxies/{resource}/testIamPermissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -99945,9 +112462,9 @@ func (c *TargetHttpsProxiesTestIamPermissionsCall) Do(opts ...googleapi.CallOpti // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "(?:[-a-z0-9_]{0,62}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -100096,9 +112613,13 @@ func (c *TargetInstancesAggregatedListCall) doRequest(alt string) (*http.Respons } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/aggregated/targetInstances") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -100290,9 +112811,13 @@ func (c *TargetInstancesDeleteCall) doRequest(alt string) (*http.Response, error reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/targetInstances/{targetInstance}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -100458,9 +112983,13 @@ func (c *TargetInstancesGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/targetInstances/{targetInstance}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -100632,9 +113161,13 @@ func (c *TargetInstancesInsertCall) doRequest(alt string) (*http.Response, error } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/targetInstances") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -100855,9 +113388,13 @@ func (c *TargetInstancesListCall) doRequest(alt string) (*http.Response, error) } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/targetInstances") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -101046,9 +113583,13 @@ func (c *TargetInstancesTestIamPermissionsCall) doRequest(alt string) (*http.Res } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/targetInstances/{resource}/testIamPermissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -101113,9 +113654,9 @@ func (c *TargetInstancesTestIamPermissionsCall) Do(opts ...googleapi.CallOption) // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -101224,9 +113765,13 @@ func (c *TargetPoolsAddHealthCheckCall) doRequest(alt string) (*http.Response, e } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/targetPools/{targetPool}/addHealthCheck") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -101406,9 +113951,13 @@ func (c *TargetPoolsAddInstanceCall) doRequest(alt string) (*http.Response, erro } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/targetPools/{targetPool}/addInstance") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -101635,9 +114184,13 @@ func (c *TargetPoolsAggregatedListCall) doRequest(alt string) (*http.Response, e } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/aggregated/targetPools") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -101829,9 +114382,13 @@ func (c *TargetPoolsDeleteCall) doRequest(alt string) (*http.Response, error) { reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/targetPools/{targetPool}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -101997,9 +114554,13 @@ func (c *TargetPoolsGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/targetPools/{targetPool}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -102154,9 +114715,13 @@ func (c *TargetPoolsGetHealthCall) doRequest(alt string) (*http.Response, error) } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/targetPools/{targetPool}/getHealth") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -102331,9 +114896,13 @@ func (c *TargetPoolsInsertCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/targetPools") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -102554,9 +115123,13 @@ func (c *TargetPoolsListCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/targetPools") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -102764,9 +115337,13 @@ func (c *TargetPoolsRemoveHealthCheckCall) doRequest(alt string) (*http.Response } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/targetPools/{targetPool}/removeHealthCheck") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -102946,9 +115523,13 @@ func (c *TargetPoolsRemoveInstanceCall) doRequest(alt string) (*http.Response, e } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/targetPools/{targetPool}/removeInstance") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -103135,9 +115716,13 @@ func (c *TargetPoolsSetBackupCall) doRequest(alt string) (*http.Response, error) } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/targetPools/{targetPool}/setBackup") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -103304,9 +115889,13 @@ func (c *TargetPoolsTestIamPermissionsCall) doRequest(alt string) (*http.Respons } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/targetPools/{resource}/testIamPermissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -103378,9 +115967,9 @@ func (c *TargetPoolsTestIamPermissionsCall) Do(opts ...googleapi.CallOption) (*T // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -103472,9 +116061,13 @@ func (c *TargetSslProxiesDeleteCall) doRequest(alt string) (*http.Response, erro reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/targetSslProxies/{targetSslProxy}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -103628,9 +116221,13 @@ func (c *TargetSslProxiesGetCall) doRequest(alt string) (*http.Response, error) } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/targetSslProxies/{targetSslProxy}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -103790,9 +116387,13 @@ func (c *TargetSslProxiesInsertCall) doRequest(alt string) (*http.Response, erro } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/targetSslProxies") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -104001,9 +116602,13 @@ func (c *TargetSslProxiesListCall) doRequest(alt string) (*http.Response, error) } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/targetSslProxies") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -104199,9 +116804,13 @@ func (c *TargetSslProxiesSetBackendServiceCall) doRequest(alt string) (*http.Res } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/targetSslProxies/{targetSslProxy}/setBackendService") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -104369,9 +116978,13 @@ func (c *TargetSslProxiesSetProxyHeaderCall) doRequest(alt string) (*http.Respon } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/targetSslProxies/{targetSslProxy}/setProxyHeader") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -104539,9 +117152,13 @@ func (c *TargetSslProxiesSetSslCertificatesCall) doRequest(alt string) (*http.Re } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/targetSslProxies/{targetSslProxy}/setSslCertificates") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -104712,9 +117329,13 @@ func (c *TargetSslProxiesSetSslPolicyCall) doRequest(alt string) (*http.Response } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/targetSslProxies/{targetSslProxy}/setSslPolicy") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -104863,9 +117484,13 @@ func (c *TargetSslProxiesTestIamPermissionsCall) doRequest(alt string) (*http.Re } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/targetSslProxies/{resource}/testIamPermissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -104928,9 +117553,9 @@ func (c *TargetSslProxiesTestIamPermissionsCall) Do(opts ...googleapi.CallOption // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "(?:[-a-z0-9_]{0,62}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -105022,9 +117647,13 @@ func (c *TargetTcpProxiesDeleteCall) doRequest(alt string) (*http.Response, erro reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/targetTcpProxies/{targetTcpProxy}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -105178,9 +117807,13 @@ func (c *TargetTcpProxiesGetCall) doRequest(alt string) (*http.Response, error) } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/targetTcpProxies/{targetTcpProxy}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -105340,9 +117973,13 @@ func (c *TargetTcpProxiesInsertCall) doRequest(alt string) (*http.Response, erro } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/targetTcpProxies") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -105551,9 +118188,13 @@ func (c *TargetTcpProxiesListCall) doRequest(alt string) (*http.Response, error) } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/targetTcpProxies") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -105749,9 +118390,13 @@ func (c *TargetTcpProxiesSetBackendServiceCall) doRequest(alt string) (*http.Res } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/targetTcpProxies/{targetTcpProxy}/setBackendService") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -105919,9 +118564,13 @@ func (c *TargetTcpProxiesSetProxyHeaderCall) doRequest(alt string) (*http.Respon } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/targetTcpProxies/{targetTcpProxy}/setProxyHeader") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -106138,9 +118787,13 @@ func (c *TargetVpnGatewaysAggregatedListCall) doRequest(alt string) (*http.Respo } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/aggregated/targetVpnGateways") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -106331,9 +118984,13 @@ func (c *TargetVpnGatewaysDeleteCall) doRequest(alt string) (*http.Response, err reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/targetVpnGateways/{targetVpnGateway}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -106498,9 +119155,13 @@ func (c *TargetVpnGatewaysGetCall) doRequest(alt string) (*http.Response, error) } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/targetVpnGateways/{targetVpnGateway}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -106671,9 +119332,13 @@ func (c *TargetVpnGatewaysInsertCall) doRequest(alt string) (*http.Response, err } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/targetVpnGateways") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -106893,9 +119558,13 @@ func (c *TargetVpnGatewaysListCall) doRequest(alt string) (*http.Response, error } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/targetVpnGateways") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -107103,9 +119772,13 @@ func (c *TargetVpnGatewaysSetLabelsCall) doRequest(alt string) (*http.Response, } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/targetVpnGateways/{resource}/setLabels") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -107182,9 +119855,9 @@ func (c *TargetVpnGatewaysSetLabelsCall) Do(opts ...googleapi.CallOption) (*Oper // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -107266,9 +119939,13 @@ func (c *TargetVpnGatewaysTestIamPermissionsCall) doRequest(alt string) (*http.R } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/targetVpnGateways/{resource}/testIamPermissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -107340,9 +120017,9 @@ func (c *TargetVpnGatewaysTestIamPermissionsCall) Do(opts ...googleapi.CallOptio // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -107435,9 +120112,13 @@ func (c *UrlMapsDeleteCall) doRequest(alt string) (*http.Response, error) { reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/urlMaps/{urlMap}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -107592,9 +120273,13 @@ func (c *UrlMapsGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/urlMaps/{urlMap}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -107755,9 +120440,13 @@ func (c *UrlMapsInsertCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/urlMaps") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -107917,9 +120606,13 @@ func (c *UrlMapsInvalidateCacheCall) doRequest(alt string) (*http.Response, erro } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/urlMaps/{urlMap}/invalidateCache") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -108138,9 +120831,13 @@ func (c *UrlMapsListCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/urlMaps") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -108339,9 +121036,13 @@ func (c *UrlMapsPatchCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/urlMaps/{urlMap}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PATCH", urls, body) + req, err := http.NewRequest("PATCH", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -108491,9 +121192,13 @@ func (c *UrlMapsTestIamPermissionsCall) doRequest(alt string) (*http.Response, e } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/urlMaps/{resource}/testIamPermissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -108556,9 +121261,9 @@ func (c *UrlMapsTestIamPermissionsCall) Do(opts ...googleapi.CallOption) (*TestP // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "(?:[-a-z0-9_]{0,62}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -108659,9 +121364,13 @@ func (c *UrlMapsUpdateCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/urlMaps/{urlMap}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PUT", urls, body) + req, err := http.NewRequest("PUT", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -108813,9 +121522,13 @@ func (c *UrlMapsValidateCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/urlMaps/{urlMap}/validate") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -109027,9 +121740,13 @@ func (c *VpnTunnelsAggregatedListCall) doRequest(alt string) (*http.Response, er } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/aggregated/vpnTunnels") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -109220,9 +121937,13 @@ func (c *VpnTunnelsDeleteCall) doRequest(alt string) (*http.Response, error) { reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/vpnTunnels/{vpnTunnel}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -109387,9 +122108,13 @@ func (c *VpnTunnelsGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/vpnTunnels/{vpnTunnel}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -109560,9 +122285,13 @@ func (c *VpnTunnelsInsertCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/vpnTunnels") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -109782,9 +122511,13 @@ func (c *VpnTunnelsListCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/vpnTunnels") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -109992,9 +122725,13 @@ func (c *VpnTunnelsSetLabelsCall) doRequest(alt string) (*http.Response, error) } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/vpnTunnels/{resource}/setLabels") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -110071,9 +122808,9 @@ func (c *VpnTunnelsSetLabelsCall) Do(opts ...googleapi.CallOption) (*Operation, // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -110155,9 +122892,13 @@ func (c *VpnTunnelsTestIamPermissionsCall) doRequest(alt string) (*http.Response } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/vpnTunnels/{resource}/testIamPermissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -110229,9 +122970,9 @@ func (c *VpnTunnelsTestIamPermissionsCall) Do(opts ...googleapi.CallOption) (*Te // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -110307,9 +123048,13 @@ func (c *ZoneOperationsDeleteCall) doRequest(alt string) (*http.Response, error) reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/operations/{operation}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -110441,9 +123186,13 @@ func (c *ZoneOperationsGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/operations/{operation}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -110666,9 +123415,13 @@ func (c *ZoneOperationsListCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/operations") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -110863,9 +123616,13 @@ func (c *ZonesGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -111077,9 +123834,13 @@ func (c *ZonesListCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, diff --git a/vendor/google.golang.org/api/compute/v1/BUILD b/vendor/google.golang.org/api/compute/v1/BUILD index 69ffbf0bc0d..d2c1b6b8a68 100644 --- a/vendor/google.golang.org/api/compute/v1/BUILD +++ b/vendor/google.golang.org/api/compute/v1/BUILD @@ -7,8 +7,6 @@ go_library( importpath = "google.golang.org/api/compute/v1", visibility = ["//visibility:public"], deps = [ - "//vendor/golang.org/x/net/context:go_default_library", - "//vendor/golang.org/x/net/context/ctxhttp:go_default_library", "//vendor/google.golang.org/api/gensupport:go_default_library", "//vendor/google.golang.org/api/googleapi:go_default_library", ], diff --git a/vendor/google.golang.org/api/compute/v1/compute-api.json b/vendor/google.golang.org/api/compute/v1/compute-api.json index 15363091e35..2b7e314e4b1 100644 --- a/vendor/google.golang.org/api/compute/v1/compute-api.json +++ b/vendor/google.golang.org/api/compute/v1/compute-api.json @@ -29,7 +29,7 @@ "description": "Creates and runs virtual machines on Google Cloud Platform.", "discoveryVersion": "v1", "documentationLink": "https://developers.google.com/compute/docs/reference/latest/", - "etag": "\"Zkyw9ACJZUvcYmlFaKGChzhmtnE/BGL7e2LbtubnBH3AZ2eFVpuxx2U\"", + "etag": "\"J3WqvAcMk4eQjJXvfSI4Yr8VouA/m6oCgMxscM7YlnV69HIdTmFUj8g\"", "icons": { "x16": "https://www.google.com/images/icons/product/compute_engine-16.png", "x32": "https://www.google.com/images/icons/product/compute_engine-32.png" @@ -813,7 +813,7 @@ "backendBuckets": { "methods": { "addSignedUrlKey": { - "description": "Adds the given Signed URL Key to the backend bucket.", + "description": "Adds a key for validating requests with signed URLs for this backend bucket.", "httpMethod": "POST", "id": "compute.backendBuckets.addSignedUrlKey", "parameterOrder": [ @@ -891,7 +891,7 @@ ] }, "deleteSignedUrlKey": { - "description": "Deletes the given Signed URL Key from the backend bucket.", + "description": "Deletes a key for validating requests with signed URLs for this backend bucket.", "httpMethod": "POST", "id": "compute.backendBuckets.deleteSignedUrlKey", "parameterOrder": [ @@ -1137,7 +1137,7 @@ "backendServices": { "methods": { "addSignedUrlKey": { - "description": "Adds the given Signed URL Key to the specified backend service.", + "description": "Adds a key for validating requests with signed URLs for this backend service.", "httpMethod": "POST", "id": "compute.backendServices.addSignedUrlKey", "parameterOrder": [ @@ -1264,7 +1264,7 @@ ] }, "deleteSignedUrlKey": { - "description": "Deletes the given Signed URL Key from the specified backend service.", + "description": "Deletes a key for validating requests with signed URLs for this backend service.", "httpMethod": "POST", "id": "compute.backendServices.deleteSignedUrlKey", "parameterOrder": [ @@ -1308,7 +1308,7 @@ ] }, "get": { - "description": "Returns the specified BackendService resource. Gets a list of available backend services by making a list() request.", + "description": "Returns the specified BackendService resource. Gets a list of available backend services.", "httpMethod": "GET", "id": "compute.backendServices.get", "parameterOrder": [ @@ -1471,7 +1471,7 @@ "backendService": { "description": "Name of the BackendService resource to patch.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -1500,6 +1500,46 @@ "https://www.googleapis.com/auth/compute" ] }, + "setSecurityPolicy": { + "description": "Sets the security policy for the specified backend service.", + "httpMethod": "POST", + "id": "compute.backendServices.setSecurityPolicy", + "parameterOrder": [ + "project", + "backendService" + ], + "parameters": { + "backendService": { + "description": "Name of the BackendService resource to which the security policy should be set. The name should conform to RFC1035.", + "location": "path", + "required": true, + "type": "string" + }, + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "requestId": { + "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", + "location": "query", + "type": "string" + } + }, + "path": "{project}/global/backendServices/{backendService}/setSecurityPolicy", + "request": { + "$ref": "SecurityPolicyReference" + }, + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute" + ] + }, "update": { "description": "Updates the specified BackendService resource with the data included in the request. There are several restrictions and guidelines to keep in mind when updating a backend service. Read Restrictions and Guidelines for more information.", "httpMethod": "PUT", @@ -1759,7 +1799,7 @@ "disk": { "description": "Name of the persistent disk to snapshot.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -1857,7 +1897,7 @@ "disk": { "description": "Name of the persistent disk to return.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -1886,6 +1926,48 @@ "https://www.googleapis.com/auth/compute.readonly" ] }, + "getIamPolicy": { + "description": "Gets the access control policy for a resource. May be empty if no such policy or resource exists.", + "httpMethod": "GET", + "id": "compute.disks.getIamPolicy", + "parameterOrder": [ + "project", + "zone", + "resource" + ], + "parameters": { + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "resource": { + "description": "Name or id of the resource for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + "required": true, + "type": "string" + }, + "zone": { + "description": "The name of the zone for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + } + }, + "path": "{project}/zones/{zone}/disks/{resource}/getIamPolicy", + "response": { + "$ref": "Policy" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute", + "https://www.googleapis.com/auth/compute.readonly" + ] + }, "insert": { "description": "Creates a persistent disk in the specified project using the data in the request. You can create a disk with a sourceImage, a sourceSnapshot, or create an empty 500 GB data disk by omitting all properties. You can also create a disk that is larger than the default size by specifying the sizeGb property.", "httpMethod": "POST", @@ -2002,7 +2084,7 @@ "disk": { "description": "The name of the persistent disk.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -2038,6 +2120,50 @@ "https://www.googleapis.com/auth/compute" ] }, + "setIamPolicy": { + "description": "Sets the access control policy on the specified resource. Replaces any existing policy.", + "httpMethod": "POST", + "id": "compute.disks.setIamPolicy", + "parameterOrder": [ + "project", + "zone", + "resource" + ], + "parameters": { + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "resource": { + "description": "Name or id of the resource for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + "required": true, + "type": "string" + }, + "zone": { + "description": "The name of the zone for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + } + }, + "path": "{project}/zones/{zone}/disks/{resource}/setIamPolicy", + "request": { + "$ref": "ZoneSetPolicyRequest" + }, + "response": { + "$ref": "Policy" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute" + ] + }, "setLabels": { "description": "Sets the labels on a disk. To learn more about labels, read the Labeling Resources documentation.", "httpMethod": "POST", @@ -2061,9 +2187,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -2086,6 +2212,51 @@ "https://www.googleapis.com/auth/cloud-platform", "https://www.googleapis.com/auth/compute" ] + }, + "testIamPermissions": { + "description": "Returns permissions that a caller has on the specified resource.", + "httpMethod": "POST", + "id": "compute.disks.testIamPermissions", + "parameterOrder": [ + "project", + "zone", + "resource" + ], + "parameters": { + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "resource": { + "description": "Name or id of the resource for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + "required": true, + "type": "string" + }, + "zone": { + "description": "The name of the zone for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + } + }, + "path": "{project}/zones/{zone}/disks/{resource}/testIamPermissions", + "request": { + "$ref": "TestPermissionsRequest" + }, + "response": { + "$ref": "TestPermissionsResponse" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute", + "https://www.googleapis.com/auth/compute.readonly" + ] } } }, @@ -2103,7 +2274,7 @@ "firewall": { "description": "Name of the firewall rule to delete.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -2141,7 +2312,7 @@ "firewall": { "description": "Name of the firewall rule to return.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -2257,7 +2428,7 @@ "firewall": { "description": "Name of the firewall rule to patch.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -2298,7 +2469,7 @@ "firewall": { "description": "Name of the firewall rule to update.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -3874,7 +4045,7 @@ "image": { "description": "Name of the image resource to delete.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -3912,7 +4083,7 @@ "image": { "description": "Image name.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -3953,7 +4124,7 @@ "image": { "description": "Name of the image resource to return.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -3987,7 +4158,7 @@ "family": { "description": "Name of the image family to search for.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -4009,6 +4180,40 @@ "https://www.googleapis.com/auth/compute.readonly" ] }, + "getIamPolicy": { + "description": "Gets the access control policy for a resource. May be empty if no such policy or resource exists.", + "httpMethod": "GET", + "id": "compute.images.getIamPolicy", + "parameterOrder": [ + "project", + "resource" + ], + "parameters": { + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "resource": { + "description": "Name or id of the resource for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + "required": true, + "type": "string" + } + }, + "path": "{project}/global/images/{resource}/getIamPolicy", + "response": { + "$ref": "Policy" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute", + "https://www.googleapis.com/auth/compute.readonly" + ] + }, "insert": { "description": "Creates an image in the specified project using the data included in the request.", "httpMethod": "POST", @@ -4099,6 +4304,42 @@ "https://www.googleapis.com/auth/compute.readonly" ] }, + "setIamPolicy": { + "description": "Sets the access control policy on the specified resource. Replaces any existing policy.", + "httpMethod": "POST", + "id": "compute.images.setIamPolicy", + "parameterOrder": [ + "project", + "resource" + ], + "parameters": { + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "resource": { + "description": "Name or id of the resource for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + "required": true, + "type": "string" + } + }, + "path": "{project}/global/images/{resource}/setIamPolicy", + "request": { + "$ref": "GlobalSetPolicyRequest" + }, + "response": { + "$ref": "Policy" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute" + ] + }, "setLabels": { "description": "Sets the labels on an image. To learn more about labels, read the Labeling Resources documentation.", "httpMethod": "POST", @@ -4116,9 +4357,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -4134,13 +4375,50 @@ "https://www.googleapis.com/auth/cloud-platform", "https://www.googleapis.com/auth/compute" ] + }, + "testIamPermissions": { + "description": "Returns permissions that a caller has on the specified resource.", + "httpMethod": "POST", + "id": "compute.images.testIamPermissions", + "parameterOrder": [ + "project", + "resource" + ], + "parameters": { + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "resource": { + "description": "Name or id of the resource for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + "required": true, + "type": "string" + } + }, + "path": "{project}/global/images/{resource}/testIamPermissions", + "request": { + "$ref": "TestPermissionsRequest" + }, + "response": { + "$ref": "TestPermissionsResponse" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute", + "https://www.googleapis.com/auth/compute.readonly" + ] } } }, "instanceGroupManagers": { "methods": { "abandonInstances": { - "description": "Schedules a group action to remove the specified instances from the managed instance group. Abandoning an instance does not delete the instance, but it does remove the instance from any target pools that are applied by the managed instance group. This method reduces the targetSize of the managed instance group by the number of instances that you abandon. This operation is marked as DONE when the action is scheduled even if the instances have not yet been removed from the group. You must separately verify the status of the abandoning action with the listmanagedinstances method.\n\nIf the group is part of a backend service that has enabled connection draining, it can take up to 60 seconds after the connection draining duration has elapsed before the VM instance is removed or deleted.\n\nYou can specify a maximum of 1000 instances with this method per request.", + "description": "Flags the specified instances to be removed from the managed instance group. Abandoning an instance does not delete the instance, but it does remove the instance from any target pools that are applied by the managed instance group. This method reduces the targetSize of the managed instance group by the number of instances that you abandon. This operation is marked as DONE when the action is scheduled even if the instances have not yet been removed from the group. You must separately verify the status of the abandoning action with the listmanagedinstances method.\n\nIf the group is part of a backend service that has enabled connection draining, it can take up to 60 seconds after the connection draining duration has elapsed before the VM instance is removed or deleted.\n\nYou can specify a maximum of 1000 instances with this method per request.", "httpMethod": "POST", "id": "compute.instanceGroupManagers.abandonInstances", "parameterOrder": [ @@ -4280,7 +4558,7 @@ ] }, "deleteInstances": { - "description": "Schedules a group action to delete the specified instances in the managed instance group. The instances are also removed from any target pools of which they were a member. This method reduces the targetSize of the managed instance group by the number of instances that you delete. This operation is marked as DONE when the action is scheduled even if the instances are still being deleted. You must separately verify the status of the deleting action with the listmanagedinstances method.\n\nIf the group is part of a backend service that has enabled connection draining, it can take up to 60 seconds after the connection draining duration has elapsed before the VM instance is removed or deleted.\n\nYou can specify a maximum of 1000 instances with this method per request.", + "description": "Flags the specified instances in the managed instance group for immediate deletion. The instances are also removed from any target pools of which they were a member. This method reduces the targetSize of the managed instance group by the number of instances that you delete. This operation is marked as DONE when the action is scheduled even if the instances are still being deleted. You must separately verify the status of the deleting action with the listmanagedinstances method.\n\nIf the group is part of a backend service that has enabled connection draining, it can take up to 60 seconds after the connection draining duration has elapsed before the VM instance is removed or deleted.\n\nYou can specify a maximum of 1000 instances with this method per request.", "httpMethod": "POST", "id": "compute.instanceGroupManagers.deleteInstances", "parameterOrder": [ @@ -4367,7 +4645,7 @@ ] }, "insert": { - "description": "Creates a managed instance group using the information that you specify in the request. After the group is created, it schedules an action to create instances in the group using the specified instance template. This operation is marked as DONE when the group is created even if the instances in the group have not yet been created. You must separately verify the status of the individual instances with the listmanagedinstances method.\n\nA managed instance group can have up to 1000 VM instances per group. Please contact Cloud Support if you need an increase in this limit.", + "description": "Creates a managed instance group using the information that you specify in the request. After the group is created, instances in the group are created using the specified instance template. This operation is marked as DONE when the group is created even if the instances in the group have not yet been created. You must separately verify the status of the individual instances with the listmanagedinstances method.\n\nA managed instance group can have up to 1000 VM instances per group. Please contact Cloud Support if you need an increase in this limit.", "httpMethod": "POST", "id": "compute.instanceGroupManagers.insert", "parameterOrder": [ @@ -4473,6 +4751,7 @@ ], "parameters": { "filter": { + "description": "A filter expression that filters resources listed in the response. The expression must specify the field name, a comparison operator, and the value that you want to use for filtering. The value must be a string, a number, or a boolean. The comparison operator must be either =, !=, \u003e, or \u003c.\n\nFor example, if you are filtering Compute Engine instances, you can exclude instances named example-instance by specifying name != example-instance.\n\nYou can also filter nested fields. For example, you could specify scheduling.automaticRestart = false to include instances only if they are not scheduled for automatic restarts. You can use filtering on nested fields to filter based on resource labels.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart = true) (cpuPlatform = \"Intel Skylake\"). By default, each expression is an AND expression. However, you can include AND and OR expressions explicitly. For example, (cpuPlatform = \"Intel Skylake\") OR (cpuPlatform = \"Intel Broadwell\") AND (scheduling.automaticRestart = true).", "location": "query", "type": "string" }, @@ -4484,16 +4763,19 @@ }, "maxResults": { "default": "500", + "description": "The maximum number of results per page that should be returned. If the number of available results is larger than maxResults, Compute Engine returns a nextPageToken that can be used to get the next page of results in subsequent list requests. Acceptable values are 0 to 500, inclusive. (Default: 500)", "format": "uint32", "location": "query", "minimum": "0", "type": "integer" }, "order_by": { + "description": "Sorts list results by a certain order. By default, results are returned in alphanumerical order based on the resource name.\n\nYou can also sort results in descending order based on the creation timestamp using orderBy=\"creationTimestamp desc\". This sorts results based on the creationTimestamp field in reverse chronological order (newest result first). Use this to sort resources like operations so that the newest operation is returned first.\n\nCurrently, only sorting by name or creationTimestamp desc is supported.", "location": "query", "type": "string" }, "pageToken": { + "description": "Specifies a page token to use. Set pageToken to the nextPageToken returned by a previous list request to get the next page of results.", "location": "query", "type": "string" }, @@ -4521,8 +4803,55 @@ "https://www.googleapis.com/auth/compute.readonly" ] }, + "patch": { + "description": "Updates a managed instance group using the information that you specify in the request. This operation is marked as DONE when the group is patched even if the instances in the group are still in the process of being patched. You must separately verify the status of the individual instances with the listManagedInstances method. This method supports PATCH semantics and uses the JSON merge patch format and processing rules.", + "httpMethod": "PATCH", + "id": "compute.instanceGroupManagers.patch", + "parameterOrder": [ + "project", + "zone", + "instanceGroupManager" + ], + "parameters": { + "instanceGroupManager": { + "description": "The name of the instance group manager.", + "location": "path", + "required": true, + "type": "string" + }, + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "requestId": { + "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", + "location": "query", + "type": "string" + }, + "zone": { + "description": "The name of the zone where you want to create the managed instance group.", + "location": "path", + "required": true, + "type": "string" + } + }, + "path": "{project}/zones/{zone}/instanceGroupManagers/{instanceGroupManager}", + "request": { + "$ref": "InstanceGroupManager" + }, + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute" + ] + }, "recreateInstances": { - "description": "Schedules a group action to recreate the specified instances in the managed instance group. The instances are deleted and recreated using the current instance template for the managed instance group. This operation is marked as DONE when the action is scheduled even if the instances have not yet been recreated. You must separately verify the status of the recreating action with the listmanagedinstances method.\n\nIf the group is part of a backend service that has enabled connection draining, it can take up to 60 seconds after the connection draining duration has elapsed before the VM instance is removed or deleted.\n\nYou can specify a maximum of 1000 instances with this method per request.", + "description": "Flags the specified instances in the managed instance group to be immediately recreated. The instances are deleted and recreated using the current instance template for the managed instance group. This operation is marked as DONE when the flag is set even if the instances have not yet been recreated. You must separately verify the status of the recreating action with the listmanagedinstances method.\n\nIf the group is part of a backend service that has enabled connection draining, it can take up to 60 seconds after the connection draining duration has elapsed before the VM instance is removed or deleted.\n\nYou can specify a maximum of 1000 instances with this method per request.", "httpMethod": "POST", "id": "compute.instanceGroupManagers.recreateInstances", "parameterOrder": [ @@ -4569,7 +4898,7 @@ ] }, "resize": { - "description": "Resizes the managed instance group. If you increase the size, the group creates new instances using the current instance template. If you decrease the size, the group deletes instances. The resize operation is marked DONE when the resize actions are scheduled even if the group has not yet added or deleted any instances. You must separately verify the status of the creating or deleting actions with the listmanagedinstances method.\n\nIf the group is part of a backend service that has enabled connection draining, it can take up to 60 seconds after the connection draining duration has elapsed before the VM instance is removed or deleted.", + "description": "Resizes the managed instance group. If you increase the size, the group creates new instances using the current instance template. If you decrease the size, the group deletes instances. The resize operation is marked DONE when the resize actions are scheduled even if the group has not yet added or deleted any instances. You must separately verify the status of the creating or deleting actions with the listmanagedinstances method.\n\nWhen resizing down, the instance group arbitrarily chooses the order in which VMs are deleted. The group takes into account some VM attributes when making the selection including:\n\n+ The status of the VM instance. + The health of the VM instance. + The instance template version the VM is based on. + For regional managed instance groups, the location of the VM instance.\n\nThis list is subject to change.\n\nIf the group is part of a backend service that has enabled connection draining, it can take up to 60 seconds after the connection draining duration has elapsed before the VM instance is removed or deleted.", "httpMethod": "POST", "id": "compute.instanceGroupManagers.resize", "parameterOrder": [ @@ -5230,6 +5559,40 @@ "https://www.googleapis.com/auth/compute.readonly" ] }, + "getIamPolicy": { + "description": "Gets the access control policy for a resource. May be empty if no such policy or resource exists.", + "httpMethod": "GET", + "id": "compute.instanceTemplates.getIamPolicy", + "parameterOrder": [ + "project", + "resource" + ], + "parameters": { + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "resource": { + "description": "Name or id of the resource for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + "required": true, + "type": "string" + } + }, + "path": "{project}/global/instanceTemplates/{resource}/getIamPolicy", + "response": { + "$ref": "Policy" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute", + "https://www.googleapis.com/auth/compute.readonly" + ] + }, "insert": { "description": "Creates an instance template in the specified project using the data that is included in the request. If you are creating a new template to update an existing instance group, your new instance template must use the same network or, if applicable, the same subnetwork as the original template.", "httpMethod": "POST", @@ -5311,6 +5674,79 @@ "https://www.googleapis.com/auth/compute", "https://www.googleapis.com/auth/compute.readonly" ] + }, + "setIamPolicy": { + "description": "Sets the access control policy on the specified resource. Replaces any existing policy.", + "httpMethod": "POST", + "id": "compute.instanceTemplates.setIamPolicy", + "parameterOrder": [ + "project", + "resource" + ], + "parameters": { + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "resource": { + "description": "Name or id of the resource for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + "required": true, + "type": "string" + } + }, + "path": "{project}/global/instanceTemplates/{resource}/setIamPolicy", + "request": { + "$ref": "GlobalSetPolicyRequest" + }, + "response": { + "$ref": "Policy" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute" + ] + }, + "testIamPermissions": { + "description": "Returns permissions that a caller has on the specified resource.", + "httpMethod": "POST", + "id": "compute.instanceTemplates.testIamPermissions", + "parameterOrder": [ + "project", + "resource" + ], + "parameters": { + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "resource": { + "description": "Name or id of the resource for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + "required": true, + "type": "string" + } + }, + "path": "{project}/global/instanceTemplates/{resource}/testIamPermissions", + "request": { + "$ref": "TestPermissionsRequest" + }, + "response": { + "$ref": "TestPermissionsResponse" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute", + "https://www.googleapis.com/auth/compute.readonly" + ] } } }, @@ -5330,7 +5766,7 @@ "instance": { "description": "The instance name for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -5373,7 +5809,7 @@ ] }, "aggregatedList": { - "description": "Retrieves aggregated list of instances.", + "description": "Retrieves aggregated list of all of the instances in your project across all regions and zones.", "httpMethod": "GET", "id": "compute.instances.aggregatedList", "parameterOrder": [ @@ -5439,7 +5875,7 @@ "instance": { "description": "The instance name for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -5488,7 +5924,7 @@ "instance": { "description": "Name of the instance resource to delete.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -5542,7 +5978,7 @@ "instance": { "description": "The instance name for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -5593,15 +6029,15 @@ ], "parameters": { "deviceName": { - "description": "Disk device name to detach.", + "description": "The device name of the disk to detach. Make a get() request on the instance to view currently attached disks and device names.", "location": "query", "required": true, "type": "string" }, "instance": { - "description": "Instance name.", + "description": "Instance name for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -5647,7 +6083,7 @@ "instance": { "description": "Name of the instance resource to return.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -5676,8 +6112,50 @@ "https://www.googleapis.com/auth/compute.readonly" ] }, + "getIamPolicy": { + "description": "Gets the access control policy for a resource. May be empty if no such policy or resource exists.", + "httpMethod": "GET", + "id": "compute.instances.getIamPolicy", + "parameterOrder": [ + "project", + "zone", + "resource" + ], + "parameters": { + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "resource": { + "description": "Name or id of the resource for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + "required": true, + "type": "string" + }, + "zone": { + "description": "The name of the zone for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + } + }, + "path": "{project}/zones/{zone}/instances/{resource}/getIamPolicy", + "response": { + "$ref": "Policy" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute", + "https://www.googleapis.com/auth/compute.readonly" + ] + }, "getSerialPortOutput": { - "description": "Returns the specified instance's serial port output.", + "description": "Returns the last 1 MB of serial port output from the specified instance.", "httpMethod": "GET", "id": "compute.instances.getSerialPortOutput", "parameterOrder": [ @@ -5689,7 +6167,7 @@ "instance": { "description": "Name of the instance scoping this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -5755,7 +6233,7 @@ "type": "string" }, "sourceInstanceTemplate": { - "description": "Specifies instance template to create the instance.\n\nThis field is optional. It can be a full or partial URL. For example, the following are all valid URLs to an instance template: \n- https://www.googleapis.com/compute/v1/projects/project/global/global/instanceTemplates/instanceTemplate \n- projects/project/global/global/instanceTemplates/instanceTemplate \n- global/instancesTemplates/instanceTemplate", + "description": "Specifies instance template to create the instance.\n\nThis field is optional. It can be a full or partial URL. For example, the following are all valid URLs to an instance template: \n- https://www.googleapis.com/compute/v1/projects/project/global/instanceTemplates/instanceTemplate \n- projects/project/global/instanceTemplates/instanceTemplate \n- global/instanceTemplates/instanceTemplate", "location": "query", "type": "string" }, @@ -5837,7 +6315,7 @@ ] }, "listReferrers": { - "description": "Retrieves the list of referrers to instances contained within the specified zone.", + "description": "Retrieves the list of referrers to instances contained within the specified zone. For more information, read Viewing Referrers to VM Instances.", "httpMethod": "GET", "id": "compute.instances.listReferrers", "parameterOrder": [ @@ -5854,7 +6332,7 @@ "instance": { "description": "Name of the target instance scoping this request, or '-' if the request should span over all instances in the container.", "location": "path", - "pattern": "-|[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "-|[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -5914,7 +6392,7 @@ "instance": { "description": "Name of the instance scoping this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -5976,9 +6454,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -6018,16 +6496,16 @@ "type": "boolean" }, "deviceName": { - "description": "The device name of the disk to modify.", + "description": "The device name of the disk to modify. Make a get() request on the instance to view currently attached disks and device names.", "location": "query", "pattern": "\\w[\\w.-]{0,254}", "required": true, "type": "string" }, "instance": { - "description": "The instance name.", + "description": "The instance name for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -6060,6 +6538,50 @@ "https://www.googleapis.com/auth/compute" ] }, + "setIamPolicy": { + "description": "Sets the access control policy on the specified resource. Replaces any existing policy.", + "httpMethod": "POST", + "id": "compute.instances.setIamPolicy", + "parameterOrder": [ + "project", + "zone", + "resource" + ], + "parameters": { + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "resource": { + "description": "Name or id of the resource for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + "required": true, + "type": "string" + }, + "zone": { + "description": "The name of the zone for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + } + }, + "path": "{project}/zones/{zone}/instances/{resource}/setIamPolicy", + "request": { + "$ref": "ZoneSetPolicyRequest" + }, + "response": { + "$ref": "Policy" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute" + ] + }, "setLabels": { "description": "Sets labels on an instance. To learn more about labels, read the Labeling Resources documentation.", "httpMethod": "POST", @@ -6073,7 +6595,7 @@ "instance": { "description": "Name of the instance scoping this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -6122,7 +6644,7 @@ "instance": { "description": "Name of the instance scoping this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -6171,7 +6693,7 @@ "instance": { "description": "Name of the instance scoping this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -6220,7 +6742,7 @@ "instance": { "description": "Name of the instance scoping this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -6269,7 +6791,7 @@ "instance": { "description": "Name of the instance scoping this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -6316,9 +6838,9 @@ ], "parameters": { "instance": { - "description": "Instance name.", + "description": "Instance name for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -6367,7 +6889,7 @@ "instance": { "description": "Name of the instance resource to start.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -6404,7 +6926,7 @@ ] }, "setTags": { - "description": "Sets tags for the specified instance to the data included in the request.", + "description": "Sets network tags for the specified instance to the data included in the request.", "httpMethod": "POST", "id": "compute.instances.setTags", "parameterOrder": [ @@ -6416,7 +6938,7 @@ "instance": { "description": "Name of the instance scoping this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -6452,6 +6974,47 @@ "https://www.googleapis.com/auth/compute" ] }, + "simulateMaintenanceEvent": { + "description": "Simulates a maintenance event on the instance.", + "httpMethod": "POST", + "id": "compute.instances.simulateMaintenanceEvent", + "parameterOrder": [ + "project", + "zone", + "instance" + ], + "parameters": { + "instance": { + "description": "Name of the instance scoping this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + "required": true, + "type": "string" + }, + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "zone": { + "description": "The name of the zone for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + } + }, + "path": "{project}/zones/{zone}/instances/{instance}/simulateMaintenanceEvent", + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute" + ] + }, "start": { "description": "Starts an instance that was stopped using the instances().stop method. For more information, see Restart an instance.", "httpMethod": "POST", @@ -6465,7 +7028,7 @@ "instance": { "description": "Name of the instance resource to start.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -6511,7 +7074,7 @@ "instance": { "description": "Name of the instance resource to start.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -6560,7 +7123,7 @@ "instance": { "description": "Name of the instance resource to stop.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -6593,6 +7156,51 @@ "https://www.googleapis.com/auth/compute" ] }, + "testIamPermissions": { + "description": "Returns permissions that a caller has on the specified resource.", + "httpMethod": "POST", + "id": "compute.instances.testIamPermissions", + "parameterOrder": [ + "project", + "zone", + "resource" + ], + "parameters": { + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "resource": { + "description": "Name or id of the resource for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + "required": true, + "type": "string" + }, + "zone": { + "description": "The name of the zone for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + } + }, + "path": "{project}/zones/{zone}/instances/{resource}/testIamPermissions", + "request": { + "$ref": "TestPermissionsRequest" + }, + "response": { + "$ref": "TestPermissionsResponse" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute", + "https://www.googleapis.com/auth/compute.readonly" + ] + }, "updateAccessConfig": { "description": "Updates the specified access config from an instance's network interface with the data included in the request. This method supports PATCH semantics and uses the JSON merge patch format and processing rules.", "httpMethod": "POST", @@ -6607,7 +7215,7 @@ "instance": { "description": "The instance name for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -6663,7 +7271,7 @@ "instance": { "description": "The instance name for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -7156,6 +7764,40 @@ "https://www.googleapis.com/auth/compute.readonly" ] }, + "getDiagnostics": { + "description": "Returns the interconnectDiagnostics for the specified interconnect.", + "httpMethod": "GET", + "id": "compute.interconnects.getDiagnostics", + "parameterOrder": [ + "project", + "interconnect" + ], + "parameters": { + "interconnect": { + "description": "Name of the interconnect resource to query.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + }, + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + } + }, + "path": "{project}/global/interconnects/{interconnect}/getDiagnostics", + "response": { + "$ref": "InterconnectsGetDiagnosticsResponse" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute", + "https://www.googleapis.com/auth/compute.readonly" + ] + }, "insert": { "description": "Creates a Interconnect in the specified project using the data included in the request.", "httpMethod": "POST", @@ -7334,9 +7976,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "(?:[-a-z0-9_]{0,62}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -7430,6 +8072,40 @@ "https://www.googleapis.com/auth/compute.readonly" ] }, + "getIamPolicy": { + "description": "Gets the access control policy for a resource. May be empty if no such policy or resource exists.", + "httpMethod": "GET", + "id": "compute.licenses.getIamPolicy", + "parameterOrder": [ + "project", + "resource" + ], + "parameters": { + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "resource": { + "description": "Name or id of the resource for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + "required": true, + "type": "string" + } + }, + "path": "{project}/global/licenses/{resource}/getIamPolicy", + "response": { + "$ref": "Policy" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute", + "https://www.googleapis.com/auth/compute.readonly" + ] + }, "insert": { "description": "Create a License resource in the specified project.", "httpMethod": "POST", @@ -7515,6 +8191,42 @@ "https://www.googleapis.com/auth/compute.readonly" ] }, + "setIamPolicy": { + "description": "Sets the access control policy on the specified resource. Replaces any existing policy.", + "httpMethod": "POST", + "id": "compute.licenses.setIamPolicy", + "parameterOrder": [ + "project", + "resource" + ], + "parameters": { + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "resource": { + "description": "Name or id of the resource for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + "required": true, + "type": "string" + } + }, + "path": "{project}/global/licenses/{resource}/setIamPolicy", + "request": { + "$ref": "GlobalSetPolicyRequest" + }, + "response": { + "$ref": "Policy" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute" + ] + }, "testIamPermissions": { "description": "Returns permissions that a caller has on the specified resource.", "httpMethod": "POST", @@ -7532,9 +8244,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "(?:[-a-z0-9_]{0,62}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -7720,7 +8432,7 @@ "network": { "description": "Name of the network resource to add peering to.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -7761,7 +8473,7 @@ "network": { "description": "Name of the network to delete.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -7799,7 +8511,7 @@ "network": { "description": "Name of the network to return.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -7915,7 +8627,7 @@ "network": { "description": "Name of the network to update.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -7956,7 +8668,7 @@ "network": { "description": "Name of the network resource to remove peering from.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -7997,7 +8709,7 @@ "network": { "description": "Name of the network to be updated.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -8025,6 +8737,1118 @@ } } }, + "nodeGroups": { + "methods": { + "addNodes": { + "description": "Adds specified number of nodes to the node group.", + "httpMethod": "POST", + "id": "compute.nodeGroups.addNodes", + "parameterOrder": [ + "project", + "zone", + "nodeGroup" + ], + "parameters": { + "nodeGroup": { + "description": "Name of the NodeGroup resource.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + }, + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "requestId": { + "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", + "location": "query", + "type": "string" + }, + "zone": { + "description": "The name of the zone for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + } + }, + "path": "{project}/zones/{zone}/nodeGroups/{nodeGroup}/addNodes", + "request": { + "$ref": "NodeGroupsAddNodesRequest" + }, + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute" + ] + }, + "aggregatedList": { + "description": "Retrieves an aggregated list of node groups. Note: use nodeGroups.listNodes for more details about each group.", + "httpMethod": "GET", + "id": "compute.nodeGroups.aggregatedList", + "parameterOrder": [ + "project" + ], + "parameters": { + "filter": { + "description": "A filter expression that filters resources listed in the response. The expression must specify the field name, a comparison operator, and the value that you want to use for filtering. The value must be a string, a number, or a boolean. The comparison operator must be either =, !=, \u003e, or \u003c.\n\nFor example, if you are filtering Compute Engine instances, you can exclude instances named example-instance by specifying name != example-instance.\n\nYou can also filter nested fields. For example, you could specify scheduling.automaticRestart = false to include instances only if they are not scheduled for automatic restarts. You can use filtering on nested fields to filter based on resource labels.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart = true) (cpuPlatform = \"Intel Skylake\"). By default, each expression is an AND expression. However, you can include AND and OR expressions explicitly. For example, (cpuPlatform = \"Intel Skylake\") OR (cpuPlatform = \"Intel Broadwell\") AND (scheduling.automaticRestart = true).", + "location": "query", + "type": "string" + }, + "maxResults": { + "default": "500", + "description": "The maximum number of results per page that should be returned. If the number of available results is larger than maxResults, Compute Engine returns a nextPageToken that can be used to get the next page of results in subsequent list requests. Acceptable values are 0 to 500, inclusive. (Default: 500)", + "format": "uint32", + "location": "query", + "minimum": "0", + "type": "integer" + }, + "orderBy": { + "description": "Sorts list results by a certain order. By default, results are returned in alphanumerical order based on the resource name.\n\nYou can also sort results in descending order based on the creation timestamp using orderBy=\"creationTimestamp desc\". This sorts results based on the creationTimestamp field in reverse chronological order (newest result first). Use this to sort resources like operations so that the newest operation is returned first.\n\nCurrently, only sorting by name or creationTimestamp desc is supported.", + "location": "query", + "type": "string" + }, + "pageToken": { + "description": "Specifies a page token to use. Set pageToken to the nextPageToken returned by a previous list request to get the next page of results.", + "location": "query", + "type": "string" + }, + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + } + }, + "path": "{project}/aggregated/nodeGroups", + "response": { + "$ref": "NodeGroupAggregatedList" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute", + "https://www.googleapis.com/auth/compute.readonly" + ] + }, + "delete": { + "description": "Deletes the specified NodeGroup resource.", + "httpMethod": "DELETE", + "id": "compute.nodeGroups.delete", + "parameterOrder": [ + "project", + "zone", + "nodeGroup" + ], + "parameters": { + "nodeGroup": { + "description": "Name of the NodeGroup resource to delete.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + }, + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "requestId": { + "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", + "location": "query", + "type": "string" + }, + "zone": { + "description": "The name of the zone for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + } + }, + "path": "{project}/zones/{zone}/nodeGroups/{nodeGroup}", + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute" + ] + }, + "deleteNodes": { + "description": "Deletes specified nodes from the node group.", + "httpMethod": "POST", + "id": "compute.nodeGroups.deleteNodes", + "parameterOrder": [ + "project", + "zone", + "nodeGroup" + ], + "parameters": { + "nodeGroup": { + "description": "Name of the NodeGroup resource to delete.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + }, + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "requestId": { + "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", + "location": "query", + "type": "string" + }, + "zone": { + "description": "The name of the zone for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + } + }, + "path": "{project}/zones/{zone}/nodeGroups/{nodeGroup}/deleteNodes", + "request": { + "$ref": "NodeGroupsDeleteNodesRequest" + }, + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute" + ] + }, + "get": { + "description": "Returns the specified NodeGroup. Get a list of available NodeGroups by making a list() request. Note: the \"nodes\" field should not be used. Use nodeGroups.listNodes instead.", + "httpMethod": "GET", + "id": "compute.nodeGroups.get", + "parameterOrder": [ + "project", + "zone", + "nodeGroup" + ], + "parameters": { + "nodeGroup": { + "description": "Name of the node group to return.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + }, + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "zone": { + "description": "The name of the zone for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + } + }, + "path": "{project}/zones/{zone}/nodeGroups/{nodeGroup}", + "response": { + "$ref": "NodeGroup" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute", + "https://www.googleapis.com/auth/compute.readonly" + ] + }, + "getIamPolicy": { + "description": "Gets the access control policy for a resource. May be empty if no such policy or resource exists.", + "httpMethod": "GET", + "id": "compute.nodeGroups.getIamPolicy", + "parameterOrder": [ + "project", + "zone", + "resource" + ], + "parameters": { + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "resource": { + "description": "Name or id of the resource for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + "required": true, + "type": "string" + }, + "zone": { + "description": "The name of the zone for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + } + }, + "path": "{project}/zones/{zone}/nodeGroups/{resource}/getIamPolicy", + "response": { + "$ref": "Policy" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute", + "https://www.googleapis.com/auth/compute.readonly" + ] + }, + "insert": { + "description": "Creates a NodeGroup resource in the specified project using the data included in the request.", + "httpMethod": "POST", + "id": "compute.nodeGroups.insert", + "parameterOrder": [ + "project", + "zone", + "initialNodeCount" + ], + "parameters": { + "initialNodeCount": { + "description": "Initial count of nodes in the node group.", + "format": "int32", + "location": "query", + "required": true, + "type": "integer" + }, + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "requestId": { + "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", + "location": "query", + "type": "string" + }, + "zone": { + "description": "The name of the zone for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + } + }, + "path": "{project}/zones/{zone}/nodeGroups", + "request": { + "$ref": "NodeGroup" + }, + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute" + ] + }, + "list": { + "description": "Retrieves a list of node groups available to the specified project. Note: use nodeGroups.listNodes for more details about each group.", + "httpMethod": "GET", + "id": "compute.nodeGroups.list", + "parameterOrder": [ + "project", + "zone" + ], + "parameters": { + "filter": { + "description": "A filter expression that filters resources listed in the response. The expression must specify the field name, a comparison operator, and the value that you want to use for filtering. The value must be a string, a number, or a boolean. The comparison operator must be either =, !=, \u003e, or \u003c.\n\nFor example, if you are filtering Compute Engine instances, you can exclude instances named example-instance by specifying name != example-instance.\n\nYou can also filter nested fields. For example, you could specify scheduling.automaticRestart = false to include instances only if they are not scheduled for automatic restarts. You can use filtering on nested fields to filter based on resource labels.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart = true) (cpuPlatform = \"Intel Skylake\"). By default, each expression is an AND expression. However, you can include AND and OR expressions explicitly. For example, (cpuPlatform = \"Intel Skylake\") OR (cpuPlatform = \"Intel Broadwell\") AND (scheduling.automaticRestart = true).", + "location": "query", + "type": "string" + }, + "maxResults": { + "default": "500", + "description": "The maximum number of results per page that should be returned. If the number of available results is larger than maxResults, Compute Engine returns a nextPageToken that can be used to get the next page of results in subsequent list requests. Acceptable values are 0 to 500, inclusive. (Default: 500)", + "format": "uint32", + "location": "query", + "minimum": "0", + "type": "integer" + }, + "orderBy": { + "description": "Sorts list results by a certain order. By default, results are returned in alphanumerical order based on the resource name.\n\nYou can also sort results in descending order based on the creation timestamp using orderBy=\"creationTimestamp desc\". This sorts results based on the creationTimestamp field in reverse chronological order (newest result first). Use this to sort resources like operations so that the newest operation is returned first.\n\nCurrently, only sorting by name or creationTimestamp desc is supported.", + "location": "query", + "type": "string" + }, + "pageToken": { + "description": "Specifies a page token to use. Set pageToken to the nextPageToken returned by a previous list request to get the next page of results.", + "location": "query", + "type": "string" + }, + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "zone": { + "description": "The name of the zone for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + } + }, + "path": "{project}/zones/{zone}/nodeGroups", + "response": { + "$ref": "NodeGroupList" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute", + "https://www.googleapis.com/auth/compute.readonly" + ] + }, + "listNodes": { + "description": "Lists nodes in the node group.", + "httpMethod": "POST", + "id": "compute.nodeGroups.listNodes", + "parameterOrder": [ + "project", + "zone", + "nodeGroup" + ], + "parameters": { + "filter": { + "description": "A filter expression that filters resources listed in the response. The expression must specify the field name, a comparison operator, and the value that you want to use for filtering. The value must be a string, a number, or a boolean. The comparison operator must be either =, !=, \u003e, or \u003c.\n\nFor example, if you are filtering Compute Engine instances, you can exclude instances named example-instance by specifying name != example-instance.\n\nYou can also filter nested fields. For example, you could specify scheduling.automaticRestart = false to include instances only if they are not scheduled for automatic restarts. You can use filtering on nested fields to filter based on resource labels.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart = true) (cpuPlatform = \"Intel Skylake\"). By default, each expression is an AND expression. However, you can include AND and OR expressions explicitly. For example, (cpuPlatform = \"Intel Skylake\") OR (cpuPlatform = \"Intel Broadwell\") AND (scheduling.automaticRestart = true).", + "location": "query", + "type": "string" + }, + "maxResults": { + "default": "500", + "description": "The maximum number of results per page that should be returned. If the number of available results is larger than maxResults, Compute Engine returns a nextPageToken that can be used to get the next page of results in subsequent list requests. Acceptable values are 0 to 500, inclusive. (Default: 500)", + "format": "uint32", + "location": "query", + "minimum": "0", + "type": "integer" + }, + "nodeGroup": { + "description": "Name of the NodeGroup resource whose nodes you want to list.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + }, + "orderBy": { + "description": "Sorts list results by a certain order. By default, results are returned in alphanumerical order based on the resource name.\n\nYou can also sort results in descending order based on the creation timestamp using orderBy=\"creationTimestamp desc\". This sorts results based on the creationTimestamp field in reverse chronological order (newest result first). Use this to sort resources like operations so that the newest operation is returned first.\n\nCurrently, only sorting by name or creationTimestamp desc is supported.", + "location": "query", + "type": "string" + }, + "pageToken": { + "description": "Specifies a page token to use. Set pageToken to the nextPageToken returned by a previous list request to get the next page of results.", + "location": "query", + "type": "string" + }, + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "zone": { + "description": "The name of the zone for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + } + }, + "path": "{project}/zones/{zone}/nodeGroups/{nodeGroup}/listNodes", + "response": { + "$ref": "NodeGroupsListNodes" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute", + "https://www.googleapis.com/auth/compute.readonly" + ] + }, + "setIamPolicy": { + "description": "Sets the access control policy on the specified resource. Replaces any existing policy.", + "httpMethod": "POST", + "id": "compute.nodeGroups.setIamPolicy", + "parameterOrder": [ + "project", + "zone", + "resource" + ], + "parameters": { + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "resource": { + "description": "Name or id of the resource for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + "required": true, + "type": "string" + }, + "zone": { + "description": "The name of the zone for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + } + }, + "path": "{project}/zones/{zone}/nodeGroups/{resource}/setIamPolicy", + "request": { + "$ref": "ZoneSetPolicyRequest" + }, + "response": { + "$ref": "Policy" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute" + ] + }, + "setNodeTemplate": { + "description": "Updates the node template of the node group.", + "httpMethod": "POST", + "id": "compute.nodeGroups.setNodeTemplate", + "parameterOrder": [ + "project", + "zone", + "nodeGroup" + ], + "parameters": { + "nodeGroup": { + "description": "Name of the NodeGroup resource to delete.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + }, + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "requestId": { + "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", + "location": "query", + "type": "string" + }, + "zone": { + "description": "The name of the zone for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + } + }, + "path": "{project}/zones/{zone}/nodeGroups/{nodeGroup}/setNodeTemplate", + "request": { + "$ref": "NodeGroupsSetNodeTemplateRequest" + }, + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute" + ] + }, + "testIamPermissions": { + "description": "Returns permissions that a caller has on the specified resource.", + "httpMethod": "POST", + "id": "compute.nodeGroups.testIamPermissions", + "parameterOrder": [ + "project", + "zone", + "resource" + ], + "parameters": { + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "resource": { + "description": "Name or id of the resource for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + "required": true, + "type": "string" + }, + "zone": { + "description": "The name of the zone for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + } + }, + "path": "{project}/zones/{zone}/nodeGroups/{resource}/testIamPermissions", + "request": { + "$ref": "TestPermissionsRequest" + }, + "response": { + "$ref": "TestPermissionsResponse" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute", + "https://www.googleapis.com/auth/compute.readonly" + ] + } + } + }, + "nodeTemplates": { + "methods": { + "aggregatedList": { + "description": "Retrieves an aggregated list of node templates.", + "httpMethod": "GET", + "id": "compute.nodeTemplates.aggregatedList", + "parameterOrder": [ + "project" + ], + "parameters": { + "filter": { + "description": "A filter expression that filters resources listed in the response. The expression must specify the field name, a comparison operator, and the value that you want to use for filtering. The value must be a string, a number, or a boolean. The comparison operator must be either =, !=, \u003e, or \u003c.\n\nFor example, if you are filtering Compute Engine instances, you can exclude instances named example-instance by specifying name != example-instance.\n\nYou can also filter nested fields. For example, you could specify scheduling.automaticRestart = false to include instances only if they are not scheduled for automatic restarts. You can use filtering on nested fields to filter based on resource labels.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart = true) (cpuPlatform = \"Intel Skylake\"). By default, each expression is an AND expression. However, you can include AND and OR expressions explicitly. For example, (cpuPlatform = \"Intel Skylake\") OR (cpuPlatform = \"Intel Broadwell\") AND (scheduling.automaticRestart = true).", + "location": "query", + "type": "string" + }, + "maxResults": { + "default": "500", + "description": "The maximum number of results per page that should be returned. If the number of available results is larger than maxResults, Compute Engine returns a nextPageToken that can be used to get the next page of results in subsequent list requests. Acceptable values are 0 to 500, inclusive. (Default: 500)", + "format": "uint32", + "location": "query", + "minimum": "0", + "type": "integer" + }, + "orderBy": { + "description": "Sorts list results by a certain order. By default, results are returned in alphanumerical order based on the resource name.\n\nYou can also sort results in descending order based on the creation timestamp using orderBy=\"creationTimestamp desc\". This sorts results based on the creationTimestamp field in reverse chronological order (newest result first). Use this to sort resources like operations so that the newest operation is returned first.\n\nCurrently, only sorting by name or creationTimestamp desc is supported.", + "location": "query", + "type": "string" + }, + "pageToken": { + "description": "Specifies a page token to use. Set pageToken to the nextPageToken returned by a previous list request to get the next page of results.", + "location": "query", + "type": "string" + }, + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + } + }, + "path": "{project}/aggregated/nodeTemplates", + "response": { + "$ref": "NodeTemplateAggregatedList" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute", + "https://www.googleapis.com/auth/compute.readonly" + ] + }, + "delete": { + "description": "Deletes the specified NodeTemplate resource.", + "httpMethod": "DELETE", + "id": "compute.nodeTemplates.delete", + "parameterOrder": [ + "project", + "region", + "nodeTemplate" + ], + "parameters": { + "nodeTemplate": { + "description": "Name of the NodeTemplate resource to delete.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + }, + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "region": { + "description": "The name of the region for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + }, + "requestId": { + "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", + "location": "query", + "type": "string" + } + }, + "path": "{project}/regions/{region}/nodeTemplates/{nodeTemplate}", + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute" + ] + }, + "get": { + "description": "Returns the specified node template. Gets a list of available node templates by making a list() request.", + "httpMethod": "GET", + "id": "compute.nodeTemplates.get", + "parameterOrder": [ + "project", + "region", + "nodeTemplate" + ], + "parameters": { + "nodeTemplate": { + "description": "Name of the node template to return.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + }, + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "region": { + "description": "The name of the region for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + } + }, + "path": "{project}/regions/{region}/nodeTemplates/{nodeTemplate}", + "response": { + "$ref": "NodeTemplate" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute", + "https://www.googleapis.com/auth/compute.readonly" + ] + }, + "getIamPolicy": { + "description": "Gets the access control policy for a resource. May be empty if no such policy or resource exists.", + "httpMethod": "GET", + "id": "compute.nodeTemplates.getIamPolicy", + "parameterOrder": [ + "project", + "region", + "resource" + ], + "parameters": { + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "region": { + "description": "The name of the region for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + }, + "resource": { + "description": "Name or id of the resource for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + "required": true, + "type": "string" + } + }, + "path": "{project}/regions/{region}/nodeTemplates/{resource}/getIamPolicy", + "response": { + "$ref": "Policy" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute", + "https://www.googleapis.com/auth/compute.readonly" + ] + }, + "insert": { + "description": "Creates a NodeTemplate resource in the specified project using the data included in the request.", + "httpMethod": "POST", + "id": "compute.nodeTemplates.insert", + "parameterOrder": [ + "project", + "region" + ], + "parameters": { + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "region": { + "description": "The name of the region for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + }, + "requestId": { + "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", + "location": "query", + "type": "string" + } + }, + "path": "{project}/regions/{region}/nodeTemplates", + "request": { + "$ref": "NodeTemplate" + }, + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute" + ] + }, + "list": { + "description": "Retrieves a list of node templates available to the specified project.", + "httpMethod": "GET", + "id": "compute.nodeTemplates.list", + "parameterOrder": [ + "project", + "region" + ], + "parameters": { + "filter": { + "description": "A filter expression that filters resources listed in the response. The expression must specify the field name, a comparison operator, and the value that you want to use for filtering. The value must be a string, a number, or a boolean. The comparison operator must be either =, !=, \u003e, or \u003c.\n\nFor example, if you are filtering Compute Engine instances, you can exclude instances named example-instance by specifying name != example-instance.\n\nYou can also filter nested fields. For example, you could specify scheduling.automaticRestart = false to include instances only if they are not scheduled for automatic restarts. You can use filtering on nested fields to filter based on resource labels.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart = true) (cpuPlatform = \"Intel Skylake\"). By default, each expression is an AND expression. However, you can include AND and OR expressions explicitly. For example, (cpuPlatform = \"Intel Skylake\") OR (cpuPlatform = \"Intel Broadwell\") AND (scheduling.automaticRestart = true).", + "location": "query", + "type": "string" + }, + "maxResults": { + "default": "500", + "description": "The maximum number of results per page that should be returned. If the number of available results is larger than maxResults, Compute Engine returns a nextPageToken that can be used to get the next page of results in subsequent list requests. Acceptable values are 0 to 500, inclusive. (Default: 500)", + "format": "uint32", + "location": "query", + "minimum": "0", + "type": "integer" + }, + "orderBy": { + "description": "Sorts list results by a certain order. By default, results are returned in alphanumerical order based on the resource name.\n\nYou can also sort results in descending order based on the creation timestamp using orderBy=\"creationTimestamp desc\". This sorts results based on the creationTimestamp field in reverse chronological order (newest result first). Use this to sort resources like operations so that the newest operation is returned first.\n\nCurrently, only sorting by name or creationTimestamp desc is supported.", + "location": "query", + "type": "string" + }, + "pageToken": { + "description": "Specifies a page token to use. Set pageToken to the nextPageToken returned by a previous list request to get the next page of results.", + "location": "query", + "type": "string" + }, + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "region": { + "description": "The name of the region for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + } + }, + "path": "{project}/regions/{region}/nodeTemplates", + "response": { + "$ref": "NodeTemplateList" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute", + "https://www.googleapis.com/auth/compute.readonly" + ] + }, + "setIamPolicy": { + "description": "Sets the access control policy on the specified resource. Replaces any existing policy.", + "httpMethod": "POST", + "id": "compute.nodeTemplates.setIamPolicy", + "parameterOrder": [ + "project", + "region", + "resource" + ], + "parameters": { + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "region": { + "description": "The name of the region for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + }, + "resource": { + "description": "Name or id of the resource for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + "required": true, + "type": "string" + } + }, + "path": "{project}/regions/{region}/nodeTemplates/{resource}/setIamPolicy", + "request": { + "$ref": "RegionSetPolicyRequest" + }, + "response": { + "$ref": "Policy" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute" + ] + }, + "testIamPermissions": { + "description": "Returns permissions that a caller has on the specified resource.", + "httpMethod": "POST", + "id": "compute.nodeTemplates.testIamPermissions", + "parameterOrder": [ + "project", + "region", + "resource" + ], + "parameters": { + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "region": { + "description": "The name of the region for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + }, + "resource": { + "description": "Name or id of the resource for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + "required": true, + "type": "string" + } + }, + "path": "{project}/regions/{region}/nodeTemplates/{resource}/testIamPermissions", + "request": { + "$ref": "TestPermissionsRequest" + }, + "response": { + "$ref": "TestPermissionsResponse" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute", + "https://www.googleapis.com/auth/compute.readonly" + ] + } + } + }, + "nodeTypes": { + "methods": { + "aggregatedList": { + "description": "Retrieves an aggregated list of node types.", + "httpMethod": "GET", + "id": "compute.nodeTypes.aggregatedList", + "parameterOrder": [ + "project" + ], + "parameters": { + "filter": { + "description": "A filter expression that filters resources listed in the response. The expression must specify the field name, a comparison operator, and the value that you want to use for filtering. The value must be a string, a number, or a boolean. The comparison operator must be either =, !=, \u003e, or \u003c.\n\nFor example, if you are filtering Compute Engine instances, you can exclude instances named example-instance by specifying name != example-instance.\n\nYou can also filter nested fields. For example, you could specify scheduling.automaticRestart = false to include instances only if they are not scheduled for automatic restarts. You can use filtering on nested fields to filter based on resource labels.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart = true) (cpuPlatform = \"Intel Skylake\"). By default, each expression is an AND expression. However, you can include AND and OR expressions explicitly. For example, (cpuPlatform = \"Intel Skylake\") OR (cpuPlatform = \"Intel Broadwell\") AND (scheduling.automaticRestart = true).", + "location": "query", + "type": "string" + }, + "maxResults": { + "default": "500", + "description": "The maximum number of results per page that should be returned. If the number of available results is larger than maxResults, Compute Engine returns a nextPageToken that can be used to get the next page of results in subsequent list requests. Acceptable values are 0 to 500, inclusive. (Default: 500)", + "format": "uint32", + "location": "query", + "minimum": "0", + "type": "integer" + }, + "orderBy": { + "description": "Sorts list results by a certain order. By default, results are returned in alphanumerical order based on the resource name.\n\nYou can also sort results in descending order based on the creation timestamp using orderBy=\"creationTimestamp desc\". This sorts results based on the creationTimestamp field in reverse chronological order (newest result first). Use this to sort resources like operations so that the newest operation is returned first.\n\nCurrently, only sorting by name or creationTimestamp desc is supported.", + "location": "query", + "type": "string" + }, + "pageToken": { + "description": "Specifies a page token to use. Set pageToken to the nextPageToken returned by a previous list request to get the next page of results.", + "location": "query", + "type": "string" + }, + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + } + }, + "path": "{project}/aggregated/nodeTypes", + "response": { + "$ref": "NodeTypeAggregatedList" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute", + "https://www.googleapis.com/auth/compute.readonly" + ] + }, + "get": { + "description": "Returns the specified node type. Gets a list of available node types by making a list() request.", + "httpMethod": "GET", + "id": "compute.nodeTypes.get", + "parameterOrder": [ + "project", + "zone", + "nodeType" + ], + "parameters": { + "nodeType": { + "description": "Name of the node type to return.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + }, + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "zone": { + "description": "The name of the zone for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + } + }, + "path": "{project}/zones/{zone}/nodeTypes/{nodeType}", + "response": { + "$ref": "NodeType" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute", + "https://www.googleapis.com/auth/compute.readonly" + ] + }, + "list": { + "description": "Retrieves a list of node types available to the specified project.", + "httpMethod": "GET", + "id": "compute.nodeTypes.list", + "parameterOrder": [ + "project", + "zone" + ], + "parameters": { + "filter": { + "description": "A filter expression that filters resources listed in the response. The expression must specify the field name, a comparison operator, and the value that you want to use for filtering. The value must be a string, a number, or a boolean. The comparison operator must be either =, !=, \u003e, or \u003c.\n\nFor example, if you are filtering Compute Engine instances, you can exclude instances named example-instance by specifying name != example-instance.\n\nYou can also filter nested fields. For example, you could specify scheduling.automaticRestart = false to include instances only if they are not scheduled for automatic restarts. You can use filtering on nested fields to filter based on resource labels.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart = true) (cpuPlatform = \"Intel Skylake\"). By default, each expression is an AND expression. However, you can include AND and OR expressions explicitly. For example, (cpuPlatform = \"Intel Skylake\") OR (cpuPlatform = \"Intel Broadwell\") AND (scheduling.automaticRestart = true).", + "location": "query", + "type": "string" + }, + "maxResults": { + "default": "500", + "description": "The maximum number of results per page that should be returned. If the number of available results is larger than maxResults, Compute Engine returns a nextPageToken that can be used to get the next page of results in subsequent list requests. Acceptable values are 0 to 500, inclusive. (Default: 500)", + "format": "uint32", + "location": "query", + "minimum": "0", + "type": "integer" + }, + "orderBy": { + "description": "Sorts list results by a certain order. By default, results are returned in alphanumerical order based on the resource name.\n\nYou can also sort results in descending order based on the creation timestamp using orderBy=\"creationTimestamp desc\". This sorts results based on the creationTimestamp field in reverse chronological order (newest result first). Use this to sort resources like operations so that the newest operation is returned first.\n\nCurrently, only sorting by name or creationTimestamp desc is supported.", + "location": "query", + "type": "string" + }, + "pageToken": { + "description": "Specifies a page token to use. Set pageToken to the nextPageToken returned by a previous list request to get the next page of results.", + "location": "query", + "type": "string" + }, + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "zone": { + "description": "The name of the zone for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + } + }, + "path": "{project}/zones/{zone}/nodeTypes", + "response": { + "$ref": "NodeTypeList" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute", + "https://www.googleapis.com/auth/compute.readonly" + ] + } + } + }, "projects": { "methods": { "disableXpnHost": { @@ -8213,21 +10037,25 @@ ], "parameters": { "filter": { + "description": "A filter expression that filters resources listed in the response. The expression must specify the field name, a comparison operator, and the value that you want to use for filtering. The value must be a string, a number, or a boolean. The comparison operator must be either =, !=, \u003e, or \u003c.\n\nFor example, if you are filtering Compute Engine instances, you can exclude instances named example-instance by specifying name != example-instance.\n\nYou can also filter nested fields. For example, you could specify scheduling.automaticRestart = false to include instances only if they are not scheduled for automatic restarts. You can use filtering on nested fields to filter based on resource labels.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart = true) (cpuPlatform = \"Intel Skylake\"). By default, each expression is an AND expression. However, you can include AND and OR expressions explicitly. For example, (cpuPlatform = \"Intel Skylake\") OR (cpuPlatform = \"Intel Broadwell\") AND (scheduling.automaticRestart = true).", "location": "query", "type": "string" }, "maxResults": { "default": "500", + "description": "The maximum number of results per page that should be returned. If the number of available results is larger than maxResults, Compute Engine returns a nextPageToken that can be used to get the next page of results in subsequent list requests. Acceptable values are 0 to 500, inclusive. (Default: 500)", "format": "uint32", "location": "query", "minimum": "0", "type": "integer" }, "order_by": { + "description": "Sorts list results by a certain order. By default, results are returned in alphanumerical order based on the resource name.\n\nYou can also sort results in descending order based on the creation timestamp using orderBy=\"creationTimestamp desc\". This sorts results based on the creationTimestamp field in reverse chronological order (newest result first). Use this to sort resources like operations so that the newest operation is returned first.\n\nCurrently, only sorting by name or creationTimestamp desc is supported.", "location": "query", "type": "string" }, "pageToken": { + "description": "Specifies a page token to use. Set pageToken to the nextPageToken returned by a previous list request to get the next page of results.", "location": "query", "type": "string" }, @@ -8257,21 +10085,25 @@ ], "parameters": { "filter": { + "description": "A filter expression that filters resources listed in the response. The expression must specify the field name, a comparison operator, and the value that you want to use for filtering. The value must be a string, a number, or a boolean. The comparison operator must be either =, !=, \u003e, or \u003c.\n\nFor example, if you are filtering Compute Engine instances, you can exclude instances named example-instance by specifying name != example-instance.\n\nYou can also filter nested fields. For example, you could specify scheduling.automaticRestart = false to include instances only if they are not scheduled for automatic restarts. You can use filtering on nested fields to filter based on resource labels.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart = true) (cpuPlatform = \"Intel Skylake\"). By default, each expression is an AND expression. However, you can include AND and OR expressions explicitly. For example, (cpuPlatform = \"Intel Skylake\") OR (cpuPlatform = \"Intel Broadwell\") AND (scheduling.automaticRestart = true).", "location": "query", "type": "string" }, "maxResults": { "default": "500", + "description": "The maximum number of results per page that should be returned. If the number of available results is larger than maxResults, Compute Engine returns a nextPageToken that can be used to get the next page of results in subsequent list requests. Acceptable values are 0 to 500, inclusive. (Default: 500)", "format": "uint32", "location": "query", "minimum": "0", "type": "integer" }, "order_by": { + "description": "Sorts list results by a certain order. By default, results are returned in alphanumerical order based on the resource name.\n\nYou can also sort results in descending order based on the creation timestamp using orderBy=\"creationTimestamp desc\". This sorts results based on the creationTimestamp field in reverse chronological order (newest result first). Use this to sort resources like operations so that the newest operation is returned first.\n\nCurrently, only sorting by name or creationTimestamp desc is supported.", "location": "query", "type": "string" }, "pageToken": { + "description": "Specifies a page token to use. Set pageToken to the nextPageToken returned by a previous list request to get the next page of results.", "location": "query", "type": "string" }, @@ -8394,6 +10226,39 @@ "https://www.googleapis.com/auth/compute" ] }, + "setDefaultNetworkTier": { + "description": "Sets the default network tier of the project. The default network tier is used when an address/forwardingRule/instance is created without specifying the network tier field.", + "httpMethod": "POST", + "id": "compute.projects.setDefaultNetworkTier", + "parameterOrder": [ + "project" + ], + "parameters": { + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "requestId": { + "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", + "location": "query", + "type": "string" + } + }, + "path": "{project}/setDefaultNetworkTier", + "request": { + "$ref": "ProjectsSetDefaultNetworkTierRequest" + }, + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute" + ] + }, "setUsageExportBucket": { "description": "Enables the usage export feature and sets the usage export bucket where reports are stored. If you provide an empty request body using this method, the usage export feature will be disabled.", "httpMethod": "POST", @@ -8961,7 +10826,7 @@ "backendService": { "description": "Name of the BackendService resource to patch.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -9359,7 +11224,7 @@ "disk": { "description": "Name of the regional persistent disk to snapshot.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -9453,7 +11318,7 @@ "disk": { "description": "Name of the regional persistent disk to return.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -9598,7 +11463,7 @@ "disk": { "description": "Name of the regional persistent disk.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" }, @@ -9664,9 +11529,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -9708,9 +11573,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -9733,7 +11598,7 @@ "regionInstanceGroupManagers": { "methods": { "abandonInstances": { - "description": "Schedules a group action to remove the specified instances from the managed instance group. Abandoning an instance does not delete the instance, but it does remove the instance from any target pools that are applied by the managed instance group. This method reduces the targetSize of the managed instance group by the number of instances that you abandon. This operation is marked as DONE when the action is scheduled even if the instances have not yet been removed from the group. You must separately verify the status of the abandoning action with the listmanagedinstances method.\n\nIf the group is part of a backend service that has enabled connection draining, it can take up to 60 seconds after the connection draining duration has elapsed before the VM instance is removed or deleted.\n\nYou can specify a maximum of 1000 instances with this method per request.", + "description": "Flags the specified instances to be immediately removed from the managed instance group. Abandoning an instance does not delete the instance, but it does remove the instance from any target pools that are applied by the managed instance group. This method reduces the targetSize of the managed instance group by the number of instances that you abandon. This operation is marked as DONE when the action is scheduled even if the instances have not yet been removed from the group. You must separately verify the status of the abandoning action with the listmanagedinstances method.\n\nIf the group is part of a backend service that has enabled connection draining, it can take up to 60 seconds after the connection draining duration has elapsed before the VM instance is removed or deleted.\n\nYou can specify a maximum of 1000 instances with this method per request.", "httpMethod": "POST", "id": "compute.regionInstanceGroupManagers.abandonInstances", "parameterOrder": [ @@ -9824,7 +11689,7 @@ ] }, "deleteInstances": { - "description": "Schedules a group action to delete the specified instances in the managed instance group. The instances are also removed from any target pools of which they were a member. This method reduces the targetSize of the managed instance group by the number of instances that you delete. This operation is marked as DONE when the action is scheduled even if the instances are still being deleted. You must separately verify the status of the deleting action with the listmanagedinstances method.\n\nIf the group is part of a backend service that has enabled connection draining, it can take up to 60 seconds after the connection draining duration has elapsed before the VM instance is removed or deleted.\n\nYou can specify a maximum of 1000 instances with this method per request.", + "description": "Flags the specified instances in the managed instance group to be immediately deleted. The instances are also removed from any target pools of which they were a member. This method reduces the targetSize of the managed instance group by the number of instances that you delete. The deleteInstances operation is marked DONE if the deleteInstances request is successful. The underlying actions take additional time. You must separately verify the status of the deleting action with the listmanagedinstances method.\n\nIf the group is part of a backend service that has enabled connection draining, it can take up to 60 seconds after the connection draining duration has elapsed before the VM instance is removed or deleted.\n\nYou can specify a maximum of 1000 instances with this method per request.", "httpMethod": "POST", "id": "compute.regionInstanceGroupManagers.deleteInstances", "parameterOrder": [ @@ -9911,7 +11776,7 @@ ] }, "insert": { - "description": "Creates a managed instance group using the information that you specify in the request. After the group is created, it schedules an action to create instances in the group using the specified instance template. This operation is marked as DONE when the group is created even if the instances in the group have not yet been created. You must separately verify the status of the individual instances with the listmanagedinstances method.\n\nA regional managed instance group can contain up to 2000 instances.", + "description": "Creates a managed instance group using the information that you specify in the request. After the group is created, instances in the group are created using the specified instance template. This operation is marked as DONE when the group is created even if the instances in the group have not yet been created. You must separately verify the status of the individual instances with the listmanagedinstances method.\n\nA regional managed instance group can contain up to 2000 instances.", "httpMethod": "POST", "id": "compute.regionInstanceGroupManagers.insert", "parameterOrder": [ @@ -10017,6 +11882,7 @@ ], "parameters": { "filter": { + "description": "A filter expression that filters resources listed in the response. The expression must specify the field name, a comparison operator, and the value that you want to use for filtering. The value must be a string, a number, or a boolean. The comparison operator must be either =, !=, \u003e, or \u003c.\n\nFor example, if you are filtering Compute Engine instances, you can exclude instances named example-instance by specifying name != example-instance.\n\nYou can also filter nested fields. For example, you could specify scheduling.automaticRestart = false to include instances only if they are not scheduled for automatic restarts. You can use filtering on nested fields to filter based on resource labels.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart = true) (cpuPlatform = \"Intel Skylake\"). By default, each expression is an AND expression. However, you can include AND and OR expressions explicitly. For example, (cpuPlatform = \"Intel Skylake\") OR (cpuPlatform = \"Intel Broadwell\") AND (scheduling.automaticRestart = true).", "location": "query", "type": "string" }, @@ -10028,16 +11894,19 @@ }, "maxResults": { "default": "500", + "description": "The maximum number of results per page that should be returned. If the number of available results is larger than maxResults, Compute Engine returns a nextPageToken that can be used to get the next page of results in subsequent list requests. Acceptable values are 0 to 500, inclusive. (Default: 500)", "format": "uint32", "location": "query", "minimum": "0", "type": "integer" }, "order_by": { + "description": "Sorts list results by a certain order. By default, results are returned in alphanumerical order based on the resource name.\n\nYou can also sort results in descending order based on the creation timestamp using orderBy=\"creationTimestamp desc\". This sorts results based on the creationTimestamp field in reverse chronological order (newest result first). Use this to sort resources like operations so that the newest operation is returned first.\n\nCurrently, only sorting by name or creationTimestamp desc is supported.", "location": "query", "type": "string" }, "pageToken": { + "description": "Specifies a page token to use. Set pageToken to the nextPageToken returned by a previous list request to get the next page of results.", "location": "query", "type": "string" }, @@ -10065,8 +11934,55 @@ "https://www.googleapis.com/auth/compute.readonly" ] }, + "patch": { + "description": "Updates a managed instance group using the information that you specify in the request. This operation is marked as DONE when the group is patched even if the instances in the group are still in the process of being patched. You must separately verify the status of the individual instances with the listmanagedinstances method. This method supports PATCH semantics and uses the JSON merge patch format and processing rules.", + "httpMethod": "PATCH", + "id": "compute.regionInstanceGroupManagers.patch", + "parameterOrder": [ + "project", + "region", + "instanceGroupManager" + ], + "parameters": { + "instanceGroupManager": { + "description": "The name of the instance group manager.", + "location": "path", + "required": true, + "type": "string" + }, + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "region": { + "description": "Name of the region scoping this request.", + "location": "path", + "required": true, + "type": "string" + }, + "requestId": { + "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", + "location": "query", + "type": "string" + } + }, + "path": "{project}/regions/{region}/instanceGroupManagers/{instanceGroupManager}", + "request": { + "$ref": "InstanceGroupManager" + }, + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute" + ] + }, "recreateInstances": { - "description": "Schedules a group action to recreate the specified instances in the managed instance group. The instances are deleted and recreated using the current instance template for the managed instance group. This operation is marked as DONE when the action is scheduled even if the instances have not yet been recreated. You must separately verify the status of the recreating action with the listmanagedinstances method.\n\nIf the group is part of a backend service that has enabled connection draining, it can take up to 60 seconds after the connection draining duration has elapsed before the VM instance is removed or deleted.\n\nYou can specify a maximum of 1000 instances with this method per request.", + "description": "Flags the specified instances in the managed instance group to be immediately recreated. The instances are deleted and recreated using the current instance template for the managed instance group. This operation is marked as DONE when the flag is set even if the instances have not yet been recreated. You must separately verify the status of the recreating action with the listmanagedinstances method.\n\nIf the group is part of a backend service that has enabled connection draining, it can take up to 60 seconds after the connection draining duration has elapsed before the VM instance is removed or deleted.\n\nYou can specify a maximum of 1000 instances with this method per request.", "httpMethod": "POST", "id": "compute.regionInstanceGroupManagers.recreateInstances", "parameterOrder": [ @@ -10113,7 +12029,7 @@ ] }, "resize": { - "description": "Changes the intended size for the managed instance group. If you increase the size, the group schedules actions to create new instances using the current instance template. If you decrease the size, the group schedules delete actions on one or more instances. The resize operation is marked DONE when the resize actions are scheduled even if the group has not yet added or deleted any instances. You must separately verify the status of the creating or deleting actions with the listmanagedinstances method.\n\nIf the group is part of a backend service that has enabled connection draining, it can take up to 60 seconds after the connection draining duration has elapsed before the VM instance is removed or deleted.", + "description": "Changes the intended size of the managed instance group. If you increase the size, the group creates new instances using the current instance template. If you decrease the size, the group deletes one or more instances.\n\nThe resize operation is marked DONE if the resize request is successful. The underlying actions take additional time. You must separately verify the status of the creating or deleting actions with the listmanagedinstances method.\n\nIf the group is part of a backend service that has enabled connection draining, it can take up to 60 seconds after the connection draining duration has elapsed before the VM instance is removed or deleted.", "httpMethod": "POST", "id": "compute.regionInstanceGroupManagers.resize", "parameterOrder": [ @@ -10841,6 +12757,71 @@ "https://www.googleapis.com/auth/compute.readonly" ] }, + "getNatMappingInfo": { + "description": "Retrieves runtime Nat mapping information of VM endpoints.", + "httpMethod": "GET", + "id": "compute.routers.getNatMappingInfo", + "parameterOrder": [ + "project", + "region", + "router" + ], + "parameters": { + "filter": { + "description": "A filter expression that filters resources listed in the response. The expression must specify the field name, a comparison operator, and the value that you want to use for filtering. The value must be a string, a number, or a boolean. The comparison operator must be either =, !=, \u003e, or \u003c.\n\nFor example, if you are filtering Compute Engine instances, you can exclude instances named example-instance by specifying name != example-instance.\n\nYou can also filter nested fields. For example, you could specify scheduling.automaticRestart = false to include instances only if they are not scheduled for automatic restarts. You can use filtering on nested fields to filter based on resource labels.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart = true) (cpuPlatform = \"Intel Skylake\"). By default, each expression is an AND expression. However, you can include AND and OR expressions explicitly. For example, (cpuPlatform = \"Intel Skylake\") OR (cpuPlatform = \"Intel Broadwell\") AND (scheduling.automaticRestart = true).", + "location": "query", + "type": "string" + }, + "maxResults": { + "default": "500", + "description": "The maximum number of results per page that should be returned. If the number of available results is larger than maxResults, Compute Engine returns a nextPageToken that can be used to get the next page of results in subsequent list requests. Acceptable values are 0 to 500, inclusive. (Default: 500)", + "format": "uint32", + "location": "query", + "minimum": "0", + "type": "integer" + }, + "orderBy": { + "description": "Sorts list results by a certain order. By default, results are returned in alphanumerical order based on the resource name.\n\nYou can also sort results in descending order based on the creation timestamp using orderBy=\"creationTimestamp desc\". This sorts results based on the creationTimestamp field in reverse chronological order (newest result first). Use this to sort resources like operations so that the newest operation is returned first.\n\nCurrently, only sorting by name or creationTimestamp desc is supported.", + "location": "query", + "type": "string" + }, + "pageToken": { + "description": "Specifies a page token to use. Set pageToken to the nextPageToken returned by a previous list request to get the next page of results.", + "location": "query", + "type": "string" + }, + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "region": { + "description": "Name of the region for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + }, + "router": { + "description": "Name of the Router resource to query for Nat Mapping information of VM endpoints.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + } + }, + "path": "{project}/regions/{region}/routers/{router}/getNatMappingInfo", + "response": { + "$ref": "VmEndpointNatMappingsList" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute", + "https://www.googleapis.com/auth/compute.readonly" + ] + }, "getRouterStatus": { "description": "Retrieves runtime information of the specified router.", "httpMethod": "GET", @@ -11152,7 +13133,7 @@ "route": { "description": "Name of the Route resource to delete.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -11185,7 +13166,7 @@ "route": { "description": "Name of the Route resource to return.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -11284,10 +13265,366 @@ } } }, + "securityPolicies": { + "methods": { + "addRule": { + "description": "Inserts a rule into a security policy.", + "httpMethod": "POST", + "id": "compute.securityPolicies.addRule", + "parameterOrder": [ + "project", + "securityPolicy" + ], + "parameters": { + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "securityPolicy": { + "description": "Name of the security policy to update.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + } + }, + "path": "{project}/global/securityPolicies/{securityPolicy}/addRule", + "request": { + "$ref": "SecurityPolicyRule" + }, + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute" + ] + }, + "delete": { + "description": "Deletes the specified policy.", + "httpMethod": "DELETE", + "id": "compute.securityPolicies.delete", + "parameterOrder": [ + "project", + "securityPolicy" + ], + "parameters": { + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "requestId": { + "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", + "location": "query", + "type": "string" + }, + "securityPolicy": { + "description": "Name of the security policy to delete.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + } + }, + "path": "{project}/global/securityPolicies/{securityPolicy}", + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute" + ] + }, + "get": { + "description": "List all of the ordered rules present in a single specified policy.", + "httpMethod": "GET", + "id": "compute.securityPolicies.get", + "parameterOrder": [ + "project", + "securityPolicy" + ], + "parameters": { + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "securityPolicy": { + "description": "Name of the security policy to get.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + } + }, + "path": "{project}/global/securityPolicies/{securityPolicy}", + "response": { + "$ref": "SecurityPolicy" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute", + "https://www.googleapis.com/auth/compute.readonly" + ] + }, + "getRule": { + "description": "Gets a rule at the specified priority.", + "httpMethod": "GET", + "id": "compute.securityPolicies.getRule", + "parameterOrder": [ + "project", + "securityPolicy" + ], + "parameters": { + "priority": { + "description": "The priority of the rule to get from the security policy.", + "format": "int32", + "location": "query", + "type": "integer" + }, + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "securityPolicy": { + "description": "Name of the security policy to which the queried rule belongs.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + } + }, + "path": "{project}/global/securityPolicies/{securityPolicy}/getRule", + "response": { + "$ref": "SecurityPolicyRule" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute", + "https://www.googleapis.com/auth/compute.readonly" + ] + }, + "insert": { + "description": "Creates a new policy in the specified project using the data included in the request.", + "httpMethod": "POST", + "id": "compute.securityPolicies.insert", + "parameterOrder": [ + "project" + ], + "parameters": { + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "requestId": { + "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", + "location": "query", + "type": "string" + } + }, + "path": "{project}/global/securityPolicies", + "request": { + "$ref": "SecurityPolicy" + }, + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute" + ] + }, + "list": { + "description": "List all the policies that have been configured for the specified project.", + "httpMethod": "GET", + "id": "compute.securityPolicies.list", + "parameterOrder": [ + "project" + ], + "parameters": { + "filter": { + "description": "A filter expression that filters resources listed in the response. The expression must specify the field name, a comparison operator, and the value that you want to use for filtering. The value must be a string, a number, or a boolean. The comparison operator must be either =, !=, \u003e, or \u003c.\n\nFor example, if you are filtering Compute Engine instances, you can exclude instances named example-instance by specifying name != example-instance.\n\nYou can also filter nested fields. For example, you could specify scheduling.automaticRestart = false to include instances only if they are not scheduled for automatic restarts. You can use filtering on nested fields to filter based on resource labels.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart = true) (cpuPlatform = \"Intel Skylake\"). By default, each expression is an AND expression. However, you can include AND and OR expressions explicitly. For example, (cpuPlatform = \"Intel Skylake\") OR (cpuPlatform = \"Intel Broadwell\") AND (scheduling.automaticRestart = true).", + "location": "query", + "type": "string" + }, + "maxResults": { + "default": "500", + "description": "The maximum number of results per page that should be returned. If the number of available results is larger than maxResults, Compute Engine returns a nextPageToken that can be used to get the next page of results in subsequent list requests. Acceptable values are 0 to 500, inclusive. (Default: 500)", + "format": "uint32", + "location": "query", + "minimum": "0", + "type": "integer" + }, + "orderBy": { + "description": "Sorts list results by a certain order. By default, results are returned in alphanumerical order based on the resource name.\n\nYou can also sort results in descending order based on the creation timestamp using orderBy=\"creationTimestamp desc\". This sorts results based on the creationTimestamp field in reverse chronological order (newest result first). Use this to sort resources like operations so that the newest operation is returned first.\n\nCurrently, only sorting by name or creationTimestamp desc is supported.", + "location": "query", + "type": "string" + }, + "pageToken": { + "description": "Specifies a page token to use. Set pageToken to the nextPageToken returned by a previous list request to get the next page of results.", + "location": "query", + "type": "string" + }, + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + } + }, + "path": "{project}/global/securityPolicies", + "response": { + "$ref": "SecurityPolicyList" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute", + "https://www.googleapis.com/auth/compute.readonly" + ] + }, + "patch": { + "description": "Patches the specified policy with the data included in the request.", + "httpMethod": "PATCH", + "id": "compute.securityPolicies.patch", + "parameterOrder": [ + "project", + "securityPolicy" + ], + "parameters": { + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "requestId": { + "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", + "location": "query", + "type": "string" + }, + "securityPolicy": { + "description": "Name of the security policy to update.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + } + }, + "path": "{project}/global/securityPolicies/{securityPolicy}", + "request": { + "$ref": "SecurityPolicy" + }, + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute" + ] + }, + "patchRule": { + "description": "Patches a rule at the specified priority.", + "httpMethod": "POST", + "id": "compute.securityPolicies.patchRule", + "parameterOrder": [ + "project", + "securityPolicy" + ], + "parameters": { + "priority": { + "description": "The priority of the rule to patch.", + "format": "int32", + "location": "query", + "type": "integer" + }, + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "securityPolicy": { + "description": "Name of the security policy to update.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + } + }, + "path": "{project}/global/securityPolicies/{securityPolicy}/patchRule", + "request": { + "$ref": "SecurityPolicyRule" + }, + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute" + ] + }, + "removeRule": { + "description": "Deletes a rule at the specified priority.", + "httpMethod": "POST", + "id": "compute.securityPolicies.removeRule", + "parameterOrder": [ + "project", + "securityPolicy" + ], + "parameters": { + "priority": { + "description": "The priority of the rule to remove from the security policy.", + "format": "int32", + "location": "query", + "type": "integer" + }, + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "securityPolicy": { + "description": "Name of the security policy to update.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + } + }, + "path": "{project}/global/securityPolicies/{securityPolicy}/removeRule", + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute" + ] + } + } + }, "snapshots": { "methods": { "delete": { - "description": "Deletes the specified Snapshot resource. Keep in mind that deleting a single snapshot might not necessarily delete all the data on that snapshot. If any data on the snapshot that is marked for deletion is needed for subsequent snapshots, the data will be moved to the next corresponding snapshot.\n\nFor more information, see Deleting snaphots.", + "description": "Deletes the specified Snapshot resource. Keep in mind that deleting a single snapshot might not necessarily delete all the data on that snapshot. If any data on the snapshot that is marked for deletion is needed for subsequent snapshots, the data will be moved to the next corresponding snapshot.\n\nFor more information, see Deleting snapshots.", "httpMethod": "DELETE", "id": "compute.snapshots.delete", "parameterOrder": [ @@ -11310,7 +13647,7 @@ "snapshot": { "description": "Name of the Snapshot resource to delete.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -11343,7 +13680,7 @@ "snapshot": { "description": "Name of the Snapshot resource to return.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -11358,6 +13695,40 @@ "https://www.googleapis.com/auth/compute.readonly" ] }, + "getIamPolicy": { + "description": "Gets the access control policy for a resource. May be empty if no such policy or resource exists.", + "httpMethod": "GET", + "id": "compute.snapshots.getIamPolicy", + "parameterOrder": [ + "project", + "resource" + ], + "parameters": { + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "resource": { + "description": "Name or id of the resource for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + "required": true, + "type": "string" + } + }, + "path": "{project}/global/snapshots/{resource}/getIamPolicy", + "response": { + "$ref": "Policy" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute", + "https://www.googleapis.com/auth/compute.readonly" + ] + }, "list": { "description": "Retrieves the list of Snapshot resources contained within the specified project.", "httpMethod": "GET", @@ -11407,6 +13778,42 @@ "https://www.googleapis.com/auth/compute.readonly" ] }, + "setIamPolicy": { + "description": "Sets the access control policy on the specified resource. Replaces any existing policy.", + "httpMethod": "POST", + "id": "compute.snapshots.setIamPolicy", + "parameterOrder": [ + "project", + "resource" + ], + "parameters": { + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "resource": { + "description": "Name or id of the resource for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + "required": true, + "type": "string" + } + }, + "path": "{project}/global/snapshots/{resource}/setIamPolicy", + "request": { + "$ref": "GlobalSetPolicyRequest" + }, + "response": { + "$ref": "Policy" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute" + ] + }, "setLabels": { "description": "Sets the labels on a snapshot. To learn more about labels, read the Labeling Resources documentation.", "httpMethod": "POST", @@ -11424,9 +13831,9 @@ "type": "string" }, "resource": { - "description": "Name of the resource for this request.", + "description": "Name or id of the resource for this request.", "location": "path", - "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?", + "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", "required": true, "type": "string" } @@ -11442,6 +13849,43 @@ "https://www.googleapis.com/auth/cloud-platform", "https://www.googleapis.com/auth/compute" ] + }, + "testIamPermissions": { + "description": "Returns permissions that a caller has on the specified resource.", + "httpMethod": "POST", + "id": "compute.snapshots.testIamPermissions", + "parameterOrder": [ + "project", + "resource" + ], + "parameters": { + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "resource": { + "description": "Name or id of the resource for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + "required": true, + "type": "string" + } + }, + "path": "{project}/global/snapshots/{resource}/testIamPermissions", + "request": { + "$ref": "TestPermissionsRequest" + }, + "response": { + "$ref": "TestPermissionsResponse" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute", + "https://www.googleapis.com/auth/compute.readonly" + ] } } }, @@ -12036,6 +14480,48 @@ "https://www.googleapis.com/auth/compute.readonly" ] }, + "getIamPolicy": { + "description": "Gets the access control policy for a resource. May be empty if no such policy or resource exists.", + "httpMethod": "GET", + "id": "compute.subnetworks.getIamPolicy", + "parameterOrder": [ + "project", + "region", + "resource" + ], + "parameters": { + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "region": { + "description": "The name of the region for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + }, + "resource": { + "description": "Name or id of the resource for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + "required": true, + "type": "string" + } + }, + "path": "{project}/regions/{region}/subnetworks/{resource}/getIamPolicy", + "response": { + "$ref": "Policy" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute", + "https://www.googleapis.com/auth/compute.readonly" + ] + }, "insert": { "description": "Creates a subnetwork in the specified project using the data included in the request.", "httpMethod": "POST", @@ -12134,8 +14620,57 @@ "https://www.googleapis.com/auth/compute.readonly" ] }, + "listUsable": { + "description": "Retrieves an aggregated list of usable subnetworks.", + "httpMethod": "GET", + "id": "compute.subnetworks.listUsable", + "parameterOrder": [ + "project" + ], + "parameters": { + "filter": { + "description": "A filter expression that filters resources listed in the response. The expression must specify the field name, a comparison operator, and the value that you want to use for filtering. The value must be a string, a number, or a boolean. The comparison operator must be either =, !=, \u003e, or \u003c.\n\nFor example, if you are filtering Compute Engine instances, you can exclude instances named example-instance by specifying name != example-instance.\n\nYou can also filter nested fields. For example, you could specify scheduling.automaticRestart = false to include instances only if they are not scheduled for automatic restarts. You can use filtering on nested fields to filter based on resource labels.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart = true) (cpuPlatform = \"Intel Skylake\"). By default, each expression is an AND expression. However, you can include AND and OR expressions explicitly. For example, (cpuPlatform = \"Intel Skylake\") OR (cpuPlatform = \"Intel Broadwell\") AND (scheduling.automaticRestart = true).", + "location": "query", + "type": "string" + }, + "maxResults": { + "default": "500", + "description": "The maximum number of results per page that should be returned. If the number of available results is larger than maxResults, Compute Engine returns a nextPageToken that can be used to get the next page of results in subsequent list requests. Acceptable values are 0 to 500, inclusive. (Default: 500)", + "format": "uint32", + "location": "query", + "minimum": "0", + "type": "integer" + }, + "orderBy": { + "description": "Sorts list results by a certain order. By default, results are returned in alphanumerical order based on the resource name.\n\nYou can also sort results in descending order based on the creation timestamp using orderBy=\"creationTimestamp desc\". This sorts results based on the creationTimestamp field in reverse chronological order (newest result first). Use this to sort resources like operations so that the newest operation is returned first.\n\nCurrently, only sorting by name or creationTimestamp desc is supported.", + "location": "query", + "type": "string" + }, + "pageToken": { + "description": "Specifies a page token to use. Set pageToken to the nextPageToken returned by a previous list request to get the next page of results.", + "location": "query", + "type": "string" + }, + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + } + }, + "path": "{project}/aggregated/subnetworks/listUsable", + "response": { + "$ref": "UsableSubnetworksAggregatedList" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute", + "https://www.googleapis.com/auth/compute.readonly" + ] + }, "patch": { - "description": "Patches the specified subnetwork with the data included in the request. Only the following fields within the subnetwork resource can be specified in the request: secondary_ip_range, allow_subnet_cidr_routes_overlap and role. It is also mandatory to specify the current fingeprint of the subnetwork resource being patched.", + "description": "Patches the specified subnetwork with the data included in the request. Only certain fields can up updated with a patch request as indicated in the field descriptions. You must specify the current fingeprint of the subnetwork resource being patched.", "httpMethod": "PATCH", "id": "compute.subnetworks.patch", "parameterOrder": [ @@ -12183,6 +14718,50 @@ "https://www.googleapis.com/auth/compute" ] }, + "setIamPolicy": { + "description": "Sets the access control policy on the specified resource. Replaces any existing policy.", + "httpMethod": "POST", + "id": "compute.subnetworks.setIamPolicy", + "parameterOrder": [ + "project", + "region", + "resource" + ], + "parameters": { + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "region": { + "description": "The name of the region for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + }, + "resource": { + "description": "Name or id of the resource for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + "required": true, + "type": "string" + } + }, + "path": "{project}/regions/{region}/subnetworks/{resource}/setIamPolicy", + "request": { + "$ref": "RegionSetPolicyRequest" + }, + "response": { + "$ref": "Policy" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute" + ] + }, "setPrivateIpGoogleAccess": { "description": "Set whether VMs in this subnet can access Google services without assigning external IP addresses through Private Google Access.", "httpMethod": "POST", @@ -12231,6 +14810,51 @@ "https://www.googleapis.com/auth/cloud-platform", "https://www.googleapis.com/auth/compute" ] + }, + "testIamPermissions": { + "description": "Returns permissions that a caller has on the specified resource.", + "httpMethod": "POST", + "id": "compute.subnetworks.testIamPermissions", + "parameterOrder": [ + "project", + "region", + "resource" + ], + "parameters": { + "project": { + "description": "Project ID for this request.", + "location": "path", + "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + "required": true, + "type": "string" + }, + "region": { + "description": "The name of the region for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "required": true, + "type": "string" + }, + "resource": { + "description": "Name or id of the resource for this request.", + "location": "path", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + "required": true, + "type": "string" + } + }, + "path": "{project}/regions/{region}/subnetworks/{resource}/testIamPermissions", + "request": { + "$ref": "TestPermissionsRequest" + }, + "response": { + "$ref": "TestPermissionsResponse" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/compute", + "https://www.googleapis.com/auth/compute.readonly" + ] } } }, @@ -15112,6 +17736,7 @@ } } }, + "revision": "20181130", "rootUrl": "https://www.googleapis.com/", "schemas": { "AcceleratorConfig": { @@ -15512,6 +18137,18 @@ "description": "An external IP address associated with this instance. Specify an unused static external IP address available to the project or leave this field undefined to use an IP from a shared ephemeral IP address pool. If you specify a static external IP address, it must live in the same region as the zone of the instance.", "type": "string" }, + "networkTier": { + "description": "This signifies the networking tier used for configuring this access configuration and can only take the following values: PREMIUM, STANDARD.\n\nIf an AccessConfig is specified without a valid external IP address, an ephemeral IP will be created with this networkTier.\n\nIf an AccessConfig with a valid external IP address is specified, it must match that of the networkTier associated with the Address resource owning that IP.", + "enum": [ + "PREMIUM", + "STANDARD" + ], + "enumDescriptions": [ + "", + "" + ], + "type": "string" + }, "publicPtrDomainName": { "description": "The DNS domain name for the public PTR record. This field can only be set when the set_public_ptr field is enabled.", "type": "string" @@ -15598,6 +18235,41 @@ "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", "type": "string" }, + "network": { + "description": "The URL of the network in which to reserve the address. This field can only be used with INTERNAL type with VPC_PEERING purpose.", + "type": "string" + }, + "networkTier": { + "description": "This signifies the networking tier used for configuring this Address and can only take the following values: PREMIUM, STANDARD. Global forwarding rules can only be Premium Tier. Regional forwarding rules can be either Premium or Standard Tier. Standard Tier addresses applied to regional forwarding rules can be used with any external load balancer. Regional forwarding rules in Premium Tier can only be used with a Network load balancer.\n\nIf this field is not specified, it is assumed to be PREMIUM.", + "enum": [ + "PREMIUM", + "STANDARD" + ], + "enumDescriptions": [ + "", + "" + ], + "type": "string" + }, + "prefixLength": { + "description": "The prefix length if the resource reprensents an IP range.", + "format": "int32", + "type": "integer" + }, + "purpose": { + "description": "The purpose of resource, only used with INTERNAL type.", + "enum": [ + "DNS_RESOLVER", + "GCE_ENDPOINT", + "VPC_PEERING" + ], + "enumDescriptions": [ + "", + "", + "" + ], + "type": "string" + }, "region": { "description": "[Output Only] URL of the region where the regional address resides. This field is not applicable to global addresses. You must specify this field as part of the HTTP request URL. You cannot set this field in the request body.", "type": "string" @@ -16062,8 +18734,12 @@ "description": "[Input Only] Specifies the parameters for a new disk that will be created alongside the new instance. Use initialization parameters to create boot disks or local SSDs attached to the new instance.\n\nThis property is mutually exclusive with the source property; you can only define one or the other, but not both.", "id": "AttachedDiskInitializeParams", "properties": { + "description": { + "description": "An optional description. Provide this property when creating the disk.", + "type": "string" + }, "diskName": { - "description": "Specifies the disk name. If not specified, the default is to use the name of the instance.", + "description": "Specifies the disk name. If not specified, the default is to use the name of the instance. If the disk with the instance name exists already in the given zone/region, a new name will be automatically generated.", "type": "string" }, "diskSizeGb": { @@ -16083,7 +18759,7 @@ "type": "object" }, "sourceImage": { - "description": "The source image to create this disk. When creating a new instance, one of initializeParams.sourceImage or disks.source is required except for local SSD.\n\nTo create a disk with one of the public operating system images, specify the image by its family name. For example, specify family/debian-8 to use the latest Debian 8 image:\nprojects/debian-cloud/global/images/family/debian-8\n\n\nAlternatively, use a specific version of a public operating system image:\nprojects/debian-cloud/global/images/debian-8-jessie-vYYYYMMDD\n\n\nTo create a disk with a custom image that you created, specify the image name in the following format:\nglobal/images/my-custom-image\n\n\nYou can also specify a custom image by its image family, which returns the latest version of the image in that family. Replace the image name with family/family-name:\nglobal/images/family/my-image-family\n\n\nIf the source image is deleted later, this field will not be set.", + "description": "The source image to create this disk. When creating a new instance, one of initializeParams.sourceImage or disks.source is required except for local SSD.\n\nTo create a disk with one of the public operating system images, specify the image by its family name. For example, specify family/debian-9 to use the latest Debian 9 image:\nprojects/debian-cloud/global/images/family/debian-9\n\n\nAlternatively, use a specific version of a public operating system image:\nprojects/debian-cloud/global/images/debian-9-stretch-vYYYYMMDD\n\n\nTo create a disk with a custom image that you created, specify the image name in the following format:\nglobal/images/my-custom-image\n\n\nYou can also specify a custom image by its image family, which returns the latest version of the image in that family. Replace the image name with family/family-name:\nglobal/images/family/my-image-family\n\n\nIf the source image is deleted later, this field will not be set.", "type": "string" }, "sourceImageEncryptionKey": { @@ -16093,6 +18769,86 @@ }, "type": "object" }, + "AuditConfig": { + "description": "Specifies the audit configuration for a service. The configuration determines which permission types are logged, and what identities, if any, are exempted from logging. An AuditConfig must have one or more AuditLogConfigs.\n\nIf there are AuditConfigs for both `allServices` and a specific service, the union of the two AuditConfigs is used for that service: the log_types specified in each AuditConfig are enabled, and the exempted_members in each AuditLogConfig are exempted.\n\nExample Policy with multiple AuditConfigs:\n\n{ \"audit_configs\": [ { \"service\": \"allServices\" \"audit_log_configs\": [ { \"log_type\": \"DATA_READ\", \"exempted_members\": [ \"user:foo@gmail.com\" ] }, { \"log_type\": \"DATA_WRITE\", }, { \"log_type\": \"ADMIN_READ\", } ] }, { \"service\": \"fooservice.googleapis.com\" \"audit_log_configs\": [ { \"log_type\": \"DATA_READ\", }, { \"log_type\": \"DATA_WRITE\", \"exempted_members\": [ \"user:bar@gmail.com\" ] } ] } ] }\n\nFor fooservice, this policy enables DATA_READ, DATA_WRITE and ADMIN_READ logging. It also exempts foo@gmail.com from DATA_READ logging, and bar@gmail.com from DATA_WRITE logging.", + "id": "AuditConfig", + "properties": { + "auditLogConfigs": { + "description": "The configuration for logging of each type of permission.", + "items": { + "$ref": "AuditLogConfig" + }, + "type": "array" + }, + "exemptedMembers": { + "description": "", + "items": { + "type": "string" + }, + "type": "array" + }, + "service": { + "description": "Specifies a service that will be enabled for audit logging. For example, `storage.googleapis.com`, `cloudsql.googleapis.com`. `allServices` is a special value that covers all services.", + "type": "string" + } + }, + "type": "object" + }, + "AuditLogConfig": { + "description": "Provides the configuration for logging a type of permissions. Example:\n\n{ \"audit_log_configs\": [ { \"log_type\": \"DATA_READ\", \"exempted_members\": [ \"user:foo@gmail.com\" ] }, { \"log_type\": \"DATA_WRITE\", } ] }\n\nThis enables 'DATA_READ' and 'DATA_WRITE' logging, while exempting foo@gmail.com from DATA_READ logging.", + "id": "AuditLogConfig", + "properties": { + "exemptedMembers": { + "description": "Specifies the identities that do not cause logging for this type of permission. Follows the same format of [Binding.members][].", + "items": { + "type": "string" + }, + "type": "array" + }, + "logType": { + "description": "The log type that this config enables.", + "enum": [ + "ADMIN_READ", + "DATA_READ", + "DATA_WRITE", + "LOG_TYPE_UNSPECIFIED" + ], + "enumDescriptions": [ + "", + "", + "", + "" + ], + "type": "string" + } + }, + "type": "object" + }, + "AuthorizationLoggingOptions": { + "description": "Authorization-related information used by Cloud Audit Logging.", + "id": "AuthorizationLoggingOptions", + "properties": { + "permissionType": { + "description": "The type of the permission that was checked.", + "enum": [ + "ADMIN_READ", + "ADMIN_WRITE", + "DATA_READ", + "DATA_WRITE", + "PERMISSION_TYPE_UNSPECIFIED" + ], + "enumDescriptions": [ + "", + "", + "", + "", + "" + ], + "type": "string" + } + }, + "type": "object" + }, "Autoscaler": { "description": "Represents an Autoscaler resource. Autoscalers allow you to automatically scale virtual machine instances in managed instance groups according to an autoscaling policy that you define. For more information, read Autoscaling Groups of Instances. (== resource_for beta.autoscalers ==) (== resource_for v1.autoscalers ==) (== resource_for beta.regionAutoscalers ==) (== resource_for v1.regionAutoscalers ==)", "id": "Autoscaler", @@ -16600,7 +19356,7 @@ "type": "number" }, "utilizationTargetType": { - "description": "Defines how target utilization value is expressed for a Stackdriver Monitoring metric. Either GAUGE, DELTA_PER_SECOND, or DELTA_PER_MINUTE. If not specified, the default is GAUGE.", + "description": "Defines how target utilization value is expressed for a Stackdriver Monitoring metric. Either GAUGE, DELTA_PER_SECOND, or DELTA_PER_MINUTE.", "enum": [ "DELTA_PER_MINUTE", "DELTA_PER_SECOND", @@ -16656,7 +19412,7 @@ "type": "string" }, "group": { - "description": "The fully-qualified URL of a Instance Group resource. This instance group defines the list of instances that serve traffic. Member virtual machine instances from each instance group must live in the same zone as the instance group itself. No two backends in a backend service are allowed to use same Instance Group resource.\n\nNote that you must specify an Instance Group resource using the fully-qualified URL, rather than a partial URL.\n\nWhen the BackendService has load balancing scheme INTERNAL, the instance group must be within the same region as the BackendService.", + "description": "The fully-qualified URL of an Instance Group or Network Endpoint Group resource. In case of instance group this defines the list of instances that serve traffic. Member virtual machine instances from each instance group must live in the same zone as the instance group itself. No two backends in a backend service are allowed to use same Instance Group resource.\n\nFor Network Endpoint Groups this defines list of endpoints. All endpoints of Network Endpoint Group must be hosted on instances located in the same zone as the Network Endpoint Group.\n\nBackend service can not contain mix of Instance Group and Network Endpoint Group backends.\n\nNote that you must specify an Instance Group or Network Endpoint Group resource using the fully-qualified URL, rather than a partial URL.\n\nWhen the BackendService has load balancing scheme INTERNAL, the instance group must be within the same region as the BackendService. Network Endpoint Groups are not supported for INTERNAL load balancing scheme.", "type": "string" }, "maxConnections": { @@ -16697,7 +19453,7 @@ }, "cdnPolicy": { "$ref": "BackendBucketCdnPolicy", - "description": "Cloud CDN Coniguration for this BackendBucket." + "description": "Cloud CDN configuration for this BackendBucket." }, "creationTimestamp": { "description": "[Output Only] Creation timestamp in RFC3339 text format.", @@ -16738,12 +19494,12 @@ "id": "BackendBucketCdnPolicy", "properties": { "signedUrlCacheMaxAgeSec": { - "description": "Number of seconds up to which the response to a signed URL request will be cached in the CDN. After this time period, the Signed URL will be revalidated before being served. Defaults to 1hr (3600s). If this field is set, Cloud CDN will internally act as though all responses from this bucket had a ?Cache-Control: public, max-age=[TTL]? header, regardless of any existing Cache-Control header. The actual headers served in responses will not be altered.", + "description": "Maximum number of seconds the response to a signed URL request will be considered fresh. After this time period, the response will be revalidated before being served. Defaults to 1hr (3600s). When serving responses to signed URL requests, Cloud CDN will internally behave as though all responses from this backend had a \"Cache-Control: public, max-age=[TTL]\" header, regardless of any existing Cache-Control header. The actual headers served in responses will not be altered.", "format": "int64", "type": "string" }, "signedUrlKeyNames": { - "description": "[Output Only] Names of the keys currently configured for Cloud CDN Signed URL on this backend bucket.", + "description": "[Output Only] Names of the keys for signing request URLs.", "items": { "type": "string" }, @@ -16900,7 +19656,7 @@ "type": "boolean" }, "fingerprint": { - "description": "Fingerprint of this resource. A hash of the contents stored in this object. This field is used in optimistic locking. This field will be ignored when inserting a BackendService. An up-to-date fingerprint must be provided in order to update the BackendService.", + "description": "Fingerprint of this resource. A hash of the contents stored in this object. This field is used in optimistic locking. This field will be ignored when inserting a BackendService. An up-to-date fingerprint must be provided in order to update the BackendService, otherwise the request will fail with error 412 conditionNotMet.\n\nTo see the latest fingerprint, make a get() request to retrieve a BackendService.", "format": "byte", "type": "string" }, @@ -16974,6 +19730,10 @@ "description": "[Output Only] URL of the region where the regional backend service resides. This field is not applicable to global backend services. You must specify this field as part of the HTTP request URL. It is not settable as a field in the request body.", "type": "string" }, + "securityPolicy": { + "description": "[Output Only] The resource URL for the security policy associated with this backend service.", + "type": "string" + }, "selfLink": { "description": "[Output Only] Server-defined URL for the resource.", "type": "string" @@ -17126,12 +19886,12 @@ "description": "The CacheKeyPolicy for this CdnPolicy." }, "signedUrlCacheMaxAgeSec": { - "description": "Number of seconds up to which the response to a signed URL request will be cached in the CDN. After this time period, the Signed URL will be revalidated before being served. Defaults to 1hr (3600s). If this field is set, Cloud CDN will internally act as though all responses from this backend had a ?Cache-Control: public, max-age=[TTL]? header, regardless of any existing Cache-Control header. The actual headers served in responses will not be altered.", + "description": "Maximum number of seconds the response to a signed URL request will be considered fresh. After this time period, the response will be revalidated before being served. Defaults to 1hr (3600s). When serving responses to signed URL requests, Cloud CDN will internally behave as though all responses from this backend had a \"Cache-Control: public, max-age=[TTL]\" header, regardless of any existing Cache-Control header. The actual headers served in responses will not be altered.", "format": "int64", "type": "string" }, "signedUrlKeyNames": { - "description": "[Output Only] Names of the keys currently configured for Cloud CDN Signed URL on this backend service.", + "description": "[Output Only] Names of the keys for signing request URLs.", "items": { "type": "string" }, @@ -17144,6 +19904,7 @@ "id": "BackendServiceGroupHealth", "properties": { "healthStatus": { + "description": "Health state of the backend instances or endpoints in requested instance or network endpoint group, determined based on configured health checks.", "items": { "$ref": "HealthStatus" }, @@ -17383,6 +20144,28 @@ }, "type": "object" }, + "Binding": { + "description": "Associates `members` with a `role`.", + "id": "Binding", + "properties": { + "condition": { + "$ref": "Expr", + "description": "Unimplemented. The condition that is associated with this binding. NOTE: an unsatisfied condition will not allow user access via current binding. Different bindings, including their conditions, are examined independently." + }, + "members": { + "description": "Specifies the identities requesting access for a Cloud Platform resource. `members` can have the following values:\n\n* `allUsers`: A special identifier that represents anyone who is on the internet; with or without a Google account.\n\n* `allAuthenticatedUsers`: A special identifier that represents anyone who is authenticated with a Google account or a service account.\n\n* `user:{emailid}`: An email address that represents a specific Google account. For example, `alice@gmail.com` .\n\n\n\n* `serviceAccount:{emailid}`: An email address that represents a service account. For example, `my-other-app@appspot.gserviceaccount.com`.\n\n* `group:{emailid}`: An email address that represents a Google group. For example, `admins@example.com`.\n\n\n\n* `domain:{domain}`: A Google Apps domain name that represents all the users of that domain. For example, `google.com` or `example.com`.", + "items": { + "type": "string" + }, + "type": "array" + }, + "role": { + "description": "Role that is assigned to `members`. For example, `roles/viewer`, `roles/editor`, or `roles/owner`.", + "type": "string" + } + }, + "type": "object" + }, "CacheInvalidationRule": { "id": "CacheInvalidationRule", "properties": { @@ -17834,6 +20617,88 @@ }, "type": "object" }, + "Condition": { + "description": "A condition to be met.", + "id": "Condition", + "properties": { + "iam": { + "description": "Trusted attributes supplied by the IAM system.", + "enum": [ + "APPROVER", + "ATTRIBUTION", + "AUTHORITY", + "CREDENTIALS_TYPE", + "JUSTIFICATION_TYPE", + "NO_ATTR", + "SECURITY_REALM" + ], + "enumDescriptions": [ + "", + "", + "", + "", + "", + "", + "" + ], + "type": "string" + }, + "op": { + "description": "An operator to apply the subject with.", + "enum": [ + "DISCHARGED", + "EQUALS", + "IN", + "NOT_EQUALS", + "NOT_IN", + "NO_OP" + ], + "enumDescriptions": [ + "", + "", + "", + "", + "", + "" + ], + "type": "string" + }, + "svc": { + "description": "Trusted attributes discharged by the service.", + "type": "string" + }, + "sys": { + "description": "Trusted attributes supplied by any service that owns resources and uses the IAM system for access control.", + "enum": [ + "IP", + "NAME", + "NO_ATTR", + "REGION", + "SERVICE" + ], + "enumDescriptions": [ + "", + "", + "", + "", + "" + ], + "type": "string" + }, + "value": { + "description": "DEPRECATED. Use 'values' instead.", + "type": "string" + }, + "values": { + "description": "The objects of the condition. This is mutually exclusive with 'value'.", + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object" + }, "ConnectionDraining": { "description": "Message containing connection draining configuration.", "id": "ConnectionDraining", @@ -17850,6 +20715,10 @@ "description": "Represents a customer-supplied encryption key", "id": "CustomerEncryptionKey", "properties": { + "kmsKeyName": { + "description": "The name of the encryption key that is stored in Google Cloud KMS.", + "type": "string" + }, "rawKey": { "description": "Specifies a 256-bit customer-supplied encryption key, encoded in RFC 4648 base64 to either encrypt or decrypt this resource.", "type": "string" @@ -17946,7 +20815,7 @@ "type": "string" }, "labelFingerprint": { - "description": "A fingerprint for the labels being applied to this disk, which is essentially a hash of the labels set used for optimistic locking. The fingerprint is initially generated by Compute Engine and changes after every request to modify or update labels. You must always provide an up-to-date fingerprint hash in order to update or change labels.\n\nTo see the latest fingerprint, make a get() request to retrieve a disk.", + "description": "A fingerprint for the labels being applied to this disk, which is essentially a hash of the labels set used for optimistic locking. The fingerprint is initially generated by Compute Engine and changes after every request to modify or update labels. You must always provide an up-to-date fingerprint hash in order to update or change labels, otherwise the request will fail with error 412 conditionNotMet.\n\nTo see the latest fingerprint, make a get() request to retrieve a disk.", "format": "byte", "type": "string" }, @@ -17974,7 +20843,7 @@ "type": "array" }, "licenses": { - "description": "Any applicable publicly visible licenses.", + "description": "A list of publicly visible licenses. Reserved for Google's use.", "items": { "type": "string" }, @@ -17994,6 +20863,11 @@ "description": "Internal use only.", "type": "string" }, + "physicalBlockSizeBytes": { + "description": "Physical block size of the persistent disk, in bytes. If not present in a request, a default value is used. Currently supported sizes are 4096 and 16384, other sizes may be added in the future. If an unsupported value is requested, the error message will list the supported values for the caller's project.", + "format": "int64", + "type": "string" + }, "region": { "description": "[Output Only] URL of the region where the disk resides. Only applicable for regional resources. You must specify this field as part of the HTTP request URL. It is not settable as a field in the request body.", "type": "string" @@ -18015,7 +20889,7 @@ "type": "string" }, "sourceImage": { - "description": "The source image used to create this disk. If the source image is deleted, this field will not be set.\n\nTo create a disk with one of the public operating system images, specify the image by its family name. For example, specify family/debian-8 to use the latest Debian 8 image:\nprojects/debian-cloud/global/images/family/debian-8\n\n\nAlternatively, use a specific version of a public operating system image:\nprojects/debian-cloud/global/images/debian-8-jessie-vYYYYMMDD\n\n\nTo create a disk with a custom image that you created, specify the image name in the following format:\nglobal/images/my-custom-image\n\n\nYou can also specify a custom image by its image family, which returns the latest version of the image in that family. Replace the image name with family/family-name:\nglobal/images/family/my-image-family", + "description": "The source image used to create this disk. If the source image is deleted, this field will not be set.\n\nTo create a disk with one of the public operating system images, specify the image by its family name. For example, specify family/debian-9 to use the latest Debian 9 image:\nprojects/debian-cloud/global/images/family/debian-9\n\n\nAlternatively, use a specific version of a public operating system image:\nprojects/debian-cloud/global/images/debian-9-stretch-vYYYYMMDD\n\n\nTo create a disk with a custom image that you created, specify the image name in the following format:\nglobal/images/my-custom-image\n\n\nYou can also specify a custom image by its image family, which returns the latest version of the image in that family. Replace the image name with family/family-name:\nglobal/images/family/my-image-family", "type": "string" }, "sourceImageEncryptionKey": { @@ -18829,6 +21703,57 @@ }, "type": "object" }, + "DistributionPolicy": { + "id": "DistributionPolicy", + "properties": { + "zones": { + "description": "Zones where the regional managed instance group will create and manage instances.", + "items": { + "$ref": "DistributionPolicyZoneConfiguration" + }, + "type": "array" + } + }, + "type": "object" + }, + "DistributionPolicyZoneConfiguration": { + "id": "DistributionPolicyZoneConfiguration", + "properties": { + "zone": { + "annotations": { + "required": [ + "compute.regionInstanceGroupManagers.insert" + ] + }, + "description": "The URL of the zone. The zone must exist in the region where the managed instance group is located.", + "type": "string" + } + }, + "type": "object" + }, + "Expr": { + "description": "Represents an expression text. Example:\n\ntitle: \"User account presence\" description: \"Determines whether the request has a user account\" expression: \"size(request.user) \u003e 0\"", + "id": "Expr", + "properties": { + "description": { + "description": "An optional description of the expression. This is a longer text which describes the expression, e.g. when hovered over it in a UI.", + "type": "string" + }, + "expression": { + "description": "Textual representation of an expression in Common Expression Language syntax.\n\nThe application context of the containing message determines which well-known feature set of CEL is supported.", + "type": "string" + }, + "location": { + "description": "An optional string indicating the location of the expression for error reporting, e.g. a file name and a position in the file.", + "type": "string" + }, + "title": { + "description": "An optional title for the expression, i.e. a short string describing its purpose. This can be used e.g. in UIs which allow to enter the expression.", + "type": "string" + } + }, + "type": "object" + }, "Firewall": { "description": "Represents a Firewall resource.", "id": "Firewall", @@ -18900,6 +21825,10 @@ ], "type": "string" }, + "disabled": { + "description": "Denotes whether the firewall rule is disabled, i.e not applied to the network it is associated with. When set to true, the firewall rule is not enforced and the network behaves as if it did not exist. If this is unspecified, the firewall rule will be enabled.", + "type": "boolean" + }, "id": { "description": "[Output Only] The unique identifier for the resource. This identifier is defined by the server.", "format": "uint64", @@ -18910,6 +21839,10 @@ "description": "[Output Only] Type of the resource. Always compute#firewall for firewall rules.", "type": "string" }, + "logConfig": { + "$ref": "FirewallLogConfig", + "description": "This field denotes the logging options for a particular firewall rule. If logging is enabled, logs will be exported to Stackdriver." + }, "name": { "annotations": { "required": [ @@ -19084,16 +22017,27 @@ }, "type": "object" }, + "FirewallLogConfig": { + "description": "The available logging options for a firewall rule.", + "id": "FirewallLogConfig", + "properties": { + "enable": { + "description": "This field denotes whether to enable logging for a particular firewall rule.", + "type": "boolean" + } + }, + "type": "object" + }, "ForwardingRule": { "description": "A ForwardingRule resource. A ForwardingRule resource specifies which pool of target virtual machines to forward a packet to if it matches the given [IPAddress, IPProtocol, ports] tuple. (== resource_for beta.forwardingRules ==) (== resource_for v1.forwardingRules ==) (== resource_for beta.globalForwardingRules ==) (== resource_for v1.globalForwardingRules ==) (== resource_for beta.regionForwardingRules ==) (== resource_for v1.regionForwardingRules ==)", "id": "ForwardingRule", "properties": { "IPAddress": { - "description": "The IP address that this forwarding rule is serving on behalf of.\n\nAddresses are restricted based on the forwarding rule's load balancing scheme (EXTERNAL or INTERNAL) and scope (global or regional).\n\nWhen the load balancing scheme is EXTERNAL, for global forwarding rules, the address must be a global IP, and for regional forwarding rules, the address must live in the same region as the forwarding rule. If this field is empty, an ephemeral IPv4 address from the same scope (global or regional) will be assigned. A regional forwarding rule supports IPv4 only. A global forwarding rule supports either IPv4 or IPv6.\n\nWhen the load balancing scheme is INTERNAL, this can only be an RFC 1918 IP address belonging to the network/subnet configured for the forwarding rule. By default, if this field is empty, an ephemeral internal IP address will be automatically allocated from the IP range of the subnet or network configured for this forwarding rule.\n\nAn address can be specified either by a literal IP address or a URL reference to an existing Address resource. The following examples are all valid: \n- 100.1.2.3 \n- https://www.googleapis.com/compute/v1/projects/project/regions/region/addresses/address \n- projects/project/regions/region/addresses/address \n- regions/region/addresses/address \n- global/addresses/address \n- address", + "description": "The IP address that this forwarding rule is serving on behalf of.\n\nAddresses are restricted based on the forwarding rule's load balancing scheme (EXTERNAL or INTERNAL) and scope (global or regional).\n\nWhen the load balancing scheme is EXTERNAL, for global forwarding rules, the address must be a global IP, and for regional forwarding rules, the address must live in the same region as the forwarding rule. If this field is empty, an ephemeral IPv4 address from the same scope (global or regional) will be assigned. A regional forwarding rule supports IPv4 only. A global forwarding rule supports either IPv4 or IPv6.\n\nWhen the load balancing scheme is INTERNAL_SELF_MANAGED, this must be a URL reference to an existing Address resource ( internal regional static IP address), with a purpose of GCE_END_POINT and address_type of INTERNAL.\n\nWhen the load balancing scheme is INTERNAL, this can only be an RFC 1918 IP address belonging to the network/subnet configured for the forwarding rule. By default, if this field is empty, an ephemeral internal IP address will be automatically allocated from the IP range of the subnet or network configured for this forwarding rule.\n\nAn address can be specified either by a literal IP address or a URL reference to an existing Address resource. The following examples are all valid: \n- 100.1.2.3 \n- https://www.googleapis.com/compute/v1/projects/project/regions/region/addresses/address \n- projects/project/regions/region/addresses/address \n- regions/region/addresses/address \n- global/addresses/address \n- address", "type": "string" }, "IPProtocol": { - "description": "The IP protocol to which this rule applies. Valid options are TCP, UDP, ESP, AH, SCTP or ICMP.\n\nWhen the load balancing scheme is INTERNAL, only TCP and UDP are valid.", + "description": "The IP protocol to which this rule applies. Valid options are TCP, UDP, ESP, AH, SCTP or ICMP.\n\nWhen the load balancing scheme is INTERNAL, only TCP and UDP are valid. When the load balancing scheme is INTERNAL_SELF_MANAGED, only TCPis valid.", "enum": [ "AH", "ESP", @@ -19113,7 +22057,7 @@ "type": "string" }, "backendService": { - "description": "This field is not used for external load balancing.\n\nFor internal load balancing, this field identifies the BackendService resource to receive the matched traffic.", + "description": "This field is only used for INTERNAL load balancing.\n\nFor internal load balancing, this field identifies the BackendService resource to receive the matched traffic.", "type": "string" }, "creationTimestamp": { @@ -19130,7 +22074,7 @@ "type": "string" }, "ipVersion": { - "description": "The IP Version that will be used by this forwarding rule. Valid options are IPV4 or IPV6. This can only be specified for a global forwarding rule.", + "description": "The IP Version that will be used by this forwarding rule. Valid options are IPV4 or IPV6. This can only be specified for an external global forwarding rule.", "enum": [ "IPV4", "IPV6", @@ -19149,7 +22093,7 @@ "type": "string" }, "loadBalancingScheme": { - "description": "This signifies what the ForwardingRule will be used for and can only take the following values: INTERNAL, EXTERNAL The value of INTERNAL means that this will be used for Internal Network Load Balancing (TCP, UDP). The value of EXTERNAL means that this will be used for External Load Balancing (HTTP(S) LB, External TCP/UDP LB, SSL Proxy)", + "description": "This signifies what the ForwardingRule will be used for and can only take the following values: INTERNAL, INTERNAL_SELF_MANAGED, EXTERNAL. The value of INTERNAL means that this will be used for Internal Network Load Balancing (TCP, UDP). The value of INTERNAL_SELF_MANAGED means that this will be used for Internal Global HTTP(S) LB. The value of EXTERNAL means that this will be used for External Load Balancing (HTTP(S) LB, External TCP/UDP LB, SSL Proxy)", "enum": [ "EXTERNAL", "INTERNAL", @@ -19168,7 +22112,19 @@ "type": "string" }, "network": { - "description": "This field is not used for external load balancing.\n\nFor internal load balancing, this field identifies the network that the load balanced IP should belong to for this Forwarding Rule. If this field is not specified, the default network will be used.", + "description": "This field is not used for external load balancing.\n\nFor INTERNAL and INTERNAL_SELF_MANAGED load balancing, this field identifies the network that the load balanced IP should belong to for this Forwarding Rule. If this field is not specified, the default network will be used.", + "type": "string" + }, + "networkTier": { + "description": "This signifies the networking tier used for configuring this load balancer and can only take the following values: PREMIUM , STANDARD.\n\nFor regional ForwardingRule, the valid values are PREMIUM and STANDARD. For GlobalForwardingRule, the valid value is PREMIUM.\n\nIf this field is not specified, it is assumed to be PREMIUM. If IPAddress is specified, this value must be equal to the networkTier of the Address.", + "enum": [ + "PREMIUM", + "STANDARD" + ], + "enumDescriptions": [ + "", + "" + ], "type": "string" }, "portRange": { @@ -19176,7 +22132,7 @@ "type": "string" }, "ports": { - "description": "This field is used along with the backend_service field for internal load balancing.\n\nWhen the load balancing scheme is INTERNAL, a single port or a comma separated list of ports can be configured. Only packets addressed to these ports will be forwarded to the backends configured with this forwarding rule.\n\nYou may specify a maximum of up to 5 ports.", + "description": "This field is used along with the backend_service field for internal load balancing.\n\nWhen the load balancing scheme is INTERNAL, a list of ports can be configured, for example, ['80'], ['8000','9000'] etc. Only packets addressed to these ports will be forwarded to the backends configured with this forwarding rule.\n\nYou may specify a maximum of up to 5 ports.", "items": { "type": "string" }, @@ -19191,11 +22147,11 @@ "type": "string" }, "subnetwork": { - "description": "This field is not used for external load balancing.\n\nFor internal load balancing, this field identifies the subnetwork that the load balanced IP should belong to for this Forwarding Rule.\n\nIf the network specified is in auto subnet mode, this field is optional. However, if the network is in custom subnet mode, a subnetwork must be specified.", + "description": "This field is only used for INTERNAL load balancing.\n\nFor internal load balancing, this field identifies the subnetwork that the load balanced IP should belong to for this Forwarding Rule.\n\nIf the network specified is in auto subnet mode, this field is optional. However, if the network is in custom subnet mode, a subnetwork must be specified.", "type": "string" }, "target": { - "description": "The URL of the target resource to receive the matched traffic. For regional forwarding rules, this target must live in the same region as the forwarding rule. For global forwarding rules, this target must be a global load balancing resource. The forwarded traffic must be of a type appropriate to the target object.", + "description": "The URL of the target resource to receive the matched traffic. For regional forwarding rules, this target must live in the same region as the forwarding rule. For global forwarding rules, this target must be a global load balancing resource. The forwarded traffic must be of a type appropriate to the target object. For INTERNAL_SELF_MANAGED\" load balancing, only HTTP and HTTPS targets are valid.", "type": "string" } }, @@ -19523,7 +22479,7 @@ "id": "GlobalSetLabelsRequest", "properties": { "labelFingerprint": { - "description": "The fingerprint of the previous set of labels for this resource, used to detect conflicts. The fingerprint is initially generated by Compute Engine and changes after every request to modify or update labels. You must always provide an up-to-date fingerprint hash when updating or changing labels. Make a get() request to the resource to get the latest fingerprint.", + "description": "The fingerprint of the previous set of labels for this resource, used to detect conflicts. The fingerprint is initially generated by Compute Engine and changes after every request to modify or update labels. You must always provide an up-to-date fingerprint hash when updating or changing labels, otherwise the request will fail with error 412 conditionNotMet. Make a get() request to the resource to get the latest fingerprint.", "format": "byte", "type": "string" }, @@ -19537,6 +22493,28 @@ }, "type": "object" }, + "GlobalSetPolicyRequest": { + "id": "GlobalSetPolicyRequest", + "properties": { + "bindings": { + "description": "Flatten Policy to create a backward compatible wire-format. Deprecated. Use 'policy' to specify bindings.", + "items": { + "$ref": "Binding" + }, + "type": "array" + }, + "etag": { + "description": "Flatten Policy to create a backward compatible wire-format. Deprecated. Use 'policy' to specify the etag.", + "format": "byte", + "type": "string" + }, + "policy": { + "$ref": "Policy", + "description": "REQUIRED: The complete policy to be applied to the 'resource'. The size of the policy is limited to a few 10s of KB. An empty policy is in general a valid policy but certain services (like Projects) might reject them." + } + }, + "type": "object" + }, "GuestOsFeature": { "description": "Guest OS features.", "id": "GuestOsFeature", @@ -19595,6 +22573,10 @@ "requestPath": { "description": "The request path of the HTTP health check request. The default value is /.", "type": "string" + }, + "response": { + "description": "The string to match anywhere in the first 1024 bytes of the response body. If left empty (the default value), the status code determines health. The response data can only be ASCII.", + "type": "string" } }, "type": "object" @@ -19630,6 +22612,10 @@ "requestPath": { "description": "The request path of the HTTPS health check request. The default value is /.", "type": "string" + }, + "response": { + "description": "The string to match anywhere in the first 1024 bytes of the response body. If left empty (the default value), the status code determines health. The response data can only be ASCII.", + "type": "string" } }, "type": "object" @@ -20303,7 +23289,7 @@ "type": "string" }, "labelFingerprint": { - "description": "A fingerprint for the labels being applied to this image, which is essentially a hash of the labels used for optimistic locking. The fingerprint is initially generated by Compute Engine and changes after every request to modify or update labels. You must always provide an up-to-date fingerprint hash in order to update or change labels.\n\nTo see the latest fingerprint, make a get() request to retrieve an image.", + "description": "A fingerprint for the labels being applied to this image, which is essentially a hash of the labels used for optimistic locking. The fingerprint is initially generated by Compute Engine and changes after every request to modify or update labels. You must always provide an up-to-date fingerprint hash in order to update or change labels, otherwise the request will fail with error 412 conditionNotMet.\n\nTo see the latest fingerprint, make a get() request to retrieve an image.", "format": "byte", "type": "string" }, @@ -20382,7 +23368,7 @@ "description": "The customer-supplied encryption key of the source disk. Required if the source disk is protected by a customer-supplied encryption key." }, "sourceDiskId": { - "description": "The ID value of the disk used to create this image. This value may be used to determine whether the image was taken from the current or a previous instance of a given disk name.", + "description": "[Output Only] The ID value of the disk used to create this image. This value may be used to determine whether the image was taken from the current or a previous instance of a given disk name.", "type": "string" }, "sourceImage": { @@ -20692,7 +23678,7 @@ }, "tags": { "$ref": "Tags", - "description": "A list of tags to apply to this instance. Tags are used to identify valid sources or targets for network firewalls and are specified by the client during instance creation. The tags can be later modified by the setTags method. Each tag within the list must comply with RFC1035." + "description": "Tags to apply to this instance. Tags are used to identify valid sources or targets for network firewalls and are specified by the client during instance creation. The tags can be later modified by the setTags method. Each tag within the list must comply with RFC1035. Multiple tags can be specified via the 'tags.items' field." }, "zone": { "description": "[Output Only] URL of the zone where the instance resides. You must specify this field as part of the HTTP request URL. It is not settable as a field in the request body.", @@ -21135,8 +24121,12 @@ "description": "An optional description of this resource. Provide this property when you create the resource.", "type": "string" }, + "distributionPolicy": { + "$ref": "DistributionPolicy", + "description": "Policy specifying intended distribution of instances in regional managed instance group." + }, "fingerprint": { - "description": "Fingerprint of this resource. This field may be used in optimistic locking. It will be ignored when inserting an InstanceGroupManager. An up-to-date fingerprint must be provided in order to update the InstanceGroupManager.", + "description": "Fingerprint of this resource. This field may be used in optimistic locking. It will be ignored when inserting an InstanceGroupManager. An up-to-date fingerprint must be provided in order to update the InstanceGroupManager, otherwise the request will fail with error 412 conditionNotMet.\n\nTo see the latest fingerprint, make a get() request to retrieve an InstanceGroupManager.", "format": "byte", "type": "string" }, @@ -21251,6 +24241,11 @@ "description": "[Output Only] The number of instances in the managed instance group that are scheduled to be restarted or are currently being restarted.", "format": "int32", "type": "integer" + }, + "verifying": { + "description": "[Output Only] The number of instances in the managed instance group that are being verified. See the managedInstances[].currentAction property in the listManagedInstances method documentation.", + "format": "int32", + "type": "integer" } }, "type": "object" @@ -21906,7 +24901,7 @@ "id": "InstanceGroupsSetNamedPortsRequest", "properties": { "fingerprint": { - "description": "The fingerprint of the named ports information for this instance group. Use this optional property to prevent conflicts when multiple users change the named ports settings concurrently. Obtain the fingerprint with the instanceGroups.get method. Then, include the fingerprint in your request to ensure that you do not overwrite changes that were applied from another concurrent request.", + "description": "The fingerprint of the named ports information for this instance group. Use this optional property to prevent conflicts when multiple users change the named ports settings concurrently. Obtain the fingerprint with the instanceGroups.get method. Then, include the fingerprint in your request to ensure that you do not overwrite changes that were applied from another concurrent request. A request with an incorrect fingerprint will fail with error 412 conditionNotMet.", "format": "byte", "type": "string" }, @@ -22776,7 +25771,7 @@ "type": "boolean" }, "bandwidth": { - "description": "Provisioned bandwidth capacity for the interconnectAttachment. Can be set by the partner to update the customer's provisioned bandwidth. Output only for for PARTNER type, mutable for PARTNER_PROVIDER, not available for DEDICATED.", + "description": "Provisioned bandwidth capacity for the interconnectAttachment. Can be set by the partner to update the customer's provisioned bandwidth. Output only for PARTNER type, mutable for PARTNER_PROVIDER and DEDICATED.", "enum": [ "BPS_100M", "BPS_10G", @@ -22897,7 +25892,7 @@ "type": "string" }, "router": { - "description": "URL of the cloud router to be used for dynamic routing. This router must be in the same region as this InterconnectAttachment. The InterconnectAttachment will automatically connect the Interconnect to the network \u0026 region within which the Cloud Router is configured.", + "description": "URL of the Cloud Router to be used for dynamic routing. This router must be in the same region as this InterconnectAttachment. The InterconnectAttachment will automatically connect the Interconnect to the network \u0026 region within which the Cloud Router is configured.", "type": "string" }, "selfLink": { @@ -22940,7 +25935,7 @@ "type": "string" }, "vlanTag8021q": { - "description": "Available only for DEDICATED and PARTNER_PROVIDER. Desired VLAN tag for this attachment, in the range 2-4094. This field refers to 802.1q VLAN tag, also known as IEEE 802.1Q Only specified at creation time.", + "description": "The IEEE 802.1Q VLAN tag for this attachment, in the range 2-4094. Only specified at creation time.", "format": "int32", "type": "integer" } @@ -23176,7 +26171,7 @@ "id": "InterconnectAttachmentPartnerMetadata", "properties": { "interconnectName": { - "description": "Plain text name of the Interconnect this attachment is connected to, as displayed in the Partner?s portal. For instance ?Chicago 1?. This value may be validated to match approved Partner values.", + "description": "Plain text name of the Interconnect this attachment is connected to, as displayed in the Partner?s portal. For instance \"Chicago 1\". This value may be validated to match approved Partner values.", "type": "string" }, "partnerName": { @@ -23315,6 +26310,129 @@ }, "type": "object" }, + "InterconnectDiagnostics": { + "description": "Diagnostics information about interconnect, contains detailed and current technical information about Google?s side of the connection.", + "id": "InterconnectDiagnostics", + "properties": { + "arpCaches": { + "description": "A list of InterconnectDiagnostics.ARPEntry objects, describing individual neighbors currently seen by the Google router in the ARP cache for the Interconnect. This will be empty when the Interconnect is not bundled.", + "items": { + "$ref": "InterconnectDiagnosticsARPEntry" + }, + "type": "array" + }, + "links": { + "description": "A list of InterconnectDiagnostics.LinkStatus objects, describing the status for each link on the Interconnect.", + "items": { + "$ref": "InterconnectDiagnosticsLinkStatus" + }, + "type": "array" + }, + "macAddress": { + "description": "The MAC address of the Interconnect's bundle interface.", + "type": "string" + } + }, + "type": "object" + }, + "InterconnectDiagnosticsARPEntry": { + "description": "Describing the ARP neighbor entries seen on this link", + "id": "InterconnectDiagnosticsARPEntry", + "properties": { + "ipAddress": { + "description": "The IP address of this ARP neighbor.", + "type": "string" + }, + "macAddress": { + "description": "The MAC address of this ARP neighbor.", + "type": "string" + } + }, + "type": "object" + }, + "InterconnectDiagnosticsLinkLACPStatus": { + "id": "InterconnectDiagnosticsLinkLACPStatus", + "properties": { + "googleSystemId": { + "description": "System ID of the port on Google?s side of the LACP exchange.", + "type": "string" + }, + "neighborSystemId": { + "description": "System ID of the port on the neighbor?s side of the LACP exchange.", + "type": "string" + }, + "state": { + "enum": [ + "ACTIVE", + "DETACHED" + ], + "enumDescriptions": [ + "", + "" + ], + "type": "string" + } + }, + "type": "object" + }, + "InterconnectDiagnosticsLinkOpticalPower": { + "id": "InterconnectDiagnosticsLinkOpticalPower", + "properties": { + "state": { + "enum": [ + "HIGH_ALARM", + "HIGH_WARNING", + "LOW_ALARM", + "LOW_WARNING", + "OK" + ], + "enumDescriptions": [ + "", + "", + "", + "", + "" + ], + "type": "string" + }, + "value": { + "description": "Value of the current optical power, read in dBm. Take a known good optical value, give it a 10% margin and trigger warnings relative to that value. In general, a -7dBm warning and a -11dBm alarm are good optical value estimates for most links.", + "format": "float", + "type": "number" + } + }, + "type": "object" + }, + "InterconnectDiagnosticsLinkStatus": { + "id": "InterconnectDiagnosticsLinkStatus", + "properties": { + "arpCaches": { + "description": "A list of InterconnectDiagnostics.ARPEntry objects, describing the ARP neighbor entries seen on this link. This will be empty if the link is bundled", + "items": { + "$ref": "InterconnectDiagnosticsARPEntry" + }, + "type": "array" + }, + "circuitId": { + "description": "The unique ID for this link assigned during turn up by Google.", + "type": "string" + }, + "googleDemarc": { + "description": "The Demarc address assigned by Google and provided in the LoA.", + "type": "string" + }, + "lacpStatus": { + "$ref": "InterconnectDiagnosticsLinkLACPStatus" + }, + "receivingOpticalPower": { + "$ref": "InterconnectDiagnosticsLinkOpticalPower" + }, + "transmittingOpticalPower": { + "$ref": "InterconnectDiagnosticsLinkOpticalPower" + } + }, + "type": "object" + }, "InterconnectList": { "description": "Response to the list request, and contains a list of interconnects.", "id": "InterconnectList", @@ -23436,7 +26554,7 @@ "type": "string" }, "availabilityZone": { - "description": "[Output Only] Availability zone for this location. Within a metropolitan area (metro), maintenance will not be simultaneously scheduled in more than one availability zone. Example: \"zone1\" or \"zone2\".", + "description": "[Output Only] Availability zone for this InterconnectLocation. Within a metropolitan area (metro), maintenance will not be simultaneously scheduled in more than one availability zone. Example: \"zone1\" or \"zone2\".", "type": "string" }, "city": { @@ -23739,6 +26857,16 @@ }, "type": "object" }, + "InterconnectsGetDiagnosticsResponse": { + "description": "Response for the InterconnectsGetDiagnosticsRequest.", + "id": "InterconnectsGetDiagnosticsResponse", + "properties": { + "result": { + "$ref": "InterconnectDiagnostics" + } + }, + "type": "object" + }, "License": { "description": "A license resource.", "id": "License", @@ -23776,7 +26904,7 @@ "compute.images.insert" ] }, - "description": "[Output Only] Name of the resource. The name is 1-63 characters long and complies with RFC1035.", + "description": "Name of the resource. The name must be 1-63 characters long and comply with RFC1035.", "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", "type": "string" }, @@ -23997,6 +27125,84 @@ }, "type": "object" }, + "LogConfig": { + "description": "Specifies what kind of log the caller must write", + "id": "LogConfig", + "properties": { + "cloudAudit": { + "$ref": "LogConfigCloudAuditOptions", + "description": "Cloud audit options." + }, + "counter": { + "$ref": "LogConfigCounterOptions", + "description": "Counter options." + }, + "dataAccess": { + "$ref": "LogConfigDataAccessOptions", + "description": "Data access options." + } + }, + "type": "object" + }, + "LogConfigCloudAuditOptions": { + "description": "Write a Cloud Audit log", + "id": "LogConfigCloudAuditOptions", + "properties": { + "authorizationLoggingOptions": { + "$ref": "AuthorizationLoggingOptions", + "description": "Information used by the Cloud Audit Logging pipeline." + }, + "logName": { + "description": "The log_name to populate in the Cloud Audit Record.", + "enum": [ + "ADMIN_ACTIVITY", + "DATA_ACCESS", + "UNSPECIFIED_LOG_NAME" + ], + "enumDescriptions": [ + "", + "", + "" + ], + "type": "string" + } + }, + "type": "object" + }, + "LogConfigCounterOptions": { + "description": "Increment a streamz counter with the specified metric and field names.\n\nMetric names should start with a '/', generally be lowercase-only, and end in \"_count\". Field names should not contain an initial slash. The actual exported metric names will have \"/iam/policy\" prepended.\n\nField names correspond to IAM request parameters and field values are their respective values.\n\nSupported field names: - \"authority\", which is \"[token]\" if IAMContext.token is present, otherwise the value of IAMContext.authority_selector if present, and otherwise a representation of IAMContext.principal; or - \"iam_principal\", a representation of IAMContext.principal even if a token or authority selector is present; or - \"\" (empty string), resulting in a counter with no fields.\n\nExamples: counter { metric: \"/debug_access_count\" field: \"iam_principal\" } ==\u003e increment counter /iam/policy/backend_debug_access_count {iam_principal=[value of IAMContext.principal]}\n\nAt this time we do not support multiple field names (though this may be supported in the future).", + "id": "LogConfigCounterOptions", + "properties": { + "field": { + "description": "The field value to attribute.", + "type": "string" + }, + "metric": { + "description": "The metric to update.", + "type": "string" + } + }, + "type": "object" + }, + "LogConfigDataAccessOptions": { + "description": "Write a Data Access (Gin) log", + "id": "LogConfigDataAccessOptions", + "properties": { + "logMode": { + "description": "Whether Gin logging should happen in a fail-closed manner at the caller. This is relevant only in the LocalIAM implementation, for now.\n\nNOTE: Logging to Gin in a fail-closed manner is currently unsupported while work is being done to satisfy the requirements of go/345. Currently, setting LOG_FAIL_CLOSED mode will have no effect, but still exists because there is active work being done to support it (b/115874152).", + "enum": [ + "LOG_FAIL_CLOSED", + "LOG_MODE_UNSPECIFIED" + ], + "enumDescriptions": [ + "", + "" + ], + "type": "string" + } + }, + "type": "object" + }, "MachineType": { "description": "A Machine Type resource. (== resource_for v1.machineTypes ==) (== resource_for beta.machineTypes ==)", "id": "MachineType", @@ -24414,7 +27620,8 @@ "NONE", "RECREATING", "REFRESHING", - "RESTARTING" + "RESTARTING", + "VERIFYING" ], "enumDescriptions": [ "", @@ -24424,6 +27631,7 @@ "", "", "", + "", "" ], "type": "string" @@ -24506,7 +27714,7 @@ "id": "Metadata", "properties": { "fingerprint": { - "description": "Specifies a fingerprint for this request, which is essentially a hash of the metadata's contents and used for optimistic locking. The fingerprint is initially generated by Compute Engine and changes after every request to modify or update metadata. You must always provide an up-to-date fingerprint hash in order to update or change metadata.", + "description": "Specifies a fingerprint for this request, which is essentially a hash of the metadata's contents and used for optimistic locking. The fingerprint is initially generated by Compute Engine and changes after every request to modify or update metadata. You must always provide an up-to-date fingerprint hash in order to update or change metadata, otherwise the request will fail with error 412 conditionNotMet.\n\nTo see the latest fingerprint, make a get() request to retrieve the resource.", "format": "byte", "type": "string" }, @@ -24565,7 +27773,7 @@ "type": "object" }, "Network": { - "description": "Represents a Network resource. Read Networks and Firewalls for more information. (== resource_for v1.networks ==) (== resource_for beta.networks ==)", + "description": "Represents a Network resource. Read Virtual Private Cloud (VPC) Network Overview for more information. (== resource_for v1.networks ==) (== resource_for beta.networks ==)", "id": "Network", "properties": { "IPv4Range": { @@ -24574,7 +27782,7 @@ "type": "string" }, "autoCreateSubnetworks": { - "description": "When set to true, the network is created in \"auto subnet mode\". When set to false, the network is in \"custom subnet mode\".\n\nIn \"auto subnet mode\", a newly created network is assigned the default CIDR of 10.128.0.0/9 and it automatically creates one subnetwork per region.", + "description": "When set to true, the VPC network is created in \"auto\" mode. When set to false, the VPC network is created in \"custom\" mode.\n\nAn auto mode VPC network starts with one subnet per region. Each subnet has a predetermined range as described in Auto mode VPC network IP ranges.", "type": "boolean" }, "creationTimestamp": { @@ -24586,7 +27794,7 @@ "type": "string" }, "gatewayIPv4": { - "description": "A gateway address for default routing to other networks. This value is read only and is selected by the Google Compute Engine, typically as the first usable address in the IPv4Range.", + "description": "[Output Only] The gateway address for default routing out of the network. This value is read only and is selected by GCP.", "pattern": "[0-9]{1,3}(?:\\.[0-9]{1,3}){3}", "type": "string" }, @@ -24626,7 +27834,7 @@ "type": "string" }, "subnetworks": { - "description": "[Output Only] Server-defined fully-qualified URLs for all subnetworks in this network.", + "description": "[Output Only] Server-defined fully-qualified URLs for all subnetworks in this VPC network.", "items": { "type": "string" }, @@ -24654,7 +27862,7 @@ "type": "array" }, "fingerprint": { - "description": "Fingerprint hash of contents stored in this network interface. This field will be ignored when inserting an Instance or adding a NetworkInterface. An up-to-date fingerprint must be provided in order to update the NetworkInterface.", + "description": "Fingerprint hash of contents stored in this network interface. This field will be ignored when inserting an Instance or adding a NetworkInterface. An up-to-date fingerprint must be provided in order to update the NetworkInterface, otherwise the request will fail with error 412 conditionNotMet.", "format": "byte", "type": "string" }, @@ -24799,7 +28007,7 @@ "id": "NetworkPeering", "properties": { "autoCreateRoutes": { - "description": "Whether full mesh connectivity is created and managed automatically. When it is set to true, Google Compute Engine will automatically create and manage the routes between two networks when the state is ACTIVE. Otherwise, user needs to create routes manually to route packets to peer network.", + "description": "Indicates whether full mesh connectivity is created and managed automatically. When it is set to true, Google Compute Engine will automatically create and manage the routes between two networks when the state is ACTIVE. Otherwise, user needs to create routes manually to route packets to peer network.", "type": "boolean" }, "name": { @@ -24834,7 +28042,7 @@ "id": "NetworkRoutingConfig", "properties": { "routingMode": { - "description": "The network-wide routing mode to use. If set to REGIONAL, this network's cloud routers will only advertise routes with subnetworks of this network in the same region as the router. If set to GLOBAL, this network's cloud routers will advertise routes with all subnetworks of this network, across regions.", + "description": "The network-wide routing mode to use. If set to REGIONAL, this network's cloud routers will only advertise routes with subnets of this network in the same region as the router. If set to GLOBAL, this network's cloud routers will advertise routes with all subnets of this network, across regions.", "enum": [ "GLOBAL", "REGIONAL" @@ -24881,6 +28089,1351 @@ }, "type": "object" }, + "NodeGroup": { + "description": "A NodeGroup resource.", + "id": "NodeGroup", + "properties": { + "creationTimestamp": { + "description": "[Output Only] Creation timestamp in RFC3339 text format.", + "type": "string" + }, + "description": { + "description": "An optional description of this resource. Provide this property when you create the resource.", + "type": "string" + }, + "id": { + "description": "[Output Only] The unique identifier for the resource. This identifier is defined by the server.", + "format": "uint64", + "type": "string" + }, + "kind": { + "default": "compute#nodeGroup", + "description": "[Output Only] The type of the resource. Always compute#nodeGroup for node group.", + "type": "string" + }, + "name": { + "description": "The name of the resource, provided by the client when initially creating the resource. The resource name must be 1-63 characters long, and comply with RFC1035. Specifically, the name must be 1-63 characters long and match the regular expression `[a-z]([-a-z0-9]*[a-z0-9])?` which means the first character must be a lowercase letter, and all following characters must be a dash, lowercase letter, or digit, except the last character, which cannot be a dash.", + "type": "string" + }, + "nodeTemplate": { + "description": "The URL of the node template to which this node group belongs.", + "type": "string" + }, + "selfLink": { + "description": "[Output Only] Server-defined URL for the resource.", + "type": "string" + }, + "size": { + "description": "[Output Only] The total number of nodes in the node group.", + "format": "int32", + "type": "integer" + }, + "status": { + "enum": [ + "CREATING", + "DELETING", + "INVALID", + "READY" + ], + "enumDescriptions": [ + "", + "", + "", + "" + ], + "type": "string" + }, + "zone": { + "description": "[Output Only] The name of the zone where the node group resides, such as us-central1-a.", + "type": "string" + } + }, + "type": "object" + }, + "NodeGroupAggregatedList": { + "id": "NodeGroupAggregatedList", + "properties": { + "id": { + "description": "[Output Only] Unique identifier for the resource; defined by the server.", + "type": "string" + }, + "items": { + "additionalProperties": { + "$ref": "NodeGroupsScopedList", + "description": "[Output Only] Name of the scope containing this set of node groups." + }, + "description": "A list of NodeGroupsScopedList resources.", + "type": "object" + }, + "kind": { + "default": "compute#nodeGroupAggregatedList", + "description": "[Output Only] Type of resource.Always compute#nodeGroupAggregatedList for aggregated lists of node groups.", + "type": "string" + }, + "nextPageToken": { + "description": "[Output Only] This token allows you to get the next page of results for list requests. If the number of results is larger than maxResults, use the nextPageToken as a value for the query parameter pageToken in the next list request. Subsequent list requests will have their own nextPageToken to continue paging through the results.", + "type": "string" + }, + "selfLink": { + "description": "[Output Only] Server-defined URL for this resource.", + "type": "string" + }, + "warning": { + "description": "[Output Only] Informational warning message.", + "properties": { + "code": { + "description": "[Output Only] A warning code, if applicable. For example, Compute Engine returns NO_RESULTS_ON_PAGE if there are no results in the response.", + "enum": [ + "CLEANUP_FAILED", + "DEPRECATED_RESOURCE_USED", + "DEPRECATED_TYPE_USED", + "DISK_SIZE_LARGER_THAN_IMAGE_SIZE", + "EXPERIMENTAL_TYPE_USED", + "EXTERNAL_API_WARNING", + "FIELD_VALUE_OVERRIDEN", + "INJECTED_KERNELS_DEPRECATED", + "MISSING_TYPE_DEPENDENCY", + "NEXT_HOP_ADDRESS_NOT_ASSIGNED", + "NEXT_HOP_CANNOT_IP_FORWARD", + "NEXT_HOP_INSTANCE_NOT_FOUND", + "NEXT_HOP_INSTANCE_NOT_ON_NETWORK", + "NEXT_HOP_NOT_RUNNING", + "NOT_CRITICAL_ERROR", + "NO_RESULTS_ON_PAGE", + "REQUIRED_TOS_AGREEMENT", + "RESOURCE_IN_USE_BY_OTHER_RESOURCE_WARNING", + "RESOURCE_NOT_DELETED", + "SCHEMA_VALIDATION_IGNORED", + "SINGLE_INSTANCE_PROPERTY_TEMPLATE", + "UNDECLARED_PROPERTIES", + "UNREACHABLE" + ], + "enumDescriptions": [ + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "" + ], + "type": "string" + }, + "data": { + "description": "[Output Only] Metadata about this warning in key: value format. For example:\n\"data\": [ { \"key\": \"scope\", \"value\": \"zones/us-east1-d\" }", + "items": { + "properties": { + "key": { + "description": "[Output Only] A key that provides more detail on the warning being returned. For example, for warnings where there are no results in a list request for a particular zone, this key might be scope and the key value might be the zone name. Other examples might be a key indicating a deprecated resource and a suggested replacement, or a warning about invalid network settings (for example, if an instance attempts to perform IP forwarding but is not enabled for IP forwarding).", + "type": "string" + }, + "value": { + "description": "[Output Only] A warning data value corresponding to the key.", + "type": "string" + } + }, + "type": "object" + }, + "type": "array" + }, + "message": { + "description": "[Output Only] A human-readable description of the warning code.", + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object" + }, + "NodeGroupList": { + "description": "Contains a list of nodeGroups.", + "id": "NodeGroupList", + "properties": { + "id": { + "description": "[Output Only] Unique identifier for the resource; defined by the server.", + "type": "string" + }, + "items": { + "description": "A list of NodeGroup resources.", + "items": { + "$ref": "NodeGroup" + }, + "type": "array" + }, + "kind": { + "default": "compute#nodeGroupList", + "description": "[Output Only] Type of resource.Always compute#nodeGroupList for lists of node groups.", + "type": "string" + }, + "nextPageToken": { + "description": "[Output Only] This token allows you to get the next page of results for list requests. If the number of results is larger than maxResults, use the nextPageToken as a value for the query parameter pageToken in the next list request. Subsequent list requests will have their own nextPageToken to continue paging through the results.", + "type": "string" + }, + "selfLink": { + "description": "[Output Only] Server-defined URL for this resource.", + "type": "string" + }, + "warning": { + "description": "[Output Only] Informational warning message.", + "properties": { + "code": { + "description": "[Output Only] A warning code, if applicable. For example, Compute Engine returns NO_RESULTS_ON_PAGE if there are no results in the response.", + "enum": [ + "CLEANUP_FAILED", + "DEPRECATED_RESOURCE_USED", + "DEPRECATED_TYPE_USED", + "DISK_SIZE_LARGER_THAN_IMAGE_SIZE", + "EXPERIMENTAL_TYPE_USED", + "EXTERNAL_API_WARNING", + "FIELD_VALUE_OVERRIDEN", + "INJECTED_KERNELS_DEPRECATED", + "MISSING_TYPE_DEPENDENCY", + "NEXT_HOP_ADDRESS_NOT_ASSIGNED", + "NEXT_HOP_CANNOT_IP_FORWARD", + "NEXT_HOP_INSTANCE_NOT_FOUND", + "NEXT_HOP_INSTANCE_NOT_ON_NETWORK", + "NEXT_HOP_NOT_RUNNING", + "NOT_CRITICAL_ERROR", + "NO_RESULTS_ON_PAGE", + "REQUIRED_TOS_AGREEMENT", + "RESOURCE_IN_USE_BY_OTHER_RESOURCE_WARNING", + "RESOURCE_NOT_DELETED", + "SCHEMA_VALIDATION_IGNORED", + "SINGLE_INSTANCE_PROPERTY_TEMPLATE", + "UNDECLARED_PROPERTIES", + "UNREACHABLE" + ], + "enumDescriptions": [ + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "" + ], + "type": "string" + }, + "data": { + "description": "[Output Only] Metadata about this warning in key: value format. For example:\n\"data\": [ { \"key\": \"scope\", \"value\": \"zones/us-east1-d\" }", + "items": { + "properties": { + "key": { + "description": "[Output Only] A key that provides more detail on the warning being returned. For example, for warnings where there are no results in a list request for a particular zone, this key might be scope and the key value might be the zone name. Other examples might be a key indicating a deprecated resource and a suggested replacement, or a warning about invalid network settings (for example, if an instance attempts to perform IP forwarding but is not enabled for IP forwarding).", + "type": "string" + }, + "value": { + "description": "[Output Only] A warning data value corresponding to the key.", + "type": "string" + } + }, + "type": "object" + }, + "type": "array" + }, + "message": { + "description": "[Output Only] A human-readable description of the warning code.", + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object" + }, + "NodeGroupNode": { + "id": "NodeGroupNode", + "properties": { + "instances": { + "description": "Instances scheduled on this node.", + "items": { + "type": "string" + }, + "type": "array" + }, + "name": { + "description": "The name of the node.", + "type": "string" + }, + "nodeType": { + "description": "The type of this node.", + "type": "string" + }, + "status": { + "enum": [ + "CREATING", + "DELETING", + "INVALID", + "READY", + "REPAIRING" + ], + "enumDescriptions": [ + "", + "", + "", + "", + "" + ], + "type": "string" + } + }, + "type": "object" + }, + "NodeGroupsAddNodesRequest": { + "id": "NodeGroupsAddNodesRequest", + "properties": { + "additionalNodeCount": { + "description": "Count of additional nodes to be added to the node group.", + "format": "int32", + "type": "integer" + } + }, + "type": "object" + }, + "NodeGroupsDeleteNodesRequest": { + "id": "NodeGroupsDeleteNodesRequest", + "properties": { + "nodes": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object" + }, + "NodeGroupsListNodes": { + "id": "NodeGroupsListNodes", + "properties": { + "id": { + "description": "[Output Only] Unique identifier for the resource; defined by the server.", + "type": "string" + }, + "items": { + "description": "A list of Node resources.", + "items": { + "$ref": "NodeGroupNode" + }, + "type": "array" + }, + "kind": { + "default": "compute#nodeGroupsListNodes", + "description": "[Output Only] The resource type, which is always compute.nodeGroupsListNodes for the list of nodes in the specified node group.", + "type": "string" + }, + "nextPageToken": { + "description": "[Output Only] This token allows you to get the next page of results for list requests. If the number of results is larger than maxResults, use the nextPageToken as a value for the query parameter pageToken in the next list request. Subsequent list requests will have their own nextPageToken to continue paging through the results.", + "type": "string" + }, + "selfLink": { + "description": "[Output Only] Server-defined URL for this resource.", + "type": "string" + }, + "warning": { + "description": "[Output Only] Informational warning message.", + "properties": { + "code": { + "description": "[Output Only] A warning code, if applicable. For example, Compute Engine returns NO_RESULTS_ON_PAGE if there are no results in the response.", + "enum": [ + "CLEANUP_FAILED", + "DEPRECATED_RESOURCE_USED", + "DEPRECATED_TYPE_USED", + "DISK_SIZE_LARGER_THAN_IMAGE_SIZE", + "EXPERIMENTAL_TYPE_USED", + "EXTERNAL_API_WARNING", + "FIELD_VALUE_OVERRIDEN", + "INJECTED_KERNELS_DEPRECATED", + "MISSING_TYPE_DEPENDENCY", + "NEXT_HOP_ADDRESS_NOT_ASSIGNED", + "NEXT_HOP_CANNOT_IP_FORWARD", + "NEXT_HOP_INSTANCE_NOT_FOUND", + "NEXT_HOP_INSTANCE_NOT_ON_NETWORK", + "NEXT_HOP_NOT_RUNNING", + "NOT_CRITICAL_ERROR", + "NO_RESULTS_ON_PAGE", + "REQUIRED_TOS_AGREEMENT", + "RESOURCE_IN_USE_BY_OTHER_RESOURCE_WARNING", + "RESOURCE_NOT_DELETED", + "SCHEMA_VALIDATION_IGNORED", + "SINGLE_INSTANCE_PROPERTY_TEMPLATE", + "UNDECLARED_PROPERTIES", + "UNREACHABLE" + ], + "enumDescriptions": [ + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "" + ], + "type": "string" + }, + "data": { + "description": "[Output Only] Metadata about this warning in key: value format. For example:\n\"data\": [ { \"key\": \"scope\", \"value\": \"zones/us-east1-d\" }", + "items": { + "properties": { + "key": { + "description": "[Output Only] A key that provides more detail on the warning being returned. For example, for warnings where there are no results in a list request for a particular zone, this key might be scope and the key value might be the zone name. Other examples might be a key indicating a deprecated resource and a suggested replacement, or a warning about invalid network settings (for example, if an instance attempts to perform IP forwarding but is not enabled for IP forwarding).", + "type": "string" + }, + "value": { + "description": "[Output Only] A warning data value corresponding to the key.", + "type": "string" + } + }, + "type": "object" + }, + "type": "array" + }, + "message": { + "description": "[Output Only] A human-readable description of the warning code.", + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object" + }, + "NodeGroupsScopedList": { + "id": "NodeGroupsScopedList", + "properties": { + "nodeGroups": { + "description": "[Output Only] A list of node groups contained in this scope.", + "items": { + "$ref": "NodeGroup" + }, + "type": "array" + }, + "warning": { + "description": "[Output Only] An informational warning that appears when the nodeGroup list is empty.", + "properties": { + "code": { + "description": "[Output Only] A warning code, if applicable. For example, Compute Engine returns NO_RESULTS_ON_PAGE if there are no results in the response.", + "enum": [ + "CLEANUP_FAILED", + "DEPRECATED_RESOURCE_USED", + "DEPRECATED_TYPE_USED", + "DISK_SIZE_LARGER_THAN_IMAGE_SIZE", + "EXPERIMENTAL_TYPE_USED", + "EXTERNAL_API_WARNING", + "FIELD_VALUE_OVERRIDEN", + "INJECTED_KERNELS_DEPRECATED", + "MISSING_TYPE_DEPENDENCY", + "NEXT_HOP_ADDRESS_NOT_ASSIGNED", + "NEXT_HOP_CANNOT_IP_FORWARD", + "NEXT_HOP_INSTANCE_NOT_FOUND", + "NEXT_HOP_INSTANCE_NOT_ON_NETWORK", + "NEXT_HOP_NOT_RUNNING", + "NOT_CRITICAL_ERROR", + "NO_RESULTS_ON_PAGE", + "REQUIRED_TOS_AGREEMENT", + "RESOURCE_IN_USE_BY_OTHER_RESOURCE_WARNING", + "RESOURCE_NOT_DELETED", + "SCHEMA_VALIDATION_IGNORED", + "SINGLE_INSTANCE_PROPERTY_TEMPLATE", + "UNDECLARED_PROPERTIES", + "UNREACHABLE" + ], + "enumDescriptions": [ + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "" + ], + "type": "string" + }, + "data": { + "description": "[Output Only] Metadata about this warning in key: value format. For example:\n\"data\": [ { \"key\": \"scope\", \"value\": \"zones/us-east1-d\" }", + "items": { + "properties": { + "key": { + "description": "[Output Only] A key that provides more detail on the warning being returned. For example, for warnings where there are no results in a list request for a particular zone, this key might be scope and the key value might be the zone name. Other examples might be a key indicating a deprecated resource and a suggested replacement, or a warning about invalid network settings (for example, if an instance attempts to perform IP forwarding but is not enabled for IP forwarding).", + "type": "string" + }, + "value": { + "description": "[Output Only] A warning data value corresponding to the key.", + "type": "string" + } + }, + "type": "object" + }, + "type": "array" + }, + "message": { + "description": "[Output Only] A human-readable description of the warning code.", + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object" + }, + "NodeGroupsSetNodeTemplateRequest": { + "id": "NodeGroupsSetNodeTemplateRequest", + "properties": { + "nodeTemplate": { + "description": "Full or partial URL of the node template resource to be updated for this node group.", + "type": "string" + } + }, + "type": "object" + }, + "NodeTemplate": { + "description": "A Node Template resource.", + "id": "NodeTemplate", + "properties": { + "creationTimestamp": { + "description": "[Output Only] Creation timestamp in RFC3339 text format.", + "type": "string" + }, + "description": { + "description": "An optional description of this resource. Provide this property when you create the resource.", + "type": "string" + }, + "id": { + "description": "[Output Only] The unique identifier for the resource. This identifier is defined by the server.", + "format": "uint64", + "type": "string" + }, + "kind": { + "default": "compute#nodeTemplate", + "description": "[Output Only] The type of the resource. Always compute#nodeTemplate for node templates.", + "type": "string" + }, + "name": { + "description": "The name of the resource, provided by the client when initially creating the resource. The resource name must be 1-63 characters long, and comply with RFC1035. Specifically, the name must be 1-63 characters long and match the regular expression `[a-z]([-a-z0-9]*[a-z0-9])?` which means the first character must be a lowercase letter, and all following characters must be a dash, lowercase letter, or digit, except the last character, which cannot be a dash.", + "type": "string" + }, + "nodeAffinityLabels": { + "additionalProperties": { + "type": "string" + }, + "description": "Labels to use for node affinity, which will be used in instance scheduling.", + "type": "object" + }, + "nodeType": { + "description": "The node type to use for nodes group that are created from this template.", + "type": "string" + }, + "nodeTypeFlexibility": { + "$ref": "NodeTemplateNodeTypeFlexibility", + "description": "The flexible properties of the desired node type. Node groups that use this node template will create nodes of a type that matches these properties.\n\nThis field is mutually exclusive with the node_type property; you can only define one or the other, but not both." + }, + "region": { + "description": "[Output Only] The name of the region where the node template resides, such as us-central1.", + "type": "string" + }, + "selfLink": { + "description": "[Output Only] Server-defined URL for the resource.", + "type": "string" + }, + "status": { + "description": "[Output Only] The status of the node template. One of the following values: CREATING, READY, and DELETING.", + "enum": [ + "CREATING", + "DELETING", + "INVALID", + "READY" + ], + "enumDescriptions": [ + "", + "", + "", + "" + ], + "type": "string" + }, + "statusMessage": { + "description": "[Output Only] An optional, human-readable explanation of the status.", + "type": "string" + } + }, + "type": "object" + }, + "NodeTemplateAggregatedList": { + "id": "NodeTemplateAggregatedList", + "properties": { + "id": { + "description": "[Output Only] Unique identifier for the resource; defined by the server.", + "type": "string" + }, + "items": { + "additionalProperties": { + "$ref": "NodeTemplatesScopedList", + "description": "[Output Only] Name of the scope containing this set of node templates." + }, + "description": "A list of NodeTemplatesScopedList resources.", + "type": "object" + }, + "kind": { + "default": "compute#nodeTemplateAggregatedList", + "description": "[Output Only] Type of resource.Always compute#nodeTemplateAggregatedList for aggregated lists of node templates.", + "type": "string" + }, + "nextPageToken": { + "description": "[Output Only] This token allows you to get the next page of results for list requests. If the number of results is larger than maxResults, use the nextPageToken as a value for the query parameter pageToken in the next list request. Subsequent list requests will have their own nextPageToken to continue paging through the results.", + "type": "string" + }, + "selfLink": { + "description": "[Output Only] Server-defined URL for this resource.", + "type": "string" + }, + "warning": { + "description": "[Output Only] Informational warning message.", + "properties": { + "code": { + "description": "[Output Only] A warning code, if applicable. For example, Compute Engine returns NO_RESULTS_ON_PAGE if there are no results in the response.", + "enum": [ + "CLEANUP_FAILED", + "DEPRECATED_RESOURCE_USED", + "DEPRECATED_TYPE_USED", + "DISK_SIZE_LARGER_THAN_IMAGE_SIZE", + "EXPERIMENTAL_TYPE_USED", + "EXTERNAL_API_WARNING", + "FIELD_VALUE_OVERRIDEN", + "INJECTED_KERNELS_DEPRECATED", + "MISSING_TYPE_DEPENDENCY", + "NEXT_HOP_ADDRESS_NOT_ASSIGNED", + "NEXT_HOP_CANNOT_IP_FORWARD", + "NEXT_HOP_INSTANCE_NOT_FOUND", + "NEXT_HOP_INSTANCE_NOT_ON_NETWORK", + "NEXT_HOP_NOT_RUNNING", + "NOT_CRITICAL_ERROR", + "NO_RESULTS_ON_PAGE", + "REQUIRED_TOS_AGREEMENT", + "RESOURCE_IN_USE_BY_OTHER_RESOURCE_WARNING", + "RESOURCE_NOT_DELETED", + "SCHEMA_VALIDATION_IGNORED", + "SINGLE_INSTANCE_PROPERTY_TEMPLATE", + "UNDECLARED_PROPERTIES", + "UNREACHABLE" + ], + "enumDescriptions": [ + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "" + ], + "type": "string" + }, + "data": { + "description": "[Output Only] Metadata about this warning in key: value format. For example:\n\"data\": [ { \"key\": \"scope\", \"value\": \"zones/us-east1-d\" }", + "items": { + "properties": { + "key": { + "description": "[Output Only] A key that provides more detail on the warning being returned. For example, for warnings where there are no results in a list request for a particular zone, this key might be scope and the key value might be the zone name. Other examples might be a key indicating a deprecated resource and a suggested replacement, or a warning about invalid network settings (for example, if an instance attempts to perform IP forwarding but is not enabled for IP forwarding).", + "type": "string" + }, + "value": { + "description": "[Output Only] A warning data value corresponding to the key.", + "type": "string" + } + }, + "type": "object" + }, + "type": "array" + }, + "message": { + "description": "[Output Only] A human-readable description of the warning code.", + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object" + }, + "NodeTemplateList": { + "description": "Contains a list of node templates.", + "id": "NodeTemplateList", + "properties": { + "id": { + "description": "[Output Only] Unique identifier for the resource; defined by the server.", + "type": "string" + }, + "items": { + "description": "A list of NodeTemplate resources.", + "items": { + "$ref": "NodeTemplate" + }, + "type": "array" + }, + "kind": { + "default": "compute#nodeTemplateList", + "description": "[Output Only] Type of resource.Always compute#nodeTemplateList for lists of node templates.", + "type": "string" + }, + "nextPageToken": { + "description": "[Output Only] This token allows you to get the next page of results for list requests. If the number of results is larger than maxResults, use the nextPageToken as a value for the query parameter pageToken in the next list request. Subsequent list requests will have their own nextPageToken to continue paging through the results.", + "type": "string" + }, + "selfLink": { + "description": "[Output Only] Server-defined URL for this resource.", + "type": "string" + }, + "warning": { + "description": "[Output Only] Informational warning message.", + "properties": { + "code": { + "description": "[Output Only] A warning code, if applicable. For example, Compute Engine returns NO_RESULTS_ON_PAGE if there are no results in the response.", + "enum": [ + "CLEANUP_FAILED", + "DEPRECATED_RESOURCE_USED", + "DEPRECATED_TYPE_USED", + "DISK_SIZE_LARGER_THAN_IMAGE_SIZE", + "EXPERIMENTAL_TYPE_USED", + "EXTERNAL_API_WARNING", + "FIELD_VALUE_OVERRIDEN", + "INJECTED_KERNELS_DEPRECATED", + "MISSING_TYPE_DEPENDENCY", + "NEXT_HOP_ADDRESS_NOT_ASSIGNED", + "NEXT_HOP_CANNOT_IP_FORWARD", + "NEXT_HOP_INSTANCE_NOT_FOUND", + "NEXT_HOP_INSTANCE_NOT_ON_NETWORK", + "NEXT_HOP_NOT_RUNNING", + "NOT_CRITICAL_ERROR", + "NO_RESULTS_ON_PAGE", + "REQUIRED_TOS_AGREEMENT", + "RESOURCE_IN_USE_BY_OTHER_RESOURCE_WARNING", + "RESOURCE_NOT_DELETED", + "SCHEMA_VALIDATION_IGNORED", + "SINGLE_INSTANCE_PROPERTY_TEMPLATE", + "UNDECLARED_PROPERTIES", + "UNREACHABLE" + ], + "enumDescriptions": [ + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "" + ], + "type": "string" + }, + "data": { + "description": "[Output Only] Metadata about this warning in key: value format. For example:\n\"data\": [ { \"key\": \"scope\", \"value\": \"zones/us-east1-d\" }", + "items": { + "properties": { + "key": { + "description": "[Output Only] A key that provides more detail on the warning being returned. For example, for warnings where there are no results in a list request for a particular zone, this key might be scope and the key value might be the zone name. Other examples might be a key indicating a deprecated resource and a suggested replacement, or a warning about invalid network settings (for example, if an instance attempts to perform IP forwarding but is not enabled for IP forwarding).", + "type": "string" + }, + "value": { + "description": "[Output Only] A warning data value corresponding to the key.", + "type": "string" + } + }, + "type": "object" + }, + "type": "array" + }, + "message": { + "description": "[Output Only] A human-readable description of the warning code.", + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object" + }, + "NodeTemplateNodeTypeFlexibility": { + "id": "NodeTemplateNodeTypeFlexibility", + "properties": { + "cpus": { + "type": "string" + }, + "localSsd": { + "type": "string" + }, + "memory": { + "type": "string" + } + }, + "type": "object" + }, + "NodeTemplatesScopedList": { + "id": "NodeTemplatesScopedList", + "properties": { + "nodeTemplates": { + "description": "[Output Only] A list of node templates contained in this scope.", + "items": { + "$ref": "NodeTemplate" + }, + "type": "array" + }, + "warning": { + "description": "[Output Only] An informational warning that appears when the node templates list is empty.", + "properties": { + "code": { + "description": "[Output Only] A warning code, if applicable. For example, Compute Engine returns NO_RESULTS_ON_PAGE if there are no results in the response.", + "enum": [ + "CLEANUP_FAILED", + "DEPRECATED_RESOURCE_USED", + "DEPRECATED_TYPE_USED", + "DISK_SIZE_LARGER_THAN_IMAGE_SIZE", + "EXPERIMENTAL_TYPE_USED", + "EXTERNAL_API_WARNING", + "FIELD_VALUE_OVERRIDEN", + "INJECTED_KERNELS_DEPRECATED", + "MISSING_TYPE_DEPENDENCY", + "NEXT_HOP_ADDRESS_NOT_ASSIGNED", + "NEXT_HOP_CANNOT_IP_FORWARD", + "NEXT_HOP_INSTANCE_NOT_FOUND", + "NEXT_HOP_INSTANCE_NOT_ON_NETWORK", + "NEXT_HOP_NOT_RUNNING", + "NOT_CRITICAL_ERROR", + "NO_RESULTS_ON_PAGE", + "REQUIRED_TOS_AGREEMENT", + "RESOURCE_IN_USE_BY_OTHER_RESOURCE_WARNING", + "RESOURCE_NOT_DELETED", + "SCHEMA_VALIDATION_IGNORED", + "SINGLE_INSTANCE_PROPERTY_TEMPLATE", + "UNDECLARED_PROPERTIES", + "UNREACHABLE" + ], + "enumDescriptions": [ + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "" + ], + "type": "string" + }, + "data": { + "description": "[Output Only] Metadata about this warning in key: value format. For example:\n\"data\": [ { \"key\": \"scope\", \"value\": \"zones/us-east1-d\" }", + "items": { + "properties": { + "key": { + "description": "[Output Only] A key that provides more detail on the warning being returned. For example, for warnings where there are no results in a list request for a particular zone, this key might be scope and the key value might be the zone name. Other examples might be a key indicating a deprecated resource and a suggested replacement, or a warning about invalid network settings (for example, if an instance attempts to perform IP forwarding but is not enabled for IP forwarding).", + "type": "string" + }, + "value": { + "description": "[Output Only] A warning data value corresponding to the key.", + "type": "string" + } + }, + "type": "object" + }, + "type": "array" + }, + "message": { + "description": "[Output Only] A human-readable description of the warning code.", + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object" + }, + "NodeType": { + "description": "A Node Type resource.", + "id": "NodeType", + "properties": { + "cpuPlatform": { + "description": "[Output Only] The CPU platform used by this node type.", + "type": "string" + }, + "creationTimestamp": { + "description": "[Output Only] Creation timestamp in RFC3339 text format.", + "type": "string" + }, + "deprecated": { + "$ref": "DeprecationStatus", + "description": "[Output Only] The deprecation status associated with this node type." + }, + "description": { + "description": "[Output Only] An optional textual description of the resource.", + "type": "string" + }, + "guestCpus": { + "description": "[Output Only] The number of virtual CPUs that are available to the node type.", + "format": "int32", + "type": "integer" + }, + "id": { + "description": "[Output Only] The unique identifier for the resource. This identifier is defined by the server.", + "format": "uint64", + "type": "string" + }, + "kind": { + "default": "compute#nodeType", + "description": "[Output Only] The type of the resource. Always compute#nodeType for node types.", + "type": "string" + }, + "localSsdGb": { + "description": "[Output Only] Local SSD available to the node type, defined in GB.", + "format": "int32", + "type": "integer" + }, + "memoryMb": { + "description": "[Output Only] The amount of physical memory available to the node type, defined in MB.", + "format": "int32", + "type": "integer" + }, + "name": { + "description": "[Output Only] Name of the resource.", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "type": "string" + }, + "selfLink": { + "description": "[Output Only] Server-defined URL for the resource.", + "type": "string" + }, + "zone": { + "description": "[Output Only] The name of the zone where the node type resides, such as us-central1-a.", + "type": "string" + } + }, + "type": "object" + }, + "NodeTypeAggregatedList": { + "id": "NodeTypeAggregatedList", + "properties": { + "id": { + "description": "[Output Only] Unique identifier for the resource; defined by the server.", + "type": "string" + }, + "items": { + "additionalProperties": { + "$ref": "NodeTypesScopedList", + "description": "[Output Only] Name of the scope containing this set of node types." + }, + "description": "A list of NodeTypesScopedList resources.", + "type": "object" + }, + "kind": { + "default": "compute#nodeTypeAggregatedList", + "description": "[Output Only] Type of resource.Always compute#nodeTypeAggregatedList for aggregated lists of node types.", + "type": "string" + }, + "nextPageToken": { + "description": "[Output Only] This token allows you to get the next page of results for list requests. If the number of results is larger than maxResults, use the nextPageToken as a value for the query parameter pageToken in the next list request. Subsequent list requests will have their own nextPageToken to continue paging through the results.", + "type": "string" + }, + "selfLink": { + "description": "[Output Only] Server-defined URL for this resource.", + "type": "string" + }, + "warning": { + "description": "[Output Only] Informational warning message.", + "properties": { + "code": { + "description": "[Output Only] A warning code, if applicable. For example, Compute Engine returns NO_RESULTS_ON_PAGE if there are no results in the response.", + "enum": [ + "CLEANUP_FAILED", + "DEPRECATED_RESOURCE_USED", + "DEPRECATED_TYPE_USED", + "DISK_SIZE_LARGER_THAN_IMAGE_SIZE", + "EXPERIMENTAL_TYPE_USED", + "EXTERNAL_API_WARNING", + "FIELD_VALUE_OVERRIDEN", + "INJECTED_KERNELS_DEPRECATED", + "MISSING_TYPE_DEPENDENCY", + "NEXT_HOP_ADDRESS_NOT_ASSIGNED", + "NEXT_HOP_CANNOT_IP_FORWARD", + "NEXT_HOP_INSTANCE_NOT_FOUND", + "NEXT_HOP_INSTANCE_NOT_ON_NETWORK", + "NEXT_HOP_NOT_RUNNING", + "NOT_CRITICAL_ERROR", + "NO_RESULTS_ON_PAGE", + "REQUIRED_TOS_AGREEMENT", + "RESOURCE_IN_USE_BY_OTHER_RESOURCE_WARNING", + "RESOURCE_NOT_DELETED", + "SCHEMA_VALIDATION_IGNORED", + "SINGLE_INSTANCE_PROPERTY_TEMPLATE", + "UNDECLARED_PROPERTIES", + "UNREACHABLE" + ], + "enumDescriptions": [ + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "" + ], + "type": "string" + }, + "data": { + "description": "[Output Only] Metadata about this warning in key: value format. For example:\n\"data\": [ { \"key\": \"scope\", \"value\": \"zones/us-east1-d\" }", + "items": { + "properties": { + "key": { + "description": "[Output Only] A key that provides more detail on the warning being returned. For example, for warnings where there are no results in a list request for a particular zone, this key might be scope and the key value might be the zone name. Other examples might be a key indicating a deprecated resource and a suggested replacement, or a warning about invalid network settings (for example, if an instance attempts to perform IP forwarding but is not enabled for IP forwarding).", + "type": "string" + }, + "value": { + "description": "[Output Only] A warning data value corresponding to the key.", + "type": "string" + } + }, + "type": "object" + }, + "type": "array" + }, + "message": { + "description": "[Output Only] A human-readable description of the warning code.", + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object" + }, + "NodeTypeList": { + "description": "Contains a list of node types.", + "id": "NodeTypeList", + "properties": { + "id": { + "description": "[Output Only] Unique identifier for the resource; defined by the server.", + "type": "string" + }, + "items": { + "description": "A list of NodeType resources.", + "items": { + "$ref": "NodeType" + }, + "type": "array" + }, + "kind": { + "default": "compute#nodeTypeList", + "description": "[Output Only] Type of resource.Always compute#nodeTypeList for lists of node types.", + "type": "string" + }, + "nextPageToken": { + "description": "[Output Only] This token allows you to get the next page of results for list requests. If the number of results is larger than maxResults, use the nextPageToken as a value for the query parameter pageToken in the next list request. Subsequent list requests will have their own nextPageToken to continue paging through the results.", + "type": "string" + }, + "selfLink": { + "description": "[Output Only] Server-defined URL for this resource.", + "type": "string" + }, + "warning": { + "description": "[Output Only] Informational warning message.", + "properties": { + "code": { + "description": "[Output Only] A warning code, if applicable. For example, Compute Engine returns NO_RESULTS_ON_PAGE if there are no results in the response.", + "enum": [ + "CLEANUP_FAILED", + "DEPRECATED_RESOURCE_USED", + "DEPRECATED_TYPE_USED", + "DISK_SIZE_LARGER_THAN_IMAGE_SIZE", + "EXPERIMENTAL_TYPE_USED", + "EXTERNAL_API_WARNING", + "FIELD_VALUE_OVERRIDEN", + "INJECTED_KERNELS_DEPRECATED", + "MISSING_TYPE_DEPENDENCY", + "NEXT_HOP_ADDRESS_NOT_ASSIGNED", + "NEXT_HOP_CANNOT_IP_FORWARD", + "NEXT_HOP_INSTANCE_NOT_FOUND", + "NEXT_HOP_INSTANCE_NOT_ON_NETWORK", + "NEXT_HOP_NOT_RUNNING", + "NOT_CRITICAL_ERROR", + "NO_RESULTS_ON_PAGE", + "REQUIRED_TOS_AGREEMENT", + "RESOURCE_IN_USE_BY_OTHER_RESOURCE_WARNING", + "RESOURCE_NOT_DELETED", + "SCHEMA_VALIDATION_IGNORED", + "SINGLE_INSTANCE_PROPERTY_TEMPLATE", + "UNDECLARED_PROPERTIES", + "UNREACHABLE" + ], + "enumDescriptions": [ + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "" + ], + "type": "string" + }, + "data": { + "description": "[Output Only] Metadata about this warning in key: value format. For example:\n\"data\": [ { \"key\": \"scope\", \"value\": \"zones/us-east1-d\" }", + "items": { + "properties": { + "key": { + "description": "[Output Only] A key that provides more detail on the warning being returned. For example, for warnings where there are no results in a list request for a particular zone, this key might be scope and the key value might be the zone name. Other examples might be a key indicating a deprecated resource and a suggested replacement, or a warning about invalid network settings (for example, if an instance attempts to perform IP forwarding but is not enabled for IP forwarding).", + "type": "string" + }, + "value": { + "description": "[Output Only] A warning data value corresponding to the key.", + "type": "string" + } + }, + "type": "object" + }, + "type": "array" + }, + "message": { + "description": "[Output Only] A human-readable description of the warning code.", + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object" + }, + "NodeTypesScopedList": { + "id": "NodeTypesScopedList", + "properties": { + "nodeTypes": { + "description": "[Output Only] A list of node types contained in this scope.", + "items": { + "$ref": "NodeType" + }, + "type": "array" + }, + "warning": { + "description": "[Output Only] An informational warning that appears when the node types list is empty.", + "properties": { + "code": { + "description": "[Output Only] A warning code, if applicable. For example, Compute Engine returns NO_RESULTS_ON_PAGE if there are no results in the response.", + "enum": [ + "CLEANUP_FAILED", + "DEPRECATED_RESOURCE_USED", + "DEPRECATED_TYPE_USED", + "DISK_SIZE_LARGER_THAN_IMAGE_SIZE", + "EXPERIMENTAL_TYPE_USED", + "EXTERNAL_API_WARNING", + "FIELD_VALUE_OVERRIDEN", + "INJECTED_KERNELS_DEPRECATED", + "MISSING_TYPE_DEPENDENCY", + "NEXT_HOP_ADDRESS_NOT_ASSIGNED", + "NEXT_HOP_CANNOT_IP_FORWARD", + "NEXT_HOP_INSTANCE_NOT_FOUND", + "NEXT_HOP_INSTANCE_NOT_ON_NETWORK", + "NEXT_HOP_NOT_RUNNING", + "NOT_CRITICAL_ERROR", + "NO_RESULTS_ON_PAGE", + "REQUIRED_TOS_AGREEMENT", + "RESOURCE_IN_USE_BY_OTHER_RESOURCE_WARNING", + "RESOURCE_NOT_DELETED", + "SCHEMA_VALIDATION_IGNORED", + "SINGLE_INSTANCE_PROPERTY_TEMPLATE", + "UNDECLARED_PROPERTIES", + "UNREACHABLE" + ], + "enumDescriptions": [ + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "" + ], + "type": "string" + }, + "data": { + "description": "[Output Only] Metadata about this warning in key: value format. For example:\n\"data\": [ { \"key\": \"scope\", \"value\": \"zones/us-east1-d\" }", + "items": { + "properties": { + "key": { + "description": "[Output Only] A key that provides more detail on the warning being returned. For example, for warnings where there are no results in a list request for a particular zone, this key might be scope and the key value might be the zone name. Other examples might be a key indicating a deprecated resource and a suggested replacement, or a warning about invalid network settings (for example, if an instance attempts to perform IP forwarding but is not enabled for IP forwarding).", + "type": "string" + }, + "value": { + "description": "[Output Only] A warning data value corresponding to the key.", + "type": "string" + } + }, + "type": "object" + }, + "type": "array" + }, + "message": { + "description": "[Output Only] A human-readable description of the warning code.", + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object" + }, "Operation": { "description": "An Operation resource, used to manage asynchronous API requests. (== resource_for v1.globalOperations ==) (== resource_for beta.globalOperations ==) (== resource_for v1.regionOperations ==) (== resource_for beta.regionOperations ==) (== resource_for v1.zoneOperations ==) (== resource_for beta.zoneOperations ==)", "id": "Operation", @@ -25421,7 +29974,7 @@ "id": "PathMatcher", "properties": { "defaultService": { - "description": "The full or partial URL to the BackendService resource. This will be used if none of the pathRules defined by this PathMatcher is matched by the URL's path portion. For example, the following are all valid URLs to a BackendService resource: \n- https://www.googleapis.com/compute/v1/projects/project/global/backendServices/backendService \n- compute/v1/projects/project/global/backendServices/backendService \n- global/backendServices/backendService", + "description": "The full or partial URL to the BackendService resource. This will be used if none of the pathRules or routeRules defined by this PathMatcher are matched. For example, the following are all valid URLs to a BackendService resource: \n- https://www.googleapis.com/compute/v1/projects/project/global/backendServices/backendService \n- compute/v1/projects/project/global/backendServices/backendService \n- global/backendServices/backendService \nUse defaultService instead of defaultRouteAction when simple routing to a backend service is desired and other advanced capabilities like traffic splitting and URL rewrites are not required.\nOnly one of defaultService, defaultRouteAction or defaultUrlRedirect must be set.\nAuthorization requires one or more of the following Google IAM permissions on the specified resource default_service: \n- compute.backendBuckets.use \n- compute.backendServices.use", "type": "string" }, "description": { @@ -25433,7 +29986,7 @@ "type": "string" }, "pathRules": { - "description": "The list of path rules.", + "description": "The list of path rules. Use this list instead of routeRules when routing based on simple path matching is all that's required. The order by which path rules are specified does not matter. Matches are always done on the longest-path-first basis.\nFor example: a pathRule with a path /a/b/c/* will match before /a/b/* irrespective of the order in which those paths appear in this list.\nOnly one of pathRules or routeRules must be set.", "items": { "$ref": "PathRule" }, @@ -25454,12 +30007,54 @@ "type": "array" }, "service": { - "description": "The URL of the BackendService resource if this rule is matched.", + "description": "The URL of the backend service resource if this rule is matched.\nUse service instead of routeAction when simple routing to a backend service is desired and other advanced capabilities like traffic splitting and rewrites are not required.\nOnly one of service, routeAction or urlRedirect should must be set.", "type": "string" } }, "type": "object" }, + "Policy": { + "description": "Defines an Identity and Access Management (IAM) policy. It is used to specify access control policies for Cloud Platform resources.\n\n\n\nA `Policy` consists of a list of `bindings`. A `binding` binds a list of `members` to a `role`, where the members can be user accounts, Google groups, Google domains, and service accounts. A `role` is a named list of permissions defined by IAM.\n\n**JSON Example**\n\n{ \"bindings\": [ { \"role\": \"roles/owner\", \"members\": [ \"user:mike@example.com\", \"group:admins@example.com\", \"domain:google.com\", \"serviceAccount:my-other-app@appspot.gserviceaccount.com\" ] }, { \"role\": \"roles/viewer\", \"members\": [\"user:sean@example.com\"] } ] }\n\n**YAML Example**\n\nbindings: - members: - user:mike@example.com - group:admins@example.com - domain:google.com - serviceAccount:my-other-app@appspot.gserviceaccount.com role: roles/owner - members: - user:sean@example.com role: roles/viewer\n\n\n\nFor a description of IAM and its features, see the [IAM developer's guide](https://cloud.google.com/iam/docs).", + "id": "Policy", + "properties": { + "auditConfigs": { + "description": "Specifies cloud audit logging configuration for this policy.", + "items": { + "$ref": "AuditConfig" + }, + "type": "array" + }, + "bindings": { + "description": "Associates a list of `members` to a `role`. `bindings` with no members will result in an error.", + "items": { + "$ref": "Binding" + }, + "type": "array" + }, + "etag": { + "description": "`etag` is used for optimistic concurrency control as a way to help prevent simultaneous updates of a policy from overwriting each other. It is strongly suggested that systems make use of the `etag` in the read-modify-write cycle to perform policy updates in order to avoid race conditions: An `etag` is returned in the response to `getIamPolicy`, and systems are expected to put that etag in the request to `setIamPolicy` to ensure that their change will be applied to the same version of the policy.\n\nIf no `etag` is provided in the call to `setIamPolicy`, then the existing policy is overwritten blindly.", + "format": "byte", + "type": "string" + }, + "iamOwned": { + "description": "", + "type": "boolean" + }, + "rules": { + "description": "If more than one rule is specified, the rules are applied in the following manner: - All matching LOG rules are always applied. - If any DENY/DENY_WITH_LOG rule matches, permission is denied. Logging will be applied if one or more matching rule requires logging. - Otherwise, if any ALLOW/ALLOW_WITH_LOG rule matches, permission is granted. Logging will be applied if one or more matching rule requires logging. - Otherwise, if no rule applies, permission is denied.", + "items": { + "$ref": "Rule" + }, + "type": "array" + }, + "version": { + "description": "Deprecated.", + "format": "int32", + "type": "integer" + } + }, + "type": "object" + }, "Project": { "description": "A Project resource. For an overview of projects, see Cloud Platform Resource Hierarchy. (== resource_for v1.projects ==) (== resource_for beta.projects ==)", "id": "Project", @@ -25472,6 +30067,18 @@ "description": "[Output Only] Creation timestamp in RFC3339 text format.", "type": "string" }, + "defaultNetworkTier": { + "description": "This signifies the default network tier used for configuring resources of the project and can only take the following values: PREMIUM, STANDARD. Initially the default network tier is PREMIUM.", + "enum": [ + "PREMIUM", + "STANDARD" + ], + "enumDescriptions": [ + "", + "" + ], + "type": "string" + }, "defaultServiceAccount": { "description": "[Output Only] Default service account used by VMs running in this project.", "type": "string" @@ -25583,6 +30190,24 @@ }, "type": "object" }, + "ProjectsSetDefaultNetworkTierRequest": { + "id": "ProjectsSetDefaultNetworkTierRequest", + "properties": { + "networkTier": { + "description": "Default network tier to be set.", + "enum": [ + "PREMIUM", + "STANDARD" + ], + "enumDescriptions": [ + "", + "" + ], + "type": "string" + } + }, + "type": "object" + }, "Quota": { "description": "A quotas entry.", "id": "Quota", @@ -25604,6 +30229,8 @@ "DISKS_TOTAL_GB", "FIREWALLS", "FORWARDING_RULES", + "GLOBAL_INTERNAL_ADDRESSES", + "GPUS_ALL_REGIONS", "HEALTH_CHECKS", "IMAGES", "INSTANCES", @@ -25615,18 +30242,30 @@ "INTERCONNECT_ATTACHMENTS_TOTAL_MBPS", "INTERNAL_ADDRESSES", "IN_USE_ADDRESSES", + "IN_USE_BACKUP_SCHEDULES", "LOCAL_SSD_TOTAL_GB", "NETWORKS", "NVIDIA_K80_GPUS", "NVIDIA_P100_GPUS", + "NVIDIA_P100_VWS_GPUS", + "NVIDIA_P4_GPUS", + "NVIDIA_P4_VWS_GPUS", + "NVIDIA_T4_GPUS", + "NVIDIA_T4_VWS_GPUS", "NVIDIA_V100_GPUS", "PREEMPTIBLE_CPUS", "PREEMPTIBLE_LOCAL_SSD_GB", "PREEMPTIBLE_NVIDIA_K80_GPUS", "PREEMPTIBLE_NVIDIA_P100_GPUS", + "PREEMPTIBLE_NVIDIA_P100_VWS_GPUS", + "PREEMPTIBLE_NVIDIA_P4_GPUS", + "PREEMPTIBLE_NVIDIA_P4_VWS_GPUS", + "PREEMPTIBLE_NVIDIA_T4_GPUS", + "PREEMPTIBLE_NVIDIA_T4_VWS_GPUS", "PREEMPTIBLE_NVIDIA_V100_GPUS", "REGIONAL_AUTOSCALERS", "REGIONAL_INSTANCE_GROUP_MANAGERS", + "RESOURCE_POLICIES", "ROUTERS", "ROUTES", "SECURITY_POLICIES", @@ -25644,6 +30283,7 @@ "TARGET_TCP_PROXIES", "TARGET_VPN_GATEWAYS", "URL_MAPS", + "VPN_GATEWAYS", "VPN_TUNNELS" ], "enumDescriptions": [ @@ -25696,6 +30336,21 @@ "", "", "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", "" ], "type": "string" @@ -26615,6 +31270,28 @@ }, "type": "object" }, + "RegionSetPolicyRequest": { + "id": "RegionSetPolicyRequest", + "properties": { + "bindings": { + "description": "Flatten Policy to create a backwacd compatible wire-format. Deprecated. Use 'policy' to specify bindings.", + "items": { + "$ref": "Binding" + }, + "type": "array" + }, + "etag": { + "description": "Flatten Policy to create a backward compatible wire-format. Deprecated. Use 'policy' to specify the etag.", + "format": "byte", + "type": "string" + }, + "policy": { + "$ref": "Policy", + "description": "REQUIRED: The complete policy to be applied to the 'resource'. The size of the policy is limited to a few 10s of KB. An empty policy is in general a valid policy but certain services (like Projects) might reject them." + } + }, + "type": "object" + }, "ResourceCommitment": { "description": "Commitment for a particular resource (a Commitment is composed of one or more of these).", "id": "ResourceCommitment", @@ -26645,7 +31322,7 @@ "id": "ResourceGroupReference", "properties": { "group": { - "description": "A URI referencing one of the instance groups listed in the backend service.", + "description": "A URI referencing one of the instance groups or network endpoint groups listed in the backend service.", "type": "string" } }, @@ -27000,6 +31677,13 @@ "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", "type": "string" }, + "nats": { + "description": "A list of Nat services created in this router.", + "items": { + "$ref": "RouterNat" + }, + "type": "array" + }, "network": { "annotations": { "required": [ @@ -27240,7 +31924,7 @@ "type": "string" }, "managementType": { - "description": "[Output Only] Type of how the resource/configuration of the BGP peer is managed. MANAGED_BY_USER is the default value; MANAGED_BY_ATTACHMENT represents an BGP peer that is automatically created for PARTNER interconnectAttachment, Google will automatically create/delete this type of BGP peer when the PARTNER interconnectAttachment is created/deleted.", + "description": "[Output Only] The resource that configures and manages this BGP peer. MANAGED_BY_USER is the default value and can be managed by you or other users; MANAGED_BY_ATTACHMENT is a BGP peer that is configured and managed by Cloud Interconnect, specifically by an InterconnectAttachment of type PARTNER. Google will automatically create, update, and delete this type of BGP peer when the PARTNER InterconnectAttachment is created, updated, or deleted.", "enum": [ "MANAGED_BY_ATTACHMENT", "MANAGED_BY_USER" @@ -27284,7 +31968,7 @@ "type": "string" }, "managementType": { - "description": "[Output Only] Type of how the resource/configuration of the interface is managed. MANAGED_BY_USER is the default value; MANAGED_BY_ATTACHMENT represents an interface that is automatically created for PARTNER type interconnectAttachment, Google will automatically create/update/delete this type of interface when the PARTNER interconnectAttachment is created/provisioned/deleted.", + "description": "[Output Only] The resource that configures and manages this interface. MANAGED_BY_USER is the default value and can be managed by you or other users; MANAGED_BY_ATTACHMENT is an interface that is configured and managed by Cloud Interconnect, specifically by an InterconnectAttachment of type PARTNER. Google will automatically create, update, and delete this type of interface when the PARTNER InterconnectAttachment is created, updated, or deleted.", "enum": [ "MANAGED_BY_ATTACHMENT", "MANAGED_BY_USER" @@ -27415,6 +32099,118 @@ }, "type": "object" }, + "RouterNat": { + "description": "Represents a Nat resource. It enables the VMs within the specified subnetworks to access Internet without external IP addresses. It specifies a list of subnetworks (and the ranges within) that want to use NAT. Customers can also provide the external IPs that would be used for NAT. GCP would auto-allocate ephemeral IPs if no external IPs are provided.", + "id": "RouterNat", + "properties": { + "icmpIdleTimeoutSec": { + "description": "Timeout (in seconds) for ICMP connections. Defaults to 30s if not set.", + "format": "int32", + "type": "integer" + }, + "minPortsPerVm": { + "description": "Minimum number of ports allocated to a VM from this NAT config. If not set, a default number of ports is allocated to a VM. This gets rounded up to the nearest power of 2. Eg. if the value of this field is 50, at least 64 ports will be allocated to a VM.", + "format": "int32", + "type": "integer" + }, + "name": { + "description": "Unique name of this Nat service. The name must be 1-63 characters long and comply with RFC1035.", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "type": "string" + }, + "natIpAllocateOption": { + "description": "Specify the NatIpAllocateOption. If it is AUTO_ONLY, then nat_ip should be empty.", + "enum": [ + "AUTO_ONLY", + "MANUAL_ONLY" + ], + "enumDescriptions": [ + "", + "" + ], + "type": "string" + }, + "natIps": { + "description": "A list of URLs of the IP resources used for this Nat service. These IPs must be valid static external IP addresses assigned to the project. max_length is subject to change post alpha.", + "items": { + "type": "string" + }, + "type": "array" + }, + "sourceSubnetworkIpRangesToNat": { + "description": "Specify the Nat option. If this field contains ALL_SUBNETWORKS_ALL_IP_RANGES or ALL_SUBNETWORKS_ALL_PRIMARY_IP_RANGES, then there should not be any other Router.Nat section in any Router for this network in this region.", + "enum": [ + "ALL_SUBNETWORKS_ALL_IP_RANGES", + "ALL_SUBNETWORKS_ALL_PRIMARY_IP_RANGES", + "LIST_OF_SUBNETWORKS" + ], + "enumDescriptions": [ + "", + "", + "" + ], + "type": "string" + }, + "subnetworks": { + "description": "A list of Subnetwork resources whose traffic should be translated by NAT Gateway. It is used only when LIST_OF_SUBNETWORKS is selected for the SubnetworkIpRangeToNatOption above.", + "items": { + "$ref": "RouterNatSubnetworkToNat" + }, + "type": "array" + }, + "tcpEstablishedIdleTimeoutSec": { + "description": "Timeout (in seconds) for TCP established connections. Defaults to 1200s if not set.", + "format": "int32", + "type": "integer" + }, + "tcpTransitoryIdleTimeoutSec": { + "description": "Timeout (in seconds) for TCP transitory connections. Defaults to 30s if not set.", + "format": "int32", + "type": "integer" + }, + "udpIdleTimeoutSec": { + "description": "Timeout (in seconds) for UDP connections. Defaults to 30s if not set.", + "format": "int32", + "type": "integer" + } + }, + "type": "object" + }, + "RouterNatSubnetworkToNat": { + "description": "Defines the IP ranges that want to use NAT for a subnetwork.", + "id": "RouterNatSubnetworkToNat", + "properties": { + "name": { + "description": "URL for the subnetwork resource to use NAT.", + "type": "string" + }, + "secondaryIpRangeNames": { + "description": "A list of the secondary ranges of the Subnetwork that are allowed to use NAT. This can be populated only if \"LIST_OF_SECONDARY_IP_RANGES\" is one of the values in source_ip_ranges_to_nat.", + "items": { + "type": "string" + }, + "type": "array" + }, + "sourceIpRangesToNat": { + "description": "Specify the options for NAT ranges in the Subnetwork. All usages of single value are valid except NAT_IP_RANGE_OPTION_UNSPECIFIED. The only valid option with multiple values is: [\"PRIMARY_IP_RANGE\", \"LIST_OF_SECONDARY_IP_RANGES\"] Default: [ALL_IP_RANGES]", + "items": { + "enum": [ + "ALL_IP_RANGES", + "LIST_OF_SECONDARY_IP_RANGES", + "PRIMARY_IP_RANGE" + ], + "enumDescriptions": [ + "", + "", + "" + ], + "type": "string" + }, + "type": "array" + } + }, + "type": "object" + }, "RouterStatus": { "id": "RouterStatus", "properties": { @@ -27438,6 +32234,12 @@ }, "type": "array" }, + "natStatus": { + "items": { + "$ref": "RouterStatusNatStatus" + }, + "type": "array" + }, "network": { "description": "URI of the network to which this router belongs.", "type": "string" @@ -27505,6 +32307,48 @@ }, "type": "object" }, + "RouterStatusNatStatus": { + "description": "Status of a NAT contained in this router.", + "id": "RouterStatusNatStatus", + "properties": { + "autoAllocatedNatIps": { + "description": "A list of IPs auto-allocated for NAT. Example: [\"1.1.1.1\", \"129.2.16.89\"]", + "items": { + "type": "string" + }, + "type": "array" + }, + "minExtraNatIpsNeeded": { + "description": "The number of extra IPs to allocate. This will be greater than 0 only if user-specified IPs are NOT enough to allow all configured VMs to use NAT. This value is meaningful only when auto-allocation of NAT IPs is *not* used.", + "format": "int32", + "type": "integer" + }, + "name": { + "description": "Unique name of this NAT.", + "type": "string" + }, + "numVmEndpointsWithNatMappings": { + "description": "Number of VM endpoints (i.e., Nics) that can use NAT.", + "format": "int32", + "type": "integer" + }, + "userAllocatedNatIpResources": { + "description": "A list of fully qualified URLs of reserved IP address resources.", + "items": { + "type": "string" + }, + "type": "array" + }, + "userAllocatedNatIps": { + "description": "A list of IPs user-allocated for NAT. They will be raw IP strings like \"179.12.26.133\".", + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object" + }, "RouterStatusResponse": { "id": "RouterStatusResponse", "properties": { @@ -27623,6 +32467,72 @@ }, "type": "object" }, + "Rule": { + "description": "A rule to be applied in a Policy.", + "id": "Rule", + "properties": { + "action": { + "description": "Required", + "enum": [ + "ALLOW", + "ALLOW_WITH_LOG", + "DENY", + "DENY_WITH_LOG", + "LOG", + "NO_ACTION" + ], + "enumDescriptions": [ + "", + "", + "", + "", + "", + "" + ], + "type": "string" + }, + "conditions": { + "description": "Additional restrictions that must be met. All conditions must pass for the rule to match.", + "items": { + "$ref": "Condition" + }, + "type": "array" + }, + "description": { + "description": "Human-readable description of the rule.", + "type": "string" + }, + "ins": { + "description": "If one or more 'in' clauses are specified, the rule matches if the PRINCIPAL/AUTHORITY_SELECTOR is in at least one of these entries.", + "items": { + "type": "string" + }, + "type": "array" + }, + "logConfigs": { + "description": "The config returned to callers of tech.iam.IAM.CheckPolicy for any entries that match the LOG action.", + "items": { + "$ref": "LogConfig" + }, + "type": "array" + }, + "notIns": { + "description": "If one or more 'not_in' clauses are specified, the rule matches if the PRINCIPAL/AUTHORITY_SELECTOR is in none of the entries.", + "items": { + "type": "string" + }, + "type": "array" + }, + "permissions": { + "description": "A permission is a string of form '..' (e.g., 'storage.buckets.list'). A value of '*' matches all permissions, and a verb part of '*' (e.g., 'storage.buckets.*') matches all verbs.", + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object" + }, "SSLHealthCheck": { "id": "SSLHealthCheck", "properties": { @@ -27666,6 +32576,13 @@ "description": "Specifies whether the instance should be automatically restarted if it is terminated by Compute Engine (not terminated by a user). You can only set the automatic restart option for standard instances. Preemptible instances cannot be automatically restarted.\n\nBy default, this is set to true so an instance is automatically restarted if it is terminated by Compute Engine.", "type": "boolean" }, + "nodeAffinities": { + "description": "A set of node affinity and anti-affinity.", + "items": { + "$ref": "SchedulingNodeAffinity" + }, + "type": "array" + }, "onHostMaintenance": { "description": "Defines the maintenance behavior for this instance. For standard instances, the default behavior is MIGRATE. For preemptible instances, the default and only possible behavior is TERMINATE. For more information, see Setting Instance Scheduling Options.", "enum": [ @@ -27685,6 +32602,267 @@ }, "type": "object" }, + "SchedulingNodeAffinity": { + "description": "Node Affinity: the configuration of desired nodes onto which this Instance could be scheduled.", + "id": "SchedulingNodeAffinity", + "properties": { + "key": { + "description": "Corresponds to the label key of Node resource.", + "type": "string" + }, + "operator": { + "description": "Defines the operation of node selection.", + "enum": [ + "IN", + "NOT_IN", + "OPERATOR_UNSPECIFIED" + ], + "enumDescriptions": [ + "", + "", + "" + ], + "type": "string" + }, + "values": { + "description": "Corresponds to the label values of Node resource.", + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object" + }, + "SecurityPolicy": { + "description": "A security policy is comprised of one or more rules. It can also be associated with one or more 'targets'. (== resource_for v1.securityPolicies ==) (== resource_for beta.securityPolicies ==)", + "id": "SecurityPolicy", + "properties": { + "creationTimestamp": { + "description": "[Output Only] Creation timestamp in RFC3339 text format.", + "type": "string" + }, + "description": { + "description": "An optional description of this resource. Provide this property when you create the resource.", + "type": "string" + }, + "fingerprint": { + "description": "Specifies a fingerprint for this resource, which is essentially a hash of the metadata's contents and used for optimistic locking. The fingerprint is initially generated by Compute Engine and changes after every request to modify or update metadata. You must always provide an up-to-date fingerprint hash in order to update or change metadata, otherwise the request will fail with error 412 conditionNotMet.\n\nTo see the latest fingerprint, make get() request to the security policy.", + "format": "byte", + "type": "string" + }, + "id": { + "description": "[Output Only] The unique identifier for the resource. This identifier is defined by the server.", + "format": "uint64", + "type": "string" + }, + "kind": { + "default": "compute#securityPolicy", + "description": "[Output only] Type of the resource. Always compute#securityPolicyfor security policies", + "type": "string" + }, + "name": { + "description": "Name of the resource. Provided by the client when the resource is created. The name must be 1-63 characters long, and comply with RFC1035. Specifically, the name must be 1-63 characters long and match the regular expression `[a-z]([-a-z0-9]*[a-z0-9])?` which means the first character must be a lowercase letter, and all following characters must be a dash, lowercase letter, or digit, except the last character, which cannot be a dash.", + "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + "type": "string" + }, + "rules": { + "description": "A list of rules that belong to this policy. There must always be a default rule (rule with priority 2147483647 and match \"*\"). If no rules are provided when creating a security policy, a default rule with action \"allow\" will be added.", + "items": { + "$ref": "SecurityPolicyRule" + }, + "type": "array" + }, + "selfLink": { + "description": "[Output Only] Server-defined URL for the resource.", + "type": "string" + } + }, + "type": "object" + }, + "SecurityPolicyList": { + "id": "SecurityPolicyList", + "properties": { + "id": { + "description": "[Output Only] Unique identifier for the resource; defined by the server.", + "type": "string" + }, + "items": { + "description": "A list of SecurityPolicy resources.", + "items": { + "$ref": "SecurityPolicy" + }, + "type": "array" + }, + "kind": { + "default": "compute#securityPolicyList", + "description": "[Output Only] Type of resource. Always compute#securityPolicyList for listsof securityPolicies", + "type": "string" + }, + "nextPageToken": { + "description": "[Output Only] This token allows you to get the next page of results for list requests. If the number of results is larger than maxResults, use the nextPageToken as a value for the query parameter pageToken in the next list request. Subsequent list requests will have their own nextPageToken to continue paging through the results.", + "type": "string" + }, + "warning": { + "description": "[Output Only] Informational warning message.", + "properties": { + "code": { + "description": "[Output Only] A warning code, if applicable. For example, Compute Engine returns NO_RESULTS_ON_PAGE if there are no results in the response.", + "enum": [ + "CLEANUP_FAILED", + "DEPRECATED_RESOURCE_USED", + "DEPRECATED_TYPE_USED", + "DISK_SIZE_LARGER_THAN_IMAGE_SIZE", + "EXPERIMENTAL_TYPE_USED", + "EXTERNAL_API_WARNING", + "FIELD_VALUE_OVERRIDEN", + "INJECTED_KERNELS_DEPRECATED", + "MISSING_TYPE_DEPENDENCY", + "NEXT_HOP_ADDRESS_NOT_ASSIGNED", + "NEXT_HOP_CANNOT_IP_FORWARD", + "NEXT_HOP_INSTANCE_NOT_FOUND", + "NEXT_HOP_INSTANCE_NOT_ON_NETWORK", + "NEXT_HOP_NOT_RUNNING", + "NOT_CRITICAL_ERROR", + "NO_RESULTS_ON_PAGE", + "REQUIRED_TOS_AGREEMENT", + "RESOURCE_IN_USE_BY_OTHER_RESOURCE_WARNING", + "RESOURCE_NOT_DELETED", + "SCHEMA_VALIDATION_IGNORED", + "SINGLE_INSTANCE_PROPERTY_TEMPLATE", + "UNDECLARED_PROPERTIES", + "UNREACHABLE" + ], + "enumDescriptions": [ + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "" + ], + "type": "string" + }, + "data": { + "description": "[Output Only] Metadata about this warning in key: value format. For example:\n\"data\": [ { \"key\": \"scope\", \"value\": \"zones/us-east1-d\" }", + "items": { + "properties": { + "key": { + "description": "[Output Only] A key that provides more detail on the warning being returned. For example, for warnings where there are no results in a list request for a particular zone, this key might be scope and the key value might be the zone name. Other examples might be a key indicating a deprecated resource and a suggested replacement, or a warning about invalid network settings (for example, if an instance attempts to perform IP forwarding but is not enabled for IP forwarding).", + "type": "string" + }, + "value": { + "description": "[Output Only] A warning data value corresponding to the key.", + "type": "string" + } + }, + "type": "object" + }, + "type": "array" + }, + "message": { + "description": "[Output Only] A human-readable description of the warning code.", + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object" + }, + "SecurityPolicyReference": { + "id": "SecurityPolicyReference", + "properties": { + "securityPolicy": { + "type": "string" + } + }, + "type": "object" + }, + "SecurityPolicyRule": { + "description": "Represents a rule that describes one or more match conditions along with the action to be taken when traffic matches this condition (allow or deny).", + "id": "SecurityPolicyRule", + "properties": { + "action": { + "description": "The Action to preform when the client connection triggers the rule. Can currently be either \"allow\" or \"deny()\" where valid values for status are 403, 404, and 502.", + "type": "string" + }, + "description": { + "description": "An optional description of this resource. Provide this property when you create the resource.", + "type": "string" + }, + "kind": { + "default": "compute#securityPolicyRule", + "description": "[Output only] Type of the resource. Always compute#securityPolicyRule for security policy rules", + "type": "string" + }, + "match": { + "$ref": "SecurityPolicyRuleMatcher", + "description": "A match condition that incoming traffic is evaluated against. If it evaluates to true, the corresponding ?action? is enforced." + }, + "preview": { + "description": "If set to true, the specified action is not enforced.", + "type": "boolean" + }, + "priority": { + "description": "An integer indicating the priority of a rule in the list. The priority must be a positive value between 0 and 2147483647. Rules are evaluated from highest to lowest priority where 0 is the highest priority and 2147483647 is the lowest prority.", + "format": "int32", + "type": "integer" + } + }, + "type": "object" + }, + "SecurityPolicyRuleMatcher": { + "description": "Represents a match condition that incoming traffic is evaluated against. Exactly one field must be specified.", + "id": "SecurityPolicyRuleMatcher", + "properties": { + "config": { + "$ref": "SecurityPolicyRuleMatcherConfig", + "description": "The configuration options available when specifying versioned_expr. This field must be specified if versioned_expr is specified and cannot be specified if versioned_expr is not specified." + }, + "versionedExpr": { + "description": "Preconfigured versioned expression. If this field is specified, config must also be specified. Available preconfigured expressions along with their requirements are: SRC_IPS_V1 - must specify the corresponding src_ip_range field in config.", + "enum": [ + "SRC_IPS_V1" + ], + "enumDescriptions": [ + "" + ], + "type": "string" + } + }, + "type": "object" + }, + "SecurityPolicyRuleMatcherConfig": { + "id": "SecurityPolicyRuleMatcherConfig", + "properties": { + "srcIpRanges": { + "description": "CIDR IP address range.", + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object" + }, "SerialPortOutput": { "description": "An instance's serial console output.", "id": "SerialPortOutput", @@ -27777,7 +32955,7 @@ "type": "string" }, "labelFingerprint": { - "description": "A fingerprint for the labels being applied to this snapshot, which is essentially a hash of the labels set used for optimistic locking. The fingerprint is initially generated by Compute Engine and changes after every request to modify or update labels. You must always provide an up-to-date fingerprint hash in order to update or change labels.\n\nTo see the latest fingerprint, make a get() request to retrieve a snapshot.", + "description": "A fingerprint for the labels being applied to this snapshot, which is essentially a hash of the labels set used for optimistic locking. The fingerprint is initially generated by Compute Engine and changes after every request to modify or update labels. You must always provide an up-to-date fingerprint hash in order to update or change labels, otherwise the request will fail with error 412 conditionNotMet.\n\nTo see the latest fingerprint, make a get() request to retrieve a snapshot.", "format": "byte", "type": "string" }, @@ -28296,7 +33474,7 @@ "type": "array" }, "fingerprint": { - "description": "Fingerprint of this resource. A hash of the contents stored in this object. This field is used in optimistic locking. This field will be ignored when inserting a SslPolicy. An up-to-date fingerprint must be provided in order to update the SslPolicy.", + "description": "Fingerprint of this resource. A hash of the contents stored in this object. This field is used in optimistic locking. This field will be ignored when inserting a SslPolicy. An up-to-date fingerprint must be provided in order to update the SslPolicy, otherwise the request will fail with error 412 conditionNotMet.\n\nTo see the latest fingerprint, make a get() request to retrieve an SslPolicy.", "format": "byte", "type": "string" }, @@ -28459,11 +33637,11 @@ "type": "string" }, "enableFlowLogs": { - "description": "Whether to enable flow logging for this subnetwork.", + "description": "Whether to enable flow logging for this subnetwork. If this field is not explicitly set, it will not appear in get listings. If not set the default behavior is to disable flow logging.", "type": "boolean" }, "fingerprint": { - "description": "Fingerprint of this resource. A hash of the contents stored in this object. This field is used in optimistic locking. This field will be ignored when inserting a Subnetwork. An up-to-date fingerprint must be provided in order to update the Subnetwork.", + "description": "Fingerprint of this resource. A hash of the contents stored in this object. This field is used in optimistic locking. This field will be ignored when inserting a Subnetwork. An up-to-date fingerprint must be provided in order to update the Subnetwork, otherwise the request will fail with error 412 conditionNotMet.\n\nTo see the latest fingerprint, make a get() request to retrieve a Subnetwork.", "format": "byte", "type": "string" }, @@ -28503,7 +33681,7 @@ "type": "string" }, "secondaryIpRanges": { - "description": "An array of configurations for secondary IP ranges for VM instances contained in this subnetwork. The primary IP of such VM must belong to the primary ipCidrRange of the subnetwork. The alias IPs may belong to either primary or secondary ranges.", + "description": "An array of configurations for secondary IP ranges for VM instances contained in this subnetwork. The primary IP of such VM must belong to the primary ipCidrRange of the subnetwork. The alias IPs may belong to either primary or secondary ranges. This field can be updated with a patch request.", "items": { "$ref": "SubnetworkSecondaryRange" }, @@ -29151,7 +34329,7 @@ "type": "string" }, "sslCertificates": { - "description": "URLs to SslCertificate resources that are used to authenticate connections between users and the load balancer. Currently, exactly one SSL certificate must be specified.", + "description": "URLs to SslCertificate resources that are used to authenticate connections between users and the load balancer. At least one SSL certificate must be specified. Currently, you may specify up to 15 SSL certificates.", "items": { "type": "string" }, @@ -29709,7 +34887,7 @@ "type": "string" }, "sessionAffinity": { - "description": "Sesssion affinity option, must be one of the following values:\nNONE: Connections from the same client IP may go to any instance in the pool.\nCLIENT_IP: Connections from the same client IP will go to the same instance in the pool while that instance remains healthy.\nCLIENT_IP_PROTO: Connections from the same client IP with the same IP protocol will go to the same instance in the pool while that instance remains healthy.", + "description": "Session affinity option, must be one of the following values:\nNONE: Connections from the same client IP may go to any instance in the pool.\nCLIENT_IP: Connections from the same client IP will go to the same instance in the pool while that instance remains healthy.\nCLIENT_IP_PROTO: Connections from the same client IP with the same IP protocol will go to the same instance in the pool while that instance remains healthy.", "enum": [ "CLIENT_IP", "CLIENT_IP_PORT_PROTO", @@ -30214,7 +35392,7 @@ "type": "string" }, "sslCertificates": { - "description": "URLs to SslCertificate resources that are used to authenticate connections to Backends. Currently exactly one SSL certificate must be specified.", + "description": "URLs to SslCertificate resources that are used to authenticate connections to Backends. At least one SSL certificate must be specified. Currently, you may specify up to 15 SSL certificates.", "items": { "type": "string" }, @@ -30982,7 +36160,7 @@ "type": "string" }, "defaultService": { - "description": "The URL of the BackendService resource if none of the hostRules match.", + "description": "The URL of the backendService resource if none of the hostRules match.\nUse defaultService instead of defaultRouteAction when simple routing to a backendService is desired and other advanced capabilities like traffic splitting and rewrites are not required.\nOnly one of defaultService, defaultRouteAction or defaultUrlRedirect should must be set.", "type": "string" }, "description": { @@ -30990,7 +36168,7 @@ "type": "string" }, "fingerprint": { - "description": "Fingerprint of this resource. A hash of the contents stored in this object. This field is used in optimistic locking. This field will be ignored when inserting a UrlMap. An up-to-date fingerprint must be provided in order to update the UrlMap.", + "description": "Fingerprint of this resource. A hash of the contents stored in this object. This field is used in optimistic locking. This field will be ignored when inserting a UrlMap. An up-to-date fingerprint must be provided in order to update the UrlMap, otherwise the request will fail with error 412 conditionNotMet.\n\nTo see the latest fingerprint, make a get() request to retrieve a UrlMap.", "format": "byte", "type": "string" }, @@ -31227,6 +36405,158 @@ }, "type": "object" }, + "UsableSubnetwork": { + "description": "Subnetwork which the current user has compute.subnetworks.use permission on.", + "id": "UsableSubnetwork", + "properties": { + "ipCidrRange": { + "description": "The range of internal addresses that are owned by this subnetwork.", + "type": "string" + }, + "network": { + "description": "Network URL.", + "type": "string" + }, + "secondaryIpRanges": { + "description": "Secondary IP ranges.", + "items": { + "$ref": "UsableSubnetworkSecondaryRange" + }, + "type": "array" + }, + "subnetwork": { + "description": "Subnetwork URL.", + "type": "string" + } + }, + "type": "object" + }, + "UsableSubnetworkSecondaryRange": { + "description": "Secondary IP range of a usable subnetwork.", + "id": "UsableSubnetworkSecondaryRange", + "properties": { + "ipCidrRange": { + "description": "The range of IP addresses belonging to this subnetwork secondary range.", + "type": "string" + }, + "rangeName": { + "description": "The name associated with this subnetwork secondary range, used when adding an alias IP range to a VM instance. The name must be 1-63 characters long, and comply with RFC1035. The name must be unique within the subnetwork.", + "type": "string" + } + }, + "type": "object" + }, + "UsableSubnetworksAggregatedList": { + "id": "UsableSubnetworksAggregatedList", + "properties": { + "id": { + "description": "[Output Only] The unique identifier for the resource. This identifier is defined by the server.", + "type": "string" + }, + "items": { + "description": "[Output] A list of usable subnetwork URLs.", + "items": { + "$ref": "UsableSubnetwork" + }, + "type": "array" + }, + "kind": { + "default": "compute#usableSubnetworksAggregatedList", + "description": "[Output Only] Type of resource. Always compute#usableSubnetworksAggregatedList for aggregated lists of usable subnetworks.", + "type": "string" + }, + "nextPageToken": { + "description": "[Output Only] This token allows you to get the next page of results for list requests. If the number of results is larger than maxResults, use the nextPageToken as a value for the query parameter pageToken in the next list request. Subsequent list requests will have their own nextPageToken to continue paging through the results.", + "type": "string" + }, + "selfLink": { + "description": "[Output Only] Server-defined URL for this resource.", + "type": "string" + }, + "warning": { + "description": "[Output Only] Informational warning message.", + "properties": { + "code": { + "description": "[Output Only] A warning code, if applicable. For example, Compute Engine returns NO_RESULTS_ON_PAGE if there are no results in the response.", + "enum": [ + "CLEANUP_FAILED", + "DEPRECATED_RESOURCE_USED", + "DEPRECATED_TYPE_USED", + "DISK_SIZE_LARGER_THAN_IMAGE_SIZE", + "EXPERIMENTAL_TYPE_USED", + "EXTERNAL_API_WARNING", + "FIELD_VALUE_OVERRIDEN", + "INJECTED_KERNELS_DEPRECATED", + "MISSING_TYPE_DEPENDENCY", + "NEXT_HOP_ADDRESS_NOT_ASSIGNED", + "NEXT_HOP_CANNOT_IP_FORWARD", + "NEXT_HOP_INSTANCE_NOT_FOUND", + "NEXT_HOP_INSTANCE_NOT_ON_NETWORK", + "NEXT_HOP_NOT_RUNNING", + "NOT_CRITICAL_ERROR", + "NO_RESULTS_ON_PAGE", + "REQUIRED_TOS_AGREEMENT", + "RESOURCE_IN_USE_BY_OTHER_RESOURCE_WARNING", + "RESOURCE_NOT_DELETED", + "SCHEMA_VALIDATION_IGNORED", + "SINGLE_INSTANCE_PROPERTY_TEMPLATE", + "UNDECLARED_PROPERTIES", + "UNREACHABLE" + ], + "enumDescriptions": [ + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "" + ], + "type": "string" + }, + "data": { + "description": "[Output Only] Metadata about this warning in key: value format. For example:\n\"data\": [ { \"key\": \"scope\", \"value\": \"zones/us-east1-d\" }", + "items": { + "properties": { + "key": { + "description": "[Output Only] A key that provides more detail on the warning being returned. For example, for warnings where there are no results in a list request for a particular zone, this key might be scope and the key value might be the zone name. Other examples might be a key indicating a deprecated resource and a suggested replacement, or a warning about invalid network settings (for example, if an instance attempts to perform IP forwarding but is not enabled for IP forwarding).", + "type": "string" + }, + "value": { + "description": "[Output Only] A warning data value corresponding to the key.", + "type": "string" + } + }, + "type": "object" + }, + "type": "array" + }, + "message": { + "description": "[Output Only] A human-readable description of the warning code.", + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object" + }, "UsageExportLocation": { "description": "The location in Cloud Storage and naming method of the daily usage report. Contains bucket_name and report_name prefix.", "id": "UsageExportLocation", @@ -31242,6 +36572,162 @@ }, "type": "object" }, + "VmEndpointNatMappings": { + "description": "Contain information of Nat mapping for a VM endpoint (i.e., NIC).", + "id": "VmEndpointNatMappings", + "properties": { + "instanceName": { + "description": "Name of the VM instance which the endpoint belongs to", + "type": "string" + }, + "interfaceNatMappings": { + "items": { + "$ref": "VmEndpointNatMappingsInterfaceNatMappings" + }, + "type": "array" + } + }, + "type": "object" + }, + "VmEndpointNatMappingsInterfaceNatMappings": { + "description": "Contain information of Nat mapping for an interface of this endpoint.", + "id": "VmEndpointNatMappingsInterfaceNatMappings", + "properties": { + "natIpPortRanges": { + "description": "A list of all IP:port-range mappings assigned to this interface. These ranges are inclusive, that is, both the first and the last ports can be used for NAT. Example: [\"2.2.2.2:12345-12355\", \"1.1.1.1:2234-2234\"].", + "items": { + "type": "string" + }, + "type": "array" + }, + "numTotalNatPorts": { + "description": "Total number of ports across all NAT IPs allocated to this interface. It equals to the aggregated port number in the field nat_ip_port_ranges.", + "format": "int32", + "type": "integer" + }, + "sourceAliasIpRange": { + "description": "Alias IP range for this interface endpoint. It will be a private (RFC 1918) IP range. Examples: \"10.33.4.55/32\", or \"192.168.5.0/24\".", + "type": "string" + }, + "sourceVirtualIp": { + "description": "Primary IP of the VM for this NIC.", + "type": "string" + } + }, + "type": "object" + }, + "VmEndpointNatMappingsList": { + "description": "Contains a list of VmEndpointNatMappings.", + "id": "VmEndpointNatMappingsList", + "properties": { + "id": { + "description": "[Output Only] The unique identifier for the resource. This identifier is defined by the server.", + "type": "string" + }, + "kind": { + "default": "compute#vmEndpointNatMappingsList", + "description": "[Output Only] Type of resource. Always compute#vmEndpointNatMappingsList for lists of Nat mappings of VM endpoints.", + "type": "string" + }, + "nextPageToken": { + "description": "[Output Only] This token allows you to get the next page of results for list requests. If the number of results is larger than maxResults, use the nextPageToken as a value for the query parameter pageToken in the next list request. Subsequent list requests will have their own nextPageToken to continue paging through the results.", + "type": "string" + }, + "result": { + "description": "[Output Only] A list of Nat mapping information of VM endpoints.", + "items": { + "$ref": "VmEndpointNatMappings" + }, + "type": "array" + }, + "selfLink": { + "description": "[Output Only] Server-defined URL for this resource.", + "type": "string" + }, + "warning": { + "description": "[Output Only] Informational warning message.", + "properties": { + "code": { + "description": "[Output Only] A warning code, if applicable. For example, Compute Engine returns NO_RESULTS_ON_PAGE if there are no results in the response.", + "enum": [ + "CLEANUP_FAILED", + "DEPRECATED_RESOURCE_USED", + "DEPRECATED_TYPE_USED", + "DISK_SIZE_LARGER_THAN_IMAGE_SIZE", + "EXPERIMENTAL_TYPE_USED", + "EXTERNAL_API_WARNING", + "FIELD_VALUE_OVERRIDEN", + "INJECTED_KERNELS_DEPRECATED", + "MISSING_TYPE_DEPENDENCY", + "NEXT_HOP_ADDRESS_NOT_ASSIGNED", + "NEXT_HOP_CANNOT_IP_FORWARD", + "NEXT_HOP_INSTANCE_NOT_FOUND", + "NEXT_HOP_INSTANCE_NOT_ON_NETWORK", + "NEXT_HOP_NOT_RUNNING", + "NOT_CRITICAL_ERROR", + "NO_RESULTS_ON_PAGE", + "REQUIRED_TOS_AGREEMENT", + "RESOURCE_IN_USE_BY_OTHER_RESOURCE_WARNING", + "RESOURCE_NOT_DELETED", + "SCHEMA_VALIDATION_IGNORED", + "SINGLE_INSTANCE_PROPERTY_TEMPLATE", + "UNDECLARED_PROPERTIES", + "UNREACHABLE" + ], + "enumDescriptions": [ + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "" + ], + "type": "string" + }, + "data": { + "description": "[Output Only] Metadata about this warning in key: value format. For example:\n\"data\": [ { \"key\": \"scope\", \"value\": \"zones/us-east1-d\" }", + "items": { + "properties": { + "key": { + "description": "[Output Only] A key that provides more detail on the warning being returned. For example, for warnings where there are no results in a list request for a particular zone, this key might be scope and the key value might be the zone name. Other examples might be a key indicating a deprecated resource and a suggested replacement, or a warning about invalid network settings (for example, if an instance attempts to perform IP forwarding but is not enabled for IP forwarding).", + "type": "string" + }, + "value": { + "description": "[Output Only] A warning data value corresponding to the key.", + "type": "string" + } + }, + "type": "object" + }, + "type": "array" + }, + "message": { + "description": "[Output Only] A human-readable description of the warning code.", + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object" + }, "VpnTunnel": { "description": "VPN tunnel resource. (== resource_for beta.vpnTunnels ==) (== resource_for v1.vpnTunnels ==)", "id": "VpnTunnel", @@ -31794,7 +37280,7 @@ "id": "XpnResourceId", "properties": { "id": { - "description": "The ID of the service resource. In the case of projects, this field matches the project ID (e.g., my-project), not the project number (e.g., 12345678).", + "description": "The ID of the service resource. In the case of projects, this field supports project id (e.g., my-project-123) and project number (e.g. 12345678).", "type": "string" }, "type": { @@ -32001,6 +37487,28 @@ } }, "type": "object" + }, + "ZoneSetPolicyRequest": { + "id": "ZoneSetPolicyRequest", + "properties": { + "bindings": { + "description": "Flatten Policy to create a backwacd compatible wire-format. Deprecated. Use 'policy' to specify bindings.", + "items": { + "$ref": "Binding" + }, + "type": "array" + }, + "etag": { + "description": "Flatten Policy to create a backward compatible wire-format. Deprecated. Use 'policy' to specify the etag.", + "format": "byte", + "type": "string" + }, + "policy": { + "$ref": "Policy", + "description": "REQUIRED: The complete policy to be applied to the 'resource'. The size of the policy is limited to a few 10s of KB. An empty policy is in general a valid policy but certain services (like Projects) might reject them." + } + }, + "type": "object" } }, "servicePath": "compute/v1/projects/", diff --git a/vendor/google.golang.org/api/compute/v1/compute-gen.go b/vendor/google.golang.org/api/compute/v1/compute-gen.go index e65f125137a..cfd5807ea01 100644 --- a/vendor/google.golang.org/api/compute/v1/compute-gen.go +++ b/vendor/google.golang.org/api/compute/v1/compute-gen.go @@ -1,3 +1,9 @@ +// Copyright 2018 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Code generated file. DO NOT EDIT. + // Package compute provides access to the Compute Engine API. // // See https://developers.google.com/compute/docs/reference/latest/ @@ -11,18 +17,18 @@ package compute import ( "bytes" + "context" "encoding/json" "errors" "fmt" - context "golang.org/x/net/context" - ctxhttp "golang.org/x/net/context/ctxhttp" - gensupport "google.golang.org/api/gensupport" - googleapi "google.golang.org/api/googleapi" "io" "net/http" "net/url" "strconv" "strings" + + gensupport "google.golang.org/api/gensupport" + googleapi "google.golang.org/api/googleapi" ) // Always reference these packages, just in case the auto-generated code @@ -38,7 +44,6 @@ var _ = googleapi.Version var _ = errors.New var _ = strings.Replace var _ = context.Canceled -var _ = ctxhttp.Do const apiId = "compute:v1" const apiName = "compute" @@ -98,6 +103,9 @@ func New(client *http.Client) (*Service, error) { s.Licenses = NewLicensesService(s) s.MachineTypes = NewMachineTypesService(s) s.Networks = NewNetworksService(s) + s.NodeGroups = NewNodeGroupsService(s) + s.NodeTemplates = NewNodeTemplatesService(s) + s.NodeTypes = NewNodeTypesService(s) s.Projects = NewProjectsService(s) s.RegionAutoscalers = NewRegionAutoscalersService(s) s.RegionBackendServices = NewRegionBackendServicesService(s) @@ -110,6 +118,7 @@ func New(client *http.Client) (*Service, error) { s.Regions = NewRegionsService(s) s.Routers = NewRoutersService(s) s.Routes = NewRoutesService(s) + s.SecurityPolicies = NewSecurityPoliciesService(s) s.Snapshots = NewSnapshotsService(s) s.SslCertificates = NewSslCertificatesService(s) s.SslPolicies = NewSslPoliciesService(s) @@ -187,6 +196,12 @@ type Service struct { Networks *NetworksService + NodeGroups *NodeGroupsService + + NodeTemplates *NodeTemplatesService + + NodeTypes *NodeTypesService + Projects *ProjectsService RegionAutoscalers *RegionAutoscalersService @@ -211,6 +226,8 @@ type Service struct { Routes *RoutesService + SecurityPolicies *SecurityPoliciesService + Snapshots *SnapshotsService SslCertificates *SslCertificatesService @@ -492,6 +509,33 @@ type NetworksService struct { s *Service } +func NewNodeGroupsService(s *Service) *NodeGroupsService { + rs := &NodeGroupsService{s: s} + return rs +} + +type NodeGroupsService struct { + s *Service +} + +func NewNodeTemplatesService(s *Service) *NodeTemplatesService { + rs := &NodeTemplatesService{s: s} + return rs +} + +type NodeTemplatesService struct { + s *Service +} + +func NewNodeTypesService(s *Service) *NodeTypesService { + rs := &NodeTypesService{s: s} + return rs +} + +type NodeTypesService struct { + s *Service +} + func NewProjectsService(s *Service) *ProjectsService { rs := &ProjectsService{s: s} return rs @@ -600,6 +644,15 @@ type RoutesService struct { s *Service } +func NewSecurityPoliciesService(s *Service) *SecurityPoliciesService { + rs := &SecurityPoliciesService{s: s} + return rs +} + +type SecurityPoliciesService struct { + s *Service +} + func NewSnapshotsService(s *Service) *SnapshotsService { rs := &SnapshotsService{s: s} return rs @@ -1305,6 +1358,22 @@ type AccessConfig struct { // live in the same region as the zone of the instance. NatIP string `json:"natIP,omitempty"` + // NetworkTier: This signifies the networking tier used for configuring + // this access configuration and can only take the following values: + // PREMIUM, STANDARD. + // + // If an AccessConfig is specified without a valid external IP address, + // an ephemeral IP will be created with this networkTier. + // + // If an AccessConfig with a valid external IP address is specified, it + // must match that of the networkTier associated with the Address + // resource owning that IP. + // + // Possible values: + // "PREMIUM" + // "STANDARD" + NetworkTier string `json:"networkTier,omitempty"` + // PublicPtrDomainName: The DNS domain name for the public PTR record. // This field can only be set when the set_public_ptr field is enabled. PublicPtrDomainName string `json:"publicPtrDomainName,omitempty"` @@ -1395,6 +1464,37 @@ type Address struct { // last character, which cannot be a dash. Name string `json:"name,omitempty"` + // Network: The URL of the network in which to reserve the address. This + // field can only be used with INTERNAL type with VPC_PEERING purpose. + Network string `json:"network,omitempty"` + + // NetworkTier: This signifies the networking tier used for configuring + // this Address and can only take the following values: PREMIUM, + // STANDARD. Global forwarding rules can only be Premium Tier. Regional + // forwarding rules can be either Premium or Standard Tier. Standard + // Tier addresses applied to regional forwarding rules can be used with + // any external load balancer. Regional forwarding rules in Premium Tier + // can only be used with a Network load balancer. + // + // If this field is not specified, it is assumed to be PREMIUM. + // + // Possible values: + // "PREMIUM" + // "STANDARD" + NetworkTier string `json:"networkTier,omitempty"` + + // PrefixLength: The prefix length if the resource reprensents an IP + // range. + PrefixLength int64 `json:"prefixLength,omitempty"` + + // Purpose: The purpose of resource, only used with INTERNAL type. + // + // Possible values: + // "DNS_RESOLVER" + // "GCE_ENDPOINT" + // "VPC_PEERING" + Purpose string `json:"purpose,omitempty"` + // Region: [Output Only] URL of the region where the regional address // resides. This field is not applicable to global addresses. You must // specify this field as part of the HTTP request URL. You cannot set @@ -2080,8 +2180,14 @@ func (s *AttachedDisk) MarshalJSON() ([]byte, error) { // This property is mutually exclusive with the source property; you can // only define one or the other, but not both. type AttachedDiskInitializeParams struct { + // Description: An optional description. Provide this property when + // creating the disk. + Description string `json:"description,omitempty"` + // DiskName: Specifies the disk name. If not specified, the default is - // to use the name of the instance. + // to use the name of the instance. If the disk with the instance name + // exists already in the given zone/region, a new name will be + // automatically generated. DiskName string `json:"diskName,omitempty"` // DiskSizeGb: Specifies the size of the disk in base-2 GB. @@ -2116,15 +2222,15 @@ type AttachedDiskInitializeParams struct { // // To create a disk with one of the public operating system images, // specify the image by its family name. For example, specify - // family/debian-8 to use the latest Debian 8 + // family/debian-9 to use the latest Debian 9 // image: - // projects/debian-cloud/global/images/family/debian-8 + // projects/debian-cloud/global/images/family/debian-9 // // // Alternati // vely, use a specific version of a public operating system // image: - // projects/debian-cloud/global/images/debian-8-jessie-vYYYYMMDD + // projects/debian-cloud/global/images/debian-9-stretch-vYYYYMMDD // // // @@ -2153,7 +2259,7 @@ type AttachedDiskInitializeParams struct { // the source images are encrypted with your own keys. SourceImageEncryptionKey *CustomerEncryptionKey `json:"sourceImageEncryptionKey,omitempty"` - // ForceSendFields is a list of field names (e.g. "DiskName") to + // ForceSendFields is a list of field names (e.g. "Description") to // unconditionally include in API requests. By default, fields with // empty values are omitted from API requests. However, any non-pointer, // non-interface field appearing in ForceSendFields will be sent to the @@ -2161,10 +2267,10 @@ type AttachedDiskInitializeParams struct { // used to include empty fields in Patch requests. ForceSendFields []string `json:"-"` - // NullFields is a list of field names (e.g. "DiskName") to include in - // API requests with the JSON null value. By default, fields with empty - // values are omitted from API requests. However, any field with an - // empty value appearing in NullFields will be sent to the server as + // NullFields is a list of field names (e.g. "Description") to include + // in API requests with the JSON null value. By default, fields with + // empty values are omitted from API requests. However, any field with + // an empty value appearing in NullFields will be sent to the server as // null. It is an error if a field in this list has a non-empty value. // This may be used to include null fields in Patch requests. NullFields []string `json:"-"` @@ -2176,6 +2282,150 @@ func (s *AttachedDiskInitializeParams) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +// AuditConfig: Specifies the audit configuration for a service. The +// configuration determines which permission types are logged, and what +// identities, if any, are exempted from logging. An AuditConfig must +// have one or more AuditLogConfigs. +// +// If there are AuditConfigs for both `allServices` and a specific +// service, the union of the two AuditConfigs is used for that service: +// the log_types specified in each AuditConfig are enabled, and the +// exempted_members in each AuditLogConfig are exempted. +// +// Example Policy with multiple AuditConfigs: +// +// { "audit_configs": [ { "service": "allServices" "audit_log_configs": +// [ { "log_type": "DATA_READ", "exempted_members": [ +// "user:foo@gmail.com" ] }, { "log_type": "DATA_WRITE", }, { +// "log_type": "ADMIN_READ", } ] }, { "service": +// "fooservice.googleapis.com" "audit_log_configs": [ { "log_type": +// "DATA_READ", }, { "log_type": "DATA_WRITE", "exempted_members": [ +// "user:bar@gmail.com" ] } ] } ] } +// +// For fooservice, this policy enables DATA_READ, DATA_WRITE and +// ADMIN_READ logging. It also exempts foo@gmail.com from DATA_READ +// logging, and bar@gmail.com from DATA_WRITE logging. +type AuditConfig struct { + // AuditLogConfigs: The configuration for logging of each type of + // permission. + AuditLogConfigs []*AuditLogConfig `json:"auditLogConfigs,omitempty"` + + ExemptedMembers []string `json:"exemptedMembers,omitempty"` + + // Service: Specifies a service that will be enabled for audit logging. + // For example, `storage.googleapis.com`, `cloudsql.googleapis.com`. + // `allServices` is a special value that covers all services. + Service string `json:"service,omitempty"` + + // ForceSendFields is a list of field names (e.g. "AuditLogConfigs") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "AuditLogConfigs") to + // include in API requests with the JSON null value. By default, fields + // with empty values are omitted from API requests. However, any field + // with an empty value appearing in NullFields will be sent to the + // server as null. It is an error if a field in this list has a + // non-empty value. This may be used to include null fields in Patch + // requests. + NullFields []string `json:"-"` +} + +func (s *AuditConfig) MarshalJSON() ([]byte, error) { + type NoMethod AuditConfig + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// AuditLogConfig: Provides the configuration for logging a type of +// permissions. Example: +// +// { "audit_log_configs": [ { "log_type": "DATA_READ", +// "exempted_members": [ "user:foo@gmail.com" ] }, { "log_type": +// "DATA_WRITE", } ] } +// +// This enables 'DATA_READ' and 'DATA_WRITE' logging, while exempting +// foo@gmail.com from DATA_READ logging. +type AuditLogConfig struct { + // ExemptedMembers: Specifies the identities that do not cause logging + // for this type of permission. Follows the same format of + // [Binding.members][]. + ExemptedMembers []string `json:"exemptedMembers,omitempty"` + + // LogType: The log type that this config enables. + // + // Possible values: + // "ADMIN_READ" + // "DATA_READ" + // "DATA_WRITE" + // "LOG_TYPE_UNSPECIFIED" + LogType string `json:"logType,omitempty"` + + // ForceSendFields is a list of field names (e.g. "ExemptedMembers") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "ExemptedMembers") to + // include in API requests with the JSON null value. By default, fields + // with empty values are omitted from API requests. However, any field + // with an empty value appearing in NullFields will be sent to the + // server as null. It is an error if a field in this list has a + // non-empty value. This may be used to include null fields in Patch + // requests. + NullFields []string `json:"-"` +} + +func (s *AuditLogConfig) MarshalJSON() ([]byte, error) { + type NoMethod AuditLogConfig + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// AuthorizationLoggingOptions: Authorization-related information used +// by Cloud Audit Logging. +type AuthorizationLoggingOptions struct { + // PermissionType: The type of the permission that was checked. + // + // Possible values: + // "ADMIN_READ" + // "ADMIN_WRITE" + // "DATA_READ" + // "DATA_WRITE" + // "PERMISSION_TYPE_UNSPECIFIED" + PermissionType string `json:"permissionType,omitempty"` + + // ForceSendFields is a list of field names (e.g. "PermissionType") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "PermissionType") to + // include in API requests with the JSON null value. By default, fields + // with empty values are omitted from API requests. However, any field + // with an empty value appearing in NullFields will be sent to the + // server as null. It is an error if a field in this list has a + // non-empty value. This may be used to include null fields in Patch + // requests. + NullFields []string `json:"-"` +} + +func (s *AuthorizationLoggingOptions) MarshalJSON() ([]byte, error) { + type NoMethod AuthorizationLoggingOptions + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + // Autoscaler: Represents an Autoscaler resource. Autoscalers allow you // to automatically scale virtual machine instances in managed instance // groups according to an autoscaling policy that you define. For more @@ -2907,8 +3157,7 @@ type AutoscalingPolicyCustomMetricUtilization struct { // UtilizationTargetType: Defines how target utilization value is // expressed for a Stackdriver Monitoring metric. Either GAUGE, - // DELTA_PER_SECOND, or DELTA_PER_MINUTE. If not specified, the default - // is GAUGE. + // DELTA_PER_SECOND, or DELTA_PER_MINUTE. // // Possible values: // "DELTA_PER_MINUTE" @@ -3030,18 +3279,28 @@ type Backend struct { // property when you create the resource. Description string `json:"description,omitempty"` - // Group: The fully-qualified URL of a Instance Group resource. This - // instance group defines the list of instances that serve traffic. - // Member virtual machine instances from each instance group must live - // in the same zone as the instance group itself. No two backends in a - // backend service are allowed to use same Instance Group - // resource. + // Group: The fully-qualified URL of an Instance Group or Network + // Endpoint Group resource. In case of instance group this defines the + // list of instances that serve traffic. Member virtual machine + // instances from each instance group must live in the same zone as the + // instance group itself. No two backends in a backend service are + // allowed to use same Instance Group resource. // - // Note that you must specify an Instance Group resource using the - // fully-qualified URL, rather than a partial URL. + // For Network Endpoint Groups this defines list of endpoints. All + // endpoints of Network Endpoint Group must be hosted on instances + // located in the same zone as the Network Endpoint Group. + // + // Backend service can not contain mix of Instance Group and Network + // Endpoint Group backends. + // + // Note that you must specify an Instance Group or Network Endpoint + // Group resource using the fully-qualified URL, rather than a partial + // URL. // // When the BackendService has load balancing scheme INTERNAL, the // instance group must be within the same region as the BackendService. + // Network Endpoint Groups are not supported for INTERNAL load balancing + // scheme. Group string `json:"group,omitempty"` // MaxConnections: The max number of simultaneous connections for the @@ -3131,7 +3390,7 @@ type BackendBucket struct { // BucketName: Cloud Storage bucket name. BucketName string `json:"bucketName,omitempty"` - // CdnPolicy: Cloud CDN Coniguration for this BackendBucket. + // CdnPolicy: Cloud CDN configuration for this BackendBucket. CdnPolicy *BackendBucketCdnPolicy `json:"cdnPolicy,omitempty"` // CreationTimestamp: [Output Only] Creation timestamp in RFC3339 text @@ -3194,18 +3453,18 @@ func (s *BackendBucket) MarshalJSON() ([]byte, error) { // BackendBucketCdnPolicy: Message containing Cloud CDN configuration // for a backend bucket. type BackendBucketCdnPolicy struct { - // SignedUrlCacheMaxAgeSec: Number of seconds up to which the response - // to a signed URL request will be cached in the CDN. After this time - // period, the Signed URL will be revalidated before being served. - // Defaults to 1hr (3600s). If this field is set, Cloud CDN will - // internally act as though all responses from this bucket had a - // ?Cache-Control: public, max-age=[TTL]? header, regardless of any + // SignedUrlCacheMaxAgeSec: Maximum number of seconds the response to a + // signed URL request will be considered fresh. After this time period, + // the response will be revalidated before being served. Defaults to 1hr + // (3600s). When serving responses to signed URL requests, Cloud CDN + // will internally behave as though all responses from this backend had + // a "Cache-Control: public, max-age=[TTL]" header, regardless of any // existing Cache-Control header. The actual headers served in responses // will not be altered. SignedUrlCacheMaxAgeSec int64 `json:"signedUrlCacheMaxAgeSec,omitempty,string"` - // SignedUrlKeyNames: [Output Only] Names of the keys currently - // configured for Cloud CDN Signed URL on this backend bucket. + // SignedUrlKeyNames: [Output Only] Names of the keys for signing + // request URLs. SignedUrlKeyNames []string `json:"signedUrlKeyNames,omitempty"` // ForceSendFields is a list of field names (e.g. @@ -3425,7 +3684,11 @@ type BackendService struct { // Fingerprint: Fingerprint of this resource. A hash of the contents // stored in this object. This field is used in optimistic locking. This // field will be ignored when inserting a BackendService. An up-to-date - // fingerprint must be provided in order to update the BackendService. + // fingerprint must be provided in order to update the BackendService, + // otherwise the request will fail with error 412 conditionNotMet. + // + // To see the latest fingerprint, make a get() request to retrieve a + // BackendService. Fingerprint string `json:"fingerprint,omitempty"` // HealthChecks: The list of URLs to the HttpHealthCheck or @@ -3505,6 +3768,10 @@ type BackendService struct { // URL. It is not settable as a field in the request body. Region string `json:"region,omitempty"` + // SecurityPolicy: [Output Only] The resource URL for the security + // policy associated with this backend service. + SecurityPolicy string `json:"securityPolicy,omitempty"` + // SelfLink: [Output Only] Server-defined URL for the resource. SelfLink string `json:"selfLink,omitempty"` @@ -3722,18 +3989,18 @@ type BackendServiceCdnPolicy struct { // CacheKeyPolicy: The CacheKeyPolicy for this CdnPolicy. CacheKeyPolicy *CacheKeyPolicy `json:"cacheKeyPolicy,omitempty"` - // SignedUrlCacheMaxAgeSec: Number of seconds up to which the response - // to a signed URL request will be cached in the CDN. After this time - // period, the Signed URL will be revalidated before being served. - // Defaults to 1hr (3600s). If this field is set, Cloud CDN will - // internally act as though all responses from this backend had a - // ?Cache-Control: public, max-age=[TTL]? header, regardless of any + // SignedUrlCacheMaxAgeSec: Maximum number of seconds the response to a + // signed URL request will be considered fresh. After this time period, + // the response will be revalidated before being served. Defaults to 1hr + // (3600s). When serving responses to signed URL requests, Cloud CDN + // will internally behave as though all responses from this backend had + // a "Cache-Control: public, max-age=[TTL]" header, regardless of any // existing Cache-Control header. The actual headers served in responses // will not be altered. SignedUrlCacheMaxAgeSec int64 `json:"signedUrlCacheMaxAgeSec,omitempty,string"` - // SignedUrlKeyNames: [Output Only] Names of the keys currently - // configured for Cloud CDN Signed URL on this backend service. + // SignedUrlKeyNames: [Output Only] Names of the keys for signing + // request URLs. SignedUrlKeyNames []string `json:"signedUrlKeyNames,omitempty"` // ForceSendFields is a list of field names (e.g. "CacheKeyPolicy") to @@ -3761,6 +4028,9 @@ func (s *BackendServiceCdnPolicy) MarshalJSON() ([]byte, error) { } type BackendServiceGroupHealth struct { + // HealthStatus: Health state of the backend instances or endpoints in + // requested instance or network endpoint group, determined based on + // configured health checks. HealthStatus []*HealthStatus `json:"healthStatus,omitempty"` // Kind: [Output Only] Type of resource. Always @@ -4119,6 +4389,69 @@ func (s *BackendServicesScopedListWarningData) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +// Binding: Associates `members` with a `role`. +type Binding struct { + // Condition: Unimplemented. The condition that is associated with this + // binding. NOTE: an unsatisfied condition will not allow user access + // via current binding. Different bindings, including their conditions, + // are examined independently. + Condition *Expr `json:"condition,omitempty"` + + // Members: Specifies the identities requesting access for a Cloud + // Platform resource. `members` can have the following values: + // + // * `allUsers`: A special identifier that represents anyone who is on + // the internet; with or without a Google account. + // + // * `allAuthenticatedUsers`: A special identifier that represents + // anyone who is authenticated with a Google account or a service + // account. + // + // * `user:{emailid}`: An email address that represents a specific + // Google account. For example, `alice@gmail.com` . + // + // + // + // * `serviceAccount:{emailid}`: An email address that represents a + // service account. For example, + // `my-other-app@appspot.gserviceaccount.com`. + // + // * `group:{emailid}`: An email address that represents a Google group. + // For example, `admins@example.com`. + // + // + // + // * `domain:{domain}`: A Google Apps domain name that represents all + // the users of that domain. For example, `google.com` or `example.com`. + Members []string `json:"members,omitempty"` + + // Role: Role that is assigned to `members`. For example, + // `roles/viewer`, `roles/editor`, or `roles/owner`. + Role string `json:"role,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Condition") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Condition") to include in + // API requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *Binding) MarshalJSON() ([]byte, error) { + type NoMethod Binding + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + type CacheInvalidationRule struct { // Host: If set, this invalidation rule will only apply to requests with // a Host header matching host. @@ -4755,6 +5088,75 @@ func (s *CommitmentsScopedListWarningData) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +// Condition: A condition to be met. +type Condition struct { + // Iam: Trusted attributes supplied by the IAM system. + // + // Possible values: + // "APPROVER" + // "ATTRIBUTION" + // "AUTHORITY" + // "CREDENTIALS_TYPE" + // "JUSTIFICATION_TYPE" + // "NO_ATTR" + // "SECURITY_REALM" + Iam string `json:"iam,omitempty"` + + // Op: An operator to apply the subject with. + // + // Possible values: + // "DISCHARGED" + // "EQUALS" + // "IN" + // "NOT_EQUALS" + // "NOT_IN" + // "NO_OP" + Op string `json:"op,omitempty"` + + // Svc: Trusted attributes discharged by the service. + Svc string `json:"svc,omitempty"` + + // Sys: Trusted attributes supplied by any service that owns resources + // and uses the IAM system for access control. + // + // Possible values: + // "IP" + // "NAME" + // "NO_ATTR" + // "REGION" + // "SERVICE" + Sys string `json:"sys,omitempty"` + + // Value: DEPRECATED. Use 'values' instead. + Value string `json:"value,omitempty"` + + // Values: The objects of the condition. This is mutually exclusive with + // 'value'. + Values []string `json:"values,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Iam") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Iam") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *Condition) MarshalJSON() ([]byte, error) { + type NoMethod Condition + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + // ConnectionDraining: Message containing connection draining // configuration. type ConnectionDraining struct { @@ -4788,6 +5190,10 @@ func (s *ConnectionDraining) MarshalJSON() ([]byte, error) { // CustomerEncryptionKey: Represents a customer-supplied encryption key type CustomerEncryptionKey struct { + // KmsKeyName: The name of the encryption key that is stored in Google + // Cloud KMS. + KmsKeyName string `json:"kmsKeyName,omitempty"` + // RawKey: Specifies a 256-bit customer-supplied encryption key, encoded // in RFC 4648 base64 to either encrypt or decrypt this resource. RawKey string `json:"rawKey,omitempty"` @@ -4796,7 +5202,7 @@ type CustomerEncryptionKey struct { // customer-supplied encryption key that protects this resource. Sha256 string `json:"sha256,omitempty"` - // ForceSendFields is a list of field names (e.g. "RawKey") to + // ForceSendFields is a list of field names (e.g. "KmsKeyName") to // unconditionally include in API requests. By default, fields with // empty values are omitted from API requests. However, any non-pointer, // non-interface field appearing in ForceSendFields will be sent to the @@ -4804,8 +5210,8 @@ type CustomerEncryptionKey struct { // used to include empty fields in Patch requests. ForceSendFields []string `json:"-"` - // NullFields is a list of field names (e.g. "RawKey") to include in API - // requests with the JSON null value. By default, fields with empty + // NullFields is a list of field names (e.g. "KmsKeyName") to include in + // API requests with the JSON null value. By default, fields with empty // values are omitted from API requests. However, any field with an // empty value appearing in NullFields will be sent to the server as // null. It is an error if a field in this list has a non-empty value. @@ -4959,7 +5365,8 @@ type Disk struct { // optimistic locking. The fingerprint is initially generated by Compute // Engine and changes after every request to modify or update labels. // You must always provide an up-to-date fingerprint hash in order to - // update or change labels. + // update or change labels, otherwise the request will fail with error + // 412 conditionNotMet. // // To see the latest fingerprint, make a get() request to retrieve a // disk. @@ -4981,7 +5388,8 @@ type Disk struct { // attached to this disk. LicenseCodes googleapi.Int64s `json:"licenseCodes,omitempty"` - // Licenses: Any applicable publicly visible licenses. + // Licenses: A list of publicly visible licenses. Reserved for Google's + // use. Licenses []string `json:"licenses,omitempty"` // Name: Name of the resource. Provided by the client when the resource @@ -4996,6 +5404,13 @@ type Disk struct { // Options: Internal use only. Options string `json:"options,omitempty"` + // PhysicalBlockSizeBytes: Physical block size of the persistent disk, + // in bytes. If not present in a request, a default value is used. + // Currently supported sizes are 4096 and 16384, other sizes may be + // added in the future. If an unsupported value is requested, the error + // message will list the supported values for the caller's project. + PhysicalBlockSizeBytes int64 `json:"physicalBlockSizeBytes,omitempty,string"` + // Region: [Output Only] URL of the region where the disk resides. Only // applicable for regional resources. You must specify this field as // part of the HTTP request URL. It is not settable as a field in the @@ -5026,15 +5441,15 @@ type Disk struct { // // To create a disk with one of the public operating system images, // specify the image by its family name. For example, specify - // family/debian-8 to use the latest Debian 8 + // family/debian-9 to use the latest Debian 9 // image: - // projects/debian-cloud/global/images/family/debian-8 + // projects/debian-cloud/global/images/family/debian-9 // // // Alternati // vely, use a specific version of a public operating system // image: - // projects/debian-cloud/global/images/debian-8-jessie-vYYYYMMDD + // projects/debian-cloud/global/images/debian-9-stretch-vYYYYMMDD // // // @@ -6235,6 +6650,112 @@ func (s *DisksScopedListWarningData) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +type DistributionPolicy struct { + // Zones: Zones where the regional managed instance group will create + // and manage instances. + Zones []*DistributionPolicyZoneConfiguration `json:"zones,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Zones") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Zones") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *DistributionPolicy) MarshalJSON() ([]byte, error) { + type NoMethod DistributionPolicy + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type DistributionPolicyZoneConfiguration struct { + // Zone: The URL of the zone. The zone must exist in the region where + // the managed instance group is located. + Zone string `json:"zone,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Zone") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Zone") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *DistributionPolicyZoneConfiguration) MarshalJSON() ([]byte, error) { + type NoMethod DistributionPolicyZoneConfiguration + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// Expr: Represents an expression text. Example: +// +// title: "User account presence" description: "Determines whether the +// request has a user account" expression: "size(request.user) > 0" +type Expr struct { + // Description: An optional description of the expression. This is a + // longer text which describes the expression, e.g. when hovered over it + // in a UI. + Description string `json:"description,omitempty"` + + // Expression: Textual representation of an expression in Common + // Expression Language syntax. + // + // The application context of the containing message determines which + // well-known feature set of CEL is supported. + Expression string `json:"expression,omitempty"` + + // Location: An optional string indicating the location of the + // expression for error reporting, e.g. a file name and a position in + // the file. + Location string `json:"location,omitempty"` + + // Title: An optional title for the expression, i.e. a short string + // describing its purpose. This can be used e.g. in UIs which allow to + // enter the expression. + Title string `json:"title,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Description") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Description") to include + // in API requests with the JSON null value. By default, fields with + // empty values are omitted from API requests. However, any field with + // an empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *Expr) MarshalJSON() ([]byte, error) { + type NoMethod Expr + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + // Firewall: Represents a Firewall resource. type Firewall struct { // Allowed: The list of ALLOW rules specified by this firewall. Each @@ -6271,6 +6792,12 @@ type Firewall struct { // "INGRESS" Direction string `json:"direction,omitempty"` + // Disabled: Denotes whether the firewall rule is disabled, i.e not + // applied to the network it is associated with. When set to true, the + // firewall rule is not enforced and the network behaves as if it did + // not exist. If this is unspecified, the firewall rule will be enabled. + Disabled bool `json:"disabled,omitempty"` + // Id: [Output Only] The unique identifier for the resource. This // identifier is defined by the server. Id uint64 `json:"id,omitempty,string"` @@ -6279,6 +6806,11 @@ type Firewall struct { // firewall rules. Kind string `json:"kind,omitempty"` + // LogConfig: This field denotes the logging options for a particular + // firewall rule. If logging is enabled, logs will be exported to + // Stackdriver. + LogConfig *FirewallLogConfig `json:"logConfig,omitempty"` + // Name: Name of the resource; provided by the client when the resource // is created. The name must be 1-63 characters long, and comply with // RFC1035. Specifically, the name must be 1-63 characters long and @@ -6623,6 +7155,35 @@ func (s *FirewallListWarningData) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +// FirewallLogConfig: The available logging options for a firewall rule. +type FirewallLogConfig struct { + // Enable: This field denotes whether to enable logging for a particular + // firewall rule. + Enable bool `json:"enable,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Enable") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Enable") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *FirewallLogConfig) MarshalJSON() ([]byte, error) { + type NoMethod FirewallLogConfig + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + // ForwardingRule: A ForwardingRule resource. A ForwardingRule resource // specifies which pool of target virtual machines to forward a packet // to if it matches the given [IPAddress, IPProtocol, ports] tuple. (== @@ -6647,6 +7208,11 @@ type ForwardingRule struct { // rule supports IPv4 only. A global forwarding rule supports either // IPv4 or IPv6. // + // When the load balancing scheme is INTERNAL_SELF_MANAGED, this must be + // a URL reference to an existing Address resource ( internal regional + // static IP address), with a purpose of GCE_END_POINT and address_type + // of INTERNAL. + // // When the load balancing scheme is INTERNAL, this can only be an RFC // 1918 IP address belonging to the network/subnet configured for the // forwarding rule. By default, if this field is empty, an ephemeral @@ -6669,7 +7235,8 @@ type ForwardingRule struct { // are TCP, UDP, ESP, AH, SCTP or ICMP. // // When the load balancing scheme is INTERNAL, only TCP and UDP are - // valid. + // valid. When the load balancing scheme is INTERNAL_SELF_MANAGED, only + // TCPis valid. // // Possible values: // "AH" @@ -6680,7 +7247,7 @@ type ForwardingRule struct { // "UDP" IPProtocol string `json:"IPProtocol,omitempty"` - // BackendService: This field is not used for external load + // BackendService: This field is only used for INTERNAL load // balancing. // // For internal load balancing, this field identifies the BackendService @@ -6700,8 +7267,8 @@ type ForwardingRule struct { Id uint64 `json:"id,omitempty,string"` // IpVersion: The IP Version that will be used by this forwarding rule. - // Valid options are IPV4 or IPV6. This can only be specified for a - // global forwarding rule. + // Valid options are IPV4 or IPV6. This can only be specified for an + // external global forwarding rule. // // Possible values: // "IPV4" @@ -6714,10 +7281,12 @@ type ForwardingRule struct { Kind string `json:"kind,omitempty"` // LoadBalancingScheme: This signifies what the ForwardingRule will be - // used for and can only take the following values: INTERNAL, EXTERNAL - // The value of INTERNAL means that this will be used for Internal - // Network Load Balancing (TCP, UDP). The value of EXTERNAL means that - // this will be used for External Load Balancing (HTTP(S) LB, External + // used for and can only take the following values: INTERNAL, + // INTERNAL_SELF_MANAGED, EXTERNAL. The value of INTERNAL means that + // this will be used for Internal Network Load Balancing (TCP, UDP). The + // value of INTERNAL_SELF_MANAGED means that this will be used for + // Internal Global HTTP(S) LB. The value of EXTERNAL means that this + // will be used for External Load Balancing (HTTP(S) LB, External // TCP/UDP LB, SSL Proxy) // // Possible values: @@ -6737,11 +7306,28 @@ type ForwardingRule struct { // Network: This field is not used for external load balancing. // - // For internal load balancing, this field identifies the network that - // the load balanced IP should belong to for this Forwarding Rule. If - // this field is not specified, the default network will be used. + // For INTERNAL and INTERNAL_SELF_MANAGED load balancing, this field + // identifies the network that the load balanced IP should belong to for + // this Forwarding Rule. If this field is not specified, the default + // network will be used. Network string `json:"network,omitempty"` + // NetworkTier: This signifies the networking tier used for configuring + // this load balancer and can only take the following values: PREMIUM , + // STANDARD. + // + // For regional ForwardingRule, the valid values are PREMIUM and + // STANDARD. For GlobalForwardingRule, the valid value is PREMIUM. + // + // If this field is not specified, it is assumed to be PREMIUM. If + // IPAddress is specified, this value must be equal to the networkTier + // of the Address. + // + // Possible values: + // "PREMIUM" + // "STANDARD" + NetworkTier string `json:"networkTier,omitempty"` + // PortRange: This field is used along with the target field for // TargetHttpProxy, TargetHttpsProxy, TargetSslProxy, TargetTcpProxy, // TargetVpnGateway, TargetPool, TargetInstance. @@ -6765,10 +7351,10 @@ type ForwardingRule struct { // Ports: This field is used along with the backend_service field for // internal load balancing. // - // When the load balancing scheme is INTERNAL, a single port or a comma - // separated list of ports can be configured. Only packets addressed to - // these ports will be forwarded to the backends configured with this - // forwarding rule. + // When the load balancing scheme is INTERNAL, a list of ports can be + // configured, for example, ['80'], ['8000','9000'] etc. Only packets + // addressed to these ports will be forwarded to the backends configured + // with this forwarding rule. // // You may specify a maximum of up to 5 ports. Ports []string `json:"ports,omitempty"` @@ -6782,7 +7368,7 @@ type ForwardingRule struct { // SelfLink: [Output Only] Server-defined URL for the resource. SelfLink string `json:"selfLink,omitempty"` - // Subnetwork: This field is not used for external load balancing. + // Subnetwork: This field is only used for INTERNAL load balancing. // // For internal load balancing, this field identifies the subnetwork // that the load balanced IP should belong to for this Forwarding @@ -6797,7 +7383,9 @@ type ForwardingRule struct { // traffic. For regional forwarding rules, this target must live in the // same region as the forwarding rule. For global forwarding rules, this // target must be a global load balancing resource. The forwarded - // traffic must be of a type appropriate to the target object. + // traffic must be of a type appropriate to the target object. For + // INTERNAL_SELF_MANAGED" load balancing, only HTTP and HTTPS targets + // are valid. Target string `json:"target,omitempty"` // ServerResponse contains the HTTP response code and headers from the @@ -7276,7 +7864,8 @@ type GlobalSetLabelsRequest struct { // this resource, used to detect conflicts. The fingerprint is initially // generated by Compute Engine and changes after every request to modify // or update labels. You must always provide an up-to-date fingerprint - // hash when updating or changing labels. Make a get() request to the + // hash when updating or changing labels, otherwise the request will + // fail with error 412 conditionNotMet. Make a get() request to the // resource to get the latest fingerprint. LabelFingerprint string `json:"labelFingerprint,omitempty"` @@ -7314,6 +7903,44 @@ func (s *GlobalSetLabelsRequest) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +type GlobalSetPolicyRequest struct { + // Bindings: Flatten Policy to create a backward compatible wire-format. + // Deprecated. Use 'policy' to specify bindings. + Bindings []*Binding `json:"bindings,omitempty"` + + // Etag: Flatten Policy to create a backward compatible wire-format. + // Deprecated. Use 'policy' to specify the etag. + Etag string `json:"etag,omitempty"` + + // Policy: REQUIRED: The complete policy to be applied to the + // 'resource'. The size of the policy is limited to a few 10s of KB. An + // empty policy is in general a valid policy but certain services (like + // Projects) might reject them. + Policy *Policy `json:"policy,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Bindings") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Bindings") to include in + // API requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *GlobalSetPolicyRequest) MarshalJSON() ([]byte, error) { + type NoMethod GlobalSetPolicyRequest + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + // GuestOsFeature: Guest OS features. type GuestOsFeature struct { // Type: The ID of a supported feature. Read Enabling guest operating @@ -7378,6 +8005,11 @@ type HTTPHealthCheck struct { // default value is /. RequestPath string `json:"requestPath,omitempty"` + // Response: The string to match anywhere in the first 1024 bytes of the + // response body. If left empty (the default value), the status code + // determines health. The response data can only be ASCII. + Response string `json:"response,omitempty"` + // ForceSendFields is a list of field names (e.g. "Host") to // unconditionally include in API requests. By default, fields with // empty values are omitted from API requests. However, any non-pointer, @@ -7428,6 +8060,11 @@ type HTTPSHealthCheck struct { // default value is /. RequestPath string `json:"requestPath,omitempty"` + // Response: The string to match anywhere in the first 1024 bytes of the + // response body. If left empty (the default value), the status code + // determines health. The response data can only be ASCII. + Response string `json:"response,omitempty"` + // ForceSendFields is a list of field names (e.g. "Host") to // unconditionally include in API requests. By default, fields with // empty values are omitted from API requests. However, any non-pointer, @@ -8368,7 +9005,8 @@ type Image struct { // locking. The fingerprint is initially generated by Compute Engine and // changes after every request to modify or update labels. You must // always provide an up-to-date fingerprint hash in order to update or - // change labels. + // change labels, otherwise the request will fail with error 412 + // conditionNotMet. // // To see the latest fingerprint, make a get() request to retrieve an // image. @@ -8415,9 +9053,9 @@ type Image struct { // customer-supplied encryption key. SourceDiskEncryptionKey *CustomerEncryptionKey `json:"sourceDiskEncryptionKey,omitempty"` - // SourceDiskId: The ID value of the disk used to create this image. - // This value may be used to determine whether the image was taken from - // the current or a previous instance of a given disk name. + // SourceDiskId: [Output Only] The ID value of the disk used to create + // this image. This value may be used to determine whether the image was + // taken from the current or a previous instance of a given disk name. SourceDiskId string `json:"sourceDiskId,omitempty"` // SourceImage: URL of the source image used to create this image. This @@ -8843,11 +9481,11 @@ type Instance struct { // of the status. StatusMessage string `json:"statusMessage,omitempty"` - // Tags: A list of tags to apply to this instance. Tags are used to - // identify valid sources or targets for network firewalls and are - // specified by the client during instance creation. The tags can be - // later modified by the setTags method. Each tag within the list must - // comply with RFC1035. + // Tags: Tags to apply to this instance. Tags are used to identify valid + // sources or targets for network firewalls and are specified by the + // client during instance creation. The tags can be later modified by + // the setTags method. Each tag within the list must comply with + // RFC1035. Multiple tags can be specified via the 'tags.items' field. Tags *Tags `json:"tags,omitempty"` // Zone: [Output Only] URL of the zone where the instance resides. You @@ -9468,10 +10106,18 @@ type InstanceGroupManager struct { // property when you create the resource. Description string `json:"description,omitempty"` + // DistributionPolicy: Policy specifying intended distribution of + // instances in regional managed instance group. + DistributionPolicy *DistributionPolicy `json:"distributionPolicy,omitempty"` + // Fingerprint: Fingerprint of this resource. This field may be used in // optimistic locking. It will be ignored when inserting an // InstanceGroupManager. An up-to-date fingerprint must be provided in - // order to update the InstanceGroupManager. + // order to update the InstanceGroupManager, otherwise the request will + // fail with error 412 conditionNotMet. + // + // To see the latest fingerprint, make a get() request to retrieve an + // InstanceGroupManager. Fingerprint string `json:"fingerprint,omitempty"` // Id: [Output Only] A unique identifier for this resource type. The @@ -9599,6 +10245,12 @@ type InstanceGroupManagerActionsSummary struct { // being restarted. Restarting int64 `json:"restarting,omitempty"` + // Verifying: [Output Only] The number of instances in the managed + // instance group that are being verified. See the + // managedInstances[].currentAction property in the listManagedInstances + // method documentation. + Verifying int64 `json:"verifying,omitempty"` + // ForceSendFields is a list of field names (e.g. "Abandoning") to // unconditionally include in API requests. By default, fields with // empty values are omitted from API requests. However, any non-pointer, @@ -10648,7 +11300,9 @@ type InstanceGroupsSetNamedPortsRequest struct { // multiple users change the named ports settings concurrently. Obtain // the fingerprint with the instanceGroups.get method. Then, include the // fingerprint in your request to ensure that you do not overwrite - // changes that were applied from another concurrent request. + // changes that were applied from another concurrent request. A request + // with an incorrect fingerprint will fail with error 412 + // conditionNotMet. Fingerprint string `json:"fingerprint,omitempty"` // NamedPorts: The list of named ports to set for this instance group. @@ -11899,8 +12553,8 @@ type InterconnectAttachment struct { // Bandwidth: Provisioned bandwidth capacity for the // interconnectAttachment. Can be set by the partner to update the - // customer's provisioned bandwidth. Output only for for PARTNER type, - // mutable for PARTNER_PROVIDER, not available for DEDICATED. + // customer's provisioned bandwidth. Output only for PARTNER type, + // mutable for PARTNER_PROVIDER and DEDICATED. // // Possible values: // "BPS_100M" @@ -12018,7 +12672,7 @@ type InterconnectAttachment struct { // body. Region string `json:"region,omitempty"` - // Router: URL of the cloud router to be used for dynamic routing. This + // Router: URL of the Cloud Router to be used for dynamic routing. This // router must be in the same region as this InterconnectAttachment. The // InterconnectAttachment will automatically connect the Interconnect to // the network & region within which the Cloud Router is configured. @@ -12046,10 +12700,8 @@ type InterconnectAttachment struct { // "PARTNER_PROVIDER" Type string `json:"type,omitempty"` - // VlanTag8021q: Available only for DEDICATED and PARTNER_PROVIDER. - // Desired VLAN tag for this attachment, in the range 2-4094. This field - // refers to 802.1q VLAN tag, also known as IEEE 802.1Q Only specified - // at creation time. + // VlanTag8021q: The IEEE 802.1Q VLAN tag for this attachment, in the + // range 2-4094. Only specified at creation time. VlanTag8021q int64 `json:"vlanTag8021q,omitempty"` // ServerResponse contains the HTTP response code and headers from the @@ -12400,7 +13052,7 @@ func (s *InterconnectAttachmentListWarningData) MarshalJSON() ([]byte, error) { type InterconnectAttachmentPartnerMetadata struct { // InterconnectName: Plain text name of the Interconnect this attachment // is connected to, as displayed in the Partner?s portal. For instance - // ?Chicago 1?. This value may be validated to match approved Partner + // "Chicago 1". This value may be validated to match approved Partner // values. InterconnectName string `json:"interconnectName,omitempty"` @@ -12645,6 +13297,211 @@ func (s *InterconnectCircuitInfo) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +// InterconnectDiagnostics: Diagnostics information about interconnect, +// contains detailed and current technical information about Google?s +// side of the connection. +type InterconnectDiagnostics struct { + // ArpCaches: A list of InterconnectDiagnostics.ARPEntry objects, + // describing individual neighbors currently seen by the Google router + // in the ARP cache for the Interconnect. This will be empty when the + // Interconnect is not bundled. + ArpCaches []*InterconnectDiagnosticsARPEntry `json:"arpCaches,omitempty"` + + // Links: A list of InterconnectDiagnostics.LinkStatus objects, + // describing the status for each link on the Interconnect. + Links []*InterconnectDiagnosticsLinkStatus `json:"links,omitempty"` + + // MacAddress: The MAC address of the Interconnect's bundle interface. + MacAddress string `json:"macAddress,omitempty"` + + // ForceSendFields is a list of field names (e.g. "ArpCaches") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "ArpCaches") to include in + // API requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *InterconnectDiagnostics) MarshalJSON() ([]byte, error) { + type NoMethod InterconnectDiagnostics + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// InterconnectDiagnosticsARPEntry: Describing the ARP neighbor entries +// seen on this link +type InterconnectDiagnosticsARPEntry struct { + // IpAddress: The IP address of this ARP neighbor. + IpAddress string `json:"ipAddress,omitempty"` + + // MacAddress: The MAC address of this ARP neighbor. + MacAddress string `json:"macAddress,omitempty"` + + // ForceSendFields is a list of field names (e.g. "IpAddress") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "IpAddress") to include in + // API requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *InterconnectDiagnosticsARPEntry) MarshalJSON() ([]byte, error) { + type NoMethod InterconnectDiagnosticsARPEntry + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type InterconnectDiagnosticsLinkLACPStatus struct { + // GoogleSystemId: System ID of the port on Google?s side of the LACP + // exchange. + GoogleSystemId string `json:"googleSystemId,omitempty"` + + // NeighborSystemId: System ID of the port on the neighbor?s side of the + // LACP exchange. + NeighborSystemId string `json:"neighborSystemId,omitempty"` + + // Possible values: + // "ACTIVE" + // "DETACHED" + State string `json:"state,omitempty"` + + // ForceSendFields is a list of field names (e.g. "GoogleSystemId") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "GoogleSystemId") to + // include in API requests with the JSON null value. By default, fields + // with empty values are omitted from API requests. However, any field + // with an empty value appearing in NullFields will be sent to the + // server as null. It is an error if a field in this list has a + // non-empty value. This may be used to include null fields in Patch + // requests. + NullFields []string `json:"-"` +} + +func (s *InterconnectDiagnosticsLinkLACPStatus) MarshalJSON() ([]byte, error) { + type NoMethod InterconnectDiagnosticsLinkLACPStatus + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type InterconnectDiagnosticsLinkOpticalPower struct { + // Possible values: + // "HIGH_ALARM" + // "HIGH_WARNING" + // "LOW_ALARM" + // "LOW_WARNING" + // "OK" + State string `json:"state,omitempty"` + + // Value: Value of the current optical power, read in dBm. Take a known + // good optical value, give it a 10% margin and trigger warnings + // relative to that value. In general, a -7dBm warning and a -11dBm + // alarm are good optical value estimates for most links. + Value float64 `json:"value,omitempty"` + + // ForceSendFields is a list of field names (e.g. "State") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "State") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *InterconnectDiagnosticsLinkOpticalPower) MarshalJSON() ([]byte, error) { + type NoMethod InterconnectDiagnosticsLinkOpticalPower + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +func (s *InterconnectDiagnosticsLinkOpticalPower) UnmarshalJSON(data []byte) error { + type NoMethod InterconnectDiagnosticsLinkOpticalPower + var s1 struct { + Value gensupport.JSONFloat64 `json:"value"` + *NoMethod + } + s1.NoMethod = (*NoMethod)(s) + if err := json.Unmarshal(data, &s1); err != nil { + return err + } + s.Value = float64(s1.Value) + return nil +} + +type InterconnectDiagnosticsLinkStatus struct { + // ArpCaches: A list of InterconnectDiagnostics.ARPEntry objects, + // describing the ARP neighbor entries seen on this link. This will be + // empty if the link is bundled + ArpCaches []*InterconnectDiagnosticsARPEntry `json:"arpCaches,omitempty"` + + // CircuitId: The unique ID for this link assigned during turn up by + // Google. + CircuitId string `json:"circuitId,omitempty"` + + // GoogleDemarc: The Demarc address assigned by Google and provided in + // the LoA. + GoogleDemarc string `json:"googleDemarc,omitempty"` + + LacpStatus *InterconnectDiagnosticsLinkLACPStatus `json:"lacpStatus,omitempty"` + + ReceivingOpticalPower *InterconnectDiagnosticsLinkOpticalPower `json:"receivingOpticalPower,omitempty"` + + TransmittingOpticalPower *InterconnectDiagnosticsLinkOpticalPower `json:"transmittingOpticalPower,omitempty"` + + // ForceSendFields is a list of field names (e.g. "ArpCaches") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "ArpCaches") to include in + // API requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *InterconnectDiagnosticsLinkStatus) MarshalJSON() ([]byte, error) { + type NoMethod InterconnectDiagnosticsLinkStatus + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + // InterconnectList: Response to the list request, and contains a list // of interconnects. type InterconnectList struct { @@ -12810,10 +13667,10 @@ type InterconnectLocation struct { // each line in the address is separated by a newline character. Address string `json:"address,omitempty"` - // AvailabilityZone: [Output Only] Availability zone for this location. - // Within a metropolitan area (metro), maintenance will not be - // simultaneously scheduled in more than one availability zone. Example: - // "zone1" or "zone2". + // AvailabilityZone: [Output Only] Availability zone for this + // InterconnectLocation. Within a metropolitan area (metro), maintenance + // will not be simultaneously scheduled in more than one availability + // zone. Example: "zone1" or "zone2". AvailabilityZone string `json:"availabilityZone,omitempty"` // City: [Output Only] Metropolitan area designator that indicates which @@ -13175,6 +14032,38 @@ func (s *InterconnectOutageNotification) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +// InterconnectsGetDiagnosticsResponse: Response for the +// InterconnectsGetDiagnosticsRequest. +type InterconnectsGetDiagnosticsResponse struct { + Result *InterconnectDiagnostics `json:"result,omitempty"` + + // ServerResponse contains the HTTP response code and headers from the + // server. + googleapi.ServerResponse `json:"-"` + + // ForceSendFields is a list of field names (e.g. "Result") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Result") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *InterconnectsGetDiagnosticsResponse) MarshalJSON() ([]byte, error) { + type NoMethod InterconnectsGetDiagnosticsResponse + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + // License: A license resource. type License struct { // ChargesUseFee: [Output Only] Deprecated. This field no longer @@ -13201,8 +14090,8 @@ type License struct { // license to images, snapshots, and disks. LicenseCode uint64 `json:"licenseCode,omitempty,string"` - // Name: [Output Only] Name of the resource. The name is 1-63 characters - // long and complies with RFC1035. + // Name: Name of the resource. The name must be 1-63 characters long and + // comply with RFC1035. Name string `json:"name,omitempty"` ResourceRequirements *LicenseResourceRequirements `json:"resourceRequirements,omitempty"` @@ -13527,6 +14416,175 @@ func (s *LicensesListResponseWarningData) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +// LogConfig: Specifies what kind of log the caller must write +type LogConfig struct { + // CloudAudit: Cloud audit options. + CloudAudit *LogConfigCloudAuditOptions `json:"cloudAudit,omitempty"` + + // Counter: Counter options. + Counter *LogConfigCounterOptions `json:"counter,omitempty"` + + // DataAccess: Data access options. + DataAccess *LogConfigDataAccessOptions `json:"dataAccess,omitempty"` + + // ForceSendFields is a list of field names (e.g. "CloudAudit") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "CloudAudit") to include in + // API requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *LogConfig) MarshalJSON() ([]byte, error) { + type NoMethod LogConfig + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// LogConfigCloudAuditOptions: Write a Cloud Audit log +type LogConfigCloudAuditOptions struct { + // AuthorizationLoggingOptions: Information used by the Cloud Audit + // Logging pipeline. + AuthorizationLoggingOptions *AuthorizationLoggingOptions `json:"authorizationLoggingOptions,omitempty"` + + // LogName: The log_name to populate in the Cloud Audit Record. + // + // Possible values: + // "ADMIN_ACTIVITY" + // "DATA_ACCESS" + // "UNSPECIFIED_LOG_NAME" + LogName string `json:"logName,omitempty"` + + // ForceSendFields is a list of field names (e.g. + // "AuthorizationLoggingOptions") to unconditionally include in API + // requests. By default, fields with empty values are omitted from API + // requests. However, any non-pointer, non-interface field appearing in + // ForceSendFields will be sent to the server regardless of whether the + // field is empty or not. This may be used to include empty fields in + // Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. + // "AuthorizationLoggingOptions") to include in API requests with the + // JSON null value. By default, fields with empty values are omitted + // from API requests. However, any field with an empty value appearing + // in NullFields will be sent to the server as null. It is an error if a + // field in this list has a non-empty value. This may be used to include + // null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *LogConfigCloudAuditOptions) MarshalJSON() ([]byte, error) { + type NoMethod LogConfigCloudAuditOptions + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// LogConfigCounterOptions: Increment a streamz counter with the +// specified metric and field names. +// +// Metric names should start with a '/', generally be lowercase-only, +// and end in "_count". Field names should not contain an initial slash. +// The actual exported metric names will have "/iam/policy" +// prepended. +// +// Field names correspond to IAM request parameters and field values are +// their respective values. +// +// Supported field names: - "authority", which is "[token]" if +// IAMContext.token is present, otherwise the value of +// IAMContext.authority_selector if present, and otherwise a +// representation of IAMContext.principal; or - "iam_principal", a +// representation of IAMContext.principal even if a token or authority +// selector is present; or - "" (empty string), resulting in a counter +// with no fields. +// +// Examples: counter { metric: "/debug_access_count" field: +// "iam_principal" } ==> increment counter +// /iam/policy/backend_debug_access_count {iam_principal=[value of +// IAMContext.principal]} +// +// At this time we do not support multiple field names (though this may +// be supported in the future). +type LogConfigCounterOptions struct { + // Field: The field value to attribute. + Field string `json:"field,omitempty"` + + // Metric: The metric to update. + Metric string `json:"metric,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Field") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Field") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *LogConfigCounterOptions) MarshalJSON() ([]byte, error) { + type NoMethod LogConfigCounterOptions + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// LogConfigDataAccessOptions: Write a Data Access (Gin) log +type LogConfigDataAccessOptions struct { + // LogMode: Whether Gin logging should happen in a fail-closed manner at + // the caller. This is relevant only in the LocalIAM implementation, for + // now. + // + // NOTE: Logging to Gin in a fail-closed manner is currently unsupported + // while work is being done to satisfy the requirements of go/345. + // Currently, setting LOG_FAIL_CLOSED mode will have no effect, but + // still exists because there is active work being done to support it + // (b/115874152). + // + // Possible values: + // "LOG_FAIL_CLOSED" + // "LOG_MODE_UNSPECIFIED" + LogMode string `json:"logMode,omitempty"` + + // ForceSendFields is a list of field names (e.g. "LogMode") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "LogMode") to include in + // API requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *LogConfigDataAccessOptions) MarshalJSON() ([]byte, error) { + type NoMethod LogConfigDataAccessOptions + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + // MachineType: A Machine Type resource. (== resource_for // v1.machineTypes ==) (== resource_for beta.machineTypes ==) type MachineType struct { @@ -14126,6 +15184,7 @@ type ManagedInstance struct { // "RECREATING" // "REFRESHING" // "RESTARTING" + // "VERIFYING" CurrentAction string `json:"currentAction,omitempty"` // Id: [Output only] The unique identifier for this resource. This field @@ -14276,7 +15335,11 @@ type Metadata struct { // locking. The fingerprint is initially generated by Compute Engine and // changes after every request to modify or update metadata. You must // always provide an up-to-date fingerprint hash in order to update or - // change metadata. + // change metadata, otherwise the request will fail with error 412 + // conditionNotMet. + // + // To see the latest fingerprint, make a get() request to retrieve the + // resource. Fingerprint string `json:"fingerprint,omitempty"` // Items: Array of key/value pairs. The total size of all keys and @@ -14379,22 +15442,22 @@ func (s *NamedPort) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } -// Network: Represents a Network resource. Read Networks and Firewalls -// for more information. (== resource_for v1.networks ==) (== -// resource_for beta.networks ==) +// Network: Represents a Network resource. Read Virtual Private Cloud +// (VPC) Network Overview for more information. (== resource_for +// v1.networks ==) (== resource_for beta.networks ==) type Network struct { // IPv4Range: The range of internal addresses that are legal on this // network. This range is a CIDR specification, for example: // 192.168.0.0/16. Provided by the client when the network is created. IPv4Range string `json:"IPv4Range,omitempty"` - // AutoCreateSubnetworks: When set to true, the network is created in - // "auto subnet mode". When set to false, the network is in "custom - // subnet mode". + // AutoCreateSubnetworks: When set to true, the VPC network is created + // in "auto" mode. When set to false, the VPC network is created in + // "custom" mode. // - // In "auto subnet mode", a newly created network is assigned the - // default CIDR of 10.128.0.0/9 and it automatically creates one - // subnetwork per region. + // An auto mode VPC network starts with one subnet per region. Each + // subnet has a predetermined range as described in Auto mode VPC + // network IP ranges. AutoCreateSubnetworks bool `json:"autoCreateSubnetworks,omitempty"` // CreationTimestamp: [Output Only] Creation timestamp in RFC3339 text @@ -14405,9 +15468,8 @@ type Network struct { // property when you create the resource. Description string `json:"description,omitempty"` - // GatewayIPv4: A gateway address for default routing to other networks. - // This value is read only and is selected by the Google Compute Engine, - // typically as the first usable address in the IPv4Range. + // GatewayIPv4: [Output Only] The gateway address for default routing + // out of the network. This value is read only and is selected by GCP. GatewayIPv4 string `json:"gatewayIPv4,omitempty"` // Id: [Output Only] The unique identifier for the resource. This @@ -14439,7 +15501,7 @@ type Network struct { SelfLink string `json:"selfLink,omitempty"` // Subnetworks: [Output Only] Server-defined fully-qualified URLs for - // all subnetworks in this network. + // all subnetworks in this VPC network. Subnetworks []string `json:"subnetworks,omitempty"` // ServerResponse contains the HTTP response code and headers from the @@ -14486,7 +15548,8 @@ type NetworkInterface struct { // Fingerprint: Fingerprint hash of contents stored in this network // interface. This field will be ignored when inserting an Instance or // adding a NetworkInterface. An up-to-date fingerprint must be provided - // in order to update the NetworkInterface. + // in order to update the NetworkInterface, otherwise the request will + // fail with error 412 conditionNotMet. Fingerprint string `json:"fingerprint,omitempty"` // Kind: [Output Only] Type of the resource. Always @@ -14715,11 +15778,11 @@ func (s *NetworkListWarningData) MarshalJSON() ([]byte, error) { // flag indicating whether Google Compute Engine should automatically // create routes for the peering. type NetworkPeering struct { - // AutoCreateRoutes: Whether full mesh connectivity is created and - // managed automatically. When it is set to true, Google Compute Engine - // will automatically create and manage the routes between two networks - // when the state is ACTIVE. Otherwise, user needs to create routes - // manually to route packets to peer network. + // AutoCreateRoutes: Indicates whether full mesh connectivity is created + // and managed automatically. When it is set to true, Google Compute + // Engine will automatically create and manage the routes between two + // networks when the state is ACTIVE. Otherwise, user needs to create + // routes manually to route packets to peer network. AutoCreateRoutes bool `json:"autoCreateRoutes,omitempty"` // Name: Name of this peering. Provided by the client when the peering @@ -14779,9 +15842,9 @@ func (s *NetworkPeering) MarshalJSON() ([]byte, error) { type NetworkRoutingConfig struct { // RoutingMode: The network-wide routing mode to use. If set to // REGIONAL, this network's cloud routers will only advertise routes - // with subnetworks of this network in the same region as the router. If - // set to GLOBAL, this network's cloud routers will advertise routes - // with all subnetworks of this network, across regions. + // with subnets of this network in the same region as the router. If set + // to GLOBAL, this network's cloud routers will advertise routes with + // all subnets of this network, across regions. // // Possible values: // "GLOBAL" @@ -14876,6 +15939,1893 @@ func (s *NetworksRemovePeeringRequest) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +// NodeGroup: A NodeGroup resource. +type NodeGroup struct { + // CreationTimestamp: [Output Only] Creation timestamp in RFC3339 text + // format. + CreationTimestamp string `json:"creationTimestamp,omitempty"` + + // Description: An optional description of this resource. Provide this + // property when you create the resource. + Description string `json:"description,omitempty"` + + // Id: [Output Only] The unique identifier for the resource. This + // identifier is defined by the server. + Id uint64 `json:"id,omitempty,string"` + + // Kind: [Output Only] The type of the resource. Always + // compute#nodeGroup for node group. + Kind string `json:"kind,omitempty"` + + // Name: The name of the resource, provided by the client when initially + // creating the resource. The resource name must be 1-63 characters + // long, and comply with RFC1035. Specifically, the name must be 1-63 + // characters long and match the regular expression + // `[a-z]([-a-z0-9]*[a-z0-9])?` which means the first character must be + // a lowercase letter, and all following characters must be a dash, + // lowercase letter, or digit, except the last character, which cannot + // be a dash. + Name string `json:"name,omitempty"` + + // NodeTemplate: The URL of the node template to which this node group + // belongs. + NodeTemplate string `json:"nodeTemplate,omitempty"` + + // SelfLink: [Output Only] Server-defined URL for the resource. + SelfLink string `json:"selfLink,omitempty"` + + // Size: [Output Only] The total number of nodes in the node group. + Size int64 `json:"size,omitempty"` + + // Possible values: + // "CREATING" + // "DELETING" + // "INVALID" + // "READY" + Status string `json:"status,omitempty"` + + // Zone: [Output Only] The name of the zone where the node group + // resides, such as us-central1-a. + Zone string `json:"zone,omitempty"` + + // ServerResponse contains the HTTP response code and headers from the + // server. + googleapi.ServerResponse `json:"-"` + + // ForceSendFields is a list of field names (e.g. "CreationTimestamp") + // to unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "CreationTimestamp") to + // include in API requests with the JSON null value. By default, fields + // with empty values are omitted from API requests. However, any field + // with an empty value appearing in NullFields will be sent to the + // server as null. It is an error if a field in this list has a + // non-empty value. This may be used to include null fields in Patch + // requests. + NullFields []string `json:"-"` +} + +func (s *NodeGroup) MarshalJSON() ([]byte, error) { + type NoMethod NodeGroup + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type NodeGroupAggregatedList struct { + // Id: [Output Only] Unique identifier for the resource; defined by the + // server. + Id string `json:"id,omitempty"` + + // Items: A list of NodeGroupsScopedList resources. + Items map[string]NodeGroupsScopedList `json:"items,omitempty"` + + // Kind: [Output Only] Type of resource.Always + // compute#nodeGroupAggregatedList for aggregated lists of node groups. + Kind string `json:"kind,omitempty"` + + // NextPageToken: [Output Only] This token allows you to get the next + // page of results for list requests. If the number of results is larger + // than maxResults, use the nextPageToken as a value for the query + // parameter pageToken in the next list request. Subsequent list + // requests will have their own nextPageToken to continue paging through + // the results. + NextPageToken string `json:"nextPageToken,omitempty"` + + // SelfLink: [Output Only] Server-defined URL for this resource. + SelfLink string `json:"selfLink,omitempty"` + + // Warning: [Output Only] Informational warning message. + Warning *NodeGroupAggregatedListWarning `json:"warning,omitempty"` + + // ServerResponse contains the HTTP response code and headers from the + // server. + googleapi.ServerResponse `json:"-"` + + // ForceSendFields is a list of field names (e.g. "Id") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Id") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *NodeGroupAggregatedList) MarshalJSON() ([]byte, error) { + type NoMethod NodeGroupAggregatedList + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// NodeGroupAggregatedListWarning: [Output Only] Informational warning +// message. +type NodeGroupAggregatedListWarning struct { + // Code: [Output Only] A warning code, if applicable. For example, + // Compute Engine returns NO_RESULTS_ON_PAGE if there are no results in + // the response. + // + // Possible values: + // "CLEANUP_FAILED" + // "DEPRECATED_RESOURCE_USED" + // "DEPRECATED_TYPE_USED" + // "DISK_SIZE_LARGER_THAN_IMAGE_SIZE" + // "EXPERIMENTAL_TYPE_USED" + // "EXTERNAL_API_WARNING" + // "FIELD_VALUE_OVERRIDEN" + // "INJECTED_KERNELS_DEPRECATED" + // "MISSING_TYPE_DEPENDENCY" + // "NEXT_HOP_ADDRESS_NOT_ASSIGNED" + // "NEXT_HOP_CANNOT_IP_FORWARD" + // "NEXT_HOP_INSTANCE_NOT_FOUND" + // "NEXT_HOP_INSTANCE_NOT_ON_NETWORK" + // "NEXT_HOP_NOT_RUNNING" + // "NOT_CRITICAL_ERROR" + // "NO_RESULTS_ON_PAGE" + // "REQUIRED_TOS_AGREEMENT" + // "RESOURCE_IN_USE_BY_OTHER_RESOURCE_WARNING" + // "RESOURCE_NOT_DELETED" + // "SCHEMA_VALIDATION_IGNORED" + // "SINGLE_INSTANCE_PROPERTY_TEMPLATE" + // "UNDECLARED_PROPERTIES" + // "UNREACHABLE" + Code string `json:"code,omitempty"` + + // Data: [Output Only] Metadata about this warning in key: value format. + // For example: + // "data": [ { "key": "scope", "value": "zones/us-east1-d" } + Data []*NodeGroupAggregatedListWarningData `json:"data,omitempty"` + + // Message: [Output Only] A human-readable description of the warning + // code. + Message string `json:"message,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Code") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Code") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *NodeGroupAggregatedListWarning) MarshalJSON() ([]byte, error) { + type NoMethod NodeGroupAggregatedListWarning + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type NodeGroupAggregatedListWarningData struct { + // Key: [Output Only] A key that provides more detail on the warning + // being returned. For example, for warnings where there are no results + // in a list request for a particular zone, this key might be scope and + // the key value might be the zone name. Other examples might be a key + // indicating a deprecated resource and a suggested replacement, or a + // warning about invalid network settings (for example, if an instance + // attempts to perform IP forwarding but is not enabled for IP + // forwarding). + Key string `json:"key,omitempty"` + + // Value: [Output Only] A warning data value corresponding to the key. + Value string `json:"value,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Key") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Key") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *NodeGroupAggregatedListWarningData) MarshalJSON() ([]byte, error) { + type NoMethod NodeGroupAggregatedListWarningData + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// NodeGroupList: Contains a list of nodeGroups. +type NodeGroupList struct { + // Id: [Output Only] Unique identifier for the resource; defined by the + // server. + Id string `json:"id,omitempty"` + + // Items: A list of NodeGroup resources. + Items []*NodeGroup `json:"items,omitempty"` + + // Kind: [Output Only] Type of resource.Always compute#nodeGroupList for + // lists of node groups. + Kind string `json:"kind,omitempty"` + + // NextPageToken: [Output Only] This token allows you to get the next + // page of results for list requests. If the number of results is larger + // than maxResults, use the nextPageToken as a value for the query + // parameter pageToken in the next list request. Subsequent list + // requests will have their own nextPageToken to continue paging through + // the results. + NextPageToken string `json:"nextPageToken,omitempty"` + + // SelfLink: [Output Only] Server-defined URL for this resource. + SelfLink string `json:"selfLink,omitempty"` + + // Warning: [Output Only] Informational warning message. + Warning *NodeGroupListWarning `json:"warning,omitempty"` + + // ServerResponse contains the HTTP response code and headers from the + // server. + googleapi.ServerResponse `json:"-"` + + // ForceSendFields is a list of field names (e.g. "Id") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Id") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *NodeGroupList) MarshalJSON() ([]byte, error) { + type NoMethod NodeGroupList + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// NodeGroupListWarning: [Output Only] Informational warning message. +type NodeGroupListWarning struct { + // Code: [Output Only] A warning code, if applicable. For example, + // Compute Engine returns NO_RESULTS_ON_PAGE if there are no results in + // the response. + // + // Possible values: + // "CLEANUP_FAILED" + // "DEPRECATED_RESOURCE_USED" + // "DEPRECATED_TYPE_USED" + // "DISK_SIZE_LARGER_THAN_IMAGE_SIZE" + // "EXPERIMENTAL_TYPE_USED" + // "EXTERNAL_API_WARNING" + // "FIELD_VALUE_OVERRIDEN" + // "INJECTED_KERNELS_DEPRECATED" + // "MISSING_TYPE_DEPENDENCY" + // "NEXT_HOP_ADDRESS_NOT_ASSIGNED" + // "NEXT_HOP_CANNOT_IP_FORWARD" + // "NEXT_HOP_INSTANCE_NOT_FOUND" + // "NEXT_HOP_INSTANCE_NOT_ON_NETWORK" + // "NEXT_HOP_NOT_RUNNING" + // "NOT_CRITICAL_ERROR" + // "NO_RESULTS_ON_PAGE" + // "REQUIRED_TOS_AGREEMENT" + // "RESOURCE_IN_USE_BY_OTHER_RESOURCE_WARNING" + // "RESOURCE_NOT_DELETED" + // "SCHEMA_VALIDATION_IGNORED" + // "SINGLE_INSTANCE_PROPERTY_TEMPLATE" + // "UNDECLARED_PROPERTIES" + // "UNREACHABLE" + Code string `json:"code,omitempty"` + + // Data: [Output Only] Metadata about this warning in key: value format. + // For example: + // "data": [ { "key": "scope", "value": "zones/us-east1-d" } + Data []*NodeGroupListWarningData `json:"data,omitempty"` + + // Message: [Output Only] A human-readable description of the warning + // code. + Message string `json:"message,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Code") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Code") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *NodeGroupListWarning) MarshalJSON() ([]byte, error) { + type NoMethod NodeGroupListWarning + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type NodeGroupListWarningData struct { + // Key: [Output Only] A key that provides more detail on the warning + // being returned. For example, for warnings where there are no results + // in a list request for a particular zone, this key might be scope and + // the key value might be the zone name. Other examples might be a key + // indicating a deprecated resource and a suggested replacement, or a + // warning about invalid network settings (for example, if an instance + // attempts to perform IP forwarding but is not enabled for IP + // forwarding). + Key string `json:"key,omitempty"` + + // Value: [Output Only] A warning data value corresponding to the key. + Value string `json:"value,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Key") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Key") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *NodeGroupListWarningData) MarshalJSON() ([]byte, error) { + type NoMethod NodeGroupListWarningData + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type NodeGroupNode struct { + // Instances: Instances scheduled on this node. + Instances []string `json:"instances,omitempty"` + + // Name: The name of the node. + Name string `json:"name,omitempty"` + + // NodeType: The type of this node. + NodeType string `json:"nodeType,omitempty"` + + // Possible values: + // "CREATING" + // "DELETING" + // "INVALID" + // "READY" + // "REPAIRING" + Status string `json:"status,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Instances") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Instances") to include in + // API requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *NodeGroupNode) MarshalJSON() ([]byte, error) { + type NoMethod NodeGroupNode + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type NodeGroupsAddNodesRequest struct { + // AdditionalNodeCount: Count of additional nodes to be added to the + // node group. + AdditionalNodeCount int64 `json:"additionalNodeCount,omitempty"` + + // ForceSendFields is a list of field names (e.g. "AdditionalNodeCount") + // to unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "AdditionalNodeCount") to + // include in API requests with the JSON null value. By default, fields + // with empty values are omitted from API requests. However, any field + // with an empty value appearing in NullFields will be sent to the + // server as null. It is an error if a field in this list has a + // non-empty value. This may be used to include null fields in Patch + // requests. + NullFields []string `json:"-"` +} + +func (s *NodeGroupsAddNodesRequest) MarshalJSON() ([]byte, error) { + type NoMethod NodeGroupsAddNodesRequest + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type NodeGroupsDeleteNodesRequest struct { + Nodes []string `json:"nodes,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Nodes") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Nodes") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *NodeGroupsDeleteNodesRequest) MarshalJSON() ([]byte, error) { + type NoMethod NodeGroupsDeleteNodesRequest + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type NodeGroupsListNodes struct { + // Id: [Output Only] Unique identifier for the resource; defined by the + // server. + Id string `json:"id,omitempty"` + + // Items: A list of Node resources. + Items []*NodeGroupNode `json:"items,omitempty"` + + // Kind: [Output Only] The resource type, which is always + // compute.nodeGroupsListNodes for the list of nodes in the specified + // node group. + Kind string `json:"kind,omitempty"` + + // NextPageToken: [Output Only] This token allows you to get the next + // page of results for list requests. If the number of results is larger + // than maxResults, use the nextPageToken as a value for the query + // parameter pageToken in the next list request. Subsequent list + // requests will have their own nextPageToken to continue paging through + // the results. + NextPageToken string `json:"nextPageToken,omitempty"` + + // SelfLink: [Output Only] Server-defined URL for this resource. + SelfLink string `json:"selfLink,omitempty"` + + // Warning: [Output Only] Informational warning message. + Warning *NodeGroupsListNodesWarning `json:"warning,omitempty"` + + // ServerResponse contains the HTTP response code and headers from the + // server. + googleapi.ServerResponse `json:"-"` + + // ForceSendFields is a list of field names (e.g. "Id") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Id") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *NodeGroupsListNodes) MarshalJSON() ([]byte, error) { + type NoMethod NodeGroupsListNodes + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// NodeGroupsListNodesWarning: [Output Only] Informational warning +// message. +type NodeGroupsListNodesWarning struct { + // Code: [Output Only] A warning code, if applicable. For example, + // Compute Engine returns NO_RESULTS_ON_PAGE if there are no results in + // the response. + // + // Possible values: + // "CLEANUP_FAILED" + // "DEPRECATED_RESOURCE_USED" + // "DEPRECATED_TYPE_USED" + // "DISK_SIZE_LARGER_THAN_IMAGE_SIZE" + // "EXPERIMENTAL_TYPE_USED" + // "EXTERNAL_API_WARNING" + // "FIELD_VALUE_OVERRIDEN" + // "INJECTED_KERNELS_DEPRECATED" + // "MISSING_TYPE_DEPENDENCY" + // "NEXT_HOP_ADDRESS_NOT_ASSIGNED" + // "NEXT_HOP_CANNOT_IP_FORWARD" + // "NEXT_HOP_INSTANCE_NOT_FOUND" + // "NEXT_HOP_INSTANCE_NOT_ON_NETWORK" + // "NEXT_HOP_NOT_RUNNING" + // "NOT_CRITICAL_ERROR" + // "NO_RESULTS_ON_PAGE" + // "REQUIRED_TOS_AGREEMENT" + // "RESOURCE_IN_USE_BY_OTHER_RESOURCE_WARNING" + // "RESOURCE_NOT_DELETED" + // "SCHEMA_VALIDATION_IGNORED" + // "SINGLE_INSTANCE_PROPERTY_TEMPLATE" + // "UNDECLARED_PROPERTIES" + // "UNREACHABLE" + Code string `json:"code,omitempty"` + + // Data: [Output Only] Metadata about this warning in key: value format. + // For example: + // "data": [ { "key": "scope", "value": "zones/us-east1-d" } + Data []*NodeGroupsListNodesWarningData `json:"data,omitempty"` + + // Message: [Output Only] A human-readable description of the warning + // code. + Message string `json:"message,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Code") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Code") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *NodeGroupsListNodesWarning) MarshalJSON() ([]byte, error) { + type NoMethod NodeGroupsListNodesWarning + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type NodeGroupsListNodesWarningData struct { + // Key: [Output Only] A key that provides more detail on the warning + // being returned. For example, for warnings where there are no results + // in a list request for a particular zone, this key might be scope and + // the key value might be the zone name. Other examples might be a key + // indicating a deprecated resource and a suggested replacement, or a + // warning about invalid network settings (for example, if an instance + // attempts to perform IP forwarding but is not enabled for IP + // forwarding). + Key string `json:"key,omitempty"` + + // Value: [Output Only] A warning data value corresponding to the key. + Value string `json:"value,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Key") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Key") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *NodeGroupsListNodesWarningData) MarshalJSON() ([]byte, error) { + type NoMethod NodeGroupsListNodesWarningData + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type NodeGroupsScopedList struct { + // NodeGroups: [Output Only] A list of node groups contained in this + // scope. + NodeGroups []*NodeGroup `json:"nodeGroups,omitempty"` + + // Warning: [Output Only] An informational warning that appears when the + // nodeGroup list is empty. + Warning *NodeGroupsScopedListWarning `json:"warning,omitempty"` + + // ForceSendFields is a list of field names (e.g. "NodeGroups") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "NodeGroups") to include in + // API requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *NodeGroupsScopedList) MarshalJSON() ([]byte, error) { + type NoMethod NodeGroupsScopedList + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// NodeGroupsScopedListWarning: [Output Only] An informational warning +// that appears when the nodeGroup list is empty. +type NodeGroupsScopedListWarning struct { + // Code: [Output Only] A warning code, if applicable. For example, + // Compute Engine returns NO_RESULTS_ON_PAGE if there are no results in + // the response. + // + // Possible values: + // "CLEANUP_FAILED" + // "DEPRECATED_RESOURCE_USED" + // "DEPRECATED_TYPE_USED" + // "DISK_SIZE_LARGER_THAN_IMAGE_SIZE" + // "EXPERIMENTAL_TYPE_USED" + // "EXTERNAL_API_WARNING" + // "FIELD_VALUE_OVERRIDEN" + // "INJECTED_KERNELS_DEPRECATED" + // "MISSING_TYPE_DEPENDENCY" + // "NEXT_HOP_ADDRESS_NOT_ASSIGNED" + // "NEXT_HOP_CANNOT_IP_FORWARD" + // "NEXT_HOP_INSTANCE_NOT_FOUND" + // "NEXT_HOP_INSTANCE_NOT_ON_NETWORK" + // "NEXT_HOP_NOT_RUNNING" + // "NOT_CRITICAL_ERROR" + // "NO_RESULTS_ON_PAGE" + // "REQUIRED_TOS_AGREEMENT" + // "RESOURCE_IN_USE_BY_OTHER_RESOURCE_WARNING" + // "RESOURCE_NOT_DELETED" + // "SCHEMA_VALIDATION_IGNORED" + // "SINGLE_INSTANCE_PROPERTY_TEMPLATE" + // "UNDECLARED_PROPERTIES" + // "UNREACHABLE" + Code string `json:"code,omitempty"` + + // Data: [Output Only] Metadata about this warning in key: value format. + // For example: + // "data": [ { "key": "scope", "value": "zones/us-east1-d" } + Data []*NodeGroupsScopedListWarningData `json:"data,omitempty"` + + // Message: [Output Only] A human-readable description of the warning + // code. + Message string `json:"message,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Code") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Code") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *NodeGroupsScopedListWarning) MarshalJSON() ([]byte, error) { + type NoMethod NodeGroupsScopedListWarning + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type NodeGroupsScopedListWarningData struct { + // Key: [Output Only] A key that provides more detail on the warning + // being returned. For example, for warnings where there are no results + // in a list request for a particular zone, this key might be scope and + // the key value might be the zone name. Other examples might be a key + // indicating a deprecated resource and a suggested replacement, or a + // warning about invalid network settings (for example, if an instance + // attempts to perform IP forwarding but is not enabled for IP + // forwarding). + Key string `json:"key,omitempty"` + + // Value: [Output Only] A warning data value corresponding to the key. + Value string `json:"value,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Key") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Key") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *NodeGroupsScopedListWarningData) MarshalJSON() ([]byte, error) { + type NoMethod NodeGroupsScopedListWarningData + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type NodeGroupsSetNodeTemplateRequest struct { + // NodeTemplate: Full or partial URL of the node template resource to be + // updated for this node group. + NodeTemplate string `json:"nodeTemplate,omitempty"` + + // ForceSendFields is a list of field names (e.g. "NodeTemplate") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "NodeTemplate") to include + // in API requests with the JSON null value. By default, fields with + // empty values are omitted from API requests. However, any field with + // an empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *NodeGroupsSetNodeTemplateRequest) MarshalJSON() ([]byte, error) { + type NoMethod NodeGroupsSetNodeTemplateRequest + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// NodeTemplate: A Node Template resource. +type NodeTemplate struct { + // CreationTimestamp: [Output Only] Creation timestamp in RFC3339 text + // format. + CreationTimestamp string `json:"creationTimestamp,omitempty"` + + // Description: An optional description of this resource. Provide this + // property when you create the resource. + Description string `json:"description,omitempty"` + + // Id: [Output Only] The unique identifier for the resource. This + // identifier is defined by the server. + Id uint64 `json:"id,omitempty,string"` + + // Kind: [Output Only] The type of the resource. Always + // compute#nodeTemplate for node templates. + Kind string `json:"kind,omitempty"` + + // Name: The name of the resource, provided by the client when initially + // creating the resource. The resource name must be 1-63 characters + // long, and comply with RFC1035. Specifically, the name must be 1-63 + // characters long and match the regular expression + // `[a-z]([-a-z0-9]*[a-z0-9])?` which means the first character must be + // a lowercase letter, and all following characters must be a dash, + // lowercase letter, or digit, except the last character, which cannot + // be a dash. + Name string `json:"name,omitempty"` + + // NodeAffinityLabels: Labels to use for node affinity, which will be + // used in instance scheduling. + NodeAffinityLabels map[string]string `json:"nodeAffinityLabels,omitempty"` + + // NodeType: The node type to use for nodes group that are created from + // this template. + NodeType string `json:"nodeType,omitempty"` + + // NodeTypeFlexibility: The flexible properties of the desired node + // type. Node groups that use this node template will create nodes of a + // type that matches these properties. + // + // This field is mutually exclusive with the node_type property; you can + // only define one or the other, but not both. + NodeTypeFlexibility *NodeTemplateNodeTypeFlexibility `json:"nodeTypeFlexibility,omitempty"` + + // Region: [Output Only] The name of the region where the node template + // resides, such as us-central1. + Region string `json:"region,omitempty"` + + // SelfLink: [Output Only] Server-defined URL for the resource. + SelfLink string `json:"selfLink,omitempty"` + + // Status: [Output Only] The status of the node template. One of the + // following values: CREATING, READY, and DELETING. + // + // Possible values: + // "CREATING" + // "DELETING" + // "INVALID" + // "READY" + Status string `json:"status,omitempty"` + + // StatusMessage: [Output Only] An optional, human-readable explanation + // of the status. + StatusMessage string `json:"statusMessage,omitempty"` + + // ServerResponse contains the HTTP response code and headers from the + // server. + googleapi.ServerResponse `json:"-"` + + // ForceSendFields is a list of field names (e.g. "CreationTimestamp") + // to unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "CreationTimestamp") to + // include in API requests with the JSON null value. By default, fields + // with empty values are omitted from API requests. However, any field + // with an empty value appearing in NullFields will be sent to the + // server as null. It is an error if a field in this list has a + // non-empty value. This may be used to include null fields in Patch + // requests. + NullFields []string `json:"-"` +} + +func (s *NodeTemplate) MarshalJSON() ([]byte, error) { + type NoMethod NodeTemplate + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type NodeTemplateAggregatedList struct { + // Id: [Output Only] Unique identifier for the resource; defined by the + // server. + Id string `json:"id,omitempty"` + + // Items: A list of NodeTemplatesScopedList resources. + Items map[string]NodeTemplatesScopedList `json:"items,omitempty"` + + // Kind: [Output Only] Type of resource.Always + // compute#nodeTemplateAggregatedList for aggregated lists of node + // templates. + Kind string `json:"kind,omitempty"` + + // NextPageToken: [Output Only] This token allows you to get the next + // page of results for list requests. If the number of results is larger + // than maxResults, use the nextPageToken as a value for the query + // parameter pageToken in the next list request. Subsequent list + // requests will have their own nextPageToken to continue paging through + // the results. + NextPageToken string `json:"nextPageToken,omitempty"` + + // SelfLink: [Output Only] Server-defined URL for this resource. + SelfLink string `json:"selfLink,omitempty"` + + // Warning: [Output Only] Informational warning message. + Warning *NodeTemplateAggregatedListWarning `json:"warning,omitempty"` + + // ServerResponse contains the HTTP response code and headers from the + // server. + googleapi.ServerResponse `json:"-"` + + // ForceSendFields is a list of field names (e.g. "Id") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Id") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *NodeTemplateAggregatedList) MarshalJSON() ([]byte, error) { + type NoMethod NodeTemplateAggregatedList + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// NodeTemplateAggregatedListWarning: [Output Only] Informational +// warning message. +type NodeTemplateAggregatedListWarning struct { + // Code: [Output Only] A warning code, if applicable. For example, + // Compute Engine returns NO_RESULTS_ON_PAGE if there are no results in + // the response. + // + // Possible values: + // "CLEANUP_FAILED" + // "DEPRECATED_RESOURCE_USED" + // "DEPRECATED_TYPE_USED" + // "DISK_SIZE_LARGER_THAN_IMAGE_SIZE" + // "EXPERIMENTAL_TYPE_USED" + // "EXTERNAL_API_WARNING" + // "FIELD_VALUE_OVERRIDEN" + // "INJECTED_KERNELS_DEPRECATED" + // "MISSING_TYPE_DEPENDENCY" + // "NEXT_HOP_ADDRESS_NOT_ASSIGNED" + // "NEXT_HOP_CANNOT_IP_FORWARD" + // "NEXT_HOP_INSTANCE_NOT_FOUND" + // "NEXT_HOP_INSTANCE_NOT_ON_NETWORK" + // "NEXT_HOP_NOT_RUNNING" + // "NOT_CRITICAL_ERROR" + // "NO_RESULTS_ON_PAGE" + // "REQUIRED_TOS_AGREEMENT" + // "RESOURCE_IN_USE_BY_OTHER_RESOURCE_WARNING" + // "RESOURCE_NOT_DELETED" + // "SCHEMA_VALIDATION_IGNORED" + // "SINGLE_INSTANCE_PROPERTY_TEMPLATE" + // "UNDECLARED_PROPERTIES" + // "UNREACHABLE" + Code string `json:"code,omitempty"` + + // Data: [Output Only] Metadata about this warning in key: value format. + // For example: + // "data": [ { "key": "scope", "value": "zones/us-east1-d" } + Data []*NodeTemplateAggregatedListWarningData `json:"data,omitempty"` + + // Message: [Output Only] A human-readable description of the warning + // code. + Message string `json:"message,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Code") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Code") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *NodeTemplateAggregatedListWarning) MarshalJSON() ([]byte, error) { + type NoMethod NodeTemplateAggregatedListWarning + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type NodeTemplateAggregatedListWarningData struct { + // Key: [Output Only] A key that provides more detail on the warning + // being returned. For example, for warnings where there are no results + // in a list request for a particular zone, this key might be scope and + // the key value might be the zone name. Other examples might be a key + // indicating a deprecated resource and a suggested replacement, or a + // warning about invalid network settings (for example, if an instance + // attempts to perform IP forwarding but is not enabled for IP + // forwarding). + Key string `json:"key,omitempty"` + + // Value: [Output Only] A warning data value corresponding to the key. + Value string `json:"value,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Key") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Key") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *NodeTemplateAggregatedListWarningData) MarshalJSON() ([]byte, error) { + type NoMethod NodeTemplateAggregatedListWarningData + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// NodeTemplateList: Contains a list of node templates. +type NodeTemplateList struct { + // Id: [Output Only] Unique identifier for the resource; defined by the + // server. + Id string `json:"id,omitempty"` + + // Items: A list of NodeTemplate resources. + Items []*NodeTemplate `json:"items,omitempty"` + + // Kind: [Output Only] Type of resource.Always compute#nodeTemplateList + // for lists of node templates. + Kind string `json:"kind,omitempty"` + + // NextPageToken: [Output Only] This token allows you to get the next + // page of results for list requests. If the number of results is larger + // than maxResults, use the nextPageToken as a value for the query + // parameter pageToken in the next list request. Subsequent list + // requests will have their own nextPageToken to continue paging through + // the results. + NextPageToken string `json:"nextPageToken,omitempty"` + + // SelfLink: [Output Only] Server-defined URL for this resource. + SelfLink string `json:"selfLink,omitempty"` + + // Warning: [Output Only] Informational warning message. + Warning *NodeTemplateListWarning `json:"warning,omitempty"` + + // ServerResponse contains the HTTP response code and headers from the + // server. + googleapi.ServerResponse `json:"-"` + + // ForceSendFields is a list of field names (e.g. "Id") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Id") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *NodeTemplateList) MarshalJSON() ([]byte, error) { + type NoMethod NodeTemplateList + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// NodeTemplateListWarning: [Output Only] Informational warning message. +type NodeTemplateListWarning struct { + // Code: [Output Only] A warning code, if applicable. For example, + // Compute Engine returns NO_RESULTS_ON_PAGE if there are no results in + // the response. + // + // Possible values: + // "CLEANUP_FAILED" + // "DEPRECATED_RESOURCE_USED" + // "DEPRECATED_TYPE_USED" + // "DISK_SIZE_LARGER_THAN_IMAGE_SIZE" + // "EXPERIMENTAL_TYPE_USED" + // "EXTERNAL_API_WARNING" + // "FIELD_VALUE_OVERRIDEN" + // "INJECTED_KERNELS_DEPRECATED" + // "MISSING_TYPE_DEPENDENCY" + // "NEXT_HOP_ADDRESS_NOT_ASSIGNED" + // "NEXT_HOP_CANNOT_IP_FORWARD" + // "NEXT_HOP_INSTANCE_NOT_FOUND" + // "NEXT_HOP_INSTANCE_NOT_ON_NETWORK" + // "NEXT_HOP_NOT_RUNNING" + // "NOT_CRITICAL_ERROR" + // "NO_RESULTS_ON_PAGE" + // "REQUIRED_TOS_AGREEMENT" + // "RESOURCE_IN_USE_BY_OTHER_RESOURCE_WARNING" + // "RESOURCE_NOT_DELETED" + // "SCHEMA_VALIDATION_IGNORED" + // "SINGLE_INSTANCE_PROPERTY_TEMPLATE" + // "UNDECLARED_PROPERTIES" + // "UNREACHABLE" + Code string `json:"code,omitempty"` + + // Data: [Output Only] Metadata about this warning in key: value format. + // For example: + // "data": [ { "key": "scope", "value": "zones/us-east1-d" } + Data []*NodeTemplateListWarningData `json:"data,omitempty"` + + // Message: [Output Only] A human-readable description of the warning + // code. + Message string `json:"message,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Code") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Code") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *NodeTemplateListWarning) MarshalJSON() ([]byte, error) { + type NoMethod NodeTemplateListWarning + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type NodeTemplateListWarningData struct { + // Key: [Output Only] A key that provides more detail on the warning + // being returned. For example, for warnings where there are no results + // in a list request for a particular zone, this key might be scope and + // the key value might be the zone name. Other examples might be a key + // indicating a deprecated resource and a suggested replacement, or a + // warning about invalid network settings (for example, if an instance + // attempts to perform IP forwarding but is not enabled for IP + // forwarding). + Key string `json:"key,omitempty"` + + // Value: [Output Only] A warning data value corresponding to the key. + Value string `json:"value,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Key") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Key") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *NodeTemplateListWarningData) MarshalJSON() ([]byte, error) { + type NoMethod NodeTemplateListWarningData + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type NodeTemplateNodeTypeFlexibility struct { + Cpus string `json:"cpus,omitempty"` + + LocalSsd string `json:"localSsd,omitempty"` + + Memory string `json:"memory,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Cpus") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Cpus") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *NodeTemplateNodeTypeFlexibility) MarshalJSON() ([]byte, error) { + type NoMethod NodeTemplateNodeTypeFlexibility + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type NodeTemplatesScopedList struct { + // NodeTemplates: [Output Only] A list of node templates contained in + // this scope. + NodeTemplates []*NodeTemplate `json:"nodeTemplates,omitempty"` + + // Warning: [Output Only] An informational warning that appears when the + // node templates list is empty. + Warning *NodeTemplatesScopedListWarning `json:"warning,omitempty"` + + // ForceSendFields is a list of field names (e.g. "NodeTemplates") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "NodeTemplates") to include + // in API requests with the JSON null value. By default, fields with + // empty values are omitted from API requests. However, any field with + // an empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *NodeTemplatesScopedList) MarshalJSON() ([]byte, error) { + type NoMethod NodeTemplatesScopedList + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// NodeTemplatesScopedListWarning: [Output Only] An informational +// warning that appears when the node templates list is empty. +type NodeTemplatesScopedListWarning struct { + // Code: [Output Only] A warning code, if applicable. For example, + // Compute Engine returns NO_RESULTS_ON_PAGE if there are no results in + // the response. + // + // Possible values: + // "CLEANUP_FAILED" + // "DEPRECATED_RESOURCE_USED" + // "DEPRECATED_TYPE_USED" + // "DISK_SIZE_LARGER_THAN_IMAGE_SIZE" + // "EXPERIMENTAL_TYPE_USED" + // "EXTERNAL_API_WARNING" + // "FIELD_VALUE_OVERRIDEN" + // "INJECTED_KERNELS_DEPRECATED" + // "MISSING_TYPE_DEPENDENCY" + // "NEXT_HOP_ADDRESS_NOT_ASSIGNED" + // "NEXT_HOP_CANNOT_IP_FORWARD" + // "NEXT_HOP_INSTANCE_NOT_FOUND" + // "NEXT_HOP_INSTANCE_NOT_ON_NETWORK" + // "NEXT_HOP_NOT_RUNNING" + // "NOT_CRITICAL_ERROR" + // "NO_RESULTS_ON_PAGE" + // "REQUIRED_TOS_AGREEMENT" + // "RESOURCE_IN_USE_BY_OTHER_RESOURCE_WARNING" + // "RESOURCE_NOT_DELETED" + // "SCHEMA_VALIDATION_IGNORED" + // "SINGLE_INSTANCE_PROPERTY_TEMPLATE" + // "UNDECLARED_PROPERTIES" + // "UNREACHABLE" + Code string `json:"code,omitempty"` + + // Data: [Output Only] Metadata about this warning in key: value format. + // For example: + // "data": [ { "key": "scope", "value": "zones/us-east1-d" } + Data []*NodeTemplatesScopedListWarningData `json:"data,omitempty"` + + // Message: [Output Only] A human-readable description of the warning + // code. + Message string `json:"message,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Code") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Code") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *NodeTemplatesScopedListWarning) MarshalJSON() ([]byte, error) { + type NoMethod NodeTemplatesScopedListWarning + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type NodeTemplatesScopedListWarningData struct { + // Key: [Output Only] A key that provides more detail on the warning + // being returned. For example, for warnings where there are no results + // in a list request for a particular zone, this key might be scope and + // the key value might be the zone name. Other examples might be a key + // indicating a deprecated resource and a suggested replacement, or a + // warning about invalid network settings (for example, if an instance + // attempts to perform IP forwarding but is not enabled for IP + // forwarding). + Key string `json:"key,omitempty"` + + // Value: [Output Only] A warning data value corresponding to the key. + Value string `json:"value,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Key") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Key") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *NodeTemplatesScopedListWarningData) MarshalJSON() ([]byte, error) { + type NoMethod NodeTemplatesScopedListWarningData + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// NodeType: A Node Type resource. +type NodeType struct { + // CpuPlatform: [Output Only] The CPU platform used by this node type. + CpuPlatform string `json:"cpuPlatform,omitempty"` + + // CreationTimestamp: [Output Only] Creation timestamp in RFC3339 text + // format. + CreationTimestamp string `json:"creationTimestamp,omitempty"` + + // Deprecated: [Output Only] The deprecation status associated with this + // node type. + Deprecated *DeprecationStatus `json:"deprecated,omitempty"` + + // Description: [Output Only] An optional textual description of the + // resource. + Description string `json:"description,omitempty"` + + // GuestCpus: [Output Only] The number of virtual CPUs that are + // available to the node type. + GuestCpus int64 `json:"guestCpus,omitempty"` + + // Id: [Output Only] The unique identifier for the resource. This + // identifier is defined by the server. + Id uint64 `json:"id,omitempty,string"` + + // Kind: [Output Only] The type of the resource. Always compute#nodeType + // for node types. + Kind string `json:"kind,omitempty"` + + // LocalSsdGb: [Output Only] Local SSD available to the node type, + // defined in GB. + LocalSsdGb int64 `json:"localSsdGb,omitempty"` + + // MemoryMb: [Output Only] The amount of physical memory available to + // the node type, defined in MB. + MemoryMb int64 `json:"memoryMb,omitempty"` + + // Name: [Output Only] Name of the resource. + Name string `json:"name,omitempty"` + + // SelfLink: [Output Only] Server-defined URL for the resource. + SelfLink string `json:"selfLink,omitempty"` + + // Zone: [Output Only] The name of the zone where the node type resides, + // such as us-central1-a. + Zone string `json:"zone,omitempty"` + + // ServerResponse contains the HTTP response code and headers from the + // server. + googleapi.ServerResponse `json:"-"` + + // ForceSendFields is a list of field names (e.g. "CpuPlatform") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "CpuPlatform") to include + // in API requests with the JSON null value. By default, fields with + // empty values are omitted from API requests. However, any field with + // an empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *NodeType) MarshalJSON() ([]byte, error) { + type NoMethod NodeType + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type NodeTypeAggregatedList struct { + // Id: [Output Only] Unique identifier for the resource; defined by the + // server. + Id string `json:"id,omitempty"` + + // Items: A list of NodeTypesScopedList resources. + Items map[string]NodeTypesScopedList `json:"items,omitempty"` + + // Kind: [Output Only] Type of resource.Always + // compute#nodeTypeAggregatedList for aggregated lists of node types. + Kind string `json:"kind,omitempty"` + + // NextPageToken: [Output Only] This token allows you to get the next + // page of results for list requests. If the number of results is larger + // than maxResults, use the nextPageToken as a value for the query + // parameter pageToken in the next list request. Subsequent list + // requests will have their own nextPageToken to continue paging through + // the results. + NextPageToken string `json:"nextPageToken,omitempty"` + + // SelfLink: [Output Only] Server-defined URL for this resource. + SelfLink string `json:"selfLink,omitempty"` + + // Warning: [Output Only] Informational warning message. + Warning *NodeTypeAggregatedListWarning `json:"warning,omitempty"` + + // ServerResponse contains the HTTP response code and headers from the + // server. + googleapi.ServerResponse `json:"-"` + + // ForceSendFields is a list of field names (e.g. "Id") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Id") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *NodeTypeAggregatedList) MarshalJSON() ([]byte, error) { + type NoMethod NodeTypeAggregatedList + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// NodeTypeAggregatedListWarning: [Output Only] Informational warning +// message. +type NodeTypeAggregatedListWarning struct { + // Code: [Output Only] A warning code, if applicable. For example, + // Compute Engine returns NO_RESULTS_ON_PAGE if there are no results in + // the response. + // + // Possible values: + // "CLEANUP_FAILED" + // "DEPRECATED_RESOURCE_USED" + // "DEPRECATED_TYPE_USED" + // "DISK_SIZE_LARGER_THAN_IMAGE_SIZE" + // "EXPERIMENTAL_TYPE_USED" + // "EXTERNAL_API_WARNING" + // "FIELD_VALUE_OVERRIDEN" + // "INJECTED_KERNELS_DEPRECATED" + // "MISSING_TYPE_DEPENDENCY" + // "NEXT_HOP_ADDRESS_NOT_ASSIGNED" + // "NEXT_HOP_CANNOT_IP_FORWARD" + // "NEXT_HOP_INSTANCE_NOT_FOUND" + // "NEXT_HOP_INSTANCE_NOT_ON_NETWORK" + // "NEXT_HOP_NOT_RUNNING" + // "NOT_CRITICAL_ERROR" + // "NO_RESULTS_ON_PAGE" + // "REQUIRED_TOS_AGREEMENT" + // "RESOURCE_IN_USE_BY_OTHER_RESOURCE_WARNING" + // "RESOURCE_NOT_DELETED" + // "SCHEMA_VALIDATION_IGNORED" + // "SINGLE_INSTANCE_PROPERTY_TEMPLATE" + // "UNDECLARED_PROPERTIES" + // "UNREACHABLE" + Code string `json:"code,omitempty"` + + // Data: [Output Only] Metadata about this warning in key: value format. + // For example: + // "data": [ { "key": "scope", "value": "zones/us-east1-d" } + Data []*NodeTypeAggregatedListWarningData `json:"data,omitempty"` + + // Message: [Output Only] A human-readable description of the warning + // code. + Message string `json:"message,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Code") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Code") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *NodeTypeAggregatedListWarning) MarshalJSON() ([]byte, error) { + type NoMethod NodeTypeAggregatedListWarning + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type NodeTypeAggregatedListWarningData struct { + // Key: [Output Only] A key that provides more detail on the warning + // being returned. For example, for warnings where there are no results + // in a list request for a particular zone, this key might be scope and + // the key value might be the zone name. Other examples might be a key + // indicating a deprecated resource and a suggested replacement, or a + // warning about invalid network settings (for example, if an instance + // attempts to perform IP forwarding but is not enabled for IP + // forwarding). + Key string `json:"key,omitempty"` + + // Value: [Output Only] A warning data value corresponding to the key. + Value string `json:"value,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Key") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Key") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *NodeTypeAggregatedListWarningData) MarshalJSON() ([]byte, error) { + type NoMethod NodeTypeAggregatedListWarningData + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// NodeTypeList: Contains a list of node types. +type NodeTypeList struct { + // Id: [Output Only] Unique identifier for the resource; defined by the + // server. + Id string `json:"id,omitempty"` + + // Items: A list of NodeType resources. + Items []*NodeType `json:"items,omitempty"` + + // Kind: [Output Only] Type of resource.Always compute#nodeTypeList for + // lists of node types. + Kind string `json:"kind,omitempty"` + + // NextPageToken: [Output Only] This token allows you to get the next + // page of results for list requests. If the number of results is larger + // than maxResults, use the nextPageToken as a value for the query + // parameter pageToken in the next list request. Subsequent list + // requests will have their own nextPageToken to continue paging through + // the results. + NextPageToken string `json:"nextPageToken,omitempty"` + + // SelfLink: [Output Only] Server-defined URL for this resource. + SelfLink string `json:"selfLink,omitempty"` + + // Warning: [Output Only] Informational warning message. + Warning *NodeTypeListWarning `json:"warning,omitempty"` + + // ServerResponse contains the HTTP response code and headers from the + // server. + googleapi.ServerResponse `json:"-"` + + // ForceSendFields is a list of field names (e.g. "Id") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Id") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *NodeTypeList) MarshalJSON() ([]byte, error) { + type NoMethod NodeTypeList + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// NodeTypeListWarning: [Output Only] Informational warning message. +type NodeTypeListWarning struct { + // Code: [Output Only] A warning code, if applicable. For example, + // Compute Engine returns NO_RESULTS_ON_PAGE if there are no results in + // the response. + // + // Possible values: + // "CLEANUP_FAILED" + // "DEPRECATED_RESOURCE_USED" + // "DEPRECATED_TYPE_USED" + // "DISK_SIZE_LARGER_THAN_IMAGE_SIZE" + // "EXPERIMENTAL_TYPE_USED" + // "EXTERNAL_API_WARNING" + // "FIELD_VALUE_OVERRIDEN" + // "INJECTED_KERNELS_DEPRECATED" + // "MISSING_TYPE_DEPENDENCY" + // "NEXT_HOP_ADDRESS_NOT_ASSIGNED" + // "NEXT_HOP_CANNOT_IP_FORWARD" + // "NEXT_HOP_INSTANCE_NOT_FOUND" + // "NEXT_HOP_INSTANCE_NOT_ON_NETWORK" + // "NEXT_HOP_NOT_RUNNING" + // "NOT_CRITICAL_ERROR" + // "NO_RESULTS_ON_PAGE" + // "REQUIRED_TOS_AGREEMENT" + // "RESOURCE_IN_USE_BY_OTHER_RESOURCE_WARNING" + // "RESOURCE_NOT_DELETED" + // "SCHEMA_VALIDATION_IGNORED" + // "SINGLE_INSTANCE_PROPERTY_TEMPLATE" + // "UNDECLARED_PROPERTIES" + // "UNREACHABLE" + Code string `json:"code,omitempty"` + + // Data: [Output Only] Metadata about this warning in key: value format. + // For example: + // "data": [ { "key": "scope", "value": "zones/us-east1-d" } + Data []*NodeTypeListWarningData `json:"data,omitempty"` + + // Message: [Output Only] A human-readable description of the warning + // code. + Message string `json:"message,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Code") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Code") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *NodeTypeListWarning) MarshalJSON() ([]byte, error) { + type NoMethod NodeTypeListWarning + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type NodeTypeListWarningData struct { + // Key: [Output Only] A key that provides more detail on the warning + // being returned. For example, for warnings where there are no results + // in a list request for a particular zone, this key might be scope and + // the key value might be the zone name. Other examples might be a key + // indicating a deprecated resource and a suggested replacement, or a + // warning about invalid network settings (for example, if an instance + // attempts to perform IP forwarding but is not enabled for IP + // forwarding). + Key string `json:"key,omitempty"` + + // Value: [Output Only] A warning data value corresponding to the key. + Value string `json:"value,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Key") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Key") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *NodeTypeListWarningData) MarshalJSON() ([]byte, error) { + type NoMethod NodeTypeListWarningData + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type NodeTypesScopedList struct { + // NodeTypes: [Output Only] A list of node types contained in this + // scope. + NodeTypes []*NodeType `json:"nodeTypes,omitempty"` + + // Warning: [Output Only] An informational warning that appears when the + // node types list is empty. + Warning *NodeTypesScopedListWarning `json:"warning,omitempty"` + + // ForceSendFields is a list of field names (e.g. "NodeTypes") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "NodeTypes") to include in + // API requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *NodeTypesScopedList) MarshalJSON() ([]byte, error) { + type NoMethod NodeTypesScopedList + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// NodeTypesScopedListWarning: [Output Only] An informational warning +// that appears when the node types list is empty. +type NodeTypesScopedListWarning struct { + // Code: [Output Only] A warning code, if applicable. For example, + // Compute Engine returns NO_RESULTS_ON_PAGE if there are no results in + // the response. + // + // Possible values: + // "CLEANUP_FAILED" + // "DEPRECATED_RESOURCE_USED" + // "DEPRECATED_TYPE_USED" + // "DISK_SIZE_LARGER_THAN_IMAGE_SIZE" + // "EXPERIMENTAL_TYPE_USED" + // "EXTERNAL_API_WARNING" + // "FIELD_VALUE_OVERRIDEN" + // "INJECTED_KERNELS_DEPRECATED" + // "MISSING_TYPE_DEPENDENCY" + // "NEXT_HOP_ADDRESS_NOT_ASSIGNED" + // "NEXT_HOP_CANNOT_IP_FORWARD" + // "NEXT_HOP_INSTANCE_NOT_FOUND" + // "NEXT_HOP_INSTANCE_NOT_ON_NETWORK" + // "NEXT_HOP_NOT_RUNNING" + // "NOT_CRITICAL_ERROR" + // "NO_RESULTS_ON_PAGE" + // "REQUIRED_TOS_AGREEMENT" + // "RESOURCE_IN_USE_BY_OTHER_RESOURCE_WARNING" + // "RESOURCE_NOT_DELETED" + // "SCHEMA_VALIDATION_IGNORED" + // "SINGLE_INSTANCE_PROPERTY_TEMPLATE" + // "UNDECLARED_PROPERTIES" + // "UNREACHABLE" + Code string `json:"code,omitempty"` + + // Data: [Output Only] Metadata about this warning in key: value format. + // For example: + // "data": [ { "key": "scope", "value": "zones/us-east1-d" } + Data []*NodeTypesScopedListWarningData `json:"data,omitempty"` + + // Message: [Output Only] A human-readable description of the warning + // code. + Message string `json:"message,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Code") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Code") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *NodeTypesScopedListWarning) MarshalJSON() ([]byte, error) { + type NoMethod NodeTypesScopedListWarning + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type NodeTypesScopedListWarningData struct { + // Key: [Output Only] A key that provides more detail on the warning + // being returned. For example, for warnings where there are no results + // in a list request for a particular zone, this key might be scope and + // the key value might be the zone name. Other examples might be a key + // indicating a deprecated resource and a suggested replacement, or a + // warning about invalid network settings (for example, if an instance + // attempts to perform IP forwarding but is not enabled for IP + // forwarding). + Key string `json:"key,omitempty"` + + // Value: [Output Only] A warning data value corresponding to the key. + Value string `json:"value,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Key") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Key") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *NodeTypesScopedListWarningData) MarshalJSON() ([]byte, error) { + type NoMethod NodeTypesScopedListWarningData + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + // Operation: An Operation resource, used to manage asynchronous API // requests. (== resource_for v1.globalOperations ==) (== resource_for // beta.globalOperations ==) (== resource_for v1.regionOperations ==) @@ -15626,14 +18576,23 @@ func (s *OperationsScopedListWarningData) MarshalJSON() ([]byte, error) { // no rule was matched, the default service will be used. type PathMatcher struct { // DefaultService: The full or partial URL to the BackendService - // resource. This will be used if none of the pathRules defined by this - // PathMatcher is matched by the URL's path portion. For example, the - // following are all valid URLs to a BackendService resource: + // resource. This will be used if none of the pathRules or routeRules + // defined by this PathMatcher are matched. For example, the following + // are all valid URLs to a BackendService resource: // - // https://www.googleapis.com/compute/v1/projects/project/global/backendServices/backendService // - compute/v1/projects/project/global/backendServices/backendService // // - global/backendServices/backendService + // Use defaultService instead of defaultRouteAction when simple routing + // to a backend service is desired and other advanced capabilities like + // traffic splitting and URL rewrites are not required. + // Only one of defaultService, defaultRouteAction or defaultUrlRedirect + // must be set. + // Authorization requires one or more of the following Google IAM + // permissions on the specified resource default_service: + // - compute.backendBuckets.use + // - compute.backendServices.use DefaultService string `json:"defaultService,omitempty"` // Description: An optional description of this resource. Provide this @@ -15643,7 +18602,14 @@ type PathMatcher struct { // Name: The name to which this PathMatcher is referred by the HostRule. Name string `json:"name,omitempty"` - // PathRules: The list of path rules. + // PathRules: The list of path rules. Use this list instead of + // routeRules when routing based on simple path matching is all that's + // required. The order by which path rules are specified does not + // matter. Matches are always done on the longest-path-first basis. + // For example: a pathRule with a path /a/b/c/* will match before /a/b/* + // irrespective of the order in which those paths appear in this + // list. + // Only one of pathRules or routeRules must be set. PathRules []*PathRule `json:"pathRules,omitempty"` // ForceSendFields is a list of field names (e.g. "DefaultService") to @@ -15679,8 +18645,12 @@ type PathRule struct { // or #, and those chars are not allowed here. Paths []string `json:"paths,omitempty"` - // Service: The URL of the BackendService resource if this rule is + // Service: The URL of the backend service resource if this rule is // matched. + // Use service instead of routeAction when simple routing to a backend + // service is desired and other advanced capabilities like traffic + // splitting and rewrites are not required. + // Only one of service, routeAction or urlRedirect should must be set. Service string `json:"service,omitempty"` // ForceSendFields is a list of field names (e.g. "Paths") to @@ -15706,6 +18676,102 @@ func (s *PathRule) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +// Policy: Defines an Identity and Access Management (IAM) policy. It is +// used to specify access control policies for Cloud Platform +// resources. +// +// +// +// A `Policy` consists of a list of `bindings`. A `binding` binds a list +// of `members` to a `role`, where the members can be user accounts, +// Google groups, Google domains, and service accounts. A `role` is a +// named list of permissions defined by IAM. +// +// **JSON Example** +// +// { "bindings": [ { "role": "roles/owner", "members": [ +// "user:mike@example.com", "group:admins@example.com", +// "domain:google.com", +// "serviceAccount:my-other-app@appspot.gserviceaccount.com" ] }, { +// "role": "roles/viewer", "members": ["user:sean@example.com"] } ] +// } +// +// **YAML Example** +// +// bindings: - members: - user:mike@example.com - +// group:admins@example.com - domain:google.com - +// serviceAccount:my-other-app@appspot.gserviceaccount.com role: +// roles/owner - members: - user:sean@example.com role: +// roles/viewer +// +// +// +// For a description of IAM and its features, see the [IAM developer's +// guide](https://cloud.google.com/iam/docs). +type Policy struct { + // AuditConfigs: Specifies cloud audit logging configuration for this + // policy. + AuditConfigs []*AuditConfig `json:"auditConfigs,omitempty"` + + // Bindings: Associates a list of `members` to a `role`. `bindings` with + // no members will result in an error. + Bindings []*Binding `json:"bindings,omitempty"` + + // Etag: `etag` is used for optimistic concurrency control as a way to + // help prevent simultaneous updates of a policy from overwriting each + // other. It is strongly suggested that systems make use of the `etag` + // in the read-modify-write cycle to perform policy updates in order to + // avoid race conditions: An `etag` is returned in the response to + // `getIamPolicy`, and systems are expected to put that etag in the + // request to `setIamPolicy` to ensure that their change will be applied + // to the same version of the policy. + // + // If no `etag` is provided in the call to `setIamPolicy`, then the + // existing policy is overwritten blindly. + Etag string `json:"etag,omitempty"` + + IamOwned bool `json:"iamOwned,omitempty"` + + // Rules: If more than one rule is specified, the rules are applied in + // the following manner: - All matching LOG rules are always applied. - + // If any DENY/DENY_WITH_LOG rule matches, permission is denied. Logging + // will be applied if one or more matching rule requires logging. - + // Otherwise, if any ALLOW/ALLOW_WITH_LOG rule matches, permission is + // granted. Logging will be applied if one or more matching rule + // requires logging. - Otherwise, if no rule applies, permission is + // denied. + Rules []*Rule `json:"rules,omitempty"` + + // Version: Deprecated. + Version int64 `json:"version,omitempty"` + + // ServerResponse contains the HTTP response code and headers from the + // server. + googleapi.ServerResponse `json:"-"` + + // ForceSendFields is a list of field names (e.g. "AuditConfigs") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "AuditConfigs") to include + // in API requests with the JSON null value. By default, fields with + // empty values are omitted from API requests. However, any field with + // an empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *Policy) MarshalJSON() ([]byte, error) { + type NoMethod Policy + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + // Project: A Project resource. For an overview of projects, see Cloud // Platform Resource Hierarchy. (== resource_for v1.projects ==) (== // resource_for beta.projects ==) @@ -15719,6 +18785,16 @@ type Project struct { // format. CreationTimestamp string `json:"creationTimestamp,omitempty"` + // DefaultNetworkTier: This signifies the default network tier used for + // configuring resources of the project and can only take the following + // values: PREMIUM, STANDARD. Initially the default network tier is + // PREMIUM. + // + // Possible values: + // "PREMIUM" + // "STANDARD" + DefaultNetworkTier string `json:"defaultNetworkTier,omitempty"` + // DefaultServiceAccount: [Output Only] Default service account used by // VMs running in this project. DefaultServiceAccount string `json:"defaultServiceAccount,omitempty"` @@ -15917,6 +18993,37 @@ func (s *ProjectsListXpnHostsRequest) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +type ProjectsSetDefaultNetworkTierRequest struct { + // NetworkTier: Default network tier to be set. + // + // Possible values: + // "PREMIUM" + // "STANDARD" + NetworkTier string `json:"networkTier,omitempty"` + + // ForceSendFields is a list of field names (e.g. "NetworkTier") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "NetworkTier") to include + // in API requests with the JSON null value. By default, fields with + // empty values are omitted from API requests. However, any field with + // an empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *ProjectsSetDefaultNetworkTierRequest) MarshalJSON() ([]byte, error) { + type NoMethod ProjectsSetDefaultNetworkTierRequest + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + // Quota: A quotas entry. type Quota struct { // Limit: [Output Only] Quota limit for this metric. @@ -15934,6 +19041,8 @@ type Quota struct { // "DISKS_TOTAL_GB" // "FIREWALLS" // "FORWARDING_RULES" + // "GLOBAL_INTERNAL_ADDRESSES" + // "GPUS_ALL_REGIONS" // "HEALTH_CHECKS" // "IMAGES" // "INSTANCES" @@ -15945,18 +19054,30 @@ type Quota struct { // "INTERCONNECT_ATTACHMENTS_TOTAL_MBPS" // "INTERNAL_ADDRESSES" // "IN_USE_ADDRESSES" + // "IN_USE_BACKUP_SCHEDULES" // "LOCAL_SSD_TOTAL_GB" // "NETWORKS" // "NVIDIA_K80_GPUS" // "NVIDIA_P100_GPUS" + // "NVIDIA_P100_VWS_GPUS" + // "NVIDIA_P4_GPUS" + // "NVIDIA_P4_VWS_GPUS" + // "NVIDIA_T4_GPUS" + // "NVIDIA_T4_VWS_GPUS" // "NVIDIA_V100_GPUS" // "PREEMPTIBLE_CPUS" // "PREEMPTIBLE_LOCAL_SSD_GB" // "PREEMPTIBLE_NVIDIA_K80_GPUS" // "PREEMPTIBLE_NVIDIA_P100_GPUS" + // "PREEMPTIBLE_NVIDIA_P100_VWS_GPUS" + // "PREEMPTIBLE_NVIDIA_P4_GPUS" + // "PREEMPTIBLE_NVIDIA_P4_VWS_GPUS" + // "PREEMPTIBLE_NVIDIA_T4_GPUS" + // "PREEMPTIBLE_NVIDIA_T4_VWS_GPUS" // "PREEMPTIBLE_NVIDIA_V100_GPUS" // "REGIONAL_AUTOSCALERS" // "REGIONAL_INSTANCE_GROUP_MANAGERS" + // "RESOURCE_POLICIES" // "ROUTERS" // "ROUTES" // "SECURITY_POLICIES" @@ -15974,6 +19095,7 @@ type Quota struct { // "TARGET_TCP_PROXIES" // "TARGET_VPN_GATEWAYS" // "URL_MAPS" + // "VPN_GATEWAYS" // "VPN_TUNNELS" Metric string `json:"metric,omitempty"` @@ -17380,6 +20502,44 @@ func (s *RegionSetLabelsRequest) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +type RegionSetPolicyRequest struct { + // Bindings: Flatten Policy to create a backwacd compatible wire-format. + // Deprecated. Use 'policy' to specify bindings. + Bindings []*Binding `json:"bindings,omitempty"` + + // Etag: Flatten Policy to create a backward compatible wire-format. + // Deprecated. Use 'policy' to specify the etag. + Etag string `json:"etag,omitempty"` + + // Policy: REQUIRED: The complete policy to be applied to the + // 'resource'. The size of the policy is limited to a few 10s of KB. An + // empty policy is in general a valid policy but certain services (like + // Projects) might reject them. + Policy *Policy `json:"policy,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Bindings") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Bindings") to include in + // API requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *RegionSetPolicyRequest) MarshalJSON() ([]byte, error) { + type NoMethod RegionSetPolicyRequest + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + // ResourceCommitment: Commitment for a particular resource (a // Commitment is composed of one or more of these). type ResourceCommitment struct { @@ -17422,8 +20582,8 @@ func (s *ResourceCommitment) MarshalJSON() ([]byte, error) { } type ResourceGroupReference struct { - // Group: A URI referencing one of the instance groups listed in the - // backend service. + // Group: A URI referencing one of the instance groups or network + // endpoint groups listed in the backend service. Group string `json:"group,omitempty"` // ForceSendFields is a list of field names (e.g. "Group") to @@ -17871,6 +21031,9 @@ type Router struct { // last character, which cannot be a dash. Name string `json:"name,omitempty"` + // Nats: A list of Nat services created in this router. + Nats []*RouterNat `json:"nats,omitempty"` + // Network: URI of the network to which this router belongs. Network string `json:"network,omitempty"` @@ -18193,12 +21356,13 @@ type RouterBgpPeer struct { // Only IPv4 is supported. IpAddress string `json:"ipAddress,omitempty"` - // ManagementType: [Output Only] Type of how the resource/configuration - // of the BGP peer is managed. MANAGED_BY_USER is the default value; - // MANAGED_BY_ATTACHMENT represents an BGP peer that is automatically - // created for PARTNER interconnectAttachment, Google will automatically - // create/delete this type of BGP peer when the PARTNER - // interconnectAttachment is created/deleted. + // ManagementType: [Output Only] The resource that configures and + // manages this BGP peer. MANAGED_BY_USER is the default value and can + // be managed by you or other users; MANAGED_BY_ATTACHMENT is a BGP peer + // that is configured and managed by Cloud Interconnect, specifically by + // an InterconnectAttachment of type PARTNER. Google will automatically + // create, update, and delete this type of BGP peer when the PARTNER + // InterconnectAttachment is created, updated, or deleted. // // Possible values: // "MANAGED_BY_ATTACHMENT" @@ -18260,12 +21424,14 @@ type RouterInterface struct { // attachment. LinkedVpnTunnel string `json:"linkedVpnTunnel,omitempty"` - // ManagementType: [Output Only] Type of how the resource/configuration - // of the interface is managed. MANAGED_BY_USER is the default value; - // MANAGED_BY_ATTACHMENT represents an interface that is automatically - // created for PARTNER type interconnectAttachment, Google will - // automatically create/update/delete this type of interface when the - // PARTNER interconnectAttachment is created/provisioned/deleted. + // ManagementType: [Output Only] The resource that configures and + // manages this interface. MANAGED_BY_USER is the default value and can + // be managed by you or other users; MANAGED_BY_ATTACHMENT is an + // interface that is configured and managed by Cloud Interconnect, + // specifically by an InterconnectAttachment of type PARTNER. Google + // will automatically create, update, and delete this type of interface + // when the PARTNER InterconnectAttachment is created, updated, or + // deleted. // // Possible values: // "MANAGED_BY_ATTACHMENT" @@ -18454,6 +21620,140 @@ func (s *RouterListWarningData) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +// RouterNat: Represents a Nat resource. It enables the VMs within the +// specified subnetworks to access Internet without external IP +// addresses. It specifies a list of subnetworks (and the ranges within) +// that want to use NAT. Customers can also provide the external IPs +// that would be used for NAT. GCP would auto-allocate ephemeral IPs if +// no external IPs are provided. +type RouterNat struct { + // IcmpIdleTimeoutSec: Timeout (in seconds) for ICMP connections. + // Defaults to 30s if not set. + IcmpIdleTimeoutSec int64 `json:"icmpIdleTimeoutSec,omitempty"` + + // MinPortsPerVm: Minimum number of ports allocated to a VM from this + // NAT config. If not set, a default number of ports is allocated to a + // VM. This gets rounded up to the nearest power of 2. Eg. if the value + // of this field is 50, at least 64 ports will be allocated to a VM. + MinPortsPerVm int64 `json:"minPortsPerVm,omitempty"` + + // Name: Unique name of this Nat service. The name must be 1-63 + // characters long and comply with RFC1035. + Name string `json:"name,omitempty"` + + // NatIpAllocateOption: Specify the NatIpAllocateOption. If it is + // AUTO_ONLY, then nat_ip should be empty. + // + // Possible values: + // "AUTO_ONLY" + // "MANUAL_ONLY" + NatIpAllocateOption string `json:"natIpAllocateOption,omitempty"` + + // NatIps: A list of URLs of the IP resources used for this Nat service. + // These IPs must be valid static external IP addresses assigned to the + // project. max_length is subject to change post alpha. + NatIps []string `json:"natIps,omitempty"` + + // SourceSubnetworkIpRangesToNat: Specify the Nat option. If this field + // contains ALL_SUBNETWORKS_ALL_IP_RANGES or + // ALL_SUBNETWORKS_ALL_PRIMARY_IP_RANGES, then there should not be any + // other Router.Nat section in any Router for this network in this + // region. + // + // Possible values: + // "ALL_SUBNETWORKS_ALL_IP_RANGES" + // "ALL_SUBNETWORKS_ALL_PRIMARY_IP_RANGES" + // "LIST_OF_SUBNETWORKS" + SourceSubnetworkIpRangesToNat string `json:"sourceSubnetworkIpRangesToNat,omitempty"` + + // Subnetworks: A list of Subnetwork resources whose traffic should be + // translated by NAT Gateway. It is used only when LIST_OF_SUBNETWORKS + // is selected for the SubnetworkIpRangeToNatOption above. + Subnetworks []*RouterNatSubnetworkToNat `json:"subnetworks,omitempty"` + + // TcpEstablishedIdleTimeoutSec: Timeout (in seconds) for TCP + // established connections. Defaults to 1200s if not set. + TcpEstablishedIdleTimeoutSec int64 `json:"tcpEstablishedIdleTimeoutSec,omitempty"` + + // TcpTransitoryIdleTimeoutSec: Timeout (in seconds) for TCP transitory + // connections. Defaults to 30s if not set. + TcpTransitoryIdleTimeoutSec int64 `json:"tcpTransitoryIdleTimeoutSec,omitempty"` + + // UdpIdleTimeoutSec: Timeout (in seconds) for UDP connections. Defaults + // to 30s if not set. + UdpIdleTimeoutSec int64 `json:"udpIdleTimeoutSec,omitempty"` + + // ForceSendFields is a list of field names (e.g. "IcmpIdleTimeoutSec") + // to unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "IcmpIdleTimeoutSec") to + // include in API requests with the JSON null value. By default, fields + // with empty values are omitted from API requests. However, any field + // with an empty value appearing in NullFields will be sent to the + // server as null. It is an error if a field in this list has a + // non-empty value. This may be used to include null fields in Patch + // requests. + NullFields []string `json:"-"` +} + +func (s *RouterNat) MarshalJSON() ([]byte, error) { + type NoMethod RouterNat + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// RouterNatSubnetworkToNat: Defines the IP ranges that want to use NAT +// for a subnetwork. +type RouterNatSubnetworkToNat struct { + // Name: URL for the subnetwork resource to use NAT. + Name string `json:"name,omitempty"` + + // SecondaryIpRangeNames: A list of the secondary ranges of the + // Subnetwork that are allowed to use NAT. This can be populated only if + // "LIST_OF_SECONDARY_IP_RANGES" is one of the values in + // source_ip_ranges_to_nat. + SecondaryIpRangeNames []string `json:"secondaryIpRangeNames,omitempty"` + + // SourceIpRangesToNat: Specify the options for NAT ranges in the + // Subnetwork. All usages of single value are valid except + // NAT_IP_RANGE_OPTION_UNSPECIFIED. The only valid option with multiple + // values is: ["PRIMARY_IP_RANGE", "LIST_OF_SECONDARY_IP_RANGES"] + // Default: [ALL_IP_RANGES] + // + // Possible values: + // "ALL_IP_RANGES" + // "LIST_OF_SECONDARY_IP_RANGES" + // "PRIMARY_IP_RANGE" + SourceIpRangesToNat []string `json:"sourceIpRangesToNat,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Name") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Name") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *RouterNatSubnetworkToNat) MarshalJSON() ([]byte, error) { + type NoMethod RouterNatSubnetworkToNat + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + type RouterStatus struct { // BestRoutes: Best routes for this router's network. BestRoutes []*Route `json:"bestRoutes,omitempty"` @@ -18463,6 +21763,8 @@ type RouterStatus struct { BgpPeerStatus []*RouterStatusBgpPeerStatus `json:"bgpPeerStatus,omitempty"` + NatStatus []*RouterStatusNatStatus `json:"natStatus,omitempty"` + // Network: URI of the network to which this router belongs. Network string `json:"network,omitempty"` @@ -18550,6 +21852,57 @@ func (s *RouterStatusBgpPeerStatus) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +// RouterStatusNatStatus: Status of a NAT contained in this router. +type RouterStatusNatStatus struct { + // AutoAllocatedNatIps: A list of IPs auto-allocated for NAT. Example: + // ["1.1.1.1", "129.2.16.89"] + AutoAllocatedNatIps []string `json:"autoAllocatedNatIps,omitempty"` + + // MinExtraNatIpsNeeded: The number of extra IPs to allocate. This will + // be greater than 0 only if user-specified IPs are NOT enough to allow + // all configured VMs to use NAT. This value is meaningful only when + // auto-allocation of NAT IPs is *not* used. + MinExtraNatIpsNeeded int64 `json:"minExtraNatIpsNeeded,omitempty"` + + // Name: Unique name of this NAT. + Name string `json:"name,omitempty"` + + // NumVmEndpointsWithNatMappings: Number of VM endpoints (i.e., Nics) + // that can use NAT. + NumVmEndpointsWithNatMappings int64 `json:"numVmEndpointsWithNatMappings,omitempty"` + + // UserAllocatedNatIpResources: A list of fully qualified URLs of + // reserved IP address resources. + UserAllocatedNatIpResources []string `json:"userAllocatedNatIpResources,omitempty"` + + // UserAllocatedNatIps: A list of IPs user-allocated for NAT. They will + // be raw IP strings like "179.12.26.133". + UserAllocatedNatIps []string `json:"userAllocatedNatIps,omitempty"` + + // ForceSendFields is a list of field names (e.g. "AutoAllocatedNatIps") + // to unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "AutoAllocatedNatIps") to + // include in API requests with the JSON null value. By default, fields + // with empty values are omitted from API requests. However, any field + // with an empty value appearing in NullFields will be sent to the + // server as null. It is an error if a field in this list has a + // non-empty value. This may be used to include null fields in Patch + // requests. + NullFields []string `json:"-"` +} + +func (s *RouterStatusNatStatus) MarshalJSON() ([]byte, error) { + type NoMethod RouterStatusNatStatus + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + type RouterStatusResponse struct { // Kind: Type of resource. Kind string `json:"kind,omitempty"` @@ -18747,6 +22100,67 @@ func (s *RoutersScopedListWarningData) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +// Rule: A rule to be applied in a Policy. +type Rule struct { + // Action: Required + // + // Possible values: + // "ALLOW" + // "ALLOW_WITH_LOG" + // "DENY" + // "DENY_WITH_LOG" + // "LOG" + // "NO_ACTION" + Action string `json:"action,omitempty"` + + // Conditions: Additional restrictions that must be met. All conditions + // must pass for the rule to match. + Conditions []*Condition `json:"conditions,omitempty"` + + // Description: Human-readable description of the rule. + Description string `json:"description,omitempty"` + + // Ins: If one or more 'in' clauses are specified, the rule matches if + // the PRINCIPAL/AUTHORITY_SELECTOR is in at least one of these entries. + Ins []string `json:"ins,omitempty"` + + // LogConfigs: The config returned to callers of + // tech.iam.IAM.CheckPolicy for any entries that match the LOG action. + LogConfigs []*LogConfig `json:"logConfigs,omitempty"` + + // NotIns: If one or more 'not_in' clauses are specified, the rule + // matches if the PRINCIPAL/AUTHORITY_SELECTOR is in none of the + // entries. + NotIns []string `json:"notIns,omitempty"` + + // Permissions: A permission is a string of form '..' (e.g., + // 'storage.buckets.list'). A value of '*' matches all permissions, and + // a verb part of '*' (e.g., 'storage.buckets.*') matches all verbs. + Permissions []string `json:"permissions,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Action") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Action") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *Rule) MarshalJSON() ([]byte, error) { + type NoMethod Rule + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + type SSLHealthCheck struct { // Port: The TCP port number for the health check request. The default // value is 443. Valid values are 1 through 65535. @@ -18811,6 +22225,9 @@ type Scheduling struct { // restarted if it is terminated by Compute Engine. AutomaticRestart *bool `json:"automaticRestart,omitempty"` + // NodeAffinities: A set of node affinity and anti-affinity. + NodeAffinities []*SchedulingNodeAffinity `json:"nodeAffinities,omitempty"` + // OnHostMaintenance: Defines the maintenance behavior for this // instance. For standard instances, the default behavior is MIGRATE. // For preemptible instances, the default and only possible behavior is @@ -18851,6 +22268,428 @@ func (s *Scheduling) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +// SchedulingNodeAffinity: Node Affinity: the configuration of desired +// nodes onto which this Instance could be scheduled. +type SchedulingNodeAffinity struct { + // Key: Corresponds to the label key of Node resource. + Key string `json:"key,omitempty"` + + // Operator: Defines the operation of node selection. + // + // Possible values: + // "IN" + // "NOT_IN" + // "OPERATOR_UNSPECIFIED" + Operator string `json:"operator,omitempty"` + + // Values: Corresponds to the label values of Node resource. + Values []string `json:"values,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Key") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Key") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *SchedulingNodeAffinity) MarshalJSON() ([]byte, error) { + type NoMethod SchedulingNodeAffinity + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// SecurityPolicy: A security policy is comprised of one or more rules. +// It can also be associated with one or more 'targets'. (== +// resource_for v1.securityPolicies ==) (== resource_for +// beta.securityPolicies ==) +type SecurityPolicy struct { + // CreationTimestamp: [Output Only] Creation timestamp in RFC3339 text + // format. + CreationTimestamp string `json:"creationTimestamp,omitempty"` + + // Description: An optional description of this resource. Provide this + // property when you create the resource. + Description string `json:"description,omitempty"` + + // Fingerprint: Specifies a fingerprint for this resource, which is + // essentially a hash of the metadata's contents and used for optimistic + // locking. The fingerprint is initially generated by Compute Engine and + // changes after every request to modify or update metadata. You must + // always provide an up-to-date fingerprint hash in order to update or + // change metadata, otherwise the request will fail with error 412 + // conditionNotMet. + // + // To see the latest fingerprint, make get() request to the security + // policy. + Fingerprint string `json:"fingerprint,omitempty"` + + // Id: [Output Only] The unique identifier for the resource. This + // identifier is defined by the server. + Id uint64 `json:"id,omitempty,string"` + + // Kind: [Output only] Type of the resource. Always + // compute#securityPolicyfor security policies + Kind string `json:"kind,omitempty"` + + // Name: Name of the resource. Provided by the client when the resource + // is created. The name must be 1-63 characters long, and comply with + // RFC1035. Specifically, the name must be 1-63 characters long and + // match the regular expression `[a-z]([-a-z0-9]*[a-z0-9])?` which means + // the first character must be a lowercase letter, and all following + // characters must be a dash, lowercase letter, or digit, except the + // last character, which cannot be a dash. + Name string `json:"name,omitempty"` + + // Rules: A list of rules that belong to this policy. There must always + // be a default rule (rule with priority 2147483647 and match "*"). If + // no rules are provided when creating a security policy, a default rule + // with action "allow" will be added. + Rules []*SecurityPolicyRule `json:"rules,omitempty"` + + // SelfLink: [Output Only] Server-defined URL for the resource. + SelfLink string `json:"selfLink,omitempty"` + + // ServerResponse contains the HTTP response code and headers from the + // server. + googleapi.ServerResponse `json:"-"` + + // ForceSendFields is a list of field names (e.g. "CreationTimestamp") + // to unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "CreationTimestamp") to + // include in API requests with the JSON null value. By default, fields + // with empty values are omitted from API requests. However, any field + // with an empty value appearing in NullFields will be sent to the + // server as null. It is an error if a field in this list has a + // non-empty value. This may be used to include null fields in Patch + // requests. + NullFields []string `json:"-"` +} + +func (s *SecurityPolicy) MarshalJSON() ([]byte, error) { + type NoMethod SecurityPolicy + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type SecurityPolicyList struct { + // Id: [Output Only] Unique identifier for the resource; defined by the + // server. + Id string `json:"id,omitempty"` + + // Items: A list of SecurityPolicy resources. + Items []*SecurityPolicy `json:"items,omitempty"` + + // Kind: [Output Only] Type of resource. Always + // compute#securityPolicyList for listsof securityPolicies + Kind string `json:"kind,omitempty"` + + // NextPageToken: [Output Only] This token allows you to get the next + // page of results for list requests. If the number of results is larger + // than maxResults, use the nextPageToken as a value for the query + // parameter pageToken in the next list request. Subsequent list + // requests will have their own nextPageToken to continue paging through + // the results. + NextPageToken string `json:"nextPageToken,omitempty"` + + // Warning: [Output Only] Informational warning message. + Warning *SecurityPolicyListWarning `json:"warning,omitempty"` + + // ServerResponse contains the HTTP response code and headers from the + // server. + googleapi.ServerResponse `json:"-"` + + // ForceSendFields is a list of field names (e.g. "Id") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Id") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *SecurityPolicyList) MarshalJSON() ([]byte, error) { + type NoMethod SecurityPolicyList + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// SecurityPolicyListWarning: [Output Only] Informational warning +// message. +type SecurityPolicyListWarning struct { + // Code: [Output Only] A warning code, if applicable. For example, + // Compute Engine returns NO_RESULTS_ON_PAGE if there are no results in + // the response. + // + // Possible values: + // "CLEANUP_FAILED" + // "DEPRECATED_RESOURCE_USED" + // "DEPRECATED_TYPE_USED" + // "DISK_SIZE_LARGER_THAN_IMAGE_SIZE" + // "EXPERIMENTAL_TYPE_USED" + // "EXTERNAL_API_WARNING" + // "FIELD_VALUE_OVERRIDEN" + // "INJECTED_KERNELS_DEPRECATED" + // "MISSING_TYPE_DEPENDENCY" + // "NEXT_HOP_ADDRESS_NOT_ASSIGNED" + // "NEXT_HOP_CANNOT_IP_FORWARD" + // "NEXT_HOP_INSTANCE_NOT_FOUND" + // "NEXT_HOP_INSTANCE_NOT_ON_NETWORK" + // "NEXT_HOP_NOT_RUNNING" + // "NOT_CRITICAL_ERROR" + // "NO_RESULTS_ON_PAGE" + // "REQUIRED_TOS_AGREEMENT" + // "RESOURCE_IN_USE_BY_OTHER_RESOURCE_WARNING" + // "RESOURCE_NOT_DELETED" + // "SCHEMA_VALIDATION_IGNORED" + // "SINGLE_INSTANCE_PROPERTY_TEMPLATE" + // "UNDECLARED_PROPERTIES" + // "UNREACHABLE" + Code string `json:"code,omitempty"` + + // Data: [Output Only] Metadata about this warning in key: value format. + // For example: + // "data": [ { "key": "scope", "value": "zones/us-east1-d" } + Data []*SecurityPolicyListWarningData `json:"data,omitempty"` + + // Message: [Output Only] A human-readable description of the warning + // code. + Message string `json:"message,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Code") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Code") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *SecurityPolicyListWarning) MarshalJSON() ([]byte, error) { + type NoMethod SecurityPolicyListWarning + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type SecurityPolicyListWarningData struct { + // Key: [Output Only] A key that provides more detail on the warning + // being returned. For example, for warnings where there are no results + // in a list request for a particular zone, this key might be scope and + // the key value might be the zone name. Other examples might be a key + // indicating a deprecated resource and a suggested replacement, or a + // warning about invalid network settings (for example, if an instance + // attempts to perform IP forwarding but is not enabled for IP + // forwarding). + Key string `json:"key,omitempty"` + + // Value: [Output Only] A warning data value corresponding to the key. + Value string `json:"value,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Key") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Key") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *SecurityPolicyListWarningData) MarshalJSON() ([]byte, error) { + type NoMethod SecurityPolicyListWarningData + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type SecurityPolicyReference struct { + SecurityPolicy string `json:"securityPolicy,omitempty"` + + // ForceSendFields is a list of field names (e.g. "SecurityPolicy") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "SecurityPolicy") to + // include in API requests with the JSON null value. By default, fields + // with empty values are omitted from API requests. However, any field + // with an empty value appearing in NullFields will be sent to the + // server as null. It is an error if a field in this list has a + // non-empty value. This may be used to include null fields in Patch + // requests. + NullFields []string `json:"-"` +} + +func (s *SecurityPolicyReference) MarshalJSON() ([]byte, error) { + type NoMethod SecurityPolicyReference + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// SecurityPolicyRule: Represents a rule that describes one or more +// match conditions along with the action to be taken when traffic +// matches this condition (allow or deny). +type SecurityPolicyRule struct { + // Action: The Action to preform when the client connection triggers the + // rule. Can currently be either "allow" or "deny()" where valid values + // for status are 403, 404, and 502. + Action string `json:"action,omitempty"` + + // Description: An optional description of this resource. Provide this + // property when you create the resource. + Description string `json:"description,omitempty"` + + // Kind: [Output only] Type of the resource. Always + // compute#securityPolicyRule for security policy rules + Kind string `json:"kind,omitempty"` + + // Match: A match condition that incoming traffic is evaluated against. + // If it evaluates to true, the corresponding ?action? is enforced. + Match *SecurityPolicyRuleMatcher `json:"match,omitempty"` + + // Preview: If set to true, the specified action is not enforced. + Preview bool `json:"preview,omitempty"` + + // Priority: An integer indicating the priority of a rule in the list. + // The priority must be a positive value between 0 and 2147483647. Rules + // are evaluated from highest to lowest priority where 0 is the highest + // priority and 2147483647 is the lowest prority. + Priority int64 `json:"priority,omitempty"` + + // ServerResponse contains the HTTP response code and headers from the + // server. + googleapi.ServerResponse `json:"-"` + + // ForceSendFields is a list of field names (e.g. "Action") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Action") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *SecurityPolicyRule) MarshalJSON() ([]byte, error) { + type NoMethod SecurityPolicyRule + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// SecurityPolicyRuleMatcher: Represents a match condition that incoming +// traffic is evaluated against. Exactly one field must be specified. +type SecurityPolicyRuleMatcher struct { + // Config: The configuration options available when specifying + // versioned_expr. This field must be specified if versioned_expr is + // specified and cannot be specified if versioned_expr is not specified. + Config *SecurityPolicyRuleMatcherConfig `json:"config,omitempty"` + + // VersionedExpr: Preconfigured versioned expression. If this field is + // specified, config must also be specified. Available preconfigured + // expressions along with their requirements are: SRC_IPS_V1 - must + // specify the corresponding src_ip_range field in config. + // + // Possible values: + // "SRC_IPS_V1" + VersionedExpr string `json:"versionedExpr,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Config") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Config") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *SecurityPolicyRuleMatcher) MarshalJSON() ([]byte, error) { + type NoMethod SecurityPolicyRuleMatcher + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type SecurityPolicyRuleMatcherConfig struct { + // SrcIpRanges: CIDR IP address range. + SrcIpRanges []string `json:"srcIpRanges,omitempty"` + + // ForceSendFields is a list of field names (e.g. "SrcIpRanges") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "SrcIpRanges") to include + // in API requests with the JSON null value. By default, fields with + // empty values are omitted from API requests. However, any field with + // an empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *SecurityPolicyRuleMatcherConfig) MarshalJSON() ([]byte, error) { + type NoMethod SecurityPolicyRuleMatcherConfig + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + // SerialPortOutput: An instance's serial console output. type SerialPortOutput struct { // Contents: [Output Only] The contents of the console output. @@ -18999,7 +22838,8 @@ type Snapshot struct { // optimistic locking. The fingerprint is initially generated by Compute // Engine and changes after every request to modify or update labels. // You must always provide an up-to-date fingerprint hash in order to - // update or change labels. + // update or change labels, otherwise the request will fail with error + // 412 conditionNotMet. // // To see the latest fingerprint, make a get() request to retrieve a // snapshot. @@ -19738,7 +23578,11 @@ type SslPolicy struct { // Fingerprint: Fingerprint of this resource. A hash of the contents // stored in this object. This field is used in optimistic locking. This // field will be ignored when inserting a SslPolicy. An up-to-date - // fingerprint must be provided in order to update the SslPolicy. + // fingerprint must be provided in order to update the SslPolicy, + // otherwise the request will fail with error 412 conditionNotMet. + // + // To see the latest fingerprint, make a get() request to retrieve an + // SslPolicy. Fingerprint string `json:"fingerprint,omitempty"` // Id: [Output Only] The unique identifier for the resource. This @@ -19959,12 +23803,18 @@ type Subnetwork struct { Description string `json:"description,omitempty"` // EnableFlowLogs: Whether to enable flow logging for this subnetwork. + // If this field is not explicitly set, it will not appear in get + // listings. If not set the default behavior is to disable flow logging. EnableFlowLogs bool `json:"enableFlowLogs,omitempty"` // Fingerprint: Fingerprint of this resource. A hash of the contents // stored in this object. This field is used in optimistic locking. This // field will be ignored when inserting a Subnetwork. An up-to-date - // fingerprint must be provided in order to update the Subnetwork. + // fingerprint must be provided in order to update the Subnetwork, + // otherwise the request will fail with error 412 conditionNotMet. + // + // To see the latest fingerprint, make a get() request to retrieve a + // Subnetwork. Fingerprint string `json:"fingerprint,omitempty"` // GatewayAddress: [Output Only] The gateway address for default routes @@ -20014,7 +23864,8 @@ type Subnetwork struct { // SecondaryIpRanges: An array of configurations for secondary IP ranges // for VM instances contained in this subnetwork. The primary IP of such // VM must belong to the primary ipCidrRange of the subnetwork. The - // alias IPs may belong to either primary or secondary ranges. + // alias IPs may belong to either primary or secondary ranges. This + // field can be updated with a patch request. SecondaryIpRanges []*SubnetworkSecondaryRange `json:"secondaryIpRanges,omitempty"` // SelfLink: [Output Only] Server-defined URL for the resource. @@ -21010,8 +24861,9 @@ type TargetHttpsProxy struct { SelfLink string `json:"selfLink,omitempty"` // SslCertificates: URLs to SslCertificate resources that are used to - // authenticate connections between users and the load balancer. - // Currently, exactly one SSL certificate must be specified. + // authenticate connections between users and the load balancer. At + // least one SSL certificate must be specified. Currently, you may + // specify up to 15 SSL certificates. SslCertificates []string `json:"sslCertificates,omitempty"` // SslPolicy: URL of SslPolicy resource that will be associated with the @@ -21822,7 +25674,7 @@ type TargetPool struct { // SelfLink: [Output Only] Server-defined URL for the resource. SelfLink string `json:"selfLink,omitempty"` - // SessionAffinity: Sesssion affinity option, must be one of the + // SessionAffinity: Session affinity option, must be one of the // following values: // NONE: Connections from the same client IP may go to any instance in // the pool. @@ -22641,8 +26493,9 @@ type TargetSslProxy struct { Service string `json:"service,omitempty"` // SslCertificates: URLs to SslCertificate resources that are used to - // authenticate connections to Backends. Currently exactly one SSL - // certificate must be specified. + // authenticate connections to Backends. At least one SSL certificate + // must be specified. Currently, you may specify up to 15 SSL + // certificates. SslCertificates []string `json:"sslCertificates,omitempty"` // SslPolicy: URL of SslPolicy resource that will be associated with the @@ -23755,8 +27608,13 @@ type UrlMap struct { // format. CreationTimestamp string `json:"creationTimestamp,omitempty"` - // DefaultService: The URL of the BackendService resource if none of the + // DefaultService: The URL of the backendService resource if none of the // hostRules match. + // Use defaultService instead of defaultRouteAction when simple routing + // to a backendService is desired and other advanced capabilities like + // traffic splitting and rewrites are not required. + // Only one of defaultService, defaultRouteAction or defaultUrlRedirect + // should must be set. DefaultService string `json:"defaultService,omitempty"` // Description: An optional description of this resource. Provide this @@ -23766,7 +27624,11 @@ type UrlMap struct { // Fingerprint: Fingerprint of this resource. A hash of the contents // stored in this object. This field is used in optimistic locking. This // field will be ignored when inserting a UrlMap. An up-to-date - // fingerprint must be provided in order to update the UrlMap. + // fingerprint must be provided in order to update the UrlMap, otherwise + // the request will fail with error 412 conditionNotMet. + // + // To see the latest fingerprint, make a get() request to retrieve a + // UrlMap. Fingerprint string `json:"fingerprint,omitempty"` // HostRules: The list of HostRules to use against the URL. @@ -24142,6 +28004,237 @@ func (s *UrlMapsValidateResponse) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +// UsableSubnetwork: Subnetwork which the current user has +// compute.subnetworks.use permission on. +type UsableSubnetwork struct { + // IpCidrRange: The range of internal addresses that are owned by this + // subnetwork. + IpCidrRange string `json:"ipCidrRange,omitempty"` + + // Network: Network URL. + Network string `json:"network,omitempty"` + + // SecondaryIpRanges: Secondary IP ranges. + SecondaryIpRanges []*UsableSubnetworkSecondaryRange `json:"secondaryIpRanges,omitempty"` + + // Subnetwork: Subnetwork URL. + Subnetwork string `json:"subnetwork,omitempty"` + + // ForceSendFields is a list of field names (e.g. "IpCidrRange") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "IpCidrRange") to include + // in API requests with the JSON null value. By default, fields with + // empty values are omitted from API requests. However, any field with + // an empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *UsableSubnetwork) MarshalJSON() ([]byte, error) { + type NoMethod UsableSubnetwork + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// UsableSubnetworkSecondaryRange: Secondary IP range of a usable +// subnetwork. +type UsableSubnetworkSecondaryRange struct { + // IpCidrRange: The range of IP addresses belonging to this subnetwork + // secondary range. + IpCidrRange string `json:"ipCidrRange,omitempty"` + + // RangeName: The name associated with this subnetwork secondary range, + // used when adding an alias IP range to a VM instance. The name must be + // 1-63 characters long, and comply with RFC1035. The name must be + // unique within the subnetwork. + RangeName string `json:"rangeName,omitempty"` + + // ForceSendFields is a list of field names (e.g. "IpCidrRange") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "IpCidrRange") to include + // in API requests with the JSON null value. By default, fields with + // empty values are omitted from API requests. However, any field with + // an empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *UsableSubnetworkSecondaryRange) MarshalJSON() ([]byte, error) { + type NoMethod UsableSubnetworkSecondaryRange + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type UsableSubnetworksAggregatedList struct { + // Id: [Output Only] The unique identifier for the resource. This + // identifier is defined by the server. + Id string `json:"id,omitempty"` + + // Items: [Output] A list of usable subnetwork URLs. + Items []*UsableSubnetwork `json:"items,omitempty"` + + // Kind: [Output Only] Type of resource. Always + // compute#usableSubnetworksAggregatedList for aggregated lists of + // usable subnetworks. + Kind string `json:"kind,omitempty"` + + // NextPageToken: [Output Only] This token allows you to get the next + // page of results for list requests. If the number of results is larger + // than maxResults, use the nextPageToken as a value for the query + // parameter pageToken in the next list request. Subsequent list + // requests will have their own nextPageToken to continue paging through + // the results. + NextPageToken string `json:"nextPageToken,omitempty"` + + // SelfLink: [Output Only] Server-defined URL for this resource. + SelfLink string `json:"selfLink,omitempty"` + + // Warning: [Output Only] Informational warning message. + Warning *UsableSubnetworksAggregatedListWarning `json:"warning,omitempty"` + + // ServerResponse contains the HTTP response code and headers from the + // server. + googleapi.ServerResponse `json:"-"` + + // ForceSendFields is a list of field names (e.g. "Id") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Id") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *UsableSubnetworksAggregatedList) MarshalJSON() ([]byte, error) { + type NoMethod UsableSubnetworksAggregatedList + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// UsableSubnetworksAggregatedListWarning: [Output Only] Informational +// warning message. +type UsableSubnetworksAggregatedListWarning struct { + // Code: [Output Only] A warning code, if applicable. For example, + // Compute Engine returns NO_RESULTS_ON_PAGE if there are no results in + // the response. + // + // Possible values: + // "CLEANUP_FAILED" + // "DEPRECATED_RESOURCE_USED" + // "DEPRECATED_TYPE_USED" + // "DISK_SIZE_LARGER_THAN_IMAGE_SIZE" + // "EXPERIMENTAL_TYPE_USED" + // "EXTERNAL_API_WARNING" + // "FIELD_VALUE_OVERRIDEN" + // "INJECTED_KERNELS_DEPRECATED" + // "MISSING_TYPE_DEPENDENCY" + // "NEXT_HOP_ADDRESS_NOT_ASSIGNED" + // "NEXT_HOP_CANNOT_IP_FORWARD" + // "NEXT_HOP_INSTANCE_NOT_FOUND" + // "NEXT_HOP_INSTANCE_NOT_ON_NETWORK" + // "NEXT_HOP_NOT_RUNNING" + // "NOT_CRITICAL_ERROR" + // "NO_RESULTS_ON_PAGE" + // "REQUIRED_TOS_AGREEMENT" + // "RESOURCE_IN_USE_BY_OTHER_RESOURCE_WARNING" + // "RESOURCE_NOT_DELETED" + // "SCHEMA_VALIDATION_IGNORED" + // "SINGLE_INSTANCE_PROPERTY_TEMPLATE" + // "UNDECLARED_PROPERTIES" + // "UNREACHABLE" + Code string `json:"code,omitempty"` + + // Data: [Output Only] Metadata about this warning in key: value format. + // For example: + // "data": [ { "key": "scope", "value": "zones/us-east1-d" } + Data []*UsableSubnetworksAggregatedListWarningData `json:"data,omitempty"` + + // Message: [Output Only] A human-readable description of the warning + // code. + Message string `json:"message,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Code") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Code") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *UsableSubnetworksAggregatedListWarning) MarshalJSON() ([]byte, error) { + type NoMethod UsableSubnetworksAggregatedListWarning + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type UsableSubnetworksAggregatedListWarningData struct { + // Key: [Output Only] A key that provides more detail on the warning + // being returned. For example, for warnings where there are no results + // in a list request for a particular zone, this key might be scope and + // the key value might be the zone name. Other examples might be a key + // indicating a deprecated resource and a suggested replacement, or a + // warning about invalid network settings (for example, if an instance + // attempts to perform IP forwarding but is not enabled for IP + // forwarding). + Key string `json:"key,omitempty"` + + // Value: [Output Only] A warning data value corresponding to the key. + Value string `json:"value,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Key") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Key") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *UsableSubnetworksAggregatedListWarningData) MarshalJSON() ([]byte, error) { + type NoMethod UsableSubnetworksAggregatedListWarningData + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + // UsageExportLocation: The location in Cloud Storage and naming method // of the daily usage report. Contains bucket_name and report_name // prefix. @@ -24185,6 +28278,241 @@ func (s *UsageExportLocation) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +// VmEndpointNatMappings: Contain information of Nat mapping for a VM +// endpoint (i.e., NIC). +type VmEndpointNatMappings struct { + // InstanceName: Name of the VM instance which the endpoint belongs to + InstanceName string `json:"instanceName,omitempty"` + + InterfaceNatMappings []*VmEndpointNatMappingsInterfaceNatMappings `json:"interfaceNatMappings,omitempty"` + + // ForceSendFields is a list of field names (e.g. "InstanceName") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "InstanceName") to include + // in API requests with the JSON null value. By default, fields with + // empty values are omitted from API requests. However, any field with + // an empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *VmEndpointNatMappings) MarshalJSON() ([]byte, error) { + type NoMethod VmEndpointNatMappings + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// VmEndpointNatMappingsInterfaceNatMappings: Contain information of Nat +// mapping for an interface of this endpoint. +type VmEndpointNatMappingsInterfaceNatMappings struct { + // NatIpPortRanges: A list of all IP:port-range mappings assigned to + // this interface. These ranges are inclusive, that is, both the first + // and the last ports can be used for NAT. Example: + // ["2.2.2.2:12345-12355", "1.1.1.1:2234-2234"]. + NatIpPortRanges []string `json:"natIpPortRanges,omitempty"` + + // NumTotalNatPorts: Total number of ports across all NAT IPs allocated + // to this interface. It equals to the aggregated port number in the + // field nat_ip_port_ranges. + NumTotalNatPorts int64 `json:"numTotalNatPorts,omitempty"` + + // SourceAliasIpRange: Alias IP range for this interface endpoint. It + // will be a private (RFC 1918) IP range. Examples: "10.33.4.55/32", or + // "192.168.5.0/24". + SourceAliasIpRange string `json:"sourceAliasIpRange,omitempty"` + + // SourceVirtualIp: Primary IP of the VM for this NIC. + SourceVirtualIp string `json:"sourceVirtualIp,omitempty"` + + // ForceSendFields is a list of field names (e.g. "NatIpPortRanges") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "NatIpPortRanges") to + // include in API requests with the JSON null value. By default, fields + // with empty values are omitted from API requests. However, any field + // with an empty value appearing in NullFields will be sent to the + // server as null. It is an error if a field in this list has a + // non-empty value. This may be used to include null fields in Patch + // requests. + NullFields []string `json:"-"` +} + +func (s *VmEndpointNatMappingsInterfaceNatMappings) MarshalJSON() ([]byte, error) { + type NoMethod VmEndpointNatMappingsInterfaceNatMappings + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// VmEndpointNatMappingsList: Contains a list of VmEndpointNatMappings. +type VmEndpointNatMappingsList struct { + // Id: [Output Only] The unique identifier for the resource. This + // identifier is defined by the server. + Id string `json:"id,omitempty"` + + // Kind: [Output Only] Type of resource. Always + // compute#vmEndpointNatMappingsList for lists of Nat mappings of VM + // endpoints. + Kind string `json:"kind,omitempty"` + + // NextPageToken: [Output Only] This token allows you to get the next + // page of results for list requests. If the number of results is larger + // than maxResults, use the nextPageToken as a value for the query + // parameter pageToken in the next list request. Subsequent list + // requests will have their own nextPageToken to continue paging through + // the results. + NextPageToken string `json:"nextPageToken,omitempty"` + + // Result: [Output Only] A list of Nat mapping information of VM + // endpoints. + Result []*VmEndpointNatMappings `json:"result,omitempty"` + + // SelfLink: [Output Only] Server-defined URL for this resource. + SelfLink string `json:"selfLink,omitempty"` + + // Warning: [Output Only] Informational warning message. + Warning *VmEndpointNatMappingsListWarning `json:"warning,omitempty"` + + // ServerResponse contains the HTTP response code and headers from the + // server. + googleapi.ServerResponse `json:"-"` + + // ForceSendFields is a list of field names (e.g. "Id") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Id") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *VmEndpointNatMappingsList) MarshalJSON() ([]byte, error) { + type NoMethod VmEndpointNatMappingsList + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// VmEndpointNatMappingsListWarning: [Output Only] Informational warning +// message. +type VmEndpointNatMappingsListWarning struct { + // Code: [Output Only] A warning code, if applicable. For example, + // Compute Engine returns NO_RESULTS_ON_PAGE if there are no results in + // the response. + // + // Possible values: + // "CLEANUP_FAILED" + // "DEPRECATED_RESOURCE_USED" + // "DEPRECATED_TYPE_USED" + // "DISK_SIZE_LARGER_THAN_IMAGE_SIZE" + // "EXPERIMENTAL_TYPE_USED" + // "EXTERNAL_API_WARNING" + // "FIELD_VALUE_OVERRIDEN" + // "INJECTED_KERNELS_DEPRECATED" + // "MISSING_TYPE_DEPENDENCY" + // "NEXT_HOP_ADDRESS_NOT_ASSIGNED" + // "NEXT_HOP_CANNOT_IP_FORWARD" + // "NEXT_HOP_INSTANCE_NOT_FOUND" + // "NEXT_HOP_INSTANCE_NOT_ON_NETWORK" + // "NEXT_HOP_NOT_RUNNING" + // "NOT_CRITICAL_ERROR" + // "NO_RESULTS_ON_PAGE" + // "REQUIRED_TOS_AGREEMENT" + // "RESOURCE_IN_USE_BY_OTHER_RESOURCE_WARNING" + // "RESOURCE_NOT_DELETED" + // "SCHEMA_VALIDATION_IGNORED" + // "SINGLE_INSTANCE_PROPERTY_TEMPLATE" + // "UNDECLARED_PROPERTIES" + // "UNREACHABLE" + Code string `json:"code,omitempty"` + + // Data: [Output Only] Metadata about this warning in key: value format. + // For example: + // "data": [ { "key": "scope", "value": "zones/us-east1-d" } + Data []*VmEndpointNatMappingsListWarningData `json:"data,omitempty"` + + // Message: [Output Only] A human-readable description of the warning + // code. + Message string `json:"message,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Code") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Code") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *VmEndpointNatMappingsListWarning) MarshalJSON() ([]byte, error) { + type NoMethod VmEndpointNatMappingsListWarning + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type VmEndpointNatMappingsListWarningData struct { + // Key: [Output Only] A key that provides more detail on the warning + // being returned. For example, for warnings where there are no results + // in a list request for a particular zone, this key might be scope and + // the key value might be the zone name. Other examples might be a key + // indicating a deprecated resource and a suggested replacement, or a + // warning about invalid network settings (for example, if an instance + // attempts to perform IP forwarding but is not enabled for IP + // forwarding). + Key string `json:"key,omitempty"` + + // Value: [Output Only] A warning data value corresponding to the key. + Value string `json:"value,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Key") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Key") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *VmEndpointNatMappingsListWarningData) MarshalJSON() ([]byte, error) { + type NoMethod VmEndpointNatMappingsListWarningData + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + // VpnTunnel: VPN tunnel resource. (== resource_for beta.vpnTunnels ==) // (== resource_for v1.vpnTunnels ==) type VpnTunnel struct { @@ -24905,8 +29233,8 @@ func (s *XpnHostListWarningData) MarshalJSON() ([]byte, error) { // XpnResourceId: Service resource (a.k.a service project) ID. type XpnResourceId struct { // Id: The ID of the service resource. In the case of projects, this - // field matches the project ID (e.g., my-project), not the project - // number (e.g., 12345678). + // field supports project id (e.g., my-project-123) and project number + // (e.g. 12345678). Id string `json:"id,omitempty"` // Type: The type of the service resource. @@ -25201,6 +29529,44 @@ func (s *ZoneSetLabelsRequest) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +type ZoneSetPolicyRequest struct { + // Bindings: Flatten Policy to create a backwacd compatible wire-format. + // Deprecated. Use 'policy' to specify bindings. + Bindings []*Binding `json:"bindings,omitempty"` + + // Etag: Flatten Policy to create a backward compatible wire-format. + // Deprecated. Use 'policy' to specify the etag. + Etag string `json:"etag,omitempty"` + + // Policy: REQUIRED: The complete policy to be applied to the + // 'resource'. The size of the policy is limited to a few 10s of KB. An + // empty policy is in general a valid policy but certain services (like + // Projects) might reject them. + Policy *Policy `json:"policy,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Bindings") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Bindings") to include in + // API requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *ZoneSetPolicyRequest) MarshalJSON() ([]byte, error) { + type NoMethod ZoneSetPolicyRequest + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + // method id "compute.acceleratorTypes.aggregatedList": type AcceleratorTypesAggregatedListCall struct { @@ -25328,9 +29694,13 @@ func (c *AcceleratorTypesAggregatedListCall) doRequest(alt string) (*http.Respon } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/aggregated/acceleratorTypes") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -25516,9 +29886,13 @@ func (c *AcceleratorTypesGetCall) doRequest(alt string) (*http.Response, error) } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/acceleratorTypes/{acceleratorType}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -25740,9 +30114,13 @@ func (c *AcceleratorTypesListCall) doRequest(alt string) (*http.Response, error) } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/acceleratorTypes") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -25997,9 +30375,13 @@ func (c *AddressesAggregatedListCall) doRequest(alt string) (*http.Response, err } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/aggregated/addresses") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -26191,9 +30573,13 @@ func (c *AddressesDeleteCall) doRequest(alt string) (*http.Response, error) { reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/addresses/{address}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -26358,9 +30744,13 @@ func (c *AddressesGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/addresses/{address}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -26532,9 +30922,13 @@ func (c *AddressesInsertCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/addresses") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -26755,9 +31149,13 @@ func (c *AddressesListCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/addresses") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -27011,9 +31409,13 @@ func (c *AutoscalersAggregatedListCall) doRequest(alt string) (*http.Response, e } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/aggregated/autoscalers") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -27204,9 +31606,13 @@ func (c *AutoscalersDeleteCall) doRequest(alt string) (*http.Response, error) { reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/autoscalers/{autoscaler}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -27371,9 +31777,13 @@ func (c *AutoscalersGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/autoscalers/{autoscaler}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -27544,9 +31954,13 @@ func (c *AutoscalersInsertCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/autoscalers") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -27766,9 +32180,13 @@ func (c *AutoscalersListCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/autoscalers") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -27982,9 +32400,13 @@ func (c *AutoscalersPatchCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/autoscalers") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PATCH", urls, body) + req, err := http.NewRequest("PATCH", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -28166,9 +32588,13 @@ func (c *AutoscalersUpdateCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/autoscalers") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PUT", urls, body) + req, err := http.NewRequest("PUT", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -28276,7 +32702,8 @@ type BackendBucketsAddSignedUrlKeyCall struct { header_ http.Header } -// AddSignedUrlKey: Adds the given Signed URL Key to the backend bucket. +// AddSignedUrlKey: Adds a key for validating requests with signed URLs +// for this backend bucket. func (r *BackendBucketsService) AddSignedUrlKey(project string, backendBucket string, signedurlkey *SignedUrlKey) *BackendBucketsAddSignedUrlKeyCall { c := &BackendBucketsAddSignedUrlKeyCall{s: r.s, urlParams_: make(gensupport.URLParams)} c.project = project @@ -28342,9 +32769,13 @@ func (c *BackendBucketsAddSignedUrlKeyCall) doRequest(alt string) (*http.Respons } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/backendBuckets/{backendBucket}/addSignedUrlKey") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -28391,7 +32822,7 @@ func (c *BackendBucketsAddSignedUrlKeyCall) Do(opts ...googleapi.CallOption) (*O } return ret, nil // { - // "description": "Adds the given Signed URL Key to the backend bucket.", + // "description": "Adds a key for validating requests with signed URLs for this backend bucket.", // "httpMethod": "POST", // "id": "compute.backendBuckets.addSignedUrlKey", // "parameterOrder": [ @@ -28504,9 +32935,13 @@ func (c *BackendBucketsDeleteCall) doRequest(alt string) (*http.Response, error) reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/backendBuckets/{backendBucket}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -28604,8 +33039,8 @@ type BackendBucketsDeleteSignedUrlKeyCall struct { header_ http.Header } -// DeleteSignedUrlKey: Deletes the given Signed URL Key from the backend -// bucket. +// DeleteSignedUrlKey: Deletes a key for validating requests with signed +// URLs for this backend bucket. func (r *BackendBucketsService) DeleteSignedUrlKey(project string, backendBucket string, keyName string) *BackendBucketsDeleteSignedUrlKeyCall { c := &BackendBucketsDeleteSignedUrlKeyCall{s: r.s, urlParams_: make(gensupport.URLParams)} c.project = project @@ -28666,9 +33101,13 @@ func (c *BackendBucketsDeleteSignedUrlKeyCall) doRequest(alt string) (*http.Resp reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/backendBuckets/{backendBucket}/deleteSignedUrlKey") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -28715,7 +33154,7 @@ func (c *BackendBucketsDeleteSignedUrlKeyCall) Do(opts ...googleapi.CallOption) } return ret, nil // { - // "description": "Deletes the given Signed URL Key from the backend bucket.", + // "description": "Deletes a key for validating requests with signed URLs for this backend bucket.", // "httpMethod": "POST", // "id": "compute.backendBuckets.deleteSignedUrlKey", // "parameterOrder": [ @@ -28828,9 +33267,13 @@ func (c *BackendBucketsGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/backendBuckets/{backendBucket}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -28990,9 +33433,13 @@ func (c *BackendBucketsInsertCall) doRequest(alt string) (*http.Response, error) } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/backendBuckets") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -29201,9 +33648,13 @@ func (c *BackendBucketsListCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/backendBuckets") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -29401,9 +33852,13 @@ func (c *BackendBucketsPatchCall) doRequest(alt string) (*http.Response, error) } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/backendBuckets/{backendBucket}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PATCH", urls, body) + req, err := http.NewRequest("PATCH", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -29572,9 +34027,13 @@ func (c *BackendBucketsUpdateCall) doRequest(alt string) (*http.Response, error) } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/backendBuckets/{backendBucket}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PUT", urls, body) + req, err := http.NewRequest("PUT", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -29676,8 +34135,8 @@ type BackendServicesAddSignedUrlKeyCall struct { header_ http.Header } -// AddSignedUrlKey: Adds the given Signed URL Key to the specified -// backend service. +// AddSignedUrlKey: Adds a key for validating requests with signed URLs +// for this backend service. func (r *BackendServicesService) AddSignedUrlKey(project string, backendService string, signedurlkey *SignedUrlKey) *BackendServicesAddSignedUrlKeyCall { c := &BackendServicesAddSignedUrlKeyCall{s: r.s, urlParams_: make(gensupport.URLParams)} c.project = project @@ -29743,9 +34202,13 @@ func (c *BackendServicesAddSignedUrlKeyCall) doRequest(alt string) (*http.Respon } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/backendServices/{backendService}/addSignedUrlKey") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -29792,7 +34255,7 @@ func (c *BackendServicesAddSignedUrlKeyCall) Do(opts ...googleapi.CallOption) (* } return ret, nil // { - // "description": "Adds the given Signed URL Key to the specified backend service.", + // "description": "Adds a key for validating requests with signed URLs for this backend service.", // "httpMethod": "POST", // "id": "compute.backendServices.addSignedUrlKey", // "parameterOrder": [ @@ -29962,9 +34425,13 @@ func (c *BackendServicesAggregatedListCall) doRequest(alt string) (*http.Respons } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/aggregated/backendServices") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -30154,9 +34621,13 @@ func (c *BackendServicesDeleteCall) doRequest(alt string) (*http.Response, error reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/backendServices/{backendService}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -30254,8 +34725,8 @@ type BackendServicesDeleteSignedUrlKeyCall struct { header_ http.Header } -// DeleteSignedUrlKey: Deletes the given Signed URL Key from the -// specified backend service. +// DeleteSignedUrlKey: Deletes a key for validating requests with signed +// URLs for this backend service. func (r *BackendServicesService) DeleteSignedUrlKey(project string, backendService string, keyName string) *BackendServicesDeleteSignedUrlKeyCall { c := &BackendServicesDeleteSignedUrlKeyCall{s: r.s, urlParams_: make(gensupport.URLParams)} c.project = project @@ -30316,9 +34787,13 @@ func (c *BackendServicesDeleteSignedUrlKeyCall) doRequest(alt string) (*http.Res reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/backendServices/{backendService}/deleteSignedUrlKey") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -30365,7 +34840,7 @@ func (c *BackendServicesDeleteSignedUrlKeyCall) Do(opts ...googleapi.CallOption) } return ret, nil // { - // "description": "Deletes the given Signed URL Key from the specified backend service.", + // "description": "Deletes a key for validating requests with signed URLs for this backend service.", // "httpMethod": "POST", // "id": "compute.backendServices.deleteSignedUrlKey", // "parameterOrder": [ @@ -30424,7 +34899,7 @@ type BackendServicesGetCall struct { } // Get: Returns the specified BackendService resource. Gets a list of -// available backend services by making a list() request. +// available backend services. // For details, see https://cloud.google.com/compute/docs/reference/latest/backendServices/get func (r *BackendServicesService) Get(project string, backendService string) *BackendServicesGetCall { c := &BackendServicesGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} @@ -30479,9 +34954,13 @@ func (c *BackendServicesGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/backendServices/{backendService}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -30528,7 +35007,7 @@ func (c *BackendServicesGetCall) Do(opts ...googleapi.CallOption) (*BackendServi } return ret, nil // { - // "description": "Returns the specified BackendService resource. Gets a list of available backend services by making a list() request.", + // "description": "Returns the specified BackendService resource. Gets a list of available backend services.", // "httpMethod": "GET", // "id": "compute.backendServices.get", // "parameterOrder": [ @@ -30625,9 +35104,13 @@ func (c *BackendServicesGetHealthCall) doRequest(alt string) (*http.Response, er } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/backendServices/{backendService}/getHealth") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -30792,9 +35275,13 @@ func (c *BackendServicesInsertCall) doRequest(alt string) (*http.Response, error } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/backendServices") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -31004,9 +35491,13 @@ func (c *BackendServicesListCall) doRequest(alt string) (*http.Response, error) } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/backendServices") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -31208,9 +35699,13 @@ func (c *BackendServicesPatchCall) doRequest(alt string) (*http.Response, error) } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/backendServices/{backendService}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PATCH", urls, body) + req, err := http.NewRequest("PATCH", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -31268,7 +35763,7 @@ func (c *BackendServicesPatchCall) Do(opts ...googleapi.CallOption) (*Operation, // "backendService": { // "description": "Name of the BackendService resource to patch.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -31300,6 +35795,180 @@ func (c *BackendServicesPatchCall) Do(opts ...googleapi.CallOption) (*Operation, } +// method id "compute.backendServices.setSecurityPolicy": + +type BackendServicesSetSecurityPolicyCall struct { + s *Service + project string + backendService string + securitypolicyreference *SecurityPolicyReference + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// SetSecurityPolicy: Sets the security policy for the specified backend +// service. +func (r *BackendServicesService) SetSecurityPolicy(project string, backendService string, securitypolicyreference *SecurityPolicyReference) *BackendServicesSetSecurityPolicyCall { + c := &BackendServicesSetSecurityPolicyCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.backendService = backendService + c.securitypolicyreference = securitypolicyreference + return c +} + +// RequestId sets the optional parameter "requestId": An optional +// request ID to identify requests. Specify a unique request ID so that +// if you must retry your request, the server will know to ignore the +// request if it has already been completed. +// +// For example, consider a situation where you make an initial request +// and the request times out. If you make the request again with the +// same request ID, the server can check if original operation with the +// same request ID was received, and if so, will ignore the second +// request. This prevents clients from accidentally creating duplicate +// commitments. +// +// The request ID must be a valid UUID with the exception that zero UUID +// is not supported (00000000-0000-0000-0000-000000000000). +func (c *BackendServicesSetSecurityPolicyCall) RequestId(requestId string) *BackendServicesSetSecurityPolicyCall { + c.urlParams_.Set("requestId", requestId) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *BackendServicesSetSecurityPolicyCall) Fields(s ...googleapi.Field) *BackendServicesSetSecurityPolicyCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *BackendServicesSetSecurityPolicyCall) Context(ctx context.Context) *BackendServicesSetSecurityPolicyCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *BackendServicesSetSecurityPolicyCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *BackendServicesSetSecurityPolicyCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.securitypolicyreference) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/backendServices/{backendService}/setSecurityPolicy") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "backendService": c.backendService, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.backendServices.setSecurityPolicy" call. +// Exactly one of *Operation or error will be non-nil. Any non-2xx +// status code is an error. Response headers are in either +// *Operation.ServerResponse.Header or (if a response was returned at +// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified +// to check whether the returned error was because +// http.StatusNotModified was returned. +func (c *BackendServicesSetSecurityPolicyCall) Do(opts ...googleapi.CallOption) (*Operation, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Operation{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Sets the security policy for the specified backend service.", + // "httpMethod": "POST", + // "id": "compute.backendServices.setSecurityPolicy", + // "parameterOrder": [ + // "project", + // "backendService" + // ], + // "parameters": { + // "backendService": { + // "description": "Name of the BackendService resource to which the security policy should be set. The name should conform to RFC1035.", + // "location": "path", + // "required": true, + // "type": "string" + // }, + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "requestId": { + // "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", + // "location": "query", + // "type": "string" + // } + // }, + // "path": "{project}/global/backendServices/{backendService}/setSecurityPolicy", + // "request": { + // "$ref": "SecurityPolicyReference" + // }, + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + // method id "compute.backendServices.update": type BackendServicesUpdateCall struct { @@ -31382,9 +36051,13 @@ func (c *BackendServicesUpdateCall) doRequest(alt string) (*http.Response, error } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/backendServices/{backendService}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PUT", urls, body) + req, err := http.NewRequest("PUT", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -31602,9 +36275,13 @@ func (c *DiskTypesAggregatedListCall) doRequest(alt string) (*http.Response, err } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/aggregated/diskTypes") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -31792,9 +36469,13 @@ func (c *DiskTypesGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/diskTypes/{diskType}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -32017,9 +36698,13 @@ func (c *DiskTypesListCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/diskTypes") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -32274,9 +36959,13 @@ func (c *DisksAggregatedListCall) doRequest(alt string) (*http.Response, error) } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/aggregated/disks") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -32481,9 +37170,13 @@ func (c *DisksCreateSnapshotCall) doRequest(alt string) (*http.Response, error) } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/disks/{disk}/createSnapshot") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -32543,7 +37236,7 @@ func (c *DisksCreateSnapshotCall) Do(opts ...googleapi.CallOption) (*Operation, // "disk": { // "description": "Name of the persistent disk to snapshot.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -32663,9 +37356,13 @@ func (c *DisksDeleteCall) doRequest(alt string) (*http.Response, error) { reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/disks/{disk}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -32830,9 +37527,13 @@ func (c *DisksGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/disks/{disk}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -32892,7 +37593,7 @@ func (c *DisksGetCall) Do(opts ...googleapi.CallOption) (*Disk, error) { // "disk": { // "description": "Name of the persistent disk to return.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -32924,6 +37625,173 @@ func (c *DisksGetCall) Do(opts ...googleapi.CallOption) (*Disk, error) { } +// method id "compute.disks.getIamPolicy": + +type DisksGetIamPolicyCall struct { + s *Service + project string + zone string + resource string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// GetIamPolicy: Gets the access control policy for a resource. May be +// empty if no such policy or resource exists. +func (r *DisksService) GetIamPolicy(project string, zone string, resource string) *DisksGetIamPolicyCall { + c := &DisksGetIamPolicyCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.zone = zone + c.resource = resource + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *DisksGetIamPolicyCall) Fields(s ...googleapi.Field) *DisksGetIamPolicyCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// IfNoneMatch sets the optional parameter which makes the operation +// fail if the object's ETag matches the given value. This is useful for +// getting updates only after the object has changed since the last +// request. Use googleapi.IsNotModified to check whether the response +// error from Do is the result of In-None-Match. +func (c *DisksGetIamPolicyCall) IfNoneMatch(entityTag string) *DisksGetIamPolicyCall { + c.ifNoneMatch_ = entityTag + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *DisksGetIamPolicyCall) Context(ctx context.Context) *DisksGetIamPolicyCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *DisksGetIamPolicyCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *DisksGetIamPolicyCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + if c.ifNoneMatch_ != "" { + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) + } + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/disks/{resource}/getIamPolicy") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "zone": c.zone, + "resource": c.resource, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.disks.getIamPolicy" call. +// Exactly one of *Policy or error will be non-nil. Any non-2xx status +// code is an error. Response headers are in either +// *Policy.ServerResponse.Header or (if a response was returned at all) +// in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to +// check whether the returned error was because http.StatusNotModified +// was returned. +func (c *DisksGetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Policy, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Policy{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Gets the access control policy for a resource. May be empty if no such policy or resource exists.", + // "httpMethod": "GET", + // "id": "compute.disks.getIamPolicy", + // "parameterOrder": [ + // "project", + // "zone", + // "resource" + // ], + // "parameters": { + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "resource": { + // "description": "Name or id of the resource for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + // "required": true, + // "type": "string" + // }, + // "zone": { + // "description": "The name of the zone for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/zones/{zone}/disks/{resource}/getIamPolicy", + // "response": { + // "$ref": "Policy" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute", + // "https://www.googleapis.com/auth/compute.readonly" + // ] + // } + +} + // method id "compute.disks.insert": type DisksInsertCall struct { @@ -33014,9 +37882,13 @@ func (c *DisksInsertCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/disks") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -33242,9 +38114,13 @@ func (c *DisksListCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/disks") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -33452,9 +38328,13 @@ func (c *DisksResizeCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/disks/{disk}/resize") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -33514,7 +38394,7 @@ func (c *DisksResizeCall) Do(opts ...googleapi.CallOption) (*Operation, error) { // "disk": { // "description": "The name of the persistent disk.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -33553,6 +38433,168 @@ func (c *DisksResizeCall) Do(opts ...googleapi.CallOption) (*Operation, error) { } +// method id "compute.disks.setIamPolicy": + +type DisksSetIamPolicyCall struct { + s *Service + project string + zone string + resource string + zonesetpolicyrequest *ZoneSetPolicyRequest + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// SetIamPolicy: Sets the access control policy on the specified +// resource. Replaces any existing policy. +func (r *DisksService) SetIamPolicy(project string, zone string, resource string, zonesetpolicyrequest *ZoneSetPolicyRequest) *DisksSetIamPolicyCall { + c := &DisksSetIamPolicyCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.zone = zone + c.resource = resource + c.zonesetpolicyrequest = zonesetpolicyrequest + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *DisksSetIamPolicyCall) Fields(s ...googleapi.Field) *DisksSetIamPolicyCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *DisksSetIamPolicyCall) Context(ctx context.Context) *DisksSetIamPolicyCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *DisksSetIamPolicyCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *DisksSetIamPolicyCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.zonesetpolicyrequest) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/disks/{resource}/setIamPolicy") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "zone": c.zone, + "resource": c.resource, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.disks.setIamPolicy" call. +// Exactly one of *Policy or error will be non-nil. Any non-2xx status +// code is an error. Response headers are in either +// *Policy.ServerResponse.Header or (if a response was returned at all) +// in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to +// check whether the returned error was because http.StatusNotModified +// was returned. +func (c *DisksSetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Policy, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Policy{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Sets the access control policy on the specified resource. Replaces any existing policy.", + // "httpMethod": "POST", + // "id": "compute.disks.setIamPolicy", + // "parameterOrder": [ + // "project", + // "zone", + // "resource" + // ], + // "parameters": { + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "resource": { + // "description": "Name or id of the resource for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + // "required": true, + // "type": "string" + // }, + // "zone": { + // "description": "The name of the zone for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/zones/{zone}/disks/{resource}/setIamPolicy", + // "request": { + // "$ref": "ZoneSetPolicyRequest" + // }, + // "response": { + // "$ref": "Policy" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + // method id "compute.disks.setLabels": type DisksSetLabelsCall struct { @@ -33634,9 +38676,13 @@ func (c *DisksSetLabelsCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/disks/{resource}/setLabels") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -33706,9 +38752,9 @@ func (c *DisksSetLabelsCall) Do(opts ...googleapi.CallOption) (*Operation, error // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -33735,6 +38781,169 @@ func (c *DisksSetLabelsCall) Do(opts ...googleapi.CallOption) (*Operation, error } +// method id "compute.disks.testIamPermissions": + +type DisksTestIamPermissionsCall struct { + s *Service + project string + zone string + resource string + testpermissionsrequest *TestPermissionsRequest + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// TestIamPermissions: Returns permissions that a caller has on the +// specified resource. +func (r *DisksService) TestIamPermissions(project string, zone string, resource string, testpermissionsrequest *TestPermissionsRequest) *DisksTestIamPermissionsCall { + c := &DisksTestIamPermissionsCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.zone = zone + c.resource = resource + c.testpermissionsrequest = testpermissionsrequest + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *DisksTestIamPermissionsCall) Fields(s ...googleapi.Field) *DisksTestIamPermissionsCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *DisksTestIamPermissionsCall) Context(ctx context.Context) *DisksTestIamPermissionsCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *DisksTestIamPermissionsCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *DisksTestIamPermissionsCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.testpermissionsrequest) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/disks/{resource}/testIamPermissions") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "zone": c.zone, + "resource": c.resource, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.disks.testIamPermissions" call. +// Exactly one of *TestPermissionsResponse or error will be non-nil. Any +// non-2xx status code is an error. Response headers are in either +// *TestPermissionsResponse.ServerResponse.Header or (if a response was +// returned at all) in error.(*googleapi.Error).Header. Use +// googleapi.IsNotModified to check whether the returned error was +// because http.StatusNotModified was returned. +func (c *DisksTestIamPermissionsCall) Do(opts ...googleapi.CallOption) (*TestPermissionsResponse, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &TestPermissionsResponse{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Returns permissions that a caller has on the specified resource.", + // "httpMethod": "POST", + // "id": "compute.disks.testIamPermissions", + // "parameterOrder": [ + // "project", + // "zone", + // "resource" + // ], + // "parameters": { + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "resource": { + // "description": "Name or id of the resource for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + // "required": true, + // "type": "string" + // }, + // "zone": { + // "description": "The name of the zone for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/zones/{zone}/disks/{resource}/testIamPermissions", + // "request": { + // "$ref": "TestPermissionsRequest" + // }, + // "response": { + // "$ref": "TestPermissionsResponse" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute", + // "https://www.googleapis.com/auth/compute.readonly" + // ] + // } + +} + // method id "compute.firewalls.delete": type FirewallsDeleteCall struct { @@ -33807,9 +39016,13 @@ func (c *FirewallsDeleteCall) doRequest(alt string) (*http.Response, error) { reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/firewalls/{firewall}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -33867,7 +39080,7 @@ func (c *FirewallsDeleteCall) Do(opts ...googleapi.CallOption) (*Operation, erro // "firewall": { // "description": "Name of the firewall rule to delete.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -33963,9 +39176,13 @@ func (c *FirewallsGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/firewalls/{firewall}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -34023,7 +39240,7 @@ func (c *FirewallsGetCall) Do(opts ...googleapi.CallOption) (*Firewall, error) { // "firewall": { // "description": "Name of the firewall rule to return.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -34126,9 +39343,13 @@ func (c *FirewallsInsertCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/firewalls") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -34338,9 +39559,13 @@ func (c *FirewallsListCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/firewalls") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -34539,9 +39764,13 @@ func (c *FirewallsPatchCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/firewalls/{firewall}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PATCH", urls, body) + req, err := http.NewRequest("PATCH", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -34599,7 +39828,7 @@ func (c *FirewallsPatchCall) Do(opts ...googleapi.CallOption) (*Operation, error // "firewall": { // "description": "Name of the firewall rule to patch.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -34713,9 +39942,13 @@ func (c *FirewallsUpdateCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/firewalls/{firewall}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PUT", urls, body) + req, err := http.NewRequest("PUT", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -34773,7 +40006,7 @@ func (c *FirewallsUpdateCall) Do(opts ...googleapi.CallOption) (*Operation, erro // "firewall": { // "description": "Name of the firewall rule to update.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -34933,9 +40166,13 @@ func (c *ForwardingRulesAggregatedListCall) doRequest(alt string) (*http.Respons } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/aggregated/forwardingRules") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -35127,9 +40364,13 @@ func (c *ForwardingRulesDeleteCall) doRequest(alt string) (*http.Response, error reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/forwardingRules/{forwardingRule}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -35294,9 +40535,13 @@ func (c *ForwardingRulesGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/forwardingRules/{forwardingRule}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -35468,9 +40713,13 @@ func (c *ForwardingRulesInsertCall) doRequest(alt string) (*http.Response, error } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/forwardingRules") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -35691,9 +40940,13 @@ func (c *ForwardingRulesListCall) doRequest(alt string) (*http.Response, error) } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/forwardingRules") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -35902,9 +41155,13 @@ func (c *ForwardingRulesSetTargetCall) doRequest(alt string) (*http.Response, er } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/forwardingRules/{forwardingRule}/setTarget") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -36075,9 +41332,13 @@ func (c *GlobalAddressesDeleteCall) doRequest(alt string) (*http.Response, error reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/addresses/{address}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -36232,9 +41493,13 @@ func (c *GlobalAddressesGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/addresses/{address}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -36395,9 +41660,13 @@ func (c *GlobalAddressesInsertCall) doRequest(alt string) (*http.Response, error } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/addresses") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -36606,9 +41875,13 @@ func (c *GlobalAddressesListCall) doRequest(alt string) (*http.Response, error) } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/addresses") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -36798,9 +42071,13 @@ func (c *GlobalForwardingRulesDeleteCall) doRequest(alt string) (*http.Response, reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/forwardingRules/{forwardingRule}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -36955,9 +42232,13 @@ func (c *GlobalForwardingRulesGetCall) doRequest(alt string) (*http.Response, er } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/forwardingRules/{forwardingRule}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -37118,9 +42399,13 @@ func (c *GlobalForwardingRulesInsertCall) doRequest(alt string) (*http.Response, } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/forwardingRules") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -37330,9 +42615,13 @@ func (c *GlobalForwardingRulesListCall) doRequest(alt string) (*http.Response, e } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/forwardingRules") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -37530,9 +42819,13 @@ func (c *GlobalForwardingRulesSetTargetCall) doRequest(alt string) (*http.Respon } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/forwardingRules/{forwardingRule}/setTarget") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -37750,9 +43043,13 @@ func (c *GlobalOperationsAggregatedListCall) doRequest(alt string) (*http.Respon } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/aggregated/operations") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -37923,9 +43220,13 @@ func (c *GlobalOperationsDeleteCall) doRequest(alt string) (*http.Response, erro reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/operations/{operation}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -38047,9 +43348,13 @@ func (c *GlobalOperationsGetCall) doRequest(alt string) (*http.Response, error) } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/operations/{operation}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -38261,9 +43566,13 @@ func (c *GlobalOperationsListCall) doRequest(alt string) (*http.Response, error) } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/operations") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -38452,9 +43761,13 @@ func (c *HealthChecksDeleteCall) doRequest(alt string) (*http.Response, error) { reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/healthChecks/{healthCheck}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -38608,9 +43921,13 @@ func (c *HealthChecksGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/healthChecks/{healthCheck}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -38770,9 +44087,13 @@ func (c *HealthChecksInsertCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/healthChecks") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -38981,9 +44302,13 @@ func (c *HealthChecksListCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/healthChecks") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -39181,9 +44506,13 @@ func (c *HealthChecksPatchCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/healthChecks/{healthCheck}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PATCH", urls, body) + req, err := http.NewRequest("PATCH", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -39352,9 +44681,13 @@ func (c *HealthChecksUpdateCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/healthChecks/{healthCheck}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PUT", urls, body) + req, err := http.NewRequest("PUT", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -39516,9 +44849,13 @@ func (c *HttpHealthChecksDeleteCall) doRequest(alt string) (*http.Response, erro reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/httpHealthChecks/{httpHealthCheck}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -39673,9 +45010,13 @@ func (c *HttpHealthChecksGetCall) doRequest(alt string) (*http.Response, error) } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/httpHealthChecks/{httpHealthCheck}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -39836,9 +45177,13 @@ func (c *HttpHealthChecksInsertCall) doRequest(alt string) (*http.Response, erro } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/httpHealthChecks") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -40048,9 +45393,13 @@ func (c *HttpHealthChecksListCall) doRequest(alt string) (*http.Response, error) } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/httpHealthChecks") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -40249,9 +45598,13 @@ func (c *HttpHealthChecksPatchCall) doRequest(alt string) (*http.Response, error } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/httpHealthChecks/{httpHealthCheck}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PATCH", urls, body) + req, err := http.NewRequest("PATCH", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -40421,9 +45774,13 @@ func (c *HttpHealthChecksUpdateCall) doRequest(alt string) (*http.Response, erro } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/httpHealthChecks/{httpHealthCheck}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PUT", urls, body) + req, err := http.NewRequest("PUT", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -40584,9 +45941,13 @@ func (c *HttpsHealthChecksDeleteCall) doRequest(alt string) (*http.Response, err reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/httpsHealthChecks/{httpsHealthCheck}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -40740,9 +46101,13 @@ func (c *HttpsHealthChecksGetCall) doRequest(alt string) (*http.Response, error) } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/httpsHealthChecks/{httpsHealthCheck}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -40902,9 +46267,13 @@ func (c *HttpsHealthChecksInsertCall) doRequest(alt string) (*http.Response, err } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/httpsHealthChecks") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -41113,9 +46482,13 @@ func (c *HttpsHealthChecksListCall) doRequest(alt string) (*http.Response, error } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/httpsHealthChecks") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -41313,9 +46686,13 @@ func (c *HttpsHealthChecksPatchCall) doRequest(alt string) (*http.Response, erro } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/httpsHealthChecks/{httpsHealthCheck}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PATCH", urls, body) + req, err := http.NewRequest("PATCH", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -41484,9 +46861,13 @@ func (c *HttpsHealthChecksUpdateCall) doRequest(alt string) (*http.Response, err } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/httpsHealthChecks/{httpsHealthCheck}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PUT", urls, body) + req, err := http.NewRequest("PUT", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -41648,9 +47029,13 @@ func (c *ImagesDeleteCall) doRequest(alt string) (*http.Response, error) { reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/images/{image}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -41708,7 +47093,7 @@ func (c *ImagesDeleteCall) Do(opts ...googleapi.CallOption) (*Operation, error) // "image": { // "description": "Name of the image resource to delete.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -41819,9 +47204,13 @@ func (c *ImagesDeprecateCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/images/{image}/deprecate") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -41879,7 +47268,7 @@ func (c *ImagesDeprecateCall) Do(opts ...googleapi.CallOption) (*Operation, erro // "image": { // "description": "Image name.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -41979,9 +47368,13 @@ func (c *ImagesGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/images/{image}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -42039,7 +47432,7 @@ func (c *ImagesGetCall) Do(opts ...googleapi.CallOption) (*Image, error) { // "image": { // "description": "Name of the image resource to return.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -42131,9 +47524,13 @@ func (c *ImagesGetFromFamilyCall) doRequest(alt string) (*http.Response, error) } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/images/family/{family}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -42191,7 +47588,7 @@ func (c *ImagesGetFromFamilyCall) Do(opts ...googleapi.CallOption) (*Image, erro // "family": { // "description": "Name of the image family to search for.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -42216,6 +47613,162 @@ func (c *ImagesGetFromFamilyCall) Do(opts ...googleapi.CallOption) (*Image, erro } +// method id "compute.images.getIamPolicy": + +type ImagesGetIamPolicyCall struct { + s *Service + project string + resource string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// GetIamPolicy: Gets the access control policy for a resource. May be +// empty if no such policy or resource exists. +func (r *ImagesService) GetIamPolicy(project string, resource string) *ImagesGetIamPolicyCall { + c := &ImagesGetIamPolicyCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.resource = resource + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *ImagesGetIamPolicyCall) Fields(s ...googleapi.Field) *ImagesGetIamPolicyCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// IfNoneMatch sets the optional parameter which makes the operation +// fail if the object's ETag matches the given value. This is useful for +// getting updates only after the object has changed since the last +// request. Use googleapi.IsNotModified to check whether the response +// error from Do is the result of In-None-Match. +func (c *ImagesGetIamPolicyCall) IfNoneMatch(entityTag string) *ImagesGetIamPolicyCall { + c.ifNoneMatch_ = entityTag + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *ImagesGetIamPolicyCall) Context(ctx context.Context) *ImagesGetIamPolicyCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *ImagesGetIamPolicyCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *ImagesGetIamPolicyCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + if c.ifNoneMatch_ != "" { + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) + } + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/images/{resource}/getIamPolicy") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "resource": c.resource, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.images.getIamPolicy" call. +// Exactly one of *Policy or error will be non-nil. Any non-2xx status +// code is an error. Response headers are in either +// *Policy.ServerResponse.Header or (if a response was returned at all) +// in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to +// check whether the returned error was because http.StatusNotModified +// was returned. +func (c *ImagesGetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Policy, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Policy{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Gets the access control policy for a resource. May be empty if no such policy or resource exists.", + // "httpMethod": "GET", + // "id": "compute.images.getIamPolicy", + // "parameterOrder": [ + // "project", + // "resource" + // ], + // "parameters": { + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "resource": { + // "description": "Name or id of the resource for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/global/images/{resource}/getIamPolicy", + // "response": { + // "$ref": "Policy" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute", + // "https://www.googleapis.com/auth/compute.readonly" + // ] + // } + +} + // method id "compute.images.insert": type ImagesInsertCall struct { @@ -42301,9 +47854,13 @@ func (c *ImagesInsertCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/images") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -42526,9 +48083,13 @@ func (c *ImagesListCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/images") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -42646,6 +48207,157 @@ func (c *ImagesListCall) Pages(ctx context.Context, f func(*ImageList) error) er } } +// method id "compute.images.setIamPolicy": + +type ImagesSetIamPolicyCall struct { + s *Service + project string + resource string + globalsetpolicyrequest *GlobalSetPolicyRequest + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// SetIamPolicy: Sets the access control policy on the specified +// resource. Replaces any existing policy. +func (r *ImagesService) SetIamPolicy(project string, resource string, globalsetpolicyrequest *GlobalSetPolicyRequest) *ImagesSetIamPolicyCall { + c := &ImagesSetIamPolicyCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.resource = resource + c.globalsetpolicyrequest = globalsetpolicyrequest + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *ImagesSetIamPolicyCall) Fields(s ...googleapi.Field) *ImagesSetIamPolicyCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *ImagesSetIamPolicyCall) Context(ctx context.Context) *ImagesSetIamPolicyCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *ImagesSetIamPolicyCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *ImagesSetIamPolicyCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.globalsetpolicyrequest) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/images/{resource}/setIamPolicy") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "resource": c.resource, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.images.setIamPolicy" call. +// Exactly one of *Policy or error will be non-nil. Any non-2xx status +// code is an error. Response headers are in either +// *Policy.ServerResponse.Header or (if a response was returned at all) +// in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to +// check whether the returned error was because http.StatusNotModified +// was returned. +func (c *ImagesSetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Policy, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Policy{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Sets the access control policy on the specified resource. Replaces any existing policy.", + // "httpMethod": "POST", + // "id": "compute.images.setIamPolicy", + // "parameterOrder": [ + // "project", + // "resource" + // ], + // "parameters": { + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "resource": { + // "description": "Name or id of the resource for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/global/images/{resource}/setIamPolicy", + // "request": { + // "$ref": "GlobalSetPolicyRequest" + // }, + // "response": { + // "$ref": "Policy" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + // method id "compute.images.setLabels": type ImagesSetLabelsCall struct { @@ -42706,9 +48418,13 @@ func (c *ImagesSetLabelsCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/images/{resource}/setLabels") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -42771,9 +48487,9 @@ func (c *ImagesSetLabelsCall) Do(opts ...googleapi.CallOption) (*Operation, erro // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -42793,6 +48509,158 @@ func (c *ImagesSetLabelsCall) Do(opts ...googleapi.CallOption) (*Operation, erro } +// method id "compute.images.testIamPermissions": + +type ImagesTestIamPermissionsCall struct { + s *Service + project string + resource string + testpermissionsrequest *TestPermissionsRequest + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// TestIamPermissions: Returns permissions that a caller has on the +// specified resource. +func (r *ImagesService) TestIamPermissions(project string, resource string, testpermissionsrequest *TestPermissionsRequest) *ImagesTestIamPermissionsCall { + c := &ImagesTestIamPermissionsCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.resource = resource + c.testpermissionsrequest = testpermissionsrequest + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *ImagesTestIamPermissionsCall) Fields(s ...googleapi.Field) *ImagesTestIamPermissionsCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *ImagesTestIamPermissionsCall) Context(ctx context.Context) *ImagesTestIamPermissionsCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *ImagesTestIamPermissionsCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *ImagesTestIamPermissionsCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.testpermissionsrequest) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/images/{resource}/testIamPermissions") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "resource": c.resource, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.images.testIamPermissions" call. +// Exactly one of *TestPermissionsResponse or error will be non-nil. Any +// non-2xx status code is an error. Response headers are in either +// *TestPermissionsResponse.ServerResponse.Header or (if a response was +// returned at all) in error.(*googleapi.Error).Header. Use +// googleapi.IsNotModified to check whether the returned error was +// because http.StatusNotModified was returned. +func (c *ImagesTestIamPermissionsCall) Do(opts ...googleapi.CallOption) (*TestPermissionsResponse, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &TestPermissionsResponse{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Returns permissions that a caller has on the specified resource.", + // "httpMethod": "POST", + // "id": "compute.images.testIamPermissions", + // "parameterOrder": [ + // "project", + // "resource" + // ], + // "parameters": { + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "resource": { + // "description": "Name or id of the resource for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/global/images/{resource}/testIamPermissions", + // "request": { + // "$ref": "TestPermissionsRequest" + // }, + // "response": { + // "$ref": "TestPermissionsResponse" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute", + // "https://www.googleapis.com/auth/compute.readonly" + // ] + // } + +} + // method id "compute.instanceGroupManagers.abandonInstances": type InstanceGroupManagersAbandonInstancesCall struct { @@ -42806,15 +48674,15 @@ type InstanceGroupManagersAbandonInstancesCall struct { header_ http.Header } -// AbandonInstances: Schedules a group action to remove the specified -// instances from the managed instance group. Abandoning an instance -// does not delete the instance, but it does remove the instance from -// any target pools that are applied by the managed instance group. This -// method reduces the targetSize of the managed instance group by the -// number of instances that you abandon. This operation is marked as -// DONE when the action is scheduled even if the instances have not yet -// been removed from the group. You must separately verify the status of -// the abandoning action with the listmanagedinstances method. +// AbandonInstances: Flags the specified instances to be removed from +// the managed instance group. Abandoning an instance does not delete +// the instance, but it does remove the instance from any target pools +// that are applied by the managed instance group. This method reduces +// the targetSize of the managed instance group by the number of +// instances that you abandon. This operation is marked as DONE when the +// action is scheduled even if the instances have not yet been removed +// from the group. You must separately verify the status of the +// abandoning action with the listmanagedinstances method. // // If the group is part of a backend service that has enabled connection // draining, it can take up to 60 seconds after the connection draining @@ -42889,9 +48757,13 @@ func (c *InstanceGroupManagersAbandonInstancesCall) doRequest(alt string) (*http } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instanceGroupManagers/{instanceGroupManager}/abandonInstances") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -42939,7 +48811,7 @@ func (c *InstanceGroupManagersAbandonInstancesCall) Do(opts ...googleapi.CallOpt } return ret, nil // { - // "description": "Schedules a group action to remove the specified instances from the managed instance group. Abandoning an instance does not delete the instance, but it does remove the instance from any target pools that are applied by the managed instance group. This method reduces the targetSize of the managed instance group by the number of instances that you abandon. This operation is marked as DONE when the action is scheduled even if the instances have not yet been removed from the group. You must separately verify the status of the abandoning action with the listmanagedinstances method.\n\nIf the group is part of a backend service that has enabled connection draining, it can take up to 60 seconds after the connection draining duration has elapsed before the VM instance is removed or deleted.\n\nYou can specify a maximum of 1000 instances with this method per request.", + // "description": "Flags the specified instances to be removed from the managed instance group. Abandoning an instance does not delete the instance, but it does remove the instance from any target pools that are applied by the managed instance group. This method reduces the targetSize of the managed instance group by the number of instances that you abandon. This operation is marked as DONE when the action is scheduled even if the instances have not yet been removed from the group. You must separately verify the status of the abandoning action with the listmanagedinstances method.\n\nIf the group is part of a backend service that has enabled connection draining, it can take up to 60 seconds after the connection draining duration has elapsed before the VM instance is removed or deleted.\n\nYou can specify a maximum of 1000 instances with this method per request.", // "httpMethod": "POST", // "id": "compute.instanceGroupManagers.abandonInstances", // "parameterOrder": [ @@ -43116,9 +48988,13 @@ func (c *InstanceGroupManagersAggregatedListCall) doRequest(alt string) (*http.R } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/aggregated/instanceGroupManagers") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -43313,9 +49189,13 @@ func (c *InstanceGroupManagersDeleteCall) doRequest(alt string) (*http.Response, reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instanceGroupManagers/{instanceGroupManager}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -43422,14 +49302,14 @@ type InstanceGroupManagersDeleteInstancesCall struct { header_ http.Header } -// DeleteInstances: Schedules a group action to delete the specified -// instances in the managed instance group. The instances are also -// removed from any target pools of which they were a member. This -// method reduces the targetSize of the managed instance group by the -// number of instances that you delete. This operation is marked as DONE -// when the action is scheduled even if the instances are still being -// deleted. You must separately verify the status of the deleting action -// with the listmanagedinstances method. +// DeleteInstances: Flags the specified instances in the managed +// instance group for immediate deletion. The instances are also removed +// from any target pools of which they were a member. This method +// reduces the targetSize of the managed instance group by the number of +// instances that you delete. This operation is marked as DONE when the +// action is scheduled even if the instances are still being deleted. +// You must separately verify the status of the deleting action with the +// listmanagedinstances method. // // If the group is part of a backend service that has enabled connection // draining, it can take up to 60 seconds after the connection draining @@ -43504,9 +49384,13 @@ func (c *InstanceGroupManagersDeleteInstancesCall) doRequest(alt string) (*http. } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instanceGroupManagers/{instanceGroupManager}/deleteInstances") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -43554,7 +49438,7 @@ func (c *InstanceGroupManagersDeleteInstancesCall) Do(opts ...googleapi.CallOpti } return ret, nil // { - // "description": "Schedules a group action to delete the specified instances in the managed instance group. The instances are also removed from any target pools of which they were a member. This method reduces the targetSize of the managed instance group by the number of instances that you delete. This operation is marked as DONE when the action is scheduled even if the instances are still being deleted. You must separately verify the status of the deleting action with the listmanagedinstances method.\n\nIf the group is part of a backend service that has enabled connection draining, it can take up to 60 seconds after the connection draining duration has elapsed before the VM instance is removed or deleted.\n\nYou can specify a maximum of 1000 instances with this method per request.", + // "description": "Flags the specified instances in the managed instance group for immediate deletion. The instances are also removed from any target pools of which they were a member. This method reduces the targetSize of the managed instance group by the number of instances that you delete. This operation is marked as DONE when the action is scheduled even if the instances are still being deleted. You must separately verify the status of the deleting action with the listmanagedinstances method.\n\nIf the group is part of a backend service that has enabled connection draining, it can take up to 60 seconds after the connection draining duration has elapsed before the VM instance is removed or deleted.\n\nYou can specify a maximum of 1000 instances with this method per request.", // "httpMethod": "POST", // "id": "compute.instanceGroupManagers.deleteInstances", // "parameterOrder": [ @@ -43673,9 +49557,13 @@ func (c *InstanceGroupManagersGetCall) doRequest(alt string) (*http.Response, er } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instanceGroupManagers/{instanceGroupManager}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -43778,12 +49666,12 @@ type InstanceGroupManagersInsertCall struct { } // Insert: Creates a managed instance group using the information that -// you specify in the request. After the group is created, it schedules -// an action to create instances in the group using the specified -// instance template. This operation is marked as DONE when the group is -// created even if the instances in the group have not yet been created. -// You must separately verify the status of the individual instances -// with the listmanagedinstances method. +// you specify in the request. After the group is created, instances in +// the group are created using the specified instance template. This +// operation is marked as DONE when the group is created even if the +// instances in the group have not yet been created. You must separately +// verify the status of the individual instances with the +// listmanagedinstances method. // // A managed instance group can have up to 1000 VM instances per group. // Please contact Cloud Support if you need an increase in this limit. @@ -43852,9 +49740,13 @@ func (c *InstanceGroupManagersInsertCall) doRequest(alt string) (*http.Response, } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instanceGroupManagers") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -43901,7 +49793,7 @@ func (c *InstanceGroupManagersInsertCall) Do(opts ...googleapi.CallOption) (*Ope } return ret, nil // { - // "description": "Creates a managed instance group using the information that you specify in the request. After the group is created, it schedules an action to create instances in the group using the specified instance template. This operation is marked as DONE when the group is created even if the instances in the group have not yet been created. You must separately verify the status of the individual instances with the listmanagedinstances method.\n\nA managed instance group can have up to 1000 VM instances per group. Please contact Cloud Support if you need an increase in this limit.", + // "description": "Creates a managed instance group using the information that you specify in the request. After the group is created, instances in the group are created using the specified instance template. This operation is marked as DONE when the group is created even if the instances in the group have not yet been created. You must separately verify the status of the individual instances with the listmanagedinstances method.\n\nA managed instance group can have up to 1000 VM instances per group. Please contact Cloud Support if you need an increase in this limit.", // "httpMethod": "POST", // "id": "compute.instanceGroupManagers.insert", // "parameterOrder": [ @@ -44073,9 +49965,13 @@ func (c *InstanceGroupManagersListCall) doRequest(alt string) (*http.Response, e } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instanceGroupManagers") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -44227,25 +50123,64 @@ func (r *InstanceGroupManagersService) ListManagedInstances(project string, zone return c } -// Filter sets the optional parameter "filter": +// Filter sets the optional parameter "filter": A filter expression that +// filters resources listed in the response. The expression must specify +// the field name, a comparison operator, and the value that you want to +// use for filtering. The value must be a string, a number, or a +// boolean. The comparison operator must be either =, !=, >, or <. +// +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. +// +// You can also filter nested fields. For example, you could specify +// scheduling.automaticRestart = false to include instances only if they +// are not scheduled for automatic restarts. You can use filtering on +// nested fields to filter based on resource labels. +// +// To filter on multiple expressions, provide each separate expression +// within parentheses. For example, (scheduling.automaticRestart = true) +// (cpuPlatform = "Intel Skylake"). By default, each expression is an +// AND expression. However, you can include AND and OR expressions +// explicitly. For example, (cpuPlatform = "Intel Skylake") OR +// (cpuPlatform = "Intel Broadwell") AND (scheduling.automaticRestart = +// true). func (c *InstanceGroupManagersListManagedInstancesCall) Filter(filter string) *InstanceGroupManagersListManagedInstancesCall { c.urlParams_.Set("filter", filter) return c } -// MaxResults sets the optional parameter "maxResults": +// MaxResults sets the optional parameter "maxResults": The maximum +// number of results per page that should be returned. If the number of +// available results is larger than maxResults, Compute Engine returns a +// nextPageToken that can be used to get the next page of results in +// subsequent list requests. Acceptable values are 0 to 500, inclusive. +// (Default: 500) func (c *InstanceGroupManagersListManagedInstancesCall) MaxResults(maxResults int64) *InstanceGroupManagersListManagedInstancesCall { c.urlParams_.Set("maxResults", fmt.Sprint(maxResults)) return c } -// OrderBy sets the optional parameter "order_by": +// OrderBy sets the optional parameter "order_by": Sorts list results by +// a certain order. By default, results are returned in alphanumerical +// order based on the resource name. +// +// You can also sort results in descending order based on the creation +// timestamp using orderBy="creationTimestamp desc". This sorts results +// based on the creationTimestamp field in reverse chronological order +// (newest result first). Use this to sort resources like operations so +// that the newest operation is returned first. +// +// Currently, only sorting by name or creationTimestamp desc is +// supported. func (c *InstanceGroupManagersListManagedInstancesCall) OrderBy(orderBy string) *InstanceGroupManagersListManagedInstancesCall { c.urlParams_.Set("order_by", orderBy) return c } -// PageToken sets the optional parameter "pageToken": +// PageToken sets the optional parameter "pageToken": Specifies a page +// token to use. Set pageToken to the nextPageToken returned by a +// previous list request to get the next page of results. func (c *InstanceGroupManagersListManagedInstancesCall) PageToken(pageToken string) *InstanceGroupManagersListManagedInstancesCall { c.urlParams_.Set("pageToken", pageToken) return c @@ -44284,9 +50219,13 @@ func (c *InstanceGroupManagersListManagedInstancesCall) doRequest(alt string) (* reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instanceGroupManagers/{instanceGroupManager}/listManagedInstances") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -44346,6 +50285,7 @@ func (c *InstanceGroupManagersListManagedInstancesCall) Do(opts ...googleapi.Cal // ], // "parameters": { // "filter": { + // "description": "A filter expression that filters resources listed in the response. The expression must specify the field name, a comparison operator, and the value that you want to use for filtering. The value must be a string, a number, or a boolean. The comparison operator must be either =, !=, \u003e, or \u003c.\n\nFor example, if you are filtering Compute Engine instances, you can exclude instances named example-instance by specifying name != example-instance.\n\nYou can also filter nested fields. For example, you could specify scheduling.automaticRestart = false to include instances only if they are not scheduled for automatic restarts. You can use filtering on nested fields to filter based on resource labels.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart = true) (cpuPlatform = \"Intel Skylake\"). By default, each expression is an AND expression. However, you can include AND and OR expressions explicitly. For example, (cpuPlatform = \"Intel Skylake\") OR (cpuPlatform = \"Intel Broadwell\") AND (scheduling.automaticRestart = true).", // "location": "query", // "type": "string" // }, @@ -44357,16 +50297,19 @@ func (c *InstanceGroupManagersListManagedInstancesCall) Do(opts ...googleapi.Cal // }, // "maxResults": { // "default": "500", + // "description": "The maximum number of results per page that should be returned. If the number of available results is larger than maxResults, Compute Engine returns a nextPageToken that can be used to get the next page of results in subsequent list requests. Acceptable values are 0 to 500, inclusive. (Default: 500)", // "format": "uint32", // "location": "query", // "minimum": "0", // "type": "integer" // }, // "order_by": { + // "description": "Sorts list results by a certain order. By default, results are returned in alphanumerical order based on the resource name.\n\nYou can also sort results in descending order based on the creation timestamp using orderBy=\"creationTimestamp desc\". This sorts results based on the creationTimestamp field in reverse chronological order (newest result first). Use this to sort resources like operations so that the newest operation is returned first.\n\nCurrently, only sorting by name or creationTimestamp desc is supported.", // "location": "query", // "type": "string" // }, // "pageToken": { + // "description": "Specifies a page token to use. Set pageToken to the nextPageToken returned by a previous list request to get the next page of results.", // "location": "query", // "type": "string" // }, @@ -44397,6 +50340,195 @@ func (c *InstanceGroupManagersListManagedInstancesCall) Do(opts ...googleapi.Cal } +// method id "compute.instanceGroupManagers.patch": + +type InstanceGroupManagersPatchCall struct { + s *Service + project string + zone string + instanceGroupManager string + instancegroupmanager *InstanceGroupManager + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// Patch: Updates a managed instance group using the information that +// you specify in the request. This operation is marked as DONE when the +// group is patched even if the instances in the group are still in the +// process of being patched. You must separately verify the status of +// the individual instances with the listManagedInstances method. This +// method supports PATCH semantics and uses the JSON merge patch format +// and processing rules. +func (r *InstanceGroupManagersService) Patch(project string, zone string, instanceGroupManager string, instancegroupmanager *InstanceGroupManager) *InstanceGroupManagersPatchCall { + c := &InstanceGroupManagersPatchCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.zone = zone + c.instanceGroupManager = instanceGroupManager + c.instancegroupmanager = instancegroupmanager + return c +} + +// RequestId sets the optional parameter "requestId": An optional +// request ID to identify requests. Specify a unique request ID so that +// if you must retry your request, the server will know to ignore the +// request if it has already been completed. +// +// For example, consider a situation where you make an initial request +// and the request times out. If you make the request again with the +// same request ID, the server can check if original operation with the +// same request ID was received, and if so, will ignore the second +// request. This prevents clients from accidentally creating duplicate +// commitments. +// +// The request ID must be a valid UUID with the exception that zero UUID +// is not supported (00000000-0000-0000-0000-000000000000). +func (c *InstanceGroupManagersPatchCall) RequestId(requestId string) *InstanceGroupManagersPatchCall { + c.urlParams_.Set("requestId", requestId) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *InstanceGroupManagersPatchCall) Fields(s ...googleapi.Field) *InstanceGroupManagersPatchCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *InstanceGroupManagersPatchCall) Context(ctx context.Context) *InstanceGroupManagersPatchCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *InstanceGroupManagersPatchCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *InstanceGroupManagersPatchCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.instancegroupmanager) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instanceGroupManagers/{instanceGroupManager}") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("PATCH", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "zone": c.zone, + "instanceGroupManager": c.instanceGroupManager, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.instanceGroupManagers.patch" call. +// Exactly one of *Operation or error will be non-nil. Any non-2xx +// status code is an error. Response headers are in either +// *Operation.ServerResponse.Header or (if a response was returned at +// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified +// to check whether the returned error was because +// http.StatusNotModified was returned. +func (c *InstanceGroupManagersPatchCall) Do(opts ...googleapi.CallOption) (*Operation, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Operation{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Updates a managed instance group using the information that you specify in the request. This operation is marked as DONE when the group is patched even if the instances in the group are still in the process of being patched. You must separately verify the status of the individual instances with the listManagedInstances method. This method supports PATCH semantics and uses the JSON merge patch format and processing rules.", + // "httpMethod": "PATCH", + // "id": "compute.instanceGroupManagers.patch", + // "parameterOrder": [ + // "project", + // "zone", + // "instanceGroupManager" + // ], + // "parameters": { + // "instanceGroupManager": { + // "description": "The name of the instance group manager.", + // "location": "path", + // "required": true, + // "type": "string" + // }, + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "requestId": { + // "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", + // "location": "query", + // "type": "string" + // }, + // "zone": { + // "description": "The name of the zone where you want to create the managed instance group.", + // "location": "path", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/zones/{zone}/instanceGroupManagers/{instanceGroupManager}", + // "request": { + // "$ref": "InstanceGroupManager" + // }, + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + // method id "compute.instanceGroupManagers.recreateInstances": type InstanceGroupManagersRecreateInstancesCall struct { @@ -44410,11 +50542,11 @@ type InstanceGroupManagersRecreateInstancesCall struct { header_ http.Header } -// RecreateInstances: Schedules a group action to recreate the specified -// instances in the managed instance group. The instances are deleted +// RecreateInstances: Flags the specified instances in the managed +// instance group to be immediately recreated. The instances are deleted // and recreated using the current instance template for the managed -// instance group. This operation is marked as DONE when the action is -// scheduled even if the instances have not yet been recreated. You must +// instance group. This operation is marked as DONE when the flag is set +// even if the instances have not yet been recreated. You must // separately verify the status of the recreating action with the // listmanagedinstances method. // @@ -44491,9 +50623,13 @@ func (c *InstanceGroupManagersRecreateInstancesCall) doRequest(alt string) (*htt } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instanceGroupManagers/{instanceGroupManager}/recreateInstances") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -44541,7 +50677,7 @@ func (c *InstanceGroupManagersRecreateInstancesCall) Do(opts ...googleapi.CallOp } return ret, nil // { - // "description": "Schedules a group action to recreate the specified instances in the managed instance group. The instances are deleted and recreated using the current instance template for the managed instance group. This operation is marked as DONE when the action is scheduled even if the instances have not yet been recreated. You must separately verify the status of the recreating action with the listmanagedinstances method.\n\nIf the group is part of a backend service that has enabled connection draining, it can take up to 60 seconds after the connection draining duration has elapsed before the VM instance is removed or deleted.\n\nYou can specify a maximum of 1000 instances with this method per request.", + // "description": "Flags the specified instances in the managed instance group to be immediately recreated. The instances are deleted and recreated using the current instance template for the managed instance group. This operation is marked as DONE when the flag is set even if the instances have not yet been recreated. You must separately verify the status of the recreating action with the listmanagedinstances method.\n\nIf the group is part of a backend service that has enabled connection draining, it can take up to 60 seconds after the connection draining duration has elapsed before the VM instance is removed or deleted.\n\nYou can specify a maximum of 1000 instances with this method per request.", // "httpMethod": "POST", // "id": "compute.instanceGroupManagers.recreateInstances", // "parameterOrder": [ @@ -44610,6 +50746,16 @@ type InstanceGroupManagersResizeCall struct { // separately verify the status of the creating or deleting actions with // the listmanagedinstances method. // +// When resizing down, the instance group arbitrarily chooses the order +// in which VMs are deleted. The group takes into account some VM +// attributes when making the selection including: +// +// + The status of the VM instance. + The health of the VM instance. + +// The instance template version the VM is based on. + For regional +// managed instance groups, the location of the VM instance. +// +// This list is subject to change. +// // If the group is part of a backend service that has enabled connection // draining, it can take up to 60 seconds after the connection draining // duration has elapsed before the VM instance is removed or deleted. @@ -44674,9 +50820,13 @@ func (c *InstanceGroupManagersResizeCall) doRequest(alt string) (*http.Response, reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instanceGroupManagers/{instanceGroupManager}/resize") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -44724,7 +50874,7 @@ func (c *InstanceGroupManagersResizeCall) Do(opts ...googleapi.CallOption) (*Ope } return ret, nil // { - // "description": "Resizes the managed instance group. If you increase the size, the group creates new instances using the current instance template. If you decrease the size, the group deletes instances. The resize operation is marked DONE when the resize actions are scheduled even if the group has not yet added or deleted any instances. You must separately verify the status of the creating or deleting actions with the listmanagedinstances method.\n\nIf the group is part of a backend service that has enabled connection draining, it can take up to 60 seconds after the connection draining duration has elapsed before the VM instance is removed or deleted.", + // "description": "Resizes the managed instance group. If you increase the size, the group creates new instances using the current instance template. If you decrease the size, the group deletes instances. The resize operation is marked DONE when the resize actions are scheduled even if the group has not yet added or deleted any instances. You must separately verify the status of the creating or deleting actions with the listmanagedinstances method.\n\nWhen resizing down, the instance group arbitrarily chooses the order in which VMs are deleted. The group takes into account some VM attributes when making the selection including:\n\n+ The status of the VM instance. + The health of the VM instance. + The instance template version the VM is based on. + For regional managed instance groups, the location of the VM instance.\n\nThis list is subject to change.\n\nIf the group is part of a backend service that has enabled connection draining, it can take up to 60 seconds after the connection draining duration has elapsed before the VM instance is removed or deleted.", // "httpMethod": "POST", // "id": "compute.instanceGroupManagers.resize", // "parameterOrder": [ @@ -44860,9 +51010,13 @@ func (c *InstanceGroupManagersSetInstanceTemplateCall) doRequest(alt string) (*h } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instanceGroupManagers/{instanceGroupManager}/setInstanceTemplate") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -45045,9 +51199,13 @@ func (c *InstanceGroupManagersSetTargetPoolsCall) doRequest(alt string) (*http.R } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instanceGroupManagers/{instanceGroupManager}/setTargetPools") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -45226,9 +51384,13 @@ func (c *InstanceGroupsAddInstancesCall) doRequest(alt string) (*http.Response, } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instanceGroups/{instanceGroup}/addInstances") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -45453,9 +51615,13 @@ func (c *InstanceGroupsAggregatedListCall) doRequest(alt string) (*http.Response } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/aggregated/instanceGroups") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -45649,9 +51815,13 @@ func (c *InstanceGroupsDeleteCall) doRequest(alt string) (*http.Response, error) reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instanceGroups/{instanceGroup}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -45814,9 +51984,13 @@ func (c *InstanceGroupsGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instanceGroups/{instanceGroup}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -45985,9 +52159,13 @@ func (c *InstanceGroupsInsertCall) doRequest(alt string) (*http.Response, error) } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instanceGroups") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -46206,9 +52384,13 @@ func (c *InstanceGroupsListCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instanceGroups") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -46458,9 +52640,13 @@ func (c *InstanceGroupsListInstancesCall) doRequest(alt string) (*http.Response, } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instanceGroups/{instanceGroup}/listInstances") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -46682,9 +52868,13 @@ func (c *InstanceGroupsRemoveInstancesCall) doRequest(alt string) (*http.Respons } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instanceGroups/{instanceGroup}/removeInstances") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -46861,9 +53051,13 @@ func (c *InstanceGroupsSetNamedPortsCall) doRequest(alt string) (*http.Response, } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instanceGroups/{instanceGroup}/setNamedPorts") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -47034,9 +53228,13 @@ func (c *InstanceTemplatesDeleteCall) doRequest(alt string) (*http.Response, err reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/instanceTemplates/{instanceTemplate}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -47191,9 +53389,13 @@ func (c *InstanceTemplatesGetCall) doRequest(alt string) (*http.Response, error) } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/instanceTemplates/{instanceTemplate}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -47276,6 +53478,162 @@ func (c *InstanceTemplatesGetCall) Do(opts ...googleapi.CallOption) (*InstanceTe } +// method id "compute.instanceTemplates.getIamPolicy": + +type InstanceTemplatesGetIamPolicyCall struct { + s *Service + project string + resource string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// GetIamPolicy: Gets the access control policy for a resource. May be +// empty if no such policy or resource exists. +func (r *InstanceTemplatesService) GetIamPolicy(project string, resource string) *InstanceTemplatesGetIamPolicyCall { + c := &InstanceTemplatesGetIamPolicyCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.resource = resource + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *InstanceTemplatesGetIamPolicyCall) Fields(s ...googleapi.Field) *InstanceTemplatesGetIamPolicyCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// IfNoneMatch sets the optional parameter which makes the operation +// fail if the object's ETag matches the given value. This is useful for +// getting updates only after the object has changed since the last +// request. Use googleapi.IsNotModified to check whether the response +// error from Do is the result of In-None-Match. +func (c *InstanceTemplatesGetIamPolicyCall) IfNoneMatch(entityTag string) *InstanceTemplatesGetIamPolicyCall { + c.ifNoneMatch_ = entityTag + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *InstanceTemplatesGetIamPolicyCall) Context(ctx context.Context) *InstanceTemplatesGetIamPolicyCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *InstanceTemplatesGetIamPolicyCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *InstanceTemplatesGetIamPolicyCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + if c.ifNoneMatch_ != "" { + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) + } + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/instanceTemplates/{resource}/getIamPolicy") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "resource": c.resource, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.instanceTemplates.getIamPolicy" call. +// Exactly one of *Policy or error will be non-nil. Any non-2xx status +// code is an error. Response headers are in either +// *Policy.ServerResponse.Header or (if a response was returned at all) +// in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to +// check whether the returned error was because http.StatusNotModified +// was returned. +func (c *InstanceTemplatesGetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Policy, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Policy{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Gets the access control policy for a resource. May be empty if no such policy or resource exists.", + // "httpMethod": "GET", + // "id": "compute.instanceTemplates.getIamPolicy", + // "parameterOrder": [ + // "project", + // "resource" + // ], + // "parameters": { + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "resource": { + // "description": "Name or id of the resource for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/global/instanceTemplates/{resource}/getIamPolicy", + // "response": { + // "$ref": "Policy" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute", + // "https://www.googleapis.com/auth/compute.readonly" + // ] + // } + +} + // method id "compute.instanceTemplates.insert": type InstanceTemplatesInsertCall struct { @@ -47357,9 +53715,13 @@ func (c *InstanceTemplatesInsertCall) doRequest(alt string) (*http.Response, err } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/instanceTemplates") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -47569,9 +53931,13 @@ func (c *InstanceTemplatesListCall) doRequest(alt string) (*http.Response, error } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/instanceTemplates") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -47689,6 +54055,309 @@ func (c *InstanceTemplatesListCall) Pages(ctx context.Context, f func(*InstanceT } } +// method id "compute.instanceTemplates.setIamPolicy": + +type InstanceTemplatesSetIamPolicyCall struct { + s *Service + project string + resource string + globalsetpolicyrequest *GlobalSetPolicyRequest + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// SetIamPolicy: Sets the access control policy on the specified +// resource. Replaces any existing policy. +func (r *InstanceTemplatesService) SetIamPolicy(project string, resource string, globalsetpolicyrequest *GlobalSetPolicyRequest) *InstanceTemplatesSetIamPolicyCall { + c := &InstanceTemplatesSetIamPolicyCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.resource = resource + c.globalsetpolicyrequest = globalsetpolicyrequest + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *InstanceTemplatesSetIamPolicyCall) Fields(s ...googleapi.Field) *InstanceTemplatesSetIamPolicyCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *InstanceTemplatesSetIamPolicyCall) Context(ctx context.Context) *InstanceTemplatesSetIamPolicyCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *InstanceTemplatesSetIamPolicyCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *InstanceTemplatesSetIamPolicyCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.globalsetpolicyrequest) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/instanceTemplates/{resource}/setIamPolicy") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "resource": c.resource, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.instanceTemplates.setIamPolicy" call. +// Exactly one of *Policy or error will be non-nil. Any non-2xx status +// code is an error. Response headers are in either +// *Policy.ServerResponse.Header or (if a response was returned at all) +// in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to +// check whether the returned error was because http.StatusNotModified +// was returned. +func (c *InstanceTemplatesSetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Policy, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Policy{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Sets the access control policy on the specified resource. Replaces any existing policy.", + // "httpMethod": "POST", + // "id": "compute.instanceTemplates.setIamPolicy", + // "parameterOrder": [ + // "project", + // "resource" + // ], + // "parameters": { + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "resource": { + // "description": "Name or id of the resource for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/global/instanceTemplates/{resource}/setIamPolicy", + // "request": { + // "$ref": "GlobalSetPolicyRequest" + // }, + // "response": { + // "$ref": "Policy" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + +// method id "compute.instanceTemplates.testIamPermissions": + +type InstanceTemplatesTestIamPermissionsCall struct { + s *Service + project string + resource string + testpermissionsrequest *TestPermissionsRequest + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// TestIamPermissions: Returns permissions that a caller has on the +// specified resource. +func (r *InstanceTemplatesService) TestIamPermissions(project string, resource string, testpermissionsrequest *TestPermissionsRequest) *InstanceTemplatesTestIamPermissionsCall { + c := &InstanceTemplatesTestIamPermissionsCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.resource = resource + c.testpermissionsrequest = testpermissionsrequest + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *InstanceTemplatesTestIamPermissionsCall) Fields(s ...googleapi.Field) *InstanceTemplatesTestIamPermissionsCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *InstanceTemplatesTestIamPermissionsCall) Context(ctx context.Context) *InstanceTemplatesTestIamPermissionsCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *InstanceTemplatesTestIamPermissionsCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *InstanceTemplatesTestIamPermissionsCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.testpermissionsrequest) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/instanceTemplates/{resource}/testIamPermissions") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "resource": c.resource, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.instanceTemplates.testIamPermissions" call. +// Exactly one of *TestPermissionsResponse or error will be non-nil. Any +// non-2xx status code is an error. Response headers are in either +// *TestPermissionsResponse.ServerResponse.Header or (if a response was +// returned at all) in error.(*googleapi.Error).Header. Use +// googleapi.IsNotModified to check whether the returned error was +// because http.StatusNotModified was returned. +func (c *InstanceTemplatesTestIamPermissionsCall) Do(opts ...googleapi.CallOption) (*TestPermissionsResponse, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &TestPermissionsResponse{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Returns permissions that a caller has on the specified resource.", + // "httpMethod": "POST", + // "id": "compute.instanceTemplates.testIamPermissions", + // "parameterOrder": [ + // "project", + // "resource" + // ], + // "parameters": { + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "resource": { + // "description": "Name or id of the resource for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/global/instanceTemplates/{resource}/testIamPermissions", + // "request": { + // "$ref": "TestPermissionsRequest" + // }, + // "response": { + // "$ref": "TestPermissionsResponse" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute", + // "https://www.googleapis.com/auth/compute.readonly" + // ] + // } + +} + // method id "compute.instances.addAccessConfig": type InstancesAddAccessConfigCall struct { @@ -47772,9 +54441,13 @@ func (c *InstancesAddAccessConfigCall) doRequest(alt string) (*http.Response, er } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{instance}/addAccessConfig") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -47835,7 +54508,7 @@ func (c *InstancesAddAccessConfigCall) Do(opts ...googleapi.CallOption) (*Operat // "instance": { // "description": "The instance name for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -47891,7 +54564,8 @@ type InstancesAggregatedListCall struct { header_ http.Header } -// AggregatedList: Retrieves aggregated list of instances. +// AggregatedList: Retrieves aggregated list of all of the instances in +// your project across all regions and zones. // For details, see https://cloud.google.com/compute/docs/reference/latest/instances/aggregatedList func (r *InstancesService) AggregatedList(project string) *InstancesAggregatedListCall { c := &InstancesAggregatedListCall{s: r.s, urlParams_: make(gensupport.URLParams)} @@ -48008,9 +54682,13 @@ func (c *InstancesAggregatedListCall) doRequest(alt string) (*http.Response, err } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/aggregated/instances") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -48056,7 +54734,7 @@ func (c *InstancesAggregatedListCall) Do(opts ...googleapi.CallOption) (*Instanc } return ret, nil // { - // "description": "Retrieves aggregated list of instances.", + // "description": "Retrieves aggregated list of all of the instances in your project across all regions and zones.", // "httpMethod": "GET", // "id": "compute.instances.aggregatedList", // "parameterOrder": [ @@ -48220,9 +54898,13 @@ func (c *InstancesAttachDiskCall) doRequest(alt string) (*http.Response, error) } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{instance}/attachDisk") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -48287,7 +54969,7 @@ func (c *InstancesAttachDiskCall) Do(opts ...googleapi.CallOption) (*Operation, // "instance": { // "description": "The instance name for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -48401,9 +55083,13 @@ func (c *InstancesDeleteCall) doRequest(alt string) (*http.Response, error) { reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{instance}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -48463,7 +55149,7 @@ func (c *InstancesDeleteCall) Do(opts ...googleapi.CallOption) (*Operation, erro // "instance": { // "description": "Name of the instance resource to delete.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -48576,9 +55262,13 @@ func (c *InstancesDeleteAccessConfigCall) doRequest(alt string) (*http.Response, reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{instance}/deleteAccessConfig") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -48646,7 +55336,7 @@ func (c *InstancesDeleteAccessConfigCall) Do(opts ...googleapi.CallOption) (*Ope // "instance": { // "description": "The instance name for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -48763,9 +55453,13 @@ func (c *InstancesDetachDiskCall) doRequest(alt string) (*http.Response, error) reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{instance}/detachDisk") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -48824,15 +55518,15 @@ func (c *InstancesDetachDiskCall) Do(opts ...googleapi.CallOption) (*Operation, // ], // "parameters": { // "deviceName": { - // "description": "Disk device name to detach.", + // "description": "The device name of the disk to detach. Make a get() request on the instance to view currently attached disks and device names.", // "location": "query", // "required": true, // "type": "string" // }, // "instance": { - // "description": "Instance name.", + // "description": "Instance name for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -48938,9 +55632,13 @@ func (c *InstancesGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{instance}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -49000,7 +55698,7 @@ func (c *InstancesGetCall) Do(opts ...googleapi.CallOption) (*Instance, error) { // "instance": { // "description": "Name of the instance resource to return.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -49032,6 +55730,173 @@ func (c *InstancesGetCall) Do(opts ...googleapi.CallOption) (*Instance, error) { } +// method id "compute.instances.getIamPolicy": + +type InstancesGetIamPolicyCall struct { + s *Service + project string + zone string + resource string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// GetIamPolicy: Gets the access control policy for a resource. May be +// empty if no such policy or resource exists. +func (r *InstancesService) GetIamPolicy(project string, zone string, resource string) *InstancesGetIamPolicyCall { + c := &InstancesGetIamPolicyCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.zone = zone + c.resource = resource + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *InstancesGetIamPolicyCall) Fields(s ...googleapi.Field) *InstancesGetIamPolicyCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// IfNoneMatch sets the optional parameter which makes the operation +// fail if the object's ETag matches the given value. This is useful for +// getting updates only after the object has changed since the last +// request. Use googleapi.IsNotModified to check whether the response +// error from Do is the result of In-None-Match. +func (c *InstancesGetIamPolicyCall) IfNoneMatch(entityTag string) *InstancesGetIamPolicyCall { + c.ifNoneMatch_ = entityTag + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *InstancesGetIamPolicyCall) Context(ctx context.Context) *InstancesGetIamPolicyCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *InstancesGetIamPolicyCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *InstancesGetIamPolicyCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + if c.ifNoneMatch_ != "" { + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) + } + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{resource}/getIamPolicy") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "zone": c.zone, + "resource": c.resource, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.instances.getIamPolicy" call. +// Exactly one of *Policy or error will be non-nil. Any non-2xx status +// code is an error. Response headers are in either +// *Policy.ServerResponse.Header or (if a response was returned at all) +// in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to +// check whether the returned error was because http.StatusNotModified +// was returned. +func (c *InstancesGetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Policy, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Policy{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Gets the access control policy for a resource. May be empty if no such policy or resource exists.", + // "httpMethod": "GET", + // "id": "compute.instances.getIamPolicy", + // "parameterOrder": [ + // "project", + // "zone", + // "resource" + // ], + // "parameters": { + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "resource": { + // "description": "Name or id of the resource for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + // "required": true, + // "type": "string" + // }, + // "zone": { + // "description": "The name of the zone for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/zones/{zone}/instances/{resource}/getIamPolicy", + // "response": { + // "$ref": "Policy" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute", + // "https://www.googleapis.com/auth/compute.readonly" + // ] + // } + +} + // method id "compute.instances.getSerialPortOutput": type InstancesGetSerialPortOutputCall struct { @@ -49045,8 +55910,8 @@ type InstancesGetSerialPortOutputCall struct { header_ http.Header } -// GetSerialPortOutput: Returns the specified instance's serial port -// output. +// GetSerialPortOutput: Returns the last 1 MB of serial port output from +// the specified instance. // For details, see https://cloud.google.com/compute/docs/reference/latest/instances/getSerialPortOutput func (r *InstancesService) GetSerialPortOutput(project string, zone string, instance string) *InstancesGetSerialPortOutputCall { c := &InstancesGetSerialPortOutputCall{s: r.s, urlParams_: make(gensupport.URLParams)} @@ -49120,9 +55985,13 @@ func (c *InstancesGetSerialPortOutputCall) doRequest(alt string) (*http.Response } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{instance}/serialPort") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -49170,7 +56039,7 @@ func (c *InstancesGetSerialPortOutputCall) Do(opts ...googleapi.CallOption) (*Se } return ret, nil // { - // "description": "Returns the specified instance's serial port output.", + // "description": "Returns the last 1 MB of serial port output from the specified instance.", // "httpMethod": "GET", // "id": "compute.instances.getSerialPortOutput", // "parameterOrder": [ @@ -49182,7 +56051,7 @@ func (c *InstancesGetSerialPortOutputCall) Do(opts ...googleapi.CallOption) (*Se // "instance": { // "description": "Name of the instance scoping this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -49278,10 +56147,9 @@ func (c *InstancesInsertCall) RequestId(requestId string) *InstancesInsertCall { // This field is optional. It can be a full or partial URL. For example, // the following are all valid URLs to an instance template: // - -// https://www.googleapis.com/compute/v1/projects/project/global/global/instanceTemplates/instanceTemplate -// - projects/project/global/global/instanceTemplates/instanceTemplate -// -// - global/instancesTemplates/instanceTemplate +// https://www.googleapis.com/compute/v1/projects/project/global/instanceTemplates/instanceTemplate +// - projects/project/global/instanceTemplates/instanceTemplate +// - global/instanceTemplates/instanceTemplate func (c *InstancesInsertCall) SourceInstanceTemplate(sourceInstanceTemplate string) *InstancesInsertCall { c.urlParams_.Set("sourceInstanceTemplate", sourceInstanceTemplate) return c @@ -49325,9 +56193,13 @@ func (c *InstancesInsertCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -49395,7 +56267,7 @@ func (c *InstancesInsertCall) Do(opts ...googleapi.CallOption) (*Operation, erro // "type": "string" // }, // "sourceInstanceTemplate": { - // "description": "Specifies instance template to create the instance.\n\nThis field is optional. It can be a full or partial URL. For example, the following are all valid URLs to an instance template: \n- https://www.googleapis.com/compute/v1/projects/project/global/global/instanceTemplates/instanceTemplate \n- projects/project/global/global/instanceTemplates/instanceTemplate \n- global/instancesTemplates/instanceTemplate", + // "description": "Specifies instance template to create the instance.\n\nThis field is optional. It can be a full or partial URL. For example, the following are all valid URLs to an instance template: \n- https://www.googleapis.com/compute/v1/projects/project/global/instanceTemplates/instanceTemplate \n- projects/project/global/instanceTemplates/instanceTemplate \n- global/instanceTemplates/instanceTemplate", // "location": "query", // "type": "string" // }, @@ -49553,9 +56425,13 @@ func (c *InstancesListCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -49696,7 +56572,8 @@ type InstancesListReferrersCall struct { } // ListReferrers: Retrieves the list of referrers to instances contained -// within the specified zone. +// within the specified zone. For more information, read Viewing +// Referrers to VM Instances. func (r *InstancesService) ListReferrers(project string, zone string, instance string) *InstancesListReferrersCall { c := &InstancesListReferrersCall{s: r.s, urlParams_: make(gensupport.URLParams)} c.project = project @@ -49814,9 +56691,13 @@ func (c *InstancesListReferrersCall) doRequest(alt string) (*http.Response, erro } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{instance}/referrers") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -49864,7 +56745,7 @@ func (c *InstancesListReferrersCall) Do(opts ...googleapi.CallOption) (*Instance } return ret, nil // { - // "description": "Retrieves the list of referrers to instances contained within the specified zone.", + // "description": "Retrieves the list of referrers to instances contained within the specified zone. For more information, read Viewing Referrers to VM Instances.", // "httpMethod": "GET", // "id": "compute.instances.listReferrers", // "parameterOrder": [ @@ -49881,7 +56762,7 @@ func (c *InstancesListReferrersCall) Do(opts ...googleapi.CallOption) (*Instance // "instance": { // "description": "Name of the target instance scoping this request, or '-' if the request should span over all instances in the container.", // "location": "path", - // "pattern": "-|[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "-|[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -50027,9 +56908,13 @@ func (c *InstancesResetCall) doRequest(alt string) (*http.Response, error) { reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{instance}/reset") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -50089,7 +56974,7 @@ func (c *InstancesResetCall) Do(opts ...googleapi.CallOption) (*Operation, error // "instance": { // "description": "Name of the instance scoping this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -50205,9 +57090,13 @@ func (c *InstancesSetDeletionProtectionCall) doRequest(alt string) (*http.Respon reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{resource}/setDeletionProtection") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -50283,9 +57172,9 @@ func (c *InstancesSetDeletionProtectionCall) Do(opts ...googleapi.CallOption) (* // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -50386,9 +57275,13 @@ func (c *InstancesSetDiskAutoDeleteCall) doRequest(alt string) (*http.Response, reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{instance}/setDiskAutoDelete") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -50454,16 +57347,16 @@ func (c *InstancesSetDiskAutoDeleteCall) Do(opts ...googleapi.CallOption) (*Oper // "type": "boolean" // }, // "deviceName": { - // "description": "The device name of the disk to modify.", + // "description": "The device name of the disk to modify. Make a get() request on the instance to view currently attached disks and device names.", // "location": "query", // "pattern": "\\w[\\w.-]{0,254}", // "required": true, // "type": "string" // }, // "instance": { - // "description": "The instance name.", + // "description": "The instance name for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -50499,6 +57392,168 @@ func (c *InstancesSetDiskAutoDeleteCall) Do(opts ...googleapi.CallOption) (*Oper } +// method id "compute.instances.setIamPolicy": + +type InstancesSetIamPolicyCall struct { + s *Service + project string + zone string + resource string + zonesetpolicyrequest *ZoneSetPolicyRequest + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// SetIamPolicy: Sets the access control policy on the specified +// resource. Replaces any existing policy. +func (r *InstancesService) SetIamPolicy(project string, zone string, resource string, zonesetpolicyrequest *ZoneSetPolicyRequest) *InstancesSetIamPolicyCall { + c := &InstancesSetIamPolicyCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.zone = zone + c.resource = resource + c.zonesetpolicyrequest = zonesetpolicyrequest + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *InstancesSetIamPolicyCall) Fields(s ...googleapi.Field) *InstancesSetIamPolicyCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *InstancesSetIamPolicyCall) Context(ctx context.Context) *InstancesSetIamPolicyCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *InstancesSetIamPolicyCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *InstancesSetIamPolicyCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.zonesetpolicyrequest) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{resource}/setIamPolicy") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "zone": c.zone, + "resource": c.resource, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.instances.setIamPolicy" call. +// Exactly one of *Policy or error will be non-nil. Any non-2xx status +// code is an error. Response headers are in either +// *Policy.ServerResponse.Header or (if a response was returned at all) +// in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to +// check whether the returned error was because http.StatusNotModified +// was returned. +func (c *InstancesSetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Policy, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Policy{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Sets the access control policy on the specified resource. Replaces any existing policy.", + // "httpMethod": "POST", + // "id": "compute.instances.setIamPolicy", + // "parameterOrder": [ + // "project", + // "zone", + // "resource" + // ], + // "parameters": { + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "resource": { + // "description": "Name or id of the resource for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + // "required": true, + // "type": "string" + // }, + // "zone": { + // "description": "The name of the zone for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/zones/{zone}/instances/{resource}/setIamPolicy", + // "request": { + // "$ref": "ZoneSetPolicyRequest" + // }, + // "response": { + // "$ref": "Policy" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + // method id "compute.instances.setLabels": type InstancesSetLabelsCall struct { @@ -50580,9 +57635,13 @@ func (c *InstancesSetLabelsCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{instance}/setLabels") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -50642,7 +57701,7 @@ func (c *InstancesSetLabelsCall) Do(opts ...googleapi.CallOption) (*Operation, e // "instance": { // "description": "Name of the instance scoping this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -50762,9 +57821,13 @@ func (c *InstancesSetMachineResourcesCall) doRequest(alt string) (*http.Response } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{instance}/setMachineResources") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -50824,7 +57887,7 @@ func (c *InstancesSetMachineResourcesCall) Do(opts ...googleapi.CallOption) (*Op // "instance": { // "description": "Name of the instance scoping this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -50944,9 +58007,13 @@ func (c *InstancesSetMachineTypeCall) doRequest(alt string) (*http.Response, err } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{instance}/setMachineType") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -51006,7 +58073,7 @@ func (c *InstancesSetMachineTypeCall) Do(opts ...googleapi.CallOption) (*Operati // "instance": { // "description": "Name of the instance scoping this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -51127,9 +58194,13 @@ func (c *InstancesSetMetadataCall) doRequest(alt string) (*http.Response, error) } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{instance}/setMetadata") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -51189,7 +58260,7 @@ func (c *InstancesSetMetadataCall) Do(opts ...googleapi.CallOption) (*Operation, // "instance": { // "description": "Name of the instance scoping this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -51311,9 +58382,13 @@ func (c *InstancesSetMinCpuPlatformCall) doRequest(alt string) (*http.Response, } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{instance}/setMinCpuPlatform") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -51373,7 +58448,7 @@ func (c *InstancesSetMinCpuPlatformCall) Do(opts ...googleapi.CallOption) (*Oper // "instance": { // "description": "Name of the instance scoping this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -51493,9 +58568,13 @@ func (c *InstancesSetSchedulingCall) doRequest(alt string) (*http.Response, erro } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{instance}/setScheduling") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -51553,9 +58632,9 @@ func (c *InstancesSetSchedulingCall) Do(opts ...googleapi.CallOption) (*Operatio // ], // "parameters": { // "instance": { - // "description": "Instance name.", + // "description": "Instance name for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -51676,9 +58755,13 @@ func (c *InstancesSetServiceAccountCall) doRequest(alt string) (*http.Response, } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{instance}/setServiceAccount") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -51738,7 +58821,7 @@ func (c *InstancesSetServiceAccountCall) Do(opts ...googleapi.CallOption) (*Oper // "instance": { // "description": "Name of the instance resource to start.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -51790,8 +58873,8 @@ type InstancesSetTagsCall struct { header_ http.Header } -// SetTags: Sets tags for the specified instance to the data included in -// the request. +// SetTags: Sets network tags for the specified instance to the data +// included in the request. // For details, see https://cloud.google.com/compute/docs/reference/latest/instances/setTags func (r *InstancesService) SetTags(project string, zone string, instance string, tags *Tags) *InstancesSetTagsCall { c := &InstancesSetTagsCall{s: r.s, urlParams_: make(gensupport.URLParams)} @@ -51859,9 +58942,13 @@ func (c *InstancesSetTagsCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{instance}/setTags") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -51909,7 +58996,7 @@ func (c *InstancesSetTagsCall) Do(opts ...googleapi.CallOption) (*Operation, err } return ret, nil // { - // "description": "Sets tags for the specified instance to the data included in the request.", + // "description": "Sets network tags for the specified instance to the data included in the request.", // "httpMethod": "POST", // "id": "compute.instances.setTags", // "parameterOrder": [ @@ -51921,7 +59008,7 @@ func (c *InstancesSetTagsCall) Do(opts ...googleapi.CallOption) (*Operation, err // "instance": { // "description": "Name of the instance scoping this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -51960,6 +59047,158 @@ func (c *InstancesSetTagsCall) Do(opts ...googleapi.CallOption) (*Operation, err } +// method id "compute.instances.simulateMaintenanceEvent": + +type InstancesSimulateMaintenanceEventCall struct { + s *Service + project string + zone string + instance string + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// SimulateMaintenanceEvent: Simulates a maintenance event on the +// instance. +func (r *InstancesService) SimulateMaintenanceEvent(project string, zone string, instance string) *InstancesSimulateMaintenanceEventCall { + c := &InstancesSimulateMaintenanceEventCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.zone = zone + c.instance = instance + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *InstancesSimulateMaintenanceEventCall) Fields(s ...googleapi.Field) *InstancesSimulateMaintenanceEventCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *InstancesSimulateMaintenanceEventCall) Context(ctx context.Context) *InstancesSimulateMaintenanceEventCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *InstancesSimulateMaintenanceEventCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *InstancesSimulateMaintenanceEventCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{instance}/simulateMaintenanceEvent") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "zone": c.zone, + "instance": c.instance, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.instances.simulateMaintenanceEvent" call. +// Exactly one of *Operation or error will be non-nil. Any non-2xx +// status code is an error. Response headers are in either +// *Operation.ServerResponse.Header or (if a response was returned at +// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified +// to check whether the returned error was because +// http.StatusNotModified was returned. +func (c *InstancesSimulateMaintenanceEventCall) Do(opts ...googleapi.CallOption) (*Operation, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Operation{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Simulates a maintenance event on the instance.", + // "httpMethod": "POST", + // "id": "compute.instances.simulateMaintenanceEvent", + // "parameterOrder": [ + // "project", + // "zone", + // "instance" + // ], + // "parameters": { + // "instance": { + // "description": "Name of the instance scoping this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + // "required": true, + // "type": "string" + // }, + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "zone": { + // "description": "The name of the zone for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/zones/{zone}/instances/{instance}/simulateMaintenanceEvent", + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + // method id "compute.instances.start": type InstancesStartCall struct { @@ -52035,9 +59274,13 @@ func (c *InstancesStartCall) doRequest(alt string) (*http.Response, error) { reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{instance}/start") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -52097,7 +59340,7 @@ func (c *InstancesStartCall) Do(opts ...googleapi.CallOption) (*Operation, error // "instance": { // "description": "Name of the instance resource to start.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -52215,9 +59458,13 @@ func (c *InstancesStartWithEncryptionKeyCall) doRequest(alt string) (*http.Respo } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{instance}/startWithEncryptionKey") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -52277,7 +59524,7 @@ func (c *InstancesStartWithEncryptionKeyCall) Do(opts ...googleapi.CallOption) ( // "instance": { // "description": "Name of the instance resource to start.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -52395,9 +59642,13 @@ func (c *InstancesStopCall) doRequest(alt string) (*http.Response, error) { reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{instance}/stop") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -52457,7 +59708,7 @@ func (c *InstancesStopCall) Do(opts ...googleapi.CallOption) (*Operation, error) // "instance": { // "description": "Name of the instance resource to stop.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -52493,6 +59744,169 @@ func (c *InstancesStopCall) Do(opts ...googleapi.CallOption) (*Operation, error) } +// method id "compute.instances.testIamPermissions": + +type InstancesTestIamPermissionsCall struct { + s *Service + project string + zone string + resource string + testpermissionsrequest *TestPermissionsRequest + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// TestIamPermissions: Returns permissions that a caller has on the +// specified resource. +func (r *InstancesService) TestIamPermissions(project string, zone string, resource string, testpermissionsrequest *TestPermissionsRequest) *InstancesTestIamPermissionsCall { + c := &InstancesTestIamPermissionsCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.zone = zone + c.resource = resource + c.testpermissionsrequest = testpermissionsrequest + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *InstancesTestIamPermissionsCall) Fields(s ...googleapi.Field) *InstancesTestIamPermissionsCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *InstancesTestIamPermissionsCall) Context(ctx context.Context) *InstancesTestIamPermissionsCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *InstancesTestIamPermissionsCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *InstancesTestIamPermissionsCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.testpermissionsrequest) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{resource}/testIamPermissions") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "zone": c.zone, + "resource": c.resource, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.instances.testIamPermissions" call. +// Exactly one of *TestPermissionsResponse or error will be non-nil. Any +// non-2xx status code is an error. Response headers are in either +// *TestPermissionsResponse.ServerResponse.Header or (if a response was +// returned at all) in error.(*googleapi.Error).Header. Use +// googleapi.IsNotModified to check whether the returned error was +// because http.StatusNotModified was returned. +func (c *InstancesTestIamPermissionsCall) Do(opts ...googleapi.CallOption) (*TestPermissionsResponse, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &TestPermissionsResponse{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Returns permissions that a caller has on the specified resource.", + // "httpMethod": "POST", + // "id": "compute.instances.testIamPermissions", + // "parameterOrder": [ + // "project", + // "zone", + // "resource" + // ], + // "parameters": { + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "resource": { + // "description": "Name or id of the resource for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + // "required": true, + // "type": "string" + // }, + // "zone": { + // "description": "The name of the zone for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/zones/{zone}/instances/{resource}/testIamPermissions", + // "request": { + // "$ref": "TestPermissionsRequest" + // }, + // "response": { + // "$ref": "TestPermissionsResponse" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute", + // "https://www.googleapis.com/auth/compute.readonly" + // ] + // } + +} + // method id "compute.instances.updateAccessConfig": type InstancesUpdateAccessConfigCall struct { @@ -52577,9 +59991,13 @@ func (c *InstancesUpdateAccessConfigCall) doRequest(alt string) (*http.Response, } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{instance}/updateAccessConfig") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -52640,7 +60058,7 @@ func (c *InstancesUpdateAccessConfigCall) Do(opts ...googleapi.CallOption) (*Ope // "instance": { // "description": "The instance name for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -52767,9 +60185,13 @@ func (c *InstancesUpdateNetworkInterfaceCall) doRequest(alt string) (*http.Respo } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/instances/{instance}/updateNetworkInterface") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PATCH", urls, body) + req, err := http.NewRequest("PATCH", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -52830,7 +60252,7 @@ func (c *InstancesUpdateNetworkInterfaceCall) Do(opts ...googleapi.CallOption) ( // "instance": { // "description": "The instance name for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -53003,9 +60425,13 @@ func (c *InterconnectAttachmentsAggregatedListCall) doRequest(alt string) (*http } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/aggregated/interconnectAttachments") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -53197,9 +60623,13 @@ func (c *InterconnectAttachmentsDeleteCall) doRequest(alt string) (*http.Respons reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/interconnectAttachments/{interconnectAttachment}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -53363,9 +60793,13 @@ func (c *InterconnectAttachmentsGetCall) doRequest(alt string) (*http.Response, } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/interconnectAttachments/{interconnectAttachment}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -53536,9 +60970,13 @@ func (c *InterconnectAttachmentsInsertCall) doRequest(alt string) (*http.Respons } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/interconnectAttachments") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -53758,9 +61196,13 @@ func (c *InterconnectAttachmentsListCall) doRequest(alt string) (*http.Response, } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/interconnectAttachments") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -53969,9 +61411,13 @@ func (c *InterconnectAttachmentsPatchCall) doRequest(alt string) (*http.Response } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/interconnectAttachments/{interconnectAttachment}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PATCH", urls, body) + req, err := http.NewRequest("PATCH", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -54138,9 +61584,13 @@ func (c *InterconnectLocationsGetCall) doRequest(alt string) (*http.Response, er } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/interconnectLocations/{interconnectLocation}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -54351,9 +61801,13 @@ func (c *InterconnectLocationsListCall) doRequest(alt string) (*http.Response, e } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/interconnectLocations") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -54542,9 +61996,13 @@ func (c *InterconnectsDeleteCall) doRequest(alt string) (*http.Response, error) reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/interconnects/{interconnect}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -54698,9 +62156,13 @@ func (c *InterconnectsGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/interconnects/{interconnect}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -54783,6 +62245,163 @@ func (c *InterconnectsGetCall) Do(opts ...googleapi.CallOption) (*Interconnect, } +// method id "compute.interconnects.getDiagnostics": + +type InterconnectsGetDiagnosticsCall struct { + s *Service + project string + interconnect string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// GetDiagnostics: Returns the interconnectDiagnostics for the specified +// interconnect. +func (r *InterconnectsService) GetDiagnostics(project string, interconnect string) *InterconnectsGetDiagnosticsCall { + c := &InterconnectsGetDiagnosticsCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.interconnect = interconnect + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *InterconnectsGetDiagnosticsCall) Fields(s ...googleapi.Field) *InterconnectsGetDiagnosticsCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// IfNoneMatch sets the optional parameter which makes the operation +// fail if the object's ETag matches the given value. This is useful for +// getting updates only after the object has changed since the last +// request. Use googleapi.IsNotModified to check whether the response +// error from Do is the result of In-None-Match. +func (c *InterconnectsGetDiagnosticsCall) IfNoneMatch(entityTag string) *InterconnectsGetDiagnosticsCall { + c.ifNoneMatch_ = entityTag + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *InterconnectsGetDiagnosticsCall) Context(ctx context.Context) *InterconnectsGetDiagnosticsCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *InterconnectsGetDiagnosticsCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *InterconnectsGetDiagnosticsCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + if c.ifNoneMatch_ != "" { + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) + } + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/interconnects/{interconnect}/getDiagnostics") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "interconnect": c.interconnect, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.interconnects.getDiagnostics" call. +// Exactly one of *InterconnectsGetDiagnosticsResponse or error will be +// non-nil. Any non-2xx status code is an error. Response headers are in +// either *InterconnectsGetDiagnosticsResponse.ServerResponse.Header or +// (if a response was returned at all) in +// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check +// whether the returned error was because http.StatusNotModified was +// returned. +func (c *InterconnectsGetDiagnosticsCall) Do(opts ...googleapi.CallOption) (*InterconnectsGetDiagnosticsResponse, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &InterconnectsGetDiagnosticsResponse{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Returns the interconnectDiagnostics for the specified interconnect.", + // "httpMethod": "GET", + // "id": "compute.interconnects.getDiagnostics", + // "parameterOrder": [ + // "project", + // "interconnect" + // ], + // "parameters": { + // "interconnect": { + // "description": "Name of the interconnect resource to query.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // }, + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/global/interconnects/{interconnect}/getDiagnostics", + // "response": { + // "$ref": "InterconnectsGetDiagnosticsResponse" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute", + // "https://www.googleapis.com/auth/compute.readonly" + // ] + // } + +} + // method id "compute.interconnects.insert": type InterconnectsInsertCall struct { @@ -54860,9 +62479,13 @@ func (c *InterconnectsInsertCall) doRequest(alt string) (*http.Response, error) } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/interconnects") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -55071,9 +62694,13 @@ func (c *InterconnectsListCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/interconnects") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -55271,9 +62898,13 @@ func (c *InterconnectsPatchCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/interconnects/{interconnect}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PATCH", urls, body) + req, err := http.NewRequest("PATCH", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -55430,9 +63061,13 @@ func (c *LicenseCodesGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/licenseCodes/{licenseCode}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -55575,9 +63210,13 @@ func (c *LicenseCodesTestIamPermissionsCall) doRequest(alt string) (*http.Respon } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/licenseCodes/{resource}/testIamPermissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -55640,9 +63279,9 @@ func (c *LicenseCodesTestIamPermissionsCall) Do(opts ...googleapi.CallOption) (* // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "(?:[-a-z0-9_]{0,62}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -55734,9 +63373,13 @@ func (c *LicensesDeleteCall) doRequest(alt string) (*http.Response, error) { reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/licenses/{license}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -55890,9 +63533,13 @@ func (c *LicensesGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/licenses/{license}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -55975,6 +63622,162 @@ func (c *LicensesGetCall) Do(opts ...googleapi.CallOption) (*License, error) { } +// method id "compute.licenses.getIamPolicy": + +type LicensesGetIamPolicyCall struct { + s *Service + project string + resource string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// GetIamPolicy: Gets the access control policy for a resource. May be +// empty if no such policy or resource exists. +func (r *LicensesService) GetIamPolicy(project string, resource string) *LicensesGetIamPolicyCall { + c := &LicensesGetIamPolicyCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.resource = resource + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *LicensesGetIamPolicyCall) Fields(s ...googleapi.Field) *LicensesGetIamPolicyCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// IfNoneMatch sets the optional parameter which makes the operation +// fail if the object's ETag matches the given value. This is useful for +// getting updates only after the object has changed since the last +// request. Use googleapi.IsNotModified to check whether the response +// error from Do is the result of In-None-Match. +func (c *LicensesGetIamPolicyCall) IfNoneMatch(entityTag string) *LicensesGetIamPolicyCall { + c.ifNoneMatch_ = entityTag + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *LicensesGetIamPolicyCall) Context(ctx context.Context) *LicensesGetIamPolicyCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *LicensesGetIamPolicyCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *LicensesGetIamPolicyCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + if c.ifNoneMatch_ != "" { + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) + } + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/licenses/{resource}/getIamPolicy") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "resource": c.resource, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.licenses.getIamPolicy" call. +// Exactly one of *Policy or error will be non-nil. Any non-2xx status +// code is an error. Response headers are in either +// *Policy.ServerResponse.Header or (if a response was returned at all) +// in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to +// check whether the returned error was because http.StatusNotModified +// was returned. +func (c *LicensesGetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Policy, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Policy{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Gets the access control policy for a resource. May be empty if no such policy or resource exists.", + // "httpMethod": "GET", + // "id": "compute.licenses.getIamPolicy", + // "parameterOrder": [ + // "project", + // "resource" + // ], + // "parameters": { + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "resource": { + // "description": "Name or id of the resource for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/global/licenses/{resource}/getIamPolicy", + // "response": { + // "$ref": "Policy" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute", + // "https://www.googleapis.com/auth/compute.readonly" + // ] + // } + +} + // method id "compute.licenses.insert": type LicensesInsertCall struct { @@ -56051,9 +63854,13 @@ func (c *LicensesInsertCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/licenses") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -56269,9 +64076,13 @@ func (c *LicensesListCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/licenses") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -56389,6 +64200,157 @@ func (c *LicensesListCall) Pages(ctx context.Context, f func(*LicensesListRespon } } +// method id "compute.licenses.setIamPolicy": + +type LicensesSetIamPolicyCall struct { + s *Service + project string + resource string + globalsetpolicyrequest *GlobalSetPolicyRequest + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// SetIamPolicy: Sets the access control policy on the specified +// resource. Replaces any existing policy. +func (r *LicensesService) SetIamPolicy(project string, resource string, globalsetpolicyrequest *GlobalSetPolicyRequest) *LicensesSetIamPolicyCall { + c := &LicensesSetIamPolicyCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.resource = resource + c.globalsetpolicyrequest = globalsetpolicyrequest + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *LicensesSetIamPolicyCall) Fields(s ...googleapi.Field) *LicensesSetIamPolicyCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *LicensesSetIamPolicyCall) Context(ctx context.Context) *LicensesSetIamPolicyCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *LicensesSetIamPolicyCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *LicensesSetIamPolicyCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.globalsetpolicyrequest) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/licenses/{resource}/setIamPolicy") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "resource": c.resource, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.licenses.setIamPolicy" call. +// Exactly one of *Policy or error will be non-nil. Any non-2xx status +// code is an error. Response headers are in either +// *Policy.ServerResponse.Header or (if a response was returned at all) +// in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to +// check whether the returned error was because http.StatusNotModified +// was returned. +func (c *LicensesSetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Policy, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Policy{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Sets the access control policy on the specified resource. Replaces any existing policy.", + // "httpMethod": "POST", + // "id": "compute.licenses.setIamPolicy", + // "parameterOrder": [ + // "project", + // "resource" + // ], + // "parameters": { + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "resource": { + // "description": "Name or id of the resource for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/global/licenses/{resource}/setIamPolicy", + // "request": { + // "$ref": "GlobalSetPolicyRequest" + // }, + // "response": { + // "$ref": "Policy" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + // method id "compute.licenses.testIamPermissions": type LicensesTestIamPermissionsCall struct { @@ -56449,9 +64411,13 @@ func (c *LicensesTestIamPermissionsCall) doRequest(alt string) (*http.Response, } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/licenses/{resource}/testIamPermissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -56514,9 +64480,9 @@ func (c *LicensesTestIamPermissionsCall) Do(opts ...googleapi.CallOption) (*Test // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "(?:[-a-z0-9_]{0,62}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -56665,9 +64631,13 @@ func (c *MachineTypesAggregatedListCall) doRequest(alt string) (*http.Response, } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/aggregated/machineTypes") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -56855,9 +64825,13 @@ func (c *MachineTypesGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/machineTypes/{machineType}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -57080,9 +65054,13 @@ func (c *MachineTypesListCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/machineTypes") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -57287,9 +65265,13 @@ func (c *NetworksAddPeeringCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/networks/{network}/addPeering") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -57347,7 +65329,7 @@ func (c *NetworksAddPeeringCall) Do(opts ...googleapi.CallOption) (*Operation, e // "network": { // "description": "Name of the network resource to add peering to.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -57451,9 +65433,13 @@ func (c *NetworksDeleteCall) doRequest(alt string) (*http.Response, error) { reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/networks/{network}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -57511,7 +65497,7 @@ func (c *NetworksDeleteCall) Do(opts ...googleapi.CallOption) (*Operation, error // "network": { // "description": "Name of the network to delete.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -57608,9 +65594,13 @@ func (c *NetworksGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/networks/{network}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -57668,7 +65658,7 @@ func (c *NetworksGetCall) Do(opts ...googleapi.CallOption) (*Network, error) { // "network": { // "description": "Name of the network to return.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -57771,9 +65761,13 @@ func (c *NetworksInsertCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/networks") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -57983,9 +65977,13 @@ func (c *NetworksListCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/networks") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -58183,9 +66181,13 @@ func (c *NetworksPatchCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/networks/{network}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PATCH", urls, body) + req, err := http.NewRequest("PATCH", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -58243,7 +66245,7 @@ func (c *NetworksPatchCall) Do(opts ...googleapi.CallOption) (*Operation, error) // "network": { // "description": "Name of the network to update.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -58353,9 +66355,13 @@ func (c *NetworksRemovePeeringCall) doRequest(alt string) (*http.Response, error } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/networks/{network}/removePeering") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -58413,7 +66419,7 @@ func (c *NetworksRemovePeeringCall) Do(opts ...googleapi.CallOption) (*Operation // "network": { // "description": "Name of the network resource to remove peering from.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -58517,9 +66523,13 @@ func (c *NetworksSwitchToCustomModeCall) doRequest(alt string) (*http.Response, reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/networks/{network}/switchToCustomMode") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -58577,7 +66587,7 @@ func (c *NetworksSwitchToCustomModeCall) Do(opts ...googleapi.CallOption) (*Oper // "network": { // "description": "Name of the network to be updated.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -58606,6 +66616,4559 @@ func (c *NetworksSwitchToCustomModeCall) Do(opts ...googleapi.CallOption) (*Oper } +// method id "compute.nodeGroups.addNodes": + +type NodeGroupsAddNodesCall struct { + s *Service + project string + zone string + nodeGroup string + nodegroupsaddnodesrequest *NodeGroupsAddNodesRequest + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// AddNodes: Adds specified number of nodes to the node group. +func (r *NodeGroupsService) AddNodes(project string, zone string, nodeGroup string, nodegroupsaddnodesrequest *NodeGroupsAddNodesRequest) *NodeGroupsAddNodesCall { + c := &NodeGroupsAddNodesCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.zone = zone + c.nodeGroup = nodeGroup + c.nodegroupsaddnodesrequest = nodegroupsaddnodesrequest + return c +} + +// RequestId sets the optional parameter "requestId": An optional +// request ID to identify requests. Specify a unique request ID so that +// if you must retry your request, the server will know to ignore the +// request if it has already been completed. +// +// For example, consider a situation where you make an initial request +// and the request times out. If you make the request again with the +// same request ID, the server can check if original operation with the +// same request ID was received, and if so, will ignore the second +// request. This prevents clients from accidentally creating duplicate +// commitments. +// +// The request ID must be a valid UUID with the exception that zero UUID +// is not supported (00000000-0000-0000-0000-000000000000). +func (c *NodeGroupsAddNodesCall) RequestId(requestId string) *NodeGroupsAddNodesCall { + c.urlParams_.Set("requestId", requestId) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *NodeGroupsAddNodesCall) Fields(s ...googleapi.Field) *NodeGroupsAddNodesCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *NodeGroupsAddNodesCall) Context(ctx context.Context) *NodeGroupsAddNodesCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *NodeGroupsAddNodesCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *NodeGroupsAddNodesCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.nodegroupsaddnodesrequest) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/nodeGroups/{nodeGroup}/addNodes") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "zone": c.zone, + "nodeGroup": c.nodeGroup, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.nodeGroups.addNodes" call. +// Exactly one of *Operation or error will be non-nil. Any non-2xx +// status code is an error. Response headers are in either +// *Operation.ServerResponse.Header or (if a response was returned at +// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified +// to check whether the returned error was because +// http.StatusNotModified was returned. +func (c *NodeGroupsAddNodesCall) Do(opts ...googleapi.CallOption) (*Operation, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Operation{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Adds specified number of nodes to the node group.", + // "httpMethod": "POST", + // "id": "compute.nodeGroups.addNodes", + // "parameterOrder": [ + // "project", + // "zone", + // "nodeGroup" + // ], + // "parameters": { + // "nodeGroup": { + // "description": "Name of the NodeGroup resource.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // }, + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "requestId": { + // "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", + // "location": "query", + // "type": "string" + // }, + // "zone": { + // "description": "The name of the zone for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/zones/{zone}/nodeGroups/{nodeGroup}/addNodes", + // "request": { + // "$ref": "NodeGroupsAddNodesRequest" + // }, + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + +// method id "compute.nodeGroups.aggregatedList": + +type NodeGroupsAggregatedListCall struct { + s *Service + project string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// AggregatedList: Retrieves an aggregated list of node groups. Note: +// use nodeGroups.listNodes for more details about each group. +func (r *NodeGroupsService) AggregatedList(project string) *NodeGroupsAggregatedListCall { + c := &NodeGroupsAggregatedListCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + return c +} + +// Filter sets the optional parameter "filter": A filter expression that +// filters resources listed in the response. The expression must specify +// the field name, a comparison operator, and the value that you want to +// use for filtering. The value must be a string, a number, or a +// boolean. The comparison operator must be either =, !=, >, or <. +// +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. +// +// You can also filter nested fields. For example, you could specify +// scheduling.automaticRestart = false to include instances only if they +// are not scheduled for automatic restarts. You can use filtering on +// nested fields to filter based on resource labels. +// +// To filter on multiple expressions, provide each separate expression +// within parentheses. For example, (scheduling.automaticRestart = true) +// (cpuPlatform = "Intel Skylake"). By default, each expression is an +// AND expression. However, you can include AND and OR expressions +// explicitly. For example, (cpuPlatform = "Intel Skylake") OR +// (cpuPlatform = "Intel Broadwell") AND (scheduling.automaticRestart = +// true). +func (c *NodeGroupsAggregatedListCall) Filter(filter string) *NodeGroupsAggregatedListCall { + c.urlParams_.Set("filter", filter) + return c +} + +// MaxResults sets the optional parameter "maxResults": The maximum +// number of results per page that should be returned. If the number of +// available results is larger than maxResults, Compute Engine returns a +// nextPageToken that can be used to get the next page of results in +// subsequent list requests. Acceptable values are 0 to 500, inclusive. +// (Default: 500) +func (c *NodeGroupsAggregatedListCall) MaxResults(maxResults int64) *NodeGroupsAggregatedListCall { + c.urlParams_.Set("maxResults", fmt.Sprint(maxResults)) + return c +} + +// OrderBy sets the optional parameter "orderBy": Sorts list results by +// a certain order. By default, results are returned in alphanumerical +// order based on the resource name. +// +// You can also sort results in descending order based on the creation +// timestamp using orderBy="creationTimestamp desc". This sorts results +// based on the creationTimestamp field in reverse chronological order +// (newest result first). Use this to sort resources like operations so +// that the newest operation is returned first. +// +// Currently, only sorting by name or creationTimestamp desc is +// supported. +func (c *NodeGroupsAggregatedListCall) OrderBy(orderBy string) *NodeGroupsAggregatedListCall { + c.urlParams_.Set("orderBy", orderBy) + return c +} + +// PageToken sets the optional parameter "pageToken": Specifies a page +// token to use. Set pageToken to the nextPageToken returned by a +// previous list request to get the next page of results. +func (c *NodeGroupsAggregatedListCall) PageToken(pageToken string) *NodeGroupsAggregatedListCall { + c.urlParams_.Set("pageToken", pageToken) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *NodeGroupsAggregatedListCall) Fields(s ...googleapi.Field) *NodeGroupsAggregatedListCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// IfNoneMatch sets the optional parameter which makes the operation +// fail if the object's ETag matches the given value. This is useful for +// getting updates only after the object has changed since the last +// request. Use googleapi.IsNotModified to check whether the response +// error from Do is the result of In-None-Match. +func (c *NodeGroupsAggregatedListCall) IfNoneMatch(entityTag string) *NodeGroupsAggregatedListCall { + c.ifNoneMatch_ = entityTag + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *NodeGroupsAggregatedListCall) Context(ctx context.Context) *NodeGroupsAggregatedListCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *NodeGroupsAggregatedListCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *NodeGroupsAggregatedListCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + if c.ifNoneMatch_ != "" { + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) + } + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/aggregated/nodeGroups") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.nodeGroups.aggregatedList" call. +// Exactly one of *NodeGroupAggregatedList or error will be non-nil. Any +// non-2xx status code is an error. Response headers are in either +// *NodeGroupAggregatedList.ServerResponse.Header or (if a response was +// returned at all) in error.(*googleapi.Error).Header. Use +// googleapi.IsNotModified to check whether the returned error was +// because http.StatusNotModified was returned. +func (c *NodeGroupsAggregatedListCall) Do(opts ...googleapi.CallOption) (*NodeGroupAggregatedList, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &NodeGroupAggregatedList{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Retrieves an aggregated list of node groups. Note: use nodeGroups.listNodes for more details about each group.", + // "httpMethod": "GET", + // "id": "compute.nodeGroups.aggregatedList", + // "parameterOrder": [ + // "project" + // ], + // "parameters": { + // "filter": { + // "description": "A filter expression that filters resources listed in the response. The expression must specify the field name, a comparison operator, and the value that you want to use for filtering. The value must be a string, a number, or a boolean. The comparison operator must be either =, !=, \u003e, or \u003c.\n\nFor example, if you are filtering Compute Engine instances, you can exclude instances named example-instance by specifying name != example-instance.\n\nYou can also filter nested fields. For example, you could specify scheduling.automaticRestart = false to include instances only if they are not scheduled for automatic restarts. You can use filtering on nested fields to filter based on resource labels.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart = true) (cpuPlatform = \"Intel Skylake\"). By default, each expression is an AND expression. However, you can include AND and OR expressions explicitly. For example, (cpuPlatform = \"Intel Skylake\") OR (cpuPlatform = \"Intel Broadwell\") AND (scheduling.automaticRestart = true).", + // "location": "query", + // "type": "string" + // }, + // "maxResults": { + // "default": "500", + // "description": "The maximum number of results per page that should be returned. If the number of available results is larger than maxResults, Compute Engine returns a nextPageToken that can be used to get the next page of results in subsequent list requests. Acceptable values are 0 to 500, inclusive. (Default: 500)", + // "format": "uint32", + // "location": "query", + // "minimum": "0", + // "type": "integer" + // }, + // "orderBy": { + // "description": "Sorts list results by a certain order. By default, results are returned in alphanumerical order based on the resource name.\n\nYou can also sort results in descending order based on the creation timestamp using orderBy=\"creationTimestamp desc\". This sorts results based on the creationTimestamp field in reverse chronological order (newest result first). Use this to sort resources like operations so that the newest operation is returned first.\n\nCurrently, only sorting by name or creationTimestamp desc is supported.", + // "location": "query", + // "type": "string" + // }, + // "pageToken": { + // "description": "Specifies a page token to use. Set pageToken to the nextPageToken returned by a previous list request to get the next page of results.", + // "location": "query", + // "type": "string" + // }, + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/aggregated/nodeGroups", + // "response": { + // "$ref": "NodeGroupAggregatedList" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute", + // "https://www.googleapis.com/auth/compute.readonly" + // ] + // } + +} + +// Pages invokes f for each page of results. +// A non-nil error returned from f will halt the iteration. +// The provided context supersedes any context provided to the Context method. +func (c *NodeGroupsAggregatedListCall) Pages(ctx context.Context, f func(*NodeGroupAggregatedList) error) error { + c.ctx_ = ctx + defer c.PageToken(c.urlParams_.Get("pageToken")) // reset paging to original point + for { + x, err := c.Do() + if err != nil { + return err + } + if err := f(x); err != nil { + return err + } + if x.NextPageToken == "" { + return nil + } + c.PageToken(x.NextPageToken) + } +} + +// method id "compute.nodeGroups.delete": + +type NodeGroupsDeleteCall struct { + s *Service + project string + zone string + nodeGroup string + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// Delete: Deletes the specified NodeGroup resource. +func (r *NodeGroupsService) Delete(project string, zone string, nodeGroup string) *NodeGroupsDeleteCall { + c := &NodeGroupsDeleteCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.zone = zone + c.nodeGroup = nodeGroup + return c +} + +// RequestId sets the optional parameter "requestId": An optional +// request ID to identify requests. Specify a unique request ID so that +// if you must retry your request, the server will know to ignore the +// request if it has already been completed. +// +// For example, consider a situation where you make an initial request +// and the request times out. If you make the request again with the +// same request ID, the server can check if original operation with the +// same request ID was received, and if so, will ignore the second +// request. This prevents clients from accidentally creating duplicate +// commitments. +// +// The request ID must be a valid UUID with the exception that zero UUID +// is not supported (00000000-0000-0000-0000-000000000000). +func (c *NodeGroupsDeleteCall) RequestId(requestId string) *NodeGroupsDeleteCall { + c.urlParams_.Set("requestId", requestId) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *NodeGroupsDeleteCall) Fields(s ...googleapi.Field) *NodeGroupsDeleteCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *NodeGroupsDeleteCall) Context(ctx context.Context) *NodeGroupsDeleteCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *NodeGroupsDeleteCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *NodeGroupsDeleteCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/nodeGroups/{nodeGroup}") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "zone": c.zone, + "nodeGroup": c.nodeGroup, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.nodeGroups.delete" call. +// Exactly one of *Operation or error will be non-nil. Any non-2xx +// status code is an error. Response headers are in either +// *Operation.ServerResponse.Header or (if a response was returned at +// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified +// to check whether the returned error was because +// http.StatusNotModified was returned. +func (c *NodeGroupsDeleteCall) Do(opts ...googleapi.CallOption) (*Operation, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Operation{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Deletes the specified NodeGroup resource.", + // "httpMethod": "DELETE", + // "id": "compute.nodeGroups.delete", + // "parameterOrder": [ + // "project", + // "zone", + // "nodeGroup" + // ], + // "parameters": { + // "nodeGroup": { + // "description": "Name of the NodeGroup resource to delete.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // }, + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "requestId": { + // "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", + // "location": "query", + // "type": "string" + // }, + // "zone": { + // "description": "The name of the zone for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/zones/{zone}/nodeGroups/{nodeGroup}", + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + +// method id "compute.nodeGroups.deleteNodes": + +type NodeGroupsDeleteNodesCall struct { + s *Service + project string + zone string + nodeGroup string + nodegroupsdeletenodesrequest *NodeGroupsDeleteNodesRequest + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// DeleteNodes: Deletes specified nodes from the node group. +func (r *NodeGroupsService) DeleteNodes(project string, zone string, nodeGroup string, nodegroupsdeletenodesrequest *NodeGroupsDeleteNodesRequest) *NodeGroupsDeleteNodesCall { + c := &NodeGroupsDeleteNodesCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.zone = zone + c.nodeGroup = nodeGroup + c.nodegroupsdeletenodesrequest = nodegroupsdeletenodesrequest + return c +} + +// RequestId sets the optional parameter "requestId": An optional +// request ID to identify requests. Specify a unique request ID so that +// if you must retry your request, the server will know to ignore the +// request if it has already been completed. +// +// For example, consider a situation where you make an initial request +// and the request times out. If you make the request again with the +// same request ID, the server can check if original operation with the +// same request ID was received, and if so, will ignore the second +// request. This prevents clients from accidentally creating duplicate +// commitments. +// +// The request ID must be a valid UUID with the exception that zero UUID +// is not supported (00000000-0000-0000-0000-000000000000). +func (c *NodeGroupsDeleteNodesCall) RequestId(requestId string) *NodeGroupsDeleteNodesCall { + c.urlParams_.Set("requestId", requestId) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *NodeGroupsDeleteNodesCall) Fields(s ...googleapi.Field) *NodeGroupsDeleteNodesCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *NodeGroupsDeleteNodesCall) Context(ctx context.Context) *NodeGroupsDeleteNodesCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *NodeGroupsDeleteNodesCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *NodeGroupsDeleteNodesCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.nodegroupsdeletenodesrequest) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/nodeGroups/{nodeGroup}/deleteNodes") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "zone": c.zone, + "nodeGroup": c.nodeGroup, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.nodeGroups.deleteNodes" call. +// Exactly one of *Operation or error will be non-nil. Any non-2xx +// status code is an error. Response headers are in either +// *Operation.ServerResponse.Header or (if a response was returned at +// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified +// to check whether the returned error was because +// http.StatusNotModified was returned. +func (c *NodeGroupsDeleteNodesCall) Do(opts ...googleapi.CallOption) (*Operation, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Operation{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Deletes specified nodes from the node group.", + // "httpMethod": "POST", + // "id": "compute.nodeGroups.deleteNodes", + // "parameterOrder": [ + // "project", + // "zone", + // "nodeGroup" + // ], + // "parameters": { + // "nodeGroup": { + // "description": "Name of the NodeGroup resource to delete.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // }, + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "requestId": { + // "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", + // "location": "query", + // "type": "string" + // }, + // "zone": { + // "description": "The name of the zone for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/zones/{zone}/nodeGroups/{nodeGroup}/deleteNodes", + // "request": { + // "$ref": "NodeGroupsDeleteNodesRequest" + // }, + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + +// method id "compute.nodeGroups.get": + +type NodeGroupsGetCall struct { + s *Service + project string + zone string + nodeGroup string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// Get: Returns the specified NodeGroup. Get a list of available +// NodeGroups by making a list() request. Note: the "nodes" field should +// not be used. Use nodeGroups.listNodes instead. +func (r *NodeGroupsService) Get(project string, zone string, nodeGroup string) *NodeGroupsGetCall { + c := &NodeGroupsGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.zone = zone + c.nodeGroup = nodeGroup + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *NodeGroupsGetCall) Fields(s ...googleapi.Field) *NodeGroupsGetCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// IfNoneMatch sets the optional parameter which makes the operation +// fail if the object's ETag matches the given value. This is useful for +// getting updates only after the object has changed since the last +// request. Use googleapi.IsNotModified to check whether the response +// error from Do is the result of In-None-Match. +func (c *NodeGroupsGetCall) IfNoneMatch(entityTag string) *NodeGroupsGetCall { + c.ifNoneMatch_ = entityTag + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *NodeGroupsGetCall) Context(ctx context.Context) *NodeGroupsGetCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *NodeGroupsGetCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *NodeGroupsGetCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + if c.ifNoneMatch_ != "" { + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) + } + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/nodeGroups/{nodeGroup}") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "zone": c.zone, + "nodeGroup": c.nodeGroup, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.nodeGroups.get" call. +// Exactly one of *NodeGroup or error will be non-nil. Any non-2xx +// status code is an error. Response headers are in either +// *NodeGroup.ServerResponse.Header or (if a response was returned at +// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified +// to check whether the returned error was because +// http.StatusNotModified was returned. +func (c *NodeGroupsGetCall) Do(opts ...googleapi.CallOption) (*NodeGroup, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &NodeGroup{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Returns the specified NodeGroup. Get a list of available NodeGroups by making a list() request. Note: the \"nodes\" field should not be used. Use nodeGroups.listNodes instead.", + // "httpMethod": "GET", + // "id": "compute.nodeGroups.get", + // "parameterOrder": [ + // "project", + // "zone", + // "nodeGroup" + // ], + // "parameters": { + // "nodeGroup": { + // "description": "Name of the node group to return.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // }, + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "zone": { + // "description": "The name of the zone for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/zones/{zone}/nodeGroups/{nodeGroup}", + // "response": { + // "$ref": "NodeGroup" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute", + // "https://www.googleapis.com/auth/compute.readonly" + // ] + // } + +} + +// method id "compute.nodeGroups.getIamPolicy": + +type NodeGroupsGetIamPolicyCall struct { + s *Service + project string + zone string + resource string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// GetIamPolicy: Gets the access control policy for a resource. May be +// empty if no such policy or resource exists. +func (r *NodeGroupsService) GetIamPolicy(project string, zone string, resource string) *NodeGroupsGetIamPolicyCall { + c := &NodeGroupsGetIamPolicyCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.zone = zone + c.resource = resource + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *NodeGroupsGetIamPolicyCall) Fields(s ...googleapi.Field) *NodeGroupsGetIamPolicyCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// IfNoneMatch sets the optional parameter which makes the operation +// fail if the object's ETag matches the given value. This is useful for +// getting updates only after the object has changed since the last +// request. Use googleapi.IsNotModified to check whether the response +// error from Do is the result of In-None-Match. +func (c *NodeGroupsGetIamPolicyCall) IfNoneMatch(entityTag string) *NodeGroupsGetIamPolicyCall { + c.ifNoneMatch_ = entityTag + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *NodeGroupsGetIamPolicyCall) Context(ctx context.Context) *NodeGroupsGetIamPolicyCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *NodeGroupsGetIamPolicyCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *NodeGroupsGetIamPolicyCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + if c.ifNoneMatch_ != "" { + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) + } + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/nodeGroups/{resource}/getIamPolicy") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "zone": c.zone, + "resource": c.resource, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.nodeGroups.getIamPolicy" call. +// Exactly one of *Policy or error will be non-nil. Any non-2xx status +// code is an error. Response headers are in either +// *Policy.ServerResponse.Header or (if a response was returned at all) +// in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to +// check whether the returned error was because http.StatusNotModified +// was returned. +func (c *NodeGroupsGetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Policy, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Policy{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Gets the access control policy for a resource. May be empty if no such policy or resource exists.", + // "httpMethod": "GET", + // "id": "compute.nodeGroups.getIamPolicy", + // "parameterOrder": [ + // "project", + // "zone", + // "resource" + // ], + // "parameters": { + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "resource": { + // "description": "Name or id of the resource for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + // "required": true, + // "type": "string" + // }, + // "zone": { + // "description": "The name of the zone for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/zones/{zone}/nodeGroups/{resource}/getIamPolicy", + // "response": { + // "$ref": "Policy" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute", + // "https://www.googleapis.com/auth/compute.readonly" + // ] + // } + +} + +// method id "compute.nodeGroups.insert": + +type NodeGroupsInsertCall struct { + s *Service + project string + zone string + nodegroup *NodeGroup + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// Insert: Creates a NodeGroup resource in the specified project using +// the data included in the request. +func (r *NodeGroupsService) Insert(project string, zone string, initialNodeCount int64, nodegroup *NodeGroup) *NodeGroupsInsertCall { + c := &NodeGroupsInsertCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.zone = zone + c.urlParams_.Set("initialNodeCount", fmt.Sprint(initialNodeCount)) + c.nodegroup = nodegroup + return c +} + +// RequestId sets the optional parameter "requestId": An optional +// request ID to identify requests. Specify a unique request ID so that +// if you must retry your request, the server will know to ignore the +// request if it has already been completed. +// +// For example, consider a situation where you make an initial request +// and the request times out. If you make the request again with the +// same request ID, the server can check if original operation with the +// same request ID was received, and if so, will ignore the second +// request. This prevents clients from accidentally creating duplicate +// commitments. +// +// The request ID must be a valid UUID with the exception that zero UUID +// is not supported (00000000-0000-0000-0000-000000000000). +func (c *NodeGroupsInsertCall) RequestId(requestId string) *NodeGroupsInsertCall { + c.urlParams_.Set("requestId", requestId) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *NodeGroupsInsertCall) Fields(s ...googleapi.Field) *NodeGroupsInsertCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *NodeGroupsInsertCall) Context(ctx context.Context) *NodeGroupsInsertCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *NodeGroupsInsertCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *NodeGroupsInsertCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.nodegroup) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/nodeGroups") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "zone": c.zone, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.nodeGroups.insert" call. +// Exactly one of *Operation or error will be non-nil. Any non-2xx +// status code is an error. Response headers are in either +// *Operation.ServerResponse.Header or (if a response was returned at +// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified +// to check whether the returned error was because +// http.StatusNotModified was returned. +func (c *NodeGroupsInsertCall) Do(opts ...googleapi.CallOption) (*Operation, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Operation{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Creates a NodeGroup resource in the specified project using the data included in the request.", + // "httpMethod": "POST", + // "id": "compute.nodeGroups.insert", + // "parameterOrder": [ + // "project", + // "zone", + // "initialNodeCount" + // ], + // "parameters": { + // "initialNodeCount": { + // "description": "Initial count of nodes in the node group.", + // "format": "int32", + // "location": "query", + // "required": true, + // "type": "integer" + // }, + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "requestId": { + // "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", + // "location": "query", + // "type": "string" + // }, + // "zone": { + // "description": "The name of the zone for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/zones/{zone}/nodeGroups", + // "request": { + // "$ref": "NodeGroup" + // }, + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + +// method id "compute.nodeGroups.list": + +type NodeGroupsListCall struct { + s *Service + project string + zone string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// List: Retrieves a list of node groups available to the specified +// project. Note: use nodeGroups.listNodes for more details about each +// group. +func (r *NodeGroupsService) List(project string, zone string) *NodeGroupsListCall { + c := &NodeGroupsListCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.zone = zone + return c +} + +// Filter sets the optional parameter "filter": A filter expression that +// filters resources listed in the response. The expression must specify +// the field name, a comparison operator, and the value that you want to +// use for filtering. The value must be a string, a number, or a +// boolean. The comparison operator must be either =, !=, >, or <. +// +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. +// +// You can also filter nested fields. For example, you could specify +// scheduling.automaticRestart = false to include instances only if they +// are not scheduled for automatic restarts. You can use filtering on +// nested fields to filter based on resource labels. +// +// To filter on multiple expressions, provide each separate expression +// within parentheses. For example, (scheduling.automaticRestart = true) +// (cpuPlatform = "Intel Skylake"). By default, each expression is an +// AND expression. However, you can include AND and OR expressions +// explicitly. For example, (cpuPlatform = "Intel Skylake") OR +// (cpuPlatform = "Intel Broadwell") AND (scheduling.automaticRestart = +// true). +func (c *NodeGroupsListCall) Filter(filter string) *NodeGroupsListCall { + c.urlParams_.Set("filter", filter) + return c +} + +// MaxResults sets the optional parameter "maxResults": The maximum +// number of results per page that should be returned. If the number of +// available results is larger than maxResults, Compute Engine returns a +// nextPageToken that can be used to get the next page of results in +// subsequent list requests. Acceptable values are 0 to 500, inclusive. +// (Default: 500) +func (c *NodeGroupsListCall) MaxResults(maxResults int64) *NodeGroupsListCall { + c.urlParams_.Set("maxResults", fmt.Sprint(maxResults)) + return c +} + +// OrderBy sets the optional parameter "orderBy": Sorts list results by +// a certain order. By default, results are returned in alphanumerical +// order based on the resource name. +// +// You can also sort results in descending order based on the creation +// timestamp using orderBy="creationTimestamp desc". This sorts results +// based on the creationTimestamp field in reverse chronological order +// (newest result first). Use this to sort resources like operations so +// that the newest operation is returned first. +// +// Currently, only sorting by name or creationTimestamp desc is +// supported. +func (c *NodeGroupsListCall) OrderBy(orderBy string) *NodeGroupsListCall { + c.urlParams_.Set("orderBy", orderBy) + return c +} + +// PageToken sets the optional parameter "pageToken": Specifies a page +// token to use. Set pageToken to the nextPageToken returned by a +// previous list request to get the next page of results. +func (c *NodeGroupsListCall) PageToken(pageToken string) *NodeGroupsListCall { + c.urlParams_.Set("pageToken", pageToken) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *NodeGroupsListCall) Fields(s ...googleapi.Field) *NodeGroupsListCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// IfNoneMatch sets the optional parameter which makes the operation +// fail if the object's ETag matches the given value. This is useful for +// getting updates only after the object has changed since the last +// request. Use googleapi.IsNotModified to check whether the response +// error from Do is the result of In-None-Match. +func (c *NodeGroupsListCall) IfNoneMatch(entityTag string) *NodeGroupsListCall { + c.ifNoneMatch_ = entityTag + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *NodeGroupsListCall) Context(ctx context.Context) *NodeGroupsListCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *NodeGroupsListCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *NodeGroupsListCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + if c.ifNoneMatch_ != "" { + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) + } + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/nodeGroups") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "zone": c.zone, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.nodeGroups.list" call. +// Exactly one of *NodeGroupList or error will be non-nil. Any non-2xx +// status code is an error. Response headers are in either +// *NodeGroupList.ServerResponse.Header or (if a response was returned +// at all) in error.(*googleapi.Error).Header. Use +// googleapi.IsNotModified to check whether the returned error was +// because http.StatusNotModified was returned. +func (c *NodeGroupsListCall) Do(opts ...googleapi.CallOption) (*NodeGroupList, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &NodeGroupList{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Retrieves a list of node groups available to the specified project. Note: use nodeGroups.listNodes for more details about each group.", + // "httpMethod": "GET", + // "id": "compute.nodeGroups.list", + // "parameterOrder": [ + // "project", + // "zone" + // ], + // "parameters": { + // "filter": { + // "description": "A filter expression that filters resources listed in the response. The expression must specify the field name, a comparison operator, and the value that you want to use for filtering. The value must be a string, a number, or a boolean. The comparison operator must be either =, !=, \u003e, or \u003c.\n\nFor example, if you are filtering Compute Engine instances, you can exclude instances named example-instance by specifying name != example-instance.\n\nYou can also filter nested fields. For example, you could specify scheduling.automaticRestart = false to include instances only if they are not scheduled for automatic restarts. You can use filtering on nested fields to filter based on resource labels.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart = true) (cpuPlatform = \"Intel Skylake\"). By default, each expression is an AND expression. However, you can include AND and OR expressions explicitly. For example, (cpuPlatform = \"Intel Skylake\") OR (cpuPlatform = \"Intel Broadwell\") AND (scheduling.automaticRestart = true).", + // "location": "query", + // "type": "string" + // }, + // "maxResults": { + // "default": "500", + // "description": "The maximum number of results per page that should be returned. If the number of available results is larger than maxResults, Compute Engine returns a nextPageToken that can be used to get the next page of results in subsequent list requests. Acceptable values are 0 to 500, inclusive. (Default: 500)", + // "format": "uint32", + // "location": "query", + // "minimum": "0", + // "type": "integer" + // }, + // "orderBy": { + // "description": "Sorts list results by a certain order. By default, results are returned in alphanumerical order based on the resource name.\n\nYou can also sort results in descending order based on the creation timestamp using orderBy=\"creationTimestamp desc\". This sorts results based on the creationTimestamp field in reverse chronological order (newest result first). Use this to sort resources like operations so that the newest operation is returned first.\n\nCurrently, only sorting by name or creationTimestamp desc is supported.", + // "location": "query", + // "type": "string" + // }, + // "pageToken": { + // "description": "Specifies a page token to use. Set pageToken to the nextPageToken returned by a previous list request to get the next page of results.", + // "location": "query", + // "type": "string" + // }, + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "zone": { + // "description": "The name of the zone for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/zones/{zone}/nodeGroups", + // "response": { + // "$ref": "NodeGroupList" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute", + // "https://www.googleapis.com/auth/compute.readonly" + // ] + // } + +} + +// Pages invokes f for each page of results. +// A non-nil error returned from f will halt the iteration. +// The provided context supersedes any context provided to the Context method. +func (c *NodeGroupsListCall) Pages(ctx context.Context, f func(*NodeGroupList) error) error { + c.ctx_ = ctx + defer c.PageToken(c.urlParams_.Get("pageToken")) // reset paging to original point + for { + x, err := c.Do() + if err != nil { + return err + } + if err := f(x); err != nil { + return err + } + if x.NextPageToken == "" { + return nil + } + c.PageToken(x.NextPageToken) + } +} + +// method id "compute.nodeGroups.listNodes": + +type NodeGroupsListNodesCall struct { + s *Service + project string + zone string + nodeGroup string + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// ListNodes: Lists nodes in the node group. +func (r *NodeGroupsService) ListNodes(project string, zone string, nodeGroup string) *NodeGroupsListNodesCall { + c := &NodeGroupsListNodesCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.zone = zone + c.nodeGroup = nodeGroup + return c +} + +// Filter sets the optional parameter "filter": A filter expression that +// filters resources listed in the response. The expression must specify +// the field name, a comparison operator, and the value that you want to +// use for filtering. The value must be a string, a number, or a +// boolean. The comparison operator must be either =, !=, >, or <. +// +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. +// +// You can also filter nested fields. For example, you could specify +// scheduling.automaticRestart = false to include instances only if they +// are not scheduled for automatic restarts. You can use filtering on +// nested fields to filter based on resource labels. +// +// To filter on multiple expressions, provide each separate expression +// within parentheses. For example, (scheduling.automaticRestart = true) +// (cpuPlatform = "Intel Skylake"). By default, each expression is an +// AND expression. However, you can include AND and OR expressions +// explicitly. For example, (cpuPlatform = "Intel Skylake") OR +// (cpuPlatform = "Intel Broadwell") AND (scheduling.automaticRestart = +// true). +func (c *NodeGroupsListNodesCall) Filter(filter string) *NodeGroupsListNodesCall { + c.urlParams_.Set("filter", filter) + return c +} + +// MaxResults sets the optional parameter "maxResults": The maximum +// number of results per page that should be returned. If the number of +// available results is larger than maxResults, Compute Engine returns a +// nextPageToken that can be used to get the next page of results in +// subsequent list requests. Acceptable values are 0 to 500, inclusive. +// (Default: 500) +func (c *NodeGroupsListNodesCall) MaxResults(maxResults int64) *NodeGroupsListNodesCall { + c.urlParams_.Set("maxResults", fmt.Sprint(maxResults)) + return c +} + +// OrderBy sets the optional parameter "orderBy": Sorts list results by +// a certain order. By default, results are returned in alphanumerical +// order based on the resource name. +// +// You can also sort results in descending order based on the creation +// timestamp using orderBy="creationTimestamp desc". This sorts results +// based on the creationTimestamp field in reverse chronological order +// (newest result first). Use this to sort resources like operations so +// that the newest operation is returned first. +// +// Currently, only sorting by name or creationTimestamp desc is +// supported. +func (c *NodeGroupsListNodesCall) OrderBy(orderBy string) *NodeGroupsListNodesCall { + c.urlParams_.Set("orderBy", orderBy) + return c +} + +// PageToken sets the optional parameter "pageToken": Specifies a page +// token to use. Set pageToken to the nextPageToken returned by a +// previous list request to get the next page of results. +func (c *NodeGroupsListNodesCall) PageToken(pageToken string) *NodeGroupsListNodesCall { + c.urlParams_.Set("pageToken", pageToken) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *NodeGroupsListNodesCall) Fields(s ...googleapi.Field) *NodeGroupsListNodesCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *NodeGroupsListNodesCall) Context(ctx context.Context) *NodeGroupsListNodesCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *NodeGroupsListNodesCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *NodeGroupsListNodesCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/nodeGroups/{nodeGroup}/listNodes") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "zone": c.zone, + "nodeGroup": c.nodeGroup, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.nodeGroups.listNodes" call. +// Exactly one of *NodeGroupsListNodes or error will be non-nil. Any +// non-2xx status code is an error. Response headers are in either +// *NodeGroupsListNodes.ServerResponse.Header or (if a response was +// returned at all) in error.(*googleapi.Error).Header. Use +// googleapi.IsNotModified to check whether the returned error was +// because http.StatusNotModified was returned. +func (c *NodeGroupsListNodesCall) Do(opts ...googleapi.CallOption) (*NodeGroupsListNodes, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &NodeGroupsListNodes{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Lists nodes in the node group.", + // "httpMethod": "POST", + // "id": "compute.nodeGroups.listNodes", + // "parameterOrder": [ + // "project", + // "zone", + // "nodeGroup" + // ], + // "parameters": { + // "filter": { + // "description": "A filter expression that filters resources listed in the response. The expression must specify the field name, a comparison operator, and the value that you want to use for filtering. The value must be a string, a number, or a boolean. The comparison operator must be either =, !=, \u003e, or \u003c.\n\nFor example, if you are filtering Compute Engine instances, you can exclude instances named example-instance by specifying name != example-instance.\n\nYou can also filter nested fields. For example, you could specify scheduling.automaticRestart = false to include instances only if they are not scheduled for automatic restarts. You can use filtering on nested fields to filter based on resource labels.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart = true) (cpuPlatform = \"Intel Skylake\"). By default, each expression is an AND expression. However, you can include AND and OR expressions explicitly. For example, (cpuPlatform = \"Intel Skylake\") OR (cpuPlatform = \"Intel Broadwell\") AND (scheduling.automaticRestart = true).", + // "location": "query", + // "type": "string" + // }, + // "maxResults": { + // "default": "500", + // "description": "The maximum number of results per page that should be returned. If the number of available results is larger than maxResults, Compute Engine returns a nextPageToken that can be used to get the next page of results in subsequent list requests. Acceptable values are 0 to 500, inclusive. (Default: 500)", + // "format": "uint32", + // "location": "query", + // "minimum": "0", + // "type": "integer" + // }, + // "nodeGroup": { + // "description": "Name of the NodeGroup resource whose nodes you want to list.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // }, + // "orderBy": { + // "description": "Sorts list results by a certain order. By default, results are returned in alphanumerical order based on the resource name.\n\nYou can also sort results in descending order based on the creation timestamp using orderBy=\"creationTimestamp desc\". This sorts results based on the creationTimestamp field in reverse chronological order (newest result first). Use this to sort resources like operations so that the newest operation is returned first.\n\nCurrently, only sorting by name or creationTimestamp desc is supported.", + // "location": "query", + // "type": "string" + // }, + // "pageToken": { + // "description": "Specifies a page token to use. Set pageToken to the nextPageToken returned by a previous list request to get the next page of results.", + // "location": "query", + // "type": "string" + // }, + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "zone": { + // "description": "The name of the zone for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/zones/{zone}/nodeGroups/{nodeGroup}/listNodes", + // "response": { + // "$ref": "NodeGroupsListNodes" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute", + // "https://www.googleapis.com/auth/compute.readonly" + // ] + // } + +} + +// Pages invokes f for each page of results. +// A non-nil error returned from f will halt the iteration. +// The provided context supersedes any context provided to the Context method. +func (c *NodeGroupsListNodesCall) Pages(ctx context.Context, f func(*NodeGroupsListNodes) error) error { + c.ctx_ = ctx + defer c.PageToken(c.urlParams_.Get("pageToken")) // reset paging to original point + for { + x, err := c.Do() + if err != nil { + return err + } + if err := f(x); err != nil { + return err + } + if x.NextPageToken == "" { + return nil + } + c.PageToken(x.NextPageToken) + } +} + +// method id "compute.nodeGroups.setIamPolicy": + +type NodeGroupsSetIamPolicyCall struct { + s *Service + project string + zone string + resource string + zonesetpolicyrequest *ZoneSetPolicyRequest + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// SetIamPolicy: Sets the access control policy on the specified +// resource. Replaces any existing policy. +func (r *NodeGroupsService) SetIamPolicy(project string, zone string, resource string, zonesetpolicyrequest *ZoneSetPolicyRequest) *NodeGroupsSetIamPolicyCall { + c := &NodeGroupsSetIamPolicyCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.zone = zone + c.resource = resource + c.zonesetpolicyrequest = zonesetpolicyrequest + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *NodeGroupsSetIamPolicyCall) Fields(s ...googleapi.Field) *NodeGroupsSetIamPolicyCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *NodeGroupsSetIamPolicyCall) Context(ctx context.Context) *NodeGroupsSetIamPolicyCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *NodeGroupsSetIamPolicyCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *NodeGroupsSetIamPolicyCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.zonesetpolicyrequest) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/nodeGroups/{resource}/setIamPolicy") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "zone": c.zone, + "resource": c.resource, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.nodeGroups.setIamPolicy" call. +// Exactly one of *Policy or error will be non-nil. Any non-2xx status +// code is an error. Response headers are in either +// *Policy.ServerResponse.Header or (if a response was returned at all) +// in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to +// check whether the returned error was because http.StatusNotModified +// was returned. +func (c *NodeGroupsSetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Policy, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Policy{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Sets the access control policy on the specified resource. Replaces any existing policy.", + // "httpMethod": "POST", + // "id": "compute.nodeGroups.setIamPolicy", + // "parameterOrder": [ + // "project", + // "zone", + // "resource" + // ], + // "parameters": { + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "resource": { + // "description": "Name or id of the resource for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + // "required": true, + // "type": "string" + // }, + // "zone": { + // "description": "The name of the zone for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/zones/{zone}/nodeGroups/{resource}/setIamPolicy", + // "request": { + // "$ref": "ZoneSetPolicyRequest" + // }, + // "response": { + // "$ref": "Policy" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + +// method id "compute.nodeGroups.setNodeTemplate": + +type NodeGroupsSetNodeTemplateCall struct { + s *Service + project string + zone string + nodeGroup string + nodegroupssetnodetemplaterequest *NodeGroupsSetNodeTemplateRequest + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// SetNodeTemplate: Updates the node template of the node group. +func (r *NodeGroupsService) SetNodeTemplate(project string, zone string, nodeGroup string, nodegroupssetnodetemplaterequest *NodeGroupsSetNodeTemplateRequest) *NodeGroupsSetNodeTemplateCall { + c := &NodeGroupsSetNodeTemplateCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.zone = zone + c.nodeGroup = nodeGroup + c.nodegroupssetnodetemplaterequest = nodegroupssetnodetemplaterequest + return c +} + +// RequestId sets the optional parameter "requestId": An optional +// request ID to identify requests. Specify a unique request ID so that +// if you must retry your request, the server will know to ignore the +// request if it has already been completed. +// +// For example, consider a situation where you make an initial request +// and the request times out. If you make the request again with the +// same request ID, the server can check if original operation with the +// same request ID was received, and if so, will ignore the second +// request. This prevents clients from accidentally creating duplicate +// commitments. +// +// The request ID must be a valid UUID with the exception that zero UUID +// is not supported (00000000-0000-0000-0000-000000000000). +func (c *NodeGroupsSetNodeTemplateCall) RequestId(requestId string) *NodeGroupsSetNodeTemplateCall { + c.urlParams_.Set("requestId", requestId) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *NodeGroupsSetNodeTemplateCall) Fields(s ...googleapi.Field) *NodeGroupsSetNodeTemplateCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *NodeGroupsSetNodeTemplateCall) Context(ctx context.Context) *NodeGroupsSetNodeTemplateCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *NodeGroupsSetNodeTemplateCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *NodeGroupsSetNodeTemplateCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.nodegroupssetnodetemplaterequest) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/nodeGroups/{nodeGroup}/setNodeTemplate") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "zone": c.zone, + "nodeGroup": c.nodeGroup, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.nodeGroups.setNodeTemplate" call. +// Exactly one of *Operation or error will be non-nil. Any non-2xx +// status code is an error. Response headers are in either +// *Operation.ServerResponse.Header or (if a response was returned at +// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified +// to check whether the returned error was because +// http.StatusNotModified was returned. +func (c *NodeGroupsSetNodeTemplateCall) Do(opts ...googleapi.CallOption) (*Operation, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Operation{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Updates the node template of the node group.", + // "httpMethod": "POST", + // "id": "compute.nodeGroups.setNodeTemplate", + // "parameterOrder": [ + // "project", + // "zone", + // "nodeGroup" + // ], + // "parameters": { + // "nodeGroup": { + // "description": "Name of the NodeGroup resource to delete.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // }, + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "requestId": { + // "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", + // "location": "query", + // "type": "string" + // }, + // "zone": { + // "description": "The name of the zone for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/zones/{zone}/nodeGroups/{nodeGroup}/setNodeTemplate", + // "request": { + // "$ref": "NodeGroupsSetNodeTemplateRequest" + // }, + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + +// method id "compute.nodeGroups.testIamPermissions": + +type NodeGroupsTestIamPermissionsCall struct { + s *Service + project string + zone string + resource string + testpermissionsrequest *TestPermissionsRequest + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// TestIamPermissions: Returns permissions that a caller has on the +// specified resource. +func (r *NodeGroupsService) TestIamPermissions(project string, zone string, resource string, testpermissionsrequest *TestPermissionsRequest) *NodeGroupsTestIamPermissionsCall { + c := &NodeGroupsTestIamPermissionsCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.zone = zone + c.resource = resource + c.testpermissionsrequest = testpermissionsrequest + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *NodeGroupsTestIamPermissionsCall) Fields(s ...googleapi.Field) *NodeGroupsTestIamPermissionsCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *NodeGroupsTestIamPermissionsCall) Context(ctx context.Context) *NodeGroupsTestIamPermissionsCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *NodeGroupsTestIamPermissionsCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *NodeGroupsTestIamPermissionsCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.testpermissionsrequest) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/nodeGroups/{resource}/testIamPermissions") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "zone": c.zone, + "resource": c.resource, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.nodeGroups.testIamPermissions" call. +// Exactly one of *TestPermissionsResponse or error will be non-nil. Any +// non-2xx status code is an error. Response headers are in either +// *TestPermissionsResponse.ServerResponse.Header or (if a response was +// returned at all) in error.(*googleapi.Error).Header. Use +// googleapi.IsNotModified to check whether the returned error was +// because http.StatusNotModified was returned. +func (c *NodeGroupsTestIamPermissionsCall) Do(opts ...googleapi.CallOption) (*TestPermissionsResponse, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &TestPermissionsResponse{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Returns permissions that a caller has on the specified resource.", + // "httpMethod": "POST", + // "id": "compute.nodeGroups.testIamPermissions", + // "parameterOrder": [ + // "project", + // "zone", + // "resource" + // ], + // "parameters": { + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "resource": { + // "description": "Name or id of the resource for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + // "required": true, + // "type": "string" + // }, + // "zone": { + // "description": "The name of the zone for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/zones/{zone}/nodeGroups/{resource}/testIamPermissions", + // "request": { + // "$ref": "TestPermissionsRequest" + // }, + // "response": { + // "$ref": "TestPermissionsResponse" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute", + // "https://www.googleapis.com/auth/compute.readonly" + // ] + // } + +} + +// method id "compute.nodeTemplates.aggregatedList": + +type NodeTemplatesAggregatedListCall struct { + s *Service + project string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// AggregatedList: Retrieves an aggregated list of node templates. +func (r *NodeTemplatesService) AggregatedList(project string) *NodeTemplatesAggregatedListCall { + c := &NodeTemplatesAggregatedListCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + return c +} + +// Filter sets the optional parameter "filter": A filter expression that +// filters resources listed in the response. The expression must specify +// the field name, a comparison operator, and the value that you want to +// use for filtering. The value must be a string, a number, or a +// boolean. The comparison operator must be either =, !=, >, or <. +// +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. +// +// You can also filter nested fields. For example, you could specify +// scheduling.automaticRestart = false to include instances only if they +// are not scheduled for automatic restarts. You can use filtering on +// nested fields to filter based on resource labels. +// +// To filter on multiple expressions, provide each separate expression +// within parentheses. For example, (scheduling.automaticRestart = true) +// (cpuPlatform = "Intel Skylake"). By default, each expression is an +// AND expression. However, you can include AND and OR expressions +// explicitly. For example, (cpuPlatform = "Intel Skylake") OR +// (cpuPlatform = "Intel Broadwell") AND (scheduling.automaticRestart = +// true). +func (c *NodeTemplatesAggregatedListCall) Filter(filter string) *NodeTemplatesAggregatedListCall { + c.urlParams_.Set("filter", filter) + return c +} + +// MaxResults sets the optional parameter "maxResults": The maximum +// number of results per page that should be returned. If the number of +// available results is larger than maxResults, Compute Engine returns a +// nextPageToken that can be used to get the next page of results in +// subsequent list requests. Acceptable values are 0 to 500, inclusive. +// (Default: 500) +func (c *NodeTemplatesAggregatedListCall) MaxResults(maxResults int64) *NodeTemplatesAggregatedListCall { + c.urlParams_.Set("maxResults", fmt.Sprint(maxResults)) + return c +} + +// OrderBy sets the optional parameter "orderBy": Sorts list results by +// a certain order. By default, results are returned in alphanumerical +// order based on the resource name. +// +// You can also sort results in descending order based on the creation +// timestamp using orderBy="creationTimestamp desc". This sorts results +// based on the creationTimestamp field in reverse chronological order +// (newest result first). Use this to sort resources like operations so +// that the newest operation is returned first. +// +// Currently, only sorting by name or creationTimestamp desc is +// supported. +func (c *NodeTemplatesAggregatedListCall) OrderBy(orderBy string) *NodeTemplatesAggregatedListCall { + c.urlParams_.Set("orderBy", orderBy) + return c +} + +// PageToken sets the optional parameter "pageToken": Specifies a page +// token to use. Set pageToken to the nextPageToken returned by a +// previous list request to get the next page of results. +func (c *NodeTemplatesAggregatedListCall) PageToken(pageToken string) *NodeTemplatesAggregatedListCall { + c.urlParams_.Set("pageToken", pageToken) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *NodeTemplatesAggregatedListCall) Fields(s ...googleapi.Field) *NodeTemplatesAggregatedListCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// IfNoneMatch sets the optional parameter which makes the operation +// fail if the object's ETag matches the given value. This is useful for +// getting updates only after the object has changed since the last +// request. Use googleapi.IsNotModified to check whether the response +// error from Do is the result of In-None-Match. +func (c *NodeTemplatesAggregatedListCall) IfNoneMatch(entityTag string) *NodeTemplatesAggregatedListCall { + c.ifNoneMatch_ = entityTag + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *NodeTemplatesAggregatedListCall) Context(ctx context.Context) *NodeTemplatesAggregatedListCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *NodeTemplatesAggregatedListCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *NodeTemplatesAggregatedListCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + if c.ifNoneMatch_ != "" { + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) + } + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/aggregated/nodeTemplates") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.nodeTemplates.aggregatedList" call. +// Exactly one of *NodeTemplateAggregatedList or error will be non-nil. +// Any non-2xx status code is an error. Response headers are in either +// *NodeTemplateAggregatedList.ServerResponse.Header or (if a response +// was returned at all) in error.(*googleapi.Error).Header. Use +// googleapi.IsNotModified to check whether the returned error was +// because http.StatusNotModified was returned. +func (c *NodeTemplatesAggregatedListCall) Do(opts ...googleapi.CallOption) (*NodeTemplateAggregatedList, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &NodeTemplateAggregatedList{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Retrieves an aggregated list of node templates.", + // "httpMethod": "GET", + // "id": "compute.nodeTemplates.aggregatedList", + // "parameterOrder": [ + // "project" + // ], + // "parameters": { + // "filter": { + // "description": "A filter expression that filters resources listed in the response. The expression must specify the field name, a comparison operator, and the value that you want to use for filtering. The value must be a string, a number, or a boolean. The comparison operator must be either =, !=, \u003e, or \u003c.\n\nFor example, if you are filtering Compute Engine instances, you can exclude instances named example-instance by specifying name != example-instance.\n\nYou can also filter nested fields. For example, you could specify scheduling.automaticRestart = false to include instances only if they are not scheduled for automatic restarts. You can use filtering on nested fields to filter based on resource labels.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart = true) (cpuPlatform = \"Intel Skylake\"). By default, each expression is an AND expression. However, you can include AND and OR expressions explicitly. For example, (cpuPlatform = \"Intel Skylake\") OR (cpuPlatform = \"Intel Broadwell\") AND (scheduling.automaticRestart = true).", + // "location": "query", + // "type": "string" + // }, + // "maxResults": { + // "default": "500", + // "description": "The maximum number of results per page that should be returned. If the number of available results is larger than maxResults, Compute Engine returns a nextPageToken that can be used to get the next page of results in subsequent list requests. Acceptable values are 0 to 500, inclusive. (Default: 500)", + // "format": "uint32", + // "location": "query", + // "minimum": "0", + // "type": "integer" + // }, + // "orderBy": { + // "description": "Sorts list results by a certain order. By default, results are returned in alphanumerical order based on the resource name.\n\nYou can also sort results in descending order based on the creation timestamp using orderBy=\"creationTimestamp desc\". This sorts results based on the creationTimestamp field in reverse chronological order (newest result first). Use this to sort resources like operations so that the newest operation is returned first.\n\nCurrently, only sorting by name or creationTimestamp desc is supported.", + // "location": "query", + // "type": "string" + // }, + // "pageToken": { + // "description": "Specifies a page token to use. Set pageToken to the nextPageToken returned by a previous list request to get the next page of results.", + // "location": "query", + // "type": "string" + // }, + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/aggregated/nodeTemplates", + // "response": { + // "$ref": "NodeTemplateAggregatedList" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute", + // "https://www.googleapis.com/auth/compute.readonly" + // ] + // } + +} + +// Pages invokes f for each page of results. +// A non-nil error returned from f will halt the iteration. +// The provided context supersedes any context provided to the Context method. +func (c *NodeTemplatesAggregatedListCall) Pages(ctx context.Context, f func(*NodeTemplateAggregatedList) error) error { + c.ctx_ = ctx + defer c.PageToken(c.urlParams_.Get("pageToken")) // reset paging to original point + for { + x, err := c.Do() + if err != nil { + return err + } + if err := f(x); err != nil { + return err + } + if x.NextPageToken == "" { + return nil + } + c.PageToken(x.NextPageToken) + } +} + +// method id "compute.nodeTemplates.delete": + +type NodeTemplatesDeleteCall struct { + s *Service + project string + region string + nodeTemplate string + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// Delete: Deletes the specified NodeTemplate resource. +func (r *NodeTemplatesService) Delete(project string, region string, nodeTemplate string) *NodeTemplatesDeleteCall { + c := &NodeTemplatesDeleteCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.region = region + c.nodeTemplate = nodeTemplate + return c +} + +// RequestId sets the optional parameter "requestId": An optional +// request ID to identify requests. Specify a unique request ID so that +// if you must retry your request, the server will know to ignore the +// request if it has already been completed. +// +// For example, consider a situation where you make an initial request +// and the request times out. If you make the request again with the +// same request ID, the server can check if original operation with the +// same request ID was received, and if so, will ignore the second +// request. This prevents clients from accidentally creating duplicate +// commitments. +// +// The request ID must be a valid UUID with the exception that zero UUID +// is not supported (00000000-0000-0000-0000-000000000000). +func (c *NodeTemplatesDeleteCall) RequestId(requestId string) *NodeTemplatesDeleteCall { + c.urlParams_.Set("requestId", requestId) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *NodeTemplatesDeleteCall) Fields(s ...googleapi.Field) *NodeTemplatesDeleteCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *NodeTemplatesDeleteCall) Context(ctx context.Context) *NodeTemplatesDeleteCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *NodeTemplatesDeleteCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *NodeTemplatesDeleteCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/nodeTemplates/{nodeTemplate}") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "region": c.region, + "nodeTemplate": c.nodeTemplate, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.nodeTemplates.delete" call. +// Exactly one of *Operation or error will be non-nil. Any non-2xx +// status code is an error. Response headers are in either +// *Operation.ServerResponse.Header or (if a response was returned at +// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified +// to check whether the returned error was because +// http.StatusNotModified was returned. +func (c *NodeTemplatesDeleteCall) Do(opts ...googleapi.CallOption) (*Operation, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Operation{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Deletes the specified NodeTemplate resource.", + // "httpMethod": "DELETE", + // "id": "compute.nodeTemplates.delete", + // "parameterOrder": [ + // "project", + // "region", + // "nodeTemplate" + // ], + // "parameters": { + // "nodeTemplate": { + // "description": "Name of the NodeTemplate resource to delete.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // }, + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "region": { + // "description": "The name of the region for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // }, + // "requestId": { + // "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", + // "location": "query", + // "type": "string" + // } + // }, + // "path": "{project}/regions/{region}/nodeTemplates/{nodeTemplate}", + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + +// method id "compute.nodeTemplates.get": + +type NodeTemplatesGetCall struct { + s *Service + project string + region string + nodeTemplate string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// Get: Returns the specified node template. Gets a list of available +// node templates by making a list() request. +func (r *NodeTemplatesService) Get(project string, region string, nodeTemplate string) *NodeTemplatesGetCall { + c := &NodeTemplatesGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.region = region + c.nodeTemplate = nodeTemplate + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *NodeTemplatesGetCall) Fields(s ...googleapi.Field) *NodeTemplatesGetCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// IfNoneMatch sets the optional parameter which makes the operation +// fail if the object's ETag matches the given value. This is useful for +// getting updates only after the object has changed since the last +// request. Use googleapi.IsNotModified to check whether the response +// error from Do is the result of In-None-Match. +func (c *NodeTemplatesGetCall) IfNoneMatch(entityTag string) *NodeTemplatesGetCall { + c.ifNoneMatch_ = entityTag + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *NodeTemplatesGetCall) Context(ctx context.Context) *NodeTemplatesGetCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *NodeTemplatesGetCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *NodeTemplatesGetCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + if c.ifNoneMatch_ != "" { + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) + } + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/nodeTemplates/{nodeTemplate}") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "region": c.region, + "nodeTemplate": c.nodeTemplate, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.nodeTemplates.get" call. +// Exactly one of *NodeTemplate or error will be non-nil. Any non-2xx +// status code is an error. Response headers are in either +// *NodeTemplate.ServerResponse.Header or (if a response was returned at +// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified +// to check whether the returned error was because +// http.StatusNotModified was returned. +func (c *NodeTemplatesGetCall) Do(opts ...googleapi.CallOption) (*NodeTemplate, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &NodeTemplate{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Returns the specified node template. Gets a list of available node templates by making a list() request.", + // "httpMethod": "GET", + // "id": "compute.nodeTemplates.get", + // "parameterOrder": [ + // "project", + // "region", + // "nodeTemplate" + // ], + // "parameters": { + // "nodeTemplate": { + // "description": "Name of the node template to return.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // }, + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "region": { + // "description": "The name of the region for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/regions/{region}/nodeTemplates/{nodeTemplate}", + // "response": { + // "$ref": "NodeTemplate" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute", + // "https://www.googleapis.com/auth/compute.readonly" + // ] + // } + +} + +// method id "compute.nodeTemplates.getIamPolicy": + +type NodeTemplatesGetIamPolicyCall struct { + s *Service + project string + region string + resource string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// GetIamPolicy: Gets the access control policy for a resource. May be +// empty if no such policy or resource exists. +func (r *NodeTemplatesService) GetIamPolicy(project string, region string, resource string) *NodeTemplatesGetIamPolicyCall { + c := &NodeTemplatesGetIamPolicyCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.region = region + c.resource = resource + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *NodeTemplatesGetIamPolicyCall) Fields(s ...googleapi.Field) *NodeTemplatesGetIamPolicyCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// IfNoneMatch sets the optional parameter which makes the operation +// fail if the object's ETag matches the given value. This is useful for +// getting updates only after the object has changed since the last +// request. Use googleapi.IsNotModified to check whether the response +// error from Do is the result of In-None-Match. +func (c *NodeTemplatesGetIamPolicyCall) IfNoneMatch(entityTag string) *NodeTemplatesGetIamPolicyCall { + c.ifNoneMatch_ = entityTag + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *NodeTemplatesGetIamPolicyCall) Context(ctx context.Context) *NodeTemplatesGetIamPolicyCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *NodeTemplatesGetIamPolicyCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *NodeTemplatesGetIamPolicyCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + if c.ifNoneMatch_ != "" { + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) + } + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/nodeTemplates/{resource}/getIamPolicy") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "region": c.region, + "resource": c.resource, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.nodeTemplates.getIamPolicy" call. +// Exactly one of *Policy or error will be non-nil. Any non-2xx status +// code is an error. Response headers are in either +// *Policy.ServerResponse.Header or (if a response was returned at all) +// in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to +// check whether the returned error was because http.StatusNotModified +// was returned. +func (c *NodeTemplatesGetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Policy, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Policy{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Gets the access control policy for a resource. May be empty if no such policy or resource exists.", + // "httpMethod": "GET", + // "id": "compute.nodeTemplates.getIamPolicy", + // "parameterOrder": [ + // "project", + // "region", + // "resource" + // ], + // "parameters": { + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "region": { + // "description": "The name of the region for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // }, + // "resource": { + // "description": "Name or id of the resource for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/regions/{region}/nodeTemplates/{resource}/getIamPolicy", + // "response": { + // "$ref": "Policy" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute", + // "https://www.googleapis.com/auth/compute.readonly" + // ] + // } + +} + +// method id "compute.nodeTemplates.insert": + +type NodeTemplatesInsertCall struct { + s *Service + project string + region string + nodetemplate *NodeTemplate + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// Insert: Creates a NodeTemplate resource in the specified project +// using the data included in the request. +func (r *NodeTemplatesService) Insert(project string, region string, nodetemplate *NodeTemplate) *NodeTemplatesInsertCall { + c := &NodeTemplatesInsertCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.region = region + c.nodetemplate = nodetemplate + return c +} + +// RequestId sets the optional parameter "requestId": An optional +// request ID to identify requests. Specify a unique request ID so that +// if you must retry your request, the server will know to ignore the +// request if it has already been completed. +// +// For example, consider a situation where you make an initial request +// and the request times out. If you make the request again with the +// same request ID, the server can check if original operation with the +// same request ID was received, and if so, will ignore the second +// request. This prevents clients from accidentally creating duplicate +// commitments. +// +// The request ID must be a valid UUID with the exception that zero UUID +// is not supported (00000000-0000-0000-0000-000000000000). +func (c *NodeTemplatesInsertCall) RequestId(requestId string) *NodeTemplatesInsertCall { + c.urlParams_.Set("requestId", requestId) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *NodeTemplatesInsertCall) Fields(s ...googleapi.Field) *NodeTemplatesInsertCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *NodeTemplatesInsertCall) Context(ctx context.Context) *NodeTemplatesInsertCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *NodeTemplatesInsertCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *NodeTemplatesInsertCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.nodetemplate) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/nodeTemplates") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "region": c.region, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.nodeTemplates.insert" call. +// Exactly one of *Operation or error will be non-nil. Any non-2xx +// status code is an error. Response headers are in either +// *Operation.ServerResponse.Header or (if a response was returned at +// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified +// to check whether the returned error was because +// http.StatusNotModified was returned. +func (c *NodeTemplatesInsertCall) Do(opts ...googleapi.CallOption) (*Operation, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Operation{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Creates a NodeTemplate resource in the specified project using the data included in the request.", + // "httpMethod": "POST", + // "id": "compute.nodeTemplates.insert", + // "parameterOrder": [ + // "project", + // "region" + // ], + // "parameters": { + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "region": { + // "description": "The name of the region for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // }, + // "requestId": { + // "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", + // "location": "query", + // "type": "string" + // } + // }, + // "path": "{project}/regions/{region}/nodeTemplates", + // "request": { + // "$ref": "NodeTemplate" + // }, + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + +// method id "compute.nodeTemplates.list": + +type NodeTemplatesListCall struct { + s *Service + project string + region string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// List: Retrieves a list of node templates available to the specified +// project. +func (r *NodeTemplatesService) List(project string, region string) *NodeTemplatesListCall { + c := &NodeTemplatesListCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.region = region + return c +} + +// Filter sets the optional parameter "filter": A filter expression that +// filters resources listed in the response. The expression must specify +// the field name, a comparison operator, and the value that you want to +// use for filtering. The value must be a string, a number, or a +// boolean. The comparison operator must be either =, !=, >, or <. +// +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. +// +// You can also filter nested fields. For example, you could specify +// scheduling.automaticRestart = false to include instances only if they +// are not scheduled for automatic restarts. You can use filtering on +// nested fields to filter based on resource labels. +// +// To filter on multiple expressions, provide each separate expression +// within parentheses. For example, (scheduling.automaticRestart = true) +// (cpuPlatform = "Intel Skylake"). By default, each expression is an +// AND expression. However, you can include AND and OR expressions +// explicitly. For example, (cpuPlatform = "Intel Skylake") OR +// (cpuPlatform = "Intel Broadwell") AND (scheduling.automaticRestart = +// true). +func (c *NodeTemplatesListCall) Filter(filter string) *NodeTemplatesListCall { + c.urlParams_.Set("filter", filter) + return c +} + +// MaxResults sets the optional parameter "maxResults": The maximum +// number of results per page that should be returned. If the number of +// available results is larger than maxResults, Compute Engine returns a +// nextPageToken that can be used to get the next page of results in +// subsequent list requests. Acceptable values are 0 to 500, inclusive. +// (Default: 500) +func (c *NodeTemplatesListCall) MaxResults(maxResults int64) *NodeTemplatesListCall { + c.urlParams_.Set("maxResults", fmt.Sprint(maxResults)) + return c +} + +// OrderBy sets the optional parameter "orderBy": Sorts list results by +// a certain order. By default, results are returned in alphanumerical +// order based on the resource name. +// +// You can also sort results in descending order based on the creation +// timestamp using orderBy="creationTimestamp desc". This sorts results +// based on the creationTimestamp field in reverse chronological order +// (newest result first). Use this to sort resources like operations so +// that the newest operation is returned first. +// +// Currently, only sorting by name or creationTimestamp desc is +// supported. +func (c *NodeTemplatesListCall) OrderBy(orderBy string) *NodeTemplatesListCall { + c.urlParams_.Set("orderBy", orderBy) + return c +} + +// PageToken sets the optional parameter "pageToken": Specifies a page +// token to use. Set pageToken to the nextPageToken returned by a +// previous list request to get the next page of results. +func (c *NodeTemplatesListCall) PageToken(pageToken string) *NodeTemplatesListCall { + c.urlParams_.Set("pageToken", pageToken) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *NodeTemplatesListCall) Fields(s ...googleapi.Field) *NodeTemplatesListCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// IfNoneMatch sets the optional parameter which makes the operation +// fail if the object's ETag matches the given value. This is useful for +// getting updates only after the object has changed since the last +// request. Use googleapi.IsNotModified to check whether the response +// error from Do is the result of In-None-Match. +func (c *NodeTemplatesListCall) IfNoneMatch(entityTag string) *NodeTemplatesListCall { + c.ifNoneMatch_ = entityTag + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *NodeTemplatesListCall) Context(ctx context.Context) *NodeTemplatesListCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *NodeTemplatesListCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *NodeTemplatesListCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + if c.ifNoneMatch_ != "" { + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) + } + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/nodeTemplates") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "region": c.region, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.nodeTemplates.list" call. +// Exactly one of *NodeTemplateList or error will be non-nil. Any +// non-2xx status code is an error. Response headers are in either +// *NodeTemplateList.ServerResponse.Header or (if a response was +// returned at all) in error.(*googleapi.Error).Header. Use +// googleapi.IsNotModified to check whether the returned error was +// because http.StatusNotModified was returned. +func (c *NodeTemplatesListCall) Do(opts ...googleapi.CallOption) (*NodeTemplateList, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &NodeTemplateList{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Retrieves a list of node templates available to the specified project.", + // "httpMethod": "GET", + // "id": "compute.nodeTemplates.list", + // "parameterOrder": [ + // "project", + // "region" + // ], + // "parameters": { + // "filter": { + // "description": "A filter expression that filters resources listed in the response. The expression must specify the field name, a comparison operator, and the value that you want to use for filtering. The value must be a string, a number, or a boolean. The comparison operator must be either =, !=, \u003e, or \u003c.\n\nFor example, if you are filtering Compute Engine instances, you can exclude instances named example-instance by specifying name != example-instance.\n\nYou can also filter nested fields. For example, you could specify scheduling.automaticRestart = false to include instances only if they are not scheduled for automatic restarts. You can use filtering on nested fields to filter based on resource labels.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart = true) (cpuPlatform = \"Intel Skylake\"). By default, each expression is an AND expression. However, you can include AND and OR expressions explicitly. For example, (cpuPlatform = \"Intel Skylake\") OR (cpuPlatform = \"Intel Broadwell\") AND (scheduling.automaticRestart = true).", + // "location": "query", + // "type": "string" + // }, + // "maxResults": { + // "default": "500", + // "description": "The maximum number of results per page that should be returned. If the number of available results is larger than maxResults, Compute Engine returns a nextPageToken that can be used to get the next page of results in subsequent list requests. Acceptable values are 0 to 500, inclusive. (Default: 500)", + // "format": "uint32", + // "location": "query", + // "minimum": "0", + // "type": "integer" + // }, + // "orderBy": { + // "description": "Sorts list results by a certain order. By default, results are returned in alphanumerical order based on the resource name.\n\nYou can also sort results in descending order based on the creation timestamp using orderBy=\"creationTimestamp desc\". This sorts results based on the creationTimestamp field in reverse chronological order (newest result first). Use this to sort resources like operations so that the newest operation is returned first.\n\nCurrently, only sorting by name or creationTimestamp desc is supported.", + // "location": "query", + // "type": "string" + // }, + // "pageToken": { + // "description": "Specifies a page token to use. Set pageToken to the nextPageToken returned by a previous list request to get the next page of results.", + // "location": "query", + // "type": "string" + // }, + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "region": { + // "description": "The name of the region for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/regions/{region}/nodeTemplates", + // "response": { + // "$ref": "NodeTemplateList" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute", + // "https://www.googleapis.com/auth/compute.readonly" + // ] + // } + +} + +// Pages invokes f for each page of results. +// A non-nil error returned from f will halt the iteration. +// The provided context supersedes any context provided to the Context method. +func (c *NodeTemplatesListCall) Pages(ctx context.Context, f func(*NodeTemplateList) error) error { + c.ctx_ = ctx + defer c.PageToken(c.urlParams_.Get("pageToken")) // reset paging to original point + for { + x, err := c.Do() + if err != nil { + return err + } + if err := f(x); err != nil { + return err + } + if x.NextPageToken == "" { + return nil + } + c.PageToken(x.NextPageToken) + } +} + +// method id "compute.nodeTemplates.setIamPolicy": + +type NodeTemplatesSetIamPolicyCall struct { + s *Service + project string + region string + resource string + regionsetpolicyrequest *RegionSetPolicyRequest + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// SetIamPolicy: Sets the access control policy on the specified +// resource. Replaces any existing policy. +func (r *NodeTemplatesService) SetIamPolicy(project string, region string, resource string, regionsetpolicyrequest *RegionSetPolicyRequest) *NodeTemplatesSetIamPolicyCall { + c := &NodeTemplatesSetIamPolicyCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.region = region + c.resource = resource + c.regionsetpolicyrequest = regionsetpolicyrequest + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *NodeTemplatesSetIamPolicyCall) Fields(s ...googleapi.Field) *NodeTemplatesSetIamPolicyCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *NodeTemplatesSetIamPolicyCall) Context(ctx context.Context) *NodeTemplatesSetIamPolicyCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *NodeTemplatesSetIamPolicyCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *NodeTemplatesSetIamPolicyCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.regionsetpolicyrequest) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/nodeTemplates/{resource}/setIamPolicy") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "region": c.region, + "resource": c.resource, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.nodeTemplates.setIamPolicy" call. +// Exactly one of *Policy or error will be non-nil. Any non-2xx status +// code is an error. Response headers are in either +// *Policy.ServerResponse.Header or (if a response was returned at all) +// in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to +// check whether the returned error was because http.StatusNotModified +// was returned. +func (c *NodeTemplatesSetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Policy, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Policy{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Sets the access control policy on the specified resource. Replaces any existing policy.", + // "httpMethod": "POST", + // "id": "compute.nodeTemplates.setIamPolicy", + // "parameterOrder": [ + // "project", + // "region", + // "resource" + // ], + // "parameters": { + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "region": { + // "description": "The name of the region for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // }, + // "resource": { + // "description": "Name or id of the resource for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/regions/{region}/nodeTemplates/{resource}/setIamPolicy", + // "request": { + // "$ref": "RegionSetPolicyRequest" + // }, + // "response": { + // "$ref": "Policy" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + +// method id "compute.nodeTemplates.testIamPermissions": + +type NodeTemplatesTestIamPermissionsCall struct { + s *Service + project string + region string + resource string + testpermissionsrequest *TestPermissionsRequest + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// TestIamPermissions: Returns permissions that a caller has on the +// specified resource. +func (r *NodeTemplatesService) TestIamPermissions(project string, region string, resource string, testpermissionsrequest *TestPermissionsRequest) *NodeTemplatesTestIamPermissionsCall { + c := &NodeTemplatesTestIamPermissionsCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.region = region + c.resource = resource + c.testpermissionsrequest = testpermissionsrequest + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *NodeTemplatesTestIamPermissionsCall) Fields(s ...googleapi.Field) *NodeTemplatesTestIamPermissionsCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *NodeTemplatesTestIamPermissionsCall) Context(ctx context.Context) *NodeTemplatesTestIamPermissionsCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *NodeTemplatesTestIamPermissionsCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *NodeTemplatesTestIamPermissionsCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.testpermissionsrequest) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/nodeTemplates/{resource}/testIamPermissions") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "region": c.region, + "resource": c.resource, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.nodeTemplates.testIamPermissions" call. +// Exactly one of *TestPermissionsResponse or error will be non-nil. Any +// non-2xx status code is an error. Response headers are in either +// *TestPermissionsResponse.ServerResponse.Header or (if a response was +// returned at all) in error.(*googleapi.Error).Header. Use +// googleapi.IsNotModified to check whether the returned error was +// because http.StatusNotModified was returned. +func (c *NodeTemplatesTestIamPermissionsCall) Do(opts ...googleapi.CallOption) (*TestPermissionsResponse, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &TestPermissionsResponse{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Returns permissions that a caller has on the specified resource.", + // "httpMethod": "POST", + // "id": "compute.nodeTemplates.testIamPermissions", + // "parameterOrder": [ + // "project", + // "region", + // "resource" + // ], + // "parameters": { + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "region": { + // "description": "The name of the region for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // }, + // "resource": { + // "description": "Name or id of the resource for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/regions/{region}/nodeTemplates/{resource}/testIamPermissions", + // "request": { + // "$ref": "TestPermissionsRequest" + // }, + // "response": { + // "$ref": "TestPermissionsResponse" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute", + // "https://www.googleapis.com/auth/compute.readonly" + // ] + // } + +} + +// method id "compute.nodeTypes.aggregatedList": + +type NodeTypesAggregatedListCall struct { + s *Service + project string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// AggregatedList: Retrieves an aggregated list of node types. +func (r *NodeTypesService) AggregatedList(project string) *NodeTypesAggregatedListCall { + c := &NodeTypesAggregatedListCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + return c +} + +// Filter sets the optional parameter "filter": A filter expression that +// filters resources listed in the response. The expression must specify +// the field name, a comparison operator, and the value that you want to +// use for filtering. The value must be a string, a number, or a +// boolean. The comparison operator must be either =, !=, >, or <. +// +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. +// +// You can also filter nested fields. For example, you could specify +// scheduling.automaticRestart = false to include instances only if they +// are not scheduled for automatic restarts. You can use filtering on +// nested fields to filter based on resource labels. +// +// To filter on multiple expressions, provide each separate expression +// within parentheses. For example, (scheduling.automaticRestart = true) +// (cpuPlatform = "Intel Skylake"). By default, each expression is an +// AND expression. However, you can include AND and OR expressions +// explicitly. For example, (cpuPlatform = "Intel Skylake") OR +// (cpuPlatform = "Intel Broadwell") AND (scheduling.automaticRestart = +// true). +func (c *NodeTypesAggregatedListCall) Filter(filter string) *NodeTypesAggregatedListCall { + c.urlParams_.Set("filter", filter) + return c +} + +// MaxResults sets the optional parameter "maxResults": The maximum +// number of results per page that should be returned. If the number of +// available results is larger than maxResults, Compute Engine returns a +// nextPageToken that can be used to get the next page of results in +// subsequent list requests. Acceptable values are 0 to 500, inclusive. +// (Default: 500) +func (c *NodeTypesAggregatedListCall) MaxResults(maxResults int64) *NodeTypesAggregatedListCall { + c.urlParams_.Set("maxResults", fmt.Sprint(maxResults)) + return c +} + +// OrderBy sets the optional parameter "orderBy": Sorts list results by +// a certain order. By default, results are returned in alphanumerical +// order based on the resource name. +// +// You can also sort results in descending order based on the creation +// timestamp using orderBy="creationTimestamp desc". This sorts results +// based on the creationTimestamp field in reverse chronological order +// (newest result first). Use this to sort resources like operations so +// that the newest operation is returned first. +// +// Currently, only sorting by name or creationTimestamp desc is +// supported. +func (c *NodeTypesAggregatedListCall) OrderBy(orderBy string) *NodeTypesAggregatedListCall { + c.urlParams_.Set("orderBy", orderBy) + return c +} + +// PageToken sets the optional parameter "pageToken": Specifies a page +// token to use. Set pageToken to the nextPageToken returned by a +// previous list request to get the next page of results. +func (c *NodeTypesAggregatedListCall) PageToken(pageToken string) *NodeTypesAggregatedListCall { + c.urlParams_.Set("pageToken", pageToken) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *NodeTypesAggregatedListCall) Fields(s ...googleapi.Field) *NodeTypesAggregatedListCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// IfNoneMatch sets the optional parameter which makes the operation +// fail if the object's ETag matches the given value. This is useful for +// getting updates only after the object has changed since the last +// request. Use googleapi.IsNotModified to check whether the response +// error from Do is the result of In-None-Match. +func (c *NodeTypesAggregatedListCall) IfNoneMatch(entityTag string) *NodeTypesAggregatedListCall { + c.ifNoneMatch_ = entityTag + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *NodeTypesAggregatedListCall) Context(ctx context.Context) *NodeTypesAggregatedListCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *NodeTypesAggregatedListCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *NodeTypesAggregatedListCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + if c.ifNoneMatch_ != "" { + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) + } + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/aggregated/nodeTypes") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.nodeTypes.aggregatedList" call. +// Exactly one of *NodeTypeAggregatedList or error will be non-nil. Any +// non-2xx status code is an error. Response headers are in either +// *NodeTypeAggregatedList.ServerResponse.Header or (if a response was +// returned at all) in error.(*googleapi.Error).Header. Use +// googleapi.IsNotModified to check whether the returned error was +// because http.StatusNotModified was returned. +func (c *NodeTypesAggregatedListCall) Do(opts ...googleapi.CallOption) (*NodeTypeAggregatedList, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &NodeTypeAggregatedList{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Retrieves an aggregated list of node types.", + // "httpMethod": "GET", + // "id": "compute.nodeTypes.aggregatedList", + // "parameterOrder": [ + // "project" + // ], + // "parameters": { + // "filter": { + // "description": "A filter expression that filters resources listed in the response. The expression must specify the field name, a comparison operator, and the value that you want to use for filtering. The value must be a string, a number, or a boolean. The comparison operator must be either =, !=, \u003e, or \u003c.\n\nFor example, if you are filtering Compute Engine instances, you can exclude instances named example-instance by specifying name != example-instance.\n\nYou can also filter nested fields. For example, you could specify scheduling.automaticRestart = false to include instances only if they are not scheduled for automatic restarts. You can use filtering on nested fields to filter based on resource labels.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart = true) (cpuPlatform = \"Intel Skylake\"). By default, each expression is an AND expression. However, you can include AND and OR expressions explicitly. For example, (cpuPlatform = \"Intel Skylake\") OR (cpuPlatform = \"Intel Broadwell\") AND (scheduling.automaticRestart = true).", + // "location": "query", + // "type": "string" + // }, + // "maxResults": { + // "default": "500", + // "description": "The maximum number of results per page that should be returned. If the number of available results is larger than maxResults, Compute Engine returns a nextPageToken that can be used to get the next page of results in subsequent list requests. Acceptable values are 0 to 500, inclusive. (Default: 500)", + // "format": "uint32", + // "location": "query", + // "minimum": "0", + // "type": "integer" + // }, + // "orderBy": { + // "description": "Sorts list results by a certain order. By default, results are returned in alphanumerical order based on the resource name.\n\nYou can also sort results in descending order based on the creation timestamp using orderBy=\"creationTimestamp desc\". This sorts results based on the creationTimestamp field in reverse chronological order (newest result first). Use this to sort resources like operations so that the newest operation is returned first.\n\nCurrently, only sorting by name or creationTimestamp desc is supported.", + // "location": "query", + // "type": "string" + // }, + // "pageToken": { + // "description": "Specifies a page token to use. Set pageToken to the nextPageToken returned by a previous list request to get the next page of results.", + // "location": "query", + // "type": "string" + // }, + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/aggregated/nodeTypes", + // "response": { + // "$ref": "NodeTypeAggregatedList" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute", + // "https://www.googleapis.com/auth/compute.readonly" + // ] + // } + +} + +// Pages invokes f for each page of results. +// A non-nil error returned from f will halt the iteration. +// The provided context supersedes any context provided to the Context method. +func (c *NodeTypesAggregatedListCall) Pages(ctx context.Context, f func(*NodeTypeAggregatedList) error) error { + c.ctx_ = ctx + defer c.PageToken(c.urlParams_.Get("pageToken")) // reset paging to original point + for { + x, err := c.Do() + if err != nil { + return err + } + if err := f(x); err != nil { + return err + } + if x.NextPageToken == "" { + return nil + } + c.PageToken(x.NextPageToken) + } +} + +// method id "compute.nodeTypes.get": + +type NodeTypesGetCall struct { + s *Service + project string + zone string + nodeType string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// Get: Returns the specified node type. Gets a list of available node +// types by making a list() request. +func (r *NodeTypesService) Get(project string, zone string, nodeType string) *NodeTypesGetCall { + c := &NodeTypesGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.zone = zone + c.nodeType = nodeType + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *NodeTypesGetCall) Fields(s ...googleapi.Field) *NodeTypesGetCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// IfNoneMatch sets the optional parameter which makes the operation +// fail if the object's ETag matches the given value. This is useful for +// getting updates only after the object has changed since the last +// request. Use googleapi.IsNotModified to check whether the response +// error from Do is the result of In-None-Match. +func (c *NodeTypesGetCall) IfNoneMatch(entityTag string) *NodeTypesGetCall { + c.ifNoneMatch_ = entityTag + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *NodeTypesGetCall) Context(ctx context.Context) *NodeTypesGetCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *NodeTypesGetCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *NodeTypesGetCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + if c.ifNoneMatch_ != "" { + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) + } + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/nodeTypes/{nodeType}") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "zone": c.zone, + "nodeType": c.nodeType, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.nodeTypes.get" call. +// Exactly one of *NodeType or error will be non-nil. Any non-2xx status +// code is an error. Response headers are in either +// *NodeType.ServerResponse.Header or (if a response was returned at +// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified +// to check whether the returned error was because +// http.StatusNotModified was returned. +func (c *NodeTypesGetCall) Do(opts ...googleapi.CallOption) (*NodeType, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &NodeType{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Returns the specified node type. Gets a list of available node types by making a list() request.", + // "httpMethod": "GET", + // "id": "compute.nodeTypes.get", + // "parameterOrder": [ + // "project", + // "zone", + // "nodeType" + // ], + // "parameters": { + // "nodeType": { + // "description": "Name of the node type to return.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // }, + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "zone": { + // "description": "The name of the zone for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/zones/{zone}/nodeTypes/{nodeType}", + // "response": { + // "$ref": "NodeType" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute", + // "https://www.googleapis.com/auth/compute.readonly" + // ] + // } + +} + +// method id "compute.nodeTypes.list": + +type NodeTypesListCall struct { + s *Service + project string + zone string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// List: Retrieves a list of node types available to the specified +// project. +func (r *NodeTypesService) List(project string, zone string) *NodeTypesListCall { + c := &NodeTypesListCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.zone = zone + return c +} + +// Filter sets the optional parameter "filter": A filter expression that +// filters resources listed in the response. The expression must specify +// the field name, a comparison operator, and the value that you want to +// use for filtering. The value must be a string, a number, or a +// boolean. The comparison operator must be either =, !=, >, or <. +// +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. +// +// You can also filter nested fields. For example, you could specify +// scheduling.automaticRestart = false to include instances only if they +// are not scheduled for automatic restarts. You can use filtering on +// nested fields to filter based on resource labels. +// +// To filter on multiple expressions, provide each separate expression +// within parentheses. For example, (scheduling.automaticRestart = true) +// (cpuPlatform = "Intel Skylake"). By default, each expression is an +// AND expression. However, you can include AND and OR expressions +// explicitly. For example, (cpuPlatform = "Intel Skylake") OR +// (cpuPlatform = "Intel Broadwell") AND (scheduling.automaticRestart = +// true). +func (c *NodeTypesListCall) Filter(filter string) *NodeTypesListCall { + c.urlParams_.Set("filter", filter) + return c +} + +// MaxResults sets the optional parameter "maxResults": The maximum +// number of results per page that should be returned. If the number of +// available results is larger than maxResults, Compute Engine returns a +// nextPageToken that can be used to get the next page of results in +// subsequent list requests. Acceptable values are 0 to 500, inclusive. +// (Default: 500) +func (c *NodeTypesListCall) MaxResults(maxResults int64) *NodeTypesListCall { + c.urlParams_.Set("maxResults", fmt.Sprint(maxResults)) + return c +} + +// OrderBy sets the optional parameter "orderBy": Sorts list results by +// a certain order. By default, results are returned in alphanumerical +// order based on the resource name. +// +// You can also sort results in descending order based on the creation +// timestamp using orderBy="creationTimestamp desc". This sorts results +// based on the creationTimestamp field in reverse chronological order +// (newest result first). Use this to sort resources like operations so +// that the newest operation is returned first. +// +// Currently, only sorting by name or creationTimestamp desc is +// supported. +func (c *NodeTypesListCall) OrderBy(orderBy string) *NodeTypesListCall { + c.urlParams_.Set("orderBy", orderBy) + return c +} + +// PageToken sets the optional parameter "pageToken": Specifies a page +// token to use. Set pageToken to the nextPageToken returned by a +// previous list request to get the next page of results. +func (c *NodeTypesListCall) PageToken(pageToken string) *NodeTypesListCall { + c.urlParams_.Set("pageToken", pageToken) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *NodeTypesListCall) Fields(s ...googleapi.Field) *NodeTypesListCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// IfNoneMatch sets the optional parameter which makes the operation +// fail if the object's ETag matches the given value. This is useful for +// getting updates only after the object has changed since the last +// request. Use googleapi.IsNotModified to check whether the response +// error from Do is the result of In-None-Match. +func (c *NodeTypesListCall) IfNoneMatch(entityTag string) *NodeTypesListCall { + c.ifNoneMatch_ = entityTag + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *NodeTypesListCall) Context(ctx context.Context) *NodeTypesListCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *NodeTypesListCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *NodeTypesListCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + if c.ifNoneMatch_ != "" { + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) + } + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/nodeTypes") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "zone": c.zone, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.nodeTypes.list" call. +// Exactly one of *NodeTypeList or error will be non-nil. Any non-2xx +// status code is an error. Response headers are in either +// *NodeTypeList.ServerResponse.Header or (if a response was returned at +// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified +// to check whether the returned error was because +// http.StatusNotModified was returned. +func (c *NodeTypesListCall) Do(opts ...googleapi.CallOption) (*NodeTypeList, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &NodeTypeList{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Retrieves a list of node types available to the specified project.", + // "httpMethod": "GET", + // "id": "compute.nodeTypes.list", + // "parameterOrder": [ + // "project", + // "zone" + // ], + // "parameters": { + // "filter": { + // "description": "A filter expression that filters resources listed in the response. The expression must specify the field name, a comparison operator, and the value that you want to use for filtering. The value must be a string, a number, or a boolean. The comparison operator must be either =, !=, \u003e, or \u003c.\n\nFor example, if you are filtering Compute Engine instances, you can exclude instances named example-instance by specifying name != example-instance.\n\nYou can also filter nested fields. For example, you could specify scheduling.automaticRestart = false to include instances only if they are not scheduled for automatic restarts. You can use filtering on nested fields to filter based on resource labels.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart = true) (cpuPlatform = \"Intel Skylake\"). By default, each expression is an AND expression. However, you can include AND and OR expressions explicitly. For example, (cpuPlatform = \"Intel Skylake\") OR (cpuPlatform = \"Intel Broadwell\") AND (scheduling.automaticRestart = true).", + // "location": "query", + // "type": "string" + // }, + // "maxResults": { + // "default": "500", + // "description": "The maximum number of results per page that should be returned. If the number of available results is larger than maxResults, Compute Engine returns a nextPageToken that can be used to get the next page of results in subsequent list requests. Acceptable values are 0 to 500, inclusive. (Default: 500)", + // "format": "uint32", + // "location": "query", + // "minimum": "0", + // "type": "integer" + // }, + // "orderBy": { + // "description": "Sorts list results by a certain order. By default, results are returned in alphanumerical order based on the resource name.\n\nYou can also sort results in descending order based on the creation timestamp using orderBy=\"creationTimestamp desc\". This sorts results based on the creationTimestamp field in reverse chronological order (newest result first). Use this to sort resources like operations so that the newest operation is returned first.\n\nCurrently, only sorting by name or creationTimestamp desc is supported.", + // "location": "query", + // "type": "string" + // }, + // "pageToken": { + // "description": "Specifies a page token to use. Set pageToken to the nextPageToken returned by a previous list request to get the next page of results.", + // "location": "query", + // "type": "string" + // }, + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "zone": { + // "description": "The name of the zone for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/zones/{zone}/nodeTypes", + // "response": { + // "$ref": "NodeTypeList" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute", + // "https://www.googleapis.com/auth/compute.readonly" + // ] + // } + +} + +// Pages invokes f for each page of results. +// A non-nil error returned from f will halt the iteration. +// The provided context supersedes any context provided to the Context method. +func (c *NodeTypesListCall) Pages(ctx context.Context, f func(*NodeTypeList) error) error { + c.ctx_ = ctx + defer c.PageToken(c.urlParams_.Get("pageToken")) // reset paging to original point + for { + x, err := c.Do() + if err != nil { + return err + } + if err := f(x); err != nil { + return err + } + if x.NextPageToken == "" { + return nil + } + c.PageToken(x.NextPageToken) + } +} + // method id "compute.projects.disableXpnHost": type ProjectsDisableXpnHostCall struct { @@ -58675,9 +71238,13 @@ func (c *ProjectsDisableXpnHostCall) doRequest(alt string) (*http.Response, erro reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/disableXpnHost") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -58832,9 +71399,13 @@ func (c *ProjectsDisableXpnResourceCall) doRequest(alt string) (*http.Response, } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/disableXpnResource") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -58984,9 +71555,13 @@ func (c *ProjectsEnableXpnHostCall) doRequest(alt string) (*http.Response, error reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/enableXpnHost") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -59142,9 +71717,13 @@ func (c *ProjectsEnableXpnResourceCall) doRequest(alt string) (*http.Response, e } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/enableXpnResource") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -59290,9 +71869,13 @@ func (c *ProjectsGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -59431,9 +72014,13 @@ func (c *ProjectsGetXpnHostCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/getXpnHost") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -59525,25 +72112,64 @@ func (r *ProjectsService) GetXpnResources(project string) *ProjectsGetXpnResourc return c } -// Filter sets the optional parameter "filter": +// Filter sets the optional parameter "filter": A filter expression that +// filters resources listed in the response. The expression must specify +// the field name, a comparison operator, and the value that you want to +// use for filtering. The value must be a string, a number, or a +// boolean. The comparison operator must be either =, !=, >, or <. +// +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. +// +// You can also filter nested fields. For example, you could specify +// scheduling.automaticRestart = false to include instances only if they +// are not scheduled for automatic restarts. You can use filtering on +// nested fields to filter based on resource labels. +// +// To filter on multiple expressions, provide each separate expression +// within parentheses. For example, (scheduling.automaticRestart = true) +// (cpuPlatform = "Intel Skylake"). By default, each expression is an +// AND expression. However, you can include AND and OR expressions +// explicitly. For example, (cpuPlatform = "Intel Skylake") OR +// (cpuPlatform = "Intel Broadwell") AND (scheduling.automaticRestart = +// true). func (c *ProjectsGetXpnResourcesCall) Filter(filter string) *ProjectsGetXpnResourcesCall { c.urlParams_.Set("filter", filter) return c } -// MaxResults sets the optional parameter "maxResults": +// MaxResults sets the optional parameter "maxResults": The maximum +// number of results per page that should be returned. If the number of +// available results is larger than maxResults, Compute Engine returns a +// nextPageToken that can be used to get the next page of results in +// subsequent list requests. Acceptable values are 0 to 500, inclusive. +// (Default: 500) func (c *ProjectsGetXpnResourcesCall) MaxResults(maxResults int64) *ProjectsGetXpnResourcesCall { c.urlParams_.Set("maxResults", fmt.Sprint(maxResults)) return c } -// OrderBy sets the optional parameter "order_by": +// OrderBy sets the optional parameter "order_by": Sorts list results by +// a certain order. By default, results are returned in alphanumerical +// order based on the resource name. +// +// You can also sort results in descending order based on the creation +// timestamp using orderBy="creationTimestamp desc". This sorts results +// based on the creationTimestamp field in reverse chronological order +// (newest result first). Use this to sort resources like operations so +// that the newest operation is returned first. +// +// Currently, only sorting by name or creationTimestamp desc is +// supported. func (c *ProjectsGetXpnResourcesCall) OrderBy(orderBy string) *ProjectsGetXpnResourcesCall { c.urlParams_.Set("order_by", orderBy) return c } -// PageToken sets the optional parameter "pageToken": +// PageToken sets the optional parameter "pageToken": Specifies a page +// token to use. Set pageToken to the nextPageToken returned by a +// previous list request to get the next page of results. func (c *ProjectsGetXpnResourcesCall) PageToken(pageToken string) *ProjectsGetXpnResourcesCall { c.urlParams_.Set("pageToken", pageToken) return c @@ -59595,9 +72221,13 @@ func (c *ProjectsGetXpnResourcesCall) doRequest(alt string) (*http.Response, err } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/getXpnResources") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -59651,21 +72281,25 @@ func (c *ProjectsGetXpnResourcesCall) Do(opts ...googleapi.CallOption) (*Project // ], // "parameters": { // "filter": { + // "description": "A filter expression that filters resources listed in the response. The expression must specify the field name, a comparison operator, and the value that you want to use for filtering. The value must be a string, a number, or a boolean. The comparison operator must be either =, !=, \u003e, or \u003c.\n\nFor example, if you are filtering Compute Engine instances, you can exclude instances named example-instance by specifying name != example-instance.\n\nYou can also filter nested fields. For example, you could specify scheduling.automaticRestart = false to include instances only if they are not scheduled for automatic restarts. You can use filtering on nested fields to filter based on resource labels.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart = true) (cpuPlatform = \"Intel Skylake\"). By default, each expression is an AND expression. However, you can include AND and OR expressions explicitly. For example, (cpuPlatform = \"Intel Skylake\") OR (cpuPlatform = \"Intel Broadwell\") AND (scheduling.automaticRestart = true).", // "location": "query", // "type": "string" // }, // "maxResults": { // "default": "500", + // "description": "The maximum number of results per page that should be returned. If the number of available results is larger than maxResults, Compute Engine returns a nextPageToken that can be used to get the next page of results in subsequent list requests. Acceptable values are 0 to 500, inclusive. (Default: 500)", // "format": "uint32", // "location": "query", // "minimum": "0", // "type": "integer" // }, // "order_by": { + // "description": "Sorts list results by a certain order. By default, results are returned in alphanumerical order based on the resource name.\n\nYou can also sort results in descending order based on the creation timestamp using orderBy=\"creationTimestamp desc\". This sorts results based on the creationTimestamp field in reverse chronological order (newest result first). Use this to sort resources like operations so that the newest operation is returned first.\n\nCurrently, only sorting by name or creationTimestamp desc is supported.", // "location": "query", // "type": "string" // }, // "pageToken": { + // "description": "Specifies a page token to use. Set pageToken to the nextPageToken returned by a previous list request to get the next page of results.", // "location": "query", // "type": "string" // }, @@ -59730,25 +72364,64 @@ func (r *ProjectsService) ListXpnHosts(project string, projectslistxpnhostsreque return c } -// Filter sets the optional parameter "filter": +// Filter sets the optional parameter "filter": A filter expression that +// filters resources listed in the response. The expression must specify +// the field name, a comparison operator, and the value that you want to +// use for filtering. The value must be a string, a number, or a +// boolean. The comparison operator must be either =, !=, >, or <. +// +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. +// +// You can also filter nested fields. For example, you could specify +// scheduling.automaticRestart = false to include instances only if they +// are not scheduled for automatic restarts. You can use filtering on +// nested fields to filter based on resource labels. +// +// To filter on multiple expressions, provide each separate expression +// within parentheses. For example, (scheduling.automaticRestart = true) +// (cpuPlatform = "Intel Skylake"). By default, each expression is an +// AND expression. However, you can include AND and OR expressions +// explicitly. For example, (cpuPlatform = "Intel Skylake") OR +// (cpuPlatform = "Intel Broadwell") AND (scheduling.automaticRestart = +// true). func (c *ProjectsListXpnHostsCall) Filter(filter string) *ProjectsListXpnHostsCall { c.urlParams_.Set("filter", filter) return c } -// MaxResults sets the optional parameter "maxResults": +// MaxResults sets the optional parameter "maxResults": The maximum +// number of results per page that should be returned. If the number of +// available results is larger than maxResults, Compute Engine returns a +// nextPageToken that can be used to get the next page of results in +// subsequent list requests. Acceptable values are 0 to 500, inclusive. +// (Default: 500) func (c *ProjectsListXpnHostsCall) MaxResults(maxResults int64) *ProjectsListXpnHostsCall { c.urlParams_.Set("maxResults", fmt.Sprint(maxResults)) return c } -// OrderBy sets the optional parameter "order_by": +// OrderBy sets the optional parameter "order_by": Sorts list results by +// a certain order. By default, results are returned in alphanumerical +// order based on the resource name. +// +// You can also sort results in descending order based on the creation +// timestamp using orderBy="creationTimestamp desc". This sorts results +// based on the creationTimestamp field in reverse chronological order +// (newest result first). Use this to sort resources like operations so +// that the newest operation is returned first. +// +// Currently, only sorting by name or creationTimestamp desc is +// supported. func (c *ProjectsListXpnHostsCall) OrderBy(orderBy string) *ProjectsListXpnHostsCall { c.urlParams_.Set("order_by", orderBy) return c } -// PageToken sets the optional parameter "pageToken": +// PageToken sets the optional parameter "pageToken": Specifies a page +// token to use. Set pageToken to the nextPageToken returned by a +// previous list request to get the next page of results. func (c *ProjectsListXpnHostsCall) PageToken(pageToken string) *ProjectsListXpnHostsCall { c.urlParams_.Set("pageToken", pageToken) return c @@ -59792,9 +72465,13 @@ func (c *ProjectsListXpnHostsCall) doRequest(alt string) (*http.Response, error) } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/listXpnHosts") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -59848,21 +72525,25 @@ func (c *ProjectsListXpnHostsCall) Do(opts ...googleapi.CallOption) (*XpnHostLis // ], // "parameters": { // "filter": { + // "description": "A filter expression that filters resources listed in the response. The expression must specify the field name, a comparison operator, and the value that you want to use for filtering. The value must be a string, a number, or a boolean. The comparison operator must be either =, !=, \u003e, or \u003c.\n\nFor example, if you are filtering Compute Engine instances, you can exclude instances named example-instance by specifying name != example-instance.\n\nYou can also filter nested fields. For example, you could specify scheduling.automaticRestart = false to include instances only if they are not scheduled for automatic restarts. You can use filtering on nested fields to filter based on resource labels.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart = true) (cpuPlatform = \"Intel Skylake\"). By default, each expression is an AND expression. However, you can include AND and OR expressions explicitly. For example, (cpuPlatform = \"Intel Skylake\") OR (cpuPlatform = \"Intel Broadwell\") AND (scheduling.automaticRestart = true).", // "location": "query", // "type": "string" // }, // "maxResults": { // "default": "500", + // "description": "The maximum number of results per page that should be returned. If the number of available results is larger than maxResults, Compute Engine returns a nextPageToken that can be used to get the next page of results in subsequent list requests. Acceptable values are 0 to 500, inclusive. (Default: 500)", // "format": "uint32", // "location": "query", // "minimum": "0", // "type": "integer" // }, // "order_by": { + // "description": "Sorts list results by a certain order. By default, results are returned in alphanumerical order based on the resource name.\n\nYou can also sort results in descending order based on the creation timestamp using orderBy=\"creationTimestamp desc\". This sorts results based on the creationTimestamp field in reverse chronological order (newest result first). Use this to sort resources like operations so that the newest operation is returned first.\n\nCurrently, only sorting by name or creationTimestamp desc is supported.", // "location": "query", // "type": "string" // }, // "pageToken": { + // "description": "Specifies a page token to use. Set pageToken to the nextPageToken returned by a previous list request to get the next page of results.", // "location": "query", // "type": "string" // }, @@ -59986,9 +72667,13 @@ func (c *ProjectsMoveDiskCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/moveDisk") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -60146,9 +72831,13 @@ func (c *ProjectsMoveInstanceCall) doRequest(alt string) (*http.Response, error) } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/moveInstance") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -60307,9 +72996,13 @@ func (c *ProjectsSetCommonInstanceMetadataCall) doRequest(alt string) (*http.Res } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/setCommonInstanceMetadata") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -60390,6 +73083,172 @@ func (c *ProjectsSetCommonInstanceMetadataCall) Do(opts ...googleapi.CallOption) } +// method id "compute.projects.setDefaultNetworkTier": + +type ProjectsSetDefaultNetworkTierCall struct { + s *Service + project string + projectssetdefaultnetworktierrequest *ProjectsSetDefaultNetworkTierRequest + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// SetDefaultNetworkTier: Sets the default network tier of the project. +// The default network tier is used when an +// address/forwardingRule/instance is created without specifying the +// network tier field. +func (r *ProjectsService) SetDefaultNetworkTier(project string, projectssetdefaultnetworktierrequest *ProjectsSetDefaultNetworkTierRequest) *ProjectsSetDefaultNetworkTierCall { + c := &ProjectsSetDefaultNetworkTierCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.projectssetdefaultnetworktierrequest = projectssetdefaultnetworktierrequest + return c +} + +// RequestId sets the optional parameter "requestId": An optional +// request ID to identify requests. Specify a unique request ID so that +// if you must retry your request, the server will know to ignore the +// request if it has already been completed. +// +// For example, consider a situation where you make an initial request +// and the request times out. If you make the request again with the +// same request ID, the server can check if original operation with the +// same request ID was received, and if so, will ignore the second +// request. This prevents clients from accidentally creating duplicate +// commitments. +// +// The request ID must be a valid UUID with the exception that zero UUID +// is not supported (00000000-0000-0000-0000-000000000000). +func (c *ProjectsSetDefaultNetworkTierCall) RequestId(requestId string) *ProjectsSetDefaultNetworkTierCall { + c.urlParams_.Set("requestId", requestId) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *ProjectsSetDefaultNetworkTierCall) Fields(s ...googleapi.Field) *ProjectsSetDefaultNetworkTierCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *ProjectsSetDefaultNetworkTierCall) Context(ctx context.Context) *ProjectsSetDefaultNetworkTierCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *ProjectsSetDefaultNetworkTierCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *ProjectsSetDefaultNetworkTierCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.projectssetdefaultnetworktierrequest) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/setDefaultNetworkTier") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.projects.setDefaultNetworkTier" call. +// Exactly one of *Operation or error will be non-nil. Any non-2xx +// status code is an error. Response headers are in either +// *Operation.ServerResponse.Header or (if a response was returned at +// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified +// to check whether the returned error was because +// http.StatusNotModified was returned. +func (c *ProjectsSetDefaultNetworkTierCall) Do(opts ...googleapi.CallOption) (*Operation, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Operation{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Sets the default network tier of the project. The default network tier is used when an address/forwardingRule/instance is created without specifying the network tier field.", + // "httpMethod": "POST", + // "id": "compute.projects.setDefaultNetworkTier", + // "parameterOrder": [ + // "project" + // ], + // "parameters": { + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "requestId": { + // "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", + // "location": "query", + // "type": "string" + // } + // }, + // "path": "{project}/setDefaultNetworkTier", + // "request": { + // "$ref": "ProjectsSetDefaultNetworkTierRequest" + // }, + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + // method id "compute.projects.setUsageExportBucket": type ProjectsSetUsageExportBucketCall struct { @@ -60470,9 +73329,13 @@ func (c *ProjectsSetUsageExportBucketCall) doRequest(alt string) (*http.Response } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/setUsageExportBucket") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -60629,9 +73492,13 @@ func (c *RegionAutoscalersDeleteCall) doRequest(alt string) (*http.Response, err reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/autoscalers/{autoscaler}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -60795,9 +73662,13 @@ func (c *RegionAutoscalersGetCall) doRequest(alt string) (*http.Response, error) } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/autoscalers/{autoscaler}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -60968,9 +73839,13 @@ func (c *RegionAutoscalersInsertCall) doRequest(alt string) (*http.Response, err } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/autoscalers") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -61190,9 +74065,13 @@ func (c *RegionAutoscalersListCall) doRequest(alt string) (*http.Response, error } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/autoscalers") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -61406,9 +74285,13 @@ func (c *RegionAutoscalersPatchCall) doRequest(alt string) (*http.Response, erro } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/autoscalers") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PATCH", urls, body) + req, err := http.NewRequest("PATCH", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -61590,9 +74473,13 @@ func (c *RegionAutoscalersUpdateCall) doRequest(alt string) (*http.Response, err } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/autoscalers") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PUT", urls, body) + req, err := http.NewRequest("PUT", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -61761,9 +74648,13 @@ func (c *RegionBackendServicesDeleteCall) doRequest(alt string) (*http.Response, reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/backendServices/{backendService}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -61927,9 +74818,13 @@ func (c *RegionBackendServicesGetCall) doRequest(alt string) (*http.Response, er } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/backendServices/{backendService}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -62083,9 +74978,13 @@ func (c *RegionBackendServicesGetHealthCall) doRequest(alt string) (*http.Respon } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/backendServices/{backendService}/getHealth") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -62261,9 +75160,13 @@ func (c *RegionBackendServicesInsertCall) doRequest(alt string) (*http.Response, } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/backendServices") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -62483,9 +75386,13 @@ func (c *RegionBackendServicesListCall) doRequest(alt string) (*http.Response, e } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/backendServices") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -62697,9 +75604,13 @@ func (c *RegionBackendServicesPatchCall) doRequest(alt string) (*http.Response, } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/backendServices/{backendService}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PATCH", urls, body) + req, err := http.NewRequest("PATCH", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -62759,7 +75670,7 @@ func (c *RegionBackendServicesPatchCall) Do(opts ...googleapi.CallOption) (*Oper // "backendService": { // "description": "Name of the BackendService resource to patch.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -62881,9 +75792,13 @@ func (c *RegionBackendServicesUpdateCall) doRequest(alt string) (*http.Response, } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/backendServices/{backendService}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PUT", urls, body) + req, err := http.NewRequest("PUT", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -63109,9 +76024,13 @@ func (c *RegionCommitmentsAggregatedListCall) doRequest(alt string) (*http.Respo } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/aggregated/commitments") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -63298,9 +76217,13 @@ func (c *RegionCommitmentsGetCall) doRequest(alt string) (*http.Response, error) } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/commitments/{commitment}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -63471,9 +76394,13 @@ func (c *RegionCommitmentsInsertCall) doRequest(alt string) (*http.Response, err } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/commitments") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -63693,9 +76620,13 @@ func (c *RegionCommitmentsListCall) doRequest(alt string) (*http.Response, error } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/commitments") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -63891,9 +76822,13 @@ func (c *RegionDiskTypesGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/diskTypes/{diskType}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -64115,9 +77050,13 @@ func (c *RegionDiskTypesListCall) doRequest(alt string) (*http.Response, error) } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/diskTypes") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -64324,9 +77263,13 @@ func (c *RegionDisksCreateSnapshotCall) doRequest(alt string) (*http.Response, e } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/disks/{disk}/createSnapshot") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -64386,7 +77329,7 @@ func (c *RegionDisksCreateSnapshotCall) Do(opts ...googleapi.CallOption) (*Opera // "disk": { // "description": "Name of the regional persistent disk to snapshot.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -64501,9 +77444,13 @@ func (c *RegionDisksDeleteCall) doRequest(alt string) (*http.Response, error) { reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/disks/{disk}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -64666,9 +77613,13 @@ func (c *RegionDisksGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/disks/{disk}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -64728,7 +77679,7 @@ func (c *RegionDisksGetCall) Do(opts ...googleapi.CallOption) (*Disk, error) { // "disk": { // "description": "Name of the regional persistent disk to return.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -64846,9 +77797,13 @@ func (c *RegionDisksInsertCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/disks") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -65073,9 +78028,13 @@ func (c *RegionDisksListCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/disks") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -65282,9 +78241,13 @@ func (c *RegionDisksResizeCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/disks/{disk}/resize") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -65344,7 +78307,7 @@ func (c *RegionDisksResizeCall) Do(opts ...googleapi.CallOption) (*Operation, er // "disk": { // "description": "Name of the regional persistent disk.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // }, @@ -65463,9 +78426,13 @@ func (c *RegionDisksSetLabelsCall) doRequest(alt string) (*http.Response, error) } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/disks/{resource}/setLabels") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -65542,9 +78509,9 @@ func (c *RegionDisksSetLabelsCall) Do(opts ...googleapi.CallOption) (*Operation, // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -65626,9 +78593,13 @@ func (c *RegionDisksTestIamPermissionsCall) doRequest(alt string) (*http.Respons } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/disks/{resource}/testIamPermissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -65700,9 +78671,9 @@ func (c *RegionDisksTestIamPermissionsCall) Do(opts ...googleapi.CallOption) (*T // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -65736,10 +78707,10 @@ type RegionInstanceGroupManagersAbandonInstancesCall struct { header_ http.Header } -// AbandonInstances: Schedules a group action to remove the specified -// instances from the managed instance group. Abandoning an instance -// does not delete the instance, but it does remove the instance from -// any target pools that are applied by the managed instance group. This +// AbandonInstances: Flags the specified instances to be immediately +// removed from the managed instance group. Abandoning an instance does +// not delete the instance, but it does remove the instance from any +// target pools that are applied by the managed instance group. This // method reduces the targetSize of the managed instance group by the // number of instances that you abandon. This operation is marked as // DONE when the action is scheduled even if the instances have not yet @@ -65819,9 +78790,13 @@ func (c *RegionInstanceGroupManagersAbandonInstancesCall) doRequest(alt string) } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/instanceGroupManagers/{instanceGroupManager}/abandonInstances") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -65869,7 +78844,7 @@ func (c *RegionInstanceGroupManagersAbandonInstancesCall) Do(opts ...googleapi.C } return ret, nil // { - // "description": "Schedules a group action to remove the specified instances from the managed instance group. Abandoning an instance does not delete the instance, but it does remove the instance from any target pools that are applied by the managed instance group. This method reduces the targetSize of the managed instance group by the number of instances that you abandon. This operation is marked as DONE when the action is scheduled even if the instances have not yet been removed from the group. You must separately verify the status of the abandoning action with the listmanagedinstances method.\n\nIf the group is part of a backend service that has enabled connection draining, it can take up to 60 seconds after the connection draining duration has elapsed before the VM instance is removed or deleted.\n\nYou can specify a maximum of 1000 instances with this method per request.", + // "description": "Flags the specified instances to be immediately removed from the managed instance group. Abandoning an instance does not delete the instance, but it does remove the instance from any target pools that are applied by the managed instance group. This method reduces the targetSize of the managed instance group by the number of instances that you abandon. This operation is marked as DONE when the action is scheduled even if the instances have not yet been removed from the group. You must separately verify the status of the abandoning action with the listmanagedinstances method.\n\nIf the group is part of a backend service that has enabled connection draining, it can take up to 60 seconds after the connection draining duration has elapsed before the VM instance is removed or deleted.\n\nYou can specify a maximum of 1000 instances with this method per request.", // "httpMethod": "POST", // "id": "compute.regionInstanceGroupManagers.abandonInstances", // "parameterOrder": [ @@ -65992,9 +78967,13 @@ func (c *RegionInstanceGroupManagersDeleteCall) doRequest(alt string) (*http.Res reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/instanceGroupManagers/{instanceGroupManager}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -66101,14 +79080,15 @@ type RegionInstanceGroupManagersDeleteInstancesCall struct { header_ http.Header } -// DeleteInstances: Schedules a group action to delete the specified -// instances in the managed instance group. The instances are also +// DeleteInstances: Flags the specified instances in the managed +// instance group to be immediately deleted. The instances are also // removed from any target pools of which they were a member. This // method reduces the targetSize of the managed instance group by the -// number of instances that you delete. This operation is marked as DONE -// when the action is scheduled even if the instances are still being -// deleted. You must separately verify the status of the deleting action -// with the listmanagedinstances method. +// number of instances that you delete. The deleteInstances operation is +// marked DONE if the deleteInstances request is successful. The +// underlying actions take additional time. You must separately verify +// the status of the deleting action with the listmanagedinstances +// method. // // If the group is part of a backend service that has enabled connection // draining, it can take up to 60 seconds after the connection draining @@ -66183,9 +79163,13 @@ func (c *RegionInstanceGroupManagersDeleteInstancesCall) doRequest(alt string) ( } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/instanceGroupManagers/{instanceGroupManager}/deleteInstances") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -66233,7 +79217,7 @@ func (c *RegionInstanceGroupManagersDeleteInstancesCall) Do(opts ...googleapi.Ca } return ret, nil // { - // "description": "Schedules a group action to delete the specified instances in the managed instance group. The instances are also removed from any target pools of which they were a member. This method reduces the targetSize of the managed instance group by the number of instances that you delete. This operation is marked as DONE when the action is scheduled even if the instances are still being deleted. You must separately verify the status of the deleting action with the listmanagedinstances method.\n\nIf the group is part of a backend service that has enabled connection draining, it can take up to 60 seconds after the connection draining duration has elapsed before the VM instance is removed or deleted.\n\nYou can specify a maximum of 1000 instances with this method per request.", + // "description": "Flags the specified instances in the managed instance group to be immediately deleted. The instances are also removed from any target pools of which they were a member. This method reduces the targetSize of the managed instance group by the number of instances that you delete. The deleteInstances operation is marked DONE if the deleteInstances request is successful. The underlying actions take additional time. You must separately verify the status of the deleting action with the listmanagedinstances method.\n\nIf the group is part of a backend service that has enabled connection draining, it can take up to 60 seconds after the connection draining duration has elapsed before the VM instance is removed or deleted.\n\nYou can specify a maximum of 1000 instances with this method per request.", // "httpMethod": "POST", // "id": "compute.regionInstanceGroupManagers.deleteInstances", // "parameterOrder": [ @@ -66351,9 +79335,13 @@ func (c *RegionInstanceGroupManagersGetCall) doRequest(alt string) (*http.Respon } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/instanceGroupManagers/{instanceGroupManager}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -66456,12 +79444,12 @@ type RegionInstanceGroupManagersInsertCall struct { } // Insert: Creates a managed instance group using the information that -// you specify in the request. After the group is created, it schedules -// an action to create instances in the group using the specified -// instance template. This operation is marked as DONE when the group is -// created even if the instances in the group have not yet been created. -// You must separately verify the status of the individual instances -// with the listmanagedinstances method. +// you specify in the request. After the group is created, instances in +// the group are created using the specified instance template. This +// operation is marked as DONE when the group is created even if the +// instances in the group have not yet been created. You must separately +// verify the status of the individual instances with the +// listmanagedinstances method. // // A regional managed instance group can contain up to 2000 instances. func (r *RegionInstanceGroupManagersService) Insert(project string, region string, instancegroupmanager *InstanceGroupManager) *RegionInstanceGroupManagersInsertCall { @@ -66529,9 +79517,13 @@ func (c *RegionInstanceGroupManagersInsertCall) doRequest(alt string) (*http.Res } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/instanceGroupManagers") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -66578,7 +79570,7 @@ func (c *RegionInstanceGroupManagersInsertCall) Do(opts ...googleapi.CallOption) } return ret, nil // { - // "description": "Creates a managed instance group using the information that you specify in the request. After the group is created, it schedules an action to create instances in the group using the specified instance template. This operation is marked as DONE when the group is created even if the instances in the group have not yet been created. You must separately verify the status of the individual instances with the listmanagedinstances method.\n\nA regional managed instance group can contain up to 2000 instances.", + // "description": "Creates a managed instance group using the information that you specify in the request. After the group is created, instances in the group are created using the specified instance template. This operation is marked as DONE when the group is created even if the instances in the group have not yet been created. You must separately verify the status of the individual instances with the listmanagedinstances method.\n\nA regional managed instance group can contain up to 2000 instances.", // "httpMethod": "POST", // "id": "compute.regionInstanceGroupManagers.insert", // "parameterOrder": [ @@ -66750,9 +79742,13 @@ func (c *RegionInstanceGroupManagersListCall) doRequest(alt string) (*http.Respo } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/instanceGroupManagers") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -66902,25 +79898,64 @@ func (r *RegionInstanceGroupManagersService) ListManagedInstances(project string return c } -// Filter sets the optional parameter "filter": +// Filter sets the optional parameter "filter": A filter expression that +// filters resources listed in the response. The expression must specify +// the field name, a comparison operator, and the value that you want to +// use for filtering. The value must be a string, a number, or a +// boolean. The comparison operator must be either =, !=, >, or <. +// +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. +// +// You can also filter nested fields. For example, you could specify +// scheduling.automaticRestart = false to include instances only if they +// are not scheduled for automatic restarts. You can use filtering on +// nested fields to filter based on resource labels. +// +// To filter on multiple expressions, provide each separate expression +// within parentheses. For example, (scheduling.automaticRestart = true) +// (cpuPlatform = "Intel Skylake"). By default, each expression is an +// AND expression. However, you can include AND and OR expressions +// explicitly. For example, (cpuPlatform = "Intel Skylake") OR +// (cpuPlatform = "Intel Broadwell") AND (scheduling.automaticRestart = +// true). func (c *RegionInstanceGroupManagersListManagedInstancesCall) Filter(filter string) *RegionInstanceGroupManagersListManagedInstancesCall { c.urlParams_.Set("filter", filter) return c } -// MaxResults sets the optional parameter "maxResults": +// MaxResults sets the optional parameter "maxResults": The maximum +// number of results per page that should be returned. If the number of +// available results is larger than maxResults, Compute Engine returns a +// nextPageToken that can be used to get the next page of results in +// subsequent list requests. Acceptable values are 0 to 500, inclusive. +// (Default: 500) func (c *RegionInstanceGroupManagersListManagedInstancesCall) MaxResults(maxResults int64) *RegionInstanceGroupManagersListManagedInstancesCall { c.urlParams_.Set("maxResults", fmt.Sprint(maxResults)) return c } -// OrderBy sets the optional parameter "order_by": +// OrderBy sets the optional parameter "order_by": Sorts list results by +// a certain order. By default, results are returned in alphanumerical +// order based on the resource name. +// +// You can also sort results in descending order based on the creation +// timestamp using orderBy="creationTimestamp desc". This sorts results +// based on the creationTimestamp field in reverse chronological order +// (newest result first). Use this to sort resources like operations so +// that the newest operation is returned first. +// +// Currently, only sorting by name or creationTimestamp desc is +// supported. func (c *RegionInstanceGroupManagersListManagedInstancesCall) OrderBy(orderBy string) *RegionInstanceGroupManagersListManagedInstancesCall { c.urlParams_.Set("order_by", orderBy) return c } -// PageToken sets the optional parameter "pageToken": +// PageToken sets the optional parameter "pageToken": Specifies a page +// token to use. Set pageToken to the nextPageToken returned by a +// previous list request to get the next page of results. func (c *RegionInstanceGroupManagersListManagedInstancesCall) PageToken(pageToken string) *RegionInstanceGroupManagersListManagedInstancesCall { c.urlParams_.Set("pageToken", pageToken) return c @@ -66959,9 +79994,13 @@ func (c *RegionInstanceGroupManagersListManagedInstancesCall) doRequest(alt stri reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/instanceGroupManagers/{instanceGroupManager}/listManagedInstances") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -67021,6 +80060,7 @@ func (c *RegionInstanceGroupManagersListManagedInstancesCall) Do(opts ...googlea // ], // "parameters": { // "filter": { + // "description": "A filter expression that filters resources listed in the response. The expression must specify the field name, a comparison operator, and the value that you want to use for filtering. The value must be a string, a number, or a boolean. The comparison operator must be either =, !=, \u003e, or \u003c.\n\nFor example, if you are filtering Compute Engine instances, you can exclude instances named example-instance by specifying name != example-instance.\n\nYou can also filter nested fields. For example, you could specify scheduling.automaticRestart = false to include instances only if they are not scheduled for automatic restarts. You can use filtering on nested fields to filter based on resource labels.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart = true) (cpuPlatform = \"Intel Skylake\"). By default, each expression is an AND expression. However, you can include AND and OR expressions explicitly. For example, (cpuPlatform = \"Intel Skylake\") OR (cpuPlatform = \"Intel Broadwell\") AND (scheduling.automaticRestart = true).", // "location": "query", // "type": "string" // }, @@ -67032,16 +80072,19 @@ func (c *RegionInstanceGroupManagersListManagedInstancesCall) Do(opts ...googlea // }, // "maxResults": { // "default": "500", + // "description": "The maximum number of results per page that should be returned. If the number of available results is larger than maxResults, Compute Engine returns a nextPageToken that can be used to get the next page of results in subsequent list requests. Acceptable values are 0 to 500, inclusive. (Default: 500)", // "format": "uint32", // "location": "query", // "minimum": "0", // "type": "integer" // }, // "order_by": { + // "description": "Sorts list results by a certain order. By default, results are returned in alphanumerical order based on the resource name.\n\nYou can also sort results in descending order based on the creation timestamp using orderBy=\"creationTimestamp desc\". This sorts results based on the creationTimestamp field in reverse chronological order (newest result first). Use this to sort resources like operations so that the newest operation is returned first.\n\nCurrently, only sorting by name or creationTimestamp desc is supported.", // "location": "query", // "type": "string" // }, // "pageToken": { + // "description": "Specifies a page token to use. Set pageToken to the nextPageToken returned by a previous list request to get the next page of results.", // "location": "query", // "type": "string" // }, @@ -67072,6 +80115,195 @@ func (c *RegionInstanceGroupManagersListManagedInstancesCall) Do(opts ...googlea } +// method id "compute.regionInstanceGroupManagers.patch": + +type RegionInstanceGroupManagersPatchCall struct { + s *Service + project string + region string + instanceGroupManager string + instancegroupmanager *InstanceGroupManager + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// Patch: Updates a managed instance group using the information that +// you specify in the request. This operation is marked as DONE when the +// group is patched even if the instances in the group are still in the +// process of being patched. You must separately verify the status of +// the individual instances with the listmanagedinstances method. This +// method supports PATCH semantics and uses the JSON merge patch format +// and processing rules. +func (r *RegionInstanceGroupManagersService) Patch(project string, region string, instanceGroupManager string, instancegroupmanager *InstanceGroupManager) *RegionInstanceGroupManagersPatchCall { + c := &RegionInstanceGroupManagersPatchCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.region = region + c.instanceGroupManager = instanceGroupManager + c.instancegroupmanager = instancegroupmanager + return c +} + +// RequestId sets the optional parameter "requestId": An optional +// request ID to identify requests. Specify a unique request ID so that +// if you must retry your request, the server will know to ignore the +// request if it has already been completed. +// +// For example, consider a situation where you make an initial request +// and the request times out. If you make the request again with the +// same request ID, the server can check if original operation with the +// same request ID was received, and if so, will ignore the second +// request. This prevents clients from accidentally creating duplicate +// commitments. +// +// The request ID must be a valid UUID with the exception that zero UUID +// is not supported (00000000-0000-0000-0000-000000000000). +func (c *RegionInstanceGroupManagersPatchCall) RequestId(requestId string) *RegionInstanceGroupManagersPatchCall { + c.urlParams_.Set("requestId", requestId) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *RegionInstanceGroupManagersPatchCall) Fields(s ...googleapi.Field) *RegionInstanceGroupManagersPatchCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *RegionInstanceGroupManagersPatchCall) Context(ctx context.Context) *RegionInstanceGroupManagersPatchCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *RegionInstanceGroupManagersPatchCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *RegionInstanceGroupManagersPatchCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.instancegroupmanager) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/instanceGroupManagers/{instanceGroupManager}") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("PATCH", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "region": c.region, + "instanceGroupManager": c.instanceGroupManager, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.regionInstanceGroupManagers.patch" call. +// Exactly one of *Operation or error will be non-nil. Any non-2xx +// status code is an error. Response headers are in either +// *Operation.ServerResponse.Header or (if a response was returned at +// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified +// to check whether the returned error was because +// http.StatusNotModified was returned. +func (c *RegionInstanceGroupManagersPatchCall) Do(opts ...googleapi.CallOption) (*Operation, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Operation{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Updates a managed instance group using the information that you specify in the request. This operation is marked as DONE when the group is patched even if the instances in the group are still in the process of being patched. You must separately verify the status of the individual instances with the listmanagedinstances method. This method supports PATCH semantics and uses the JSON merge patch format and processing rules.", + // "httpMethod": "PATCH", + // "id": "compute.regionInstanceGroupManagers.patch", + // "parameterOrder": [ + // "project", + // "region", + // "instanceGroupManager" + // ], + // "parameters": { + // "instanceGroupManager": { + // "description": "The name of the instance group manager.", + // "location": "path", + // "required": true, + // "type": "string" + // }, + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "region": { + // "description": "Name of the region scoping this request.", + // "location": "path", + // "required": true, + // "type": "string" + // }, + // "requestId": { + // "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", + // "location": "query", + // "type": "string" + // } + // }, + // "path": "{project}/regions/{region}/instanceGroupManagers/{instanceGroupManager}", + // "request": { + // "$ref": "InstanceGroupManager" + // }, + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + // method id "compute.regionInstanceGroupManagers.recreateInstances": type RegionInstanceGroupManagersRecreateInstancesCall struct { @@ -67085,11 +80317,11 @@ type RegionInstanceGroupManagersRecreateInstancesCall struct { header_ http.Header } -// RecreateInstances: Schedules a group action to recreate the specified -// instances in the managed instance group. The instances are deleted +// RecreateInstances: Flags the specified instances in the managed +// instance group to be immediately recreated. The instances are deleted // and recreated using the current instance template for the managed -// instance group. This operation is marked as DONE when the action is -// scheduled even if the instances have not yet been recreated. You must +// instance group. This operation is marked as DONE when the flag is set +// even if the instances have not yet been recreated. You must // separately verify the status of the recreating action with the // listmanagedinstances method. // @@ -67166,9 +80398,13 @@ func (c *RegionInstanceGroupManagersRecreateInstancesCall) doRequest(alt string) } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/instanceGroupManagers/{instanceGroupManager}/recreateInstances") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -67216,7 +80452,7 @@ func (c *RegionInstanceGroupManagersRecreateInstancesCall) Do(opts ...googleapi. } return ret, nil // { - // "description": "Schedules a group action to recreate the specified instances in the managed instance group. The instances are deleted and recreated using the current instance template for the managed instance group. This operation is marked as DONE when the action is scheduled even if the instances have not yet been recreated. You must separately verify the status of the recreating action with the listmanagedinstances method.\n\nIf the group is part of a backend service that has enabled connection draining, it can take up to 60 seconds after the connection draining duration has elapsed before the VM instance is removed or deleted.\n\nYou can specify a maximum of 1000 instances with this method per request.", + // "description": "Flags the specified instances in the managed instance group to be immediately recreated. The instances are deleted and recreated using the current instance template for the managed instance group. This operation is marked as DONE when the flag is set even if the instances have not yet been recreated. You must separately verify the status of the recreating action with the listmanagedinstances method.\n\nIf the group is part of a backend service that has enabled connection draining, it can take up to 60 seconds after the connection draining duration has elapsed before the VM instance is removed or deleted.\n\nYou can specify a maximum of 1000 instances with this method per request.", // "httpMethod": "POST", // "id": "compute.regionInstanceGroupManagers.recreateInstances", // "parameterOrder": [ @@ -67277,14 +80513,15 @@ type RegionInstanceGroupManagersResizeCall struct { header_ http.Header } -// Resize: Changes the intended size for the managed instance group. If -// you increase the size, the group schedules actions to create new -// instances using the current instance template. If you decrease the -// size, the group schedules delete actions on one or more instances. -// The resize operation is marked DONE when the resize actions are -// scheduled even if the group has not yet added or deleted any -// instances. You must separately verify the status of the creating or -// deleting actions with the listmanagedinstances method. +// Resize: Changes the intended size of the managed instance group. If +// you increase the size, the group creates new instances using the +// current instance template. If you decrease the size, the group +// deletes one or more instances. +// +// The resize operation is marked DONE if the resize request is +// successful. The underlying actions take additional time. You must +// separately verify the status of the creating or deleting actions with +// the listmanagedinstances method. // // If the group is part of a backend service that has enabled connection // draining, it can take up to 60 seconds after the connection draining @@ -67350,9 +80587,13 @@ func (c *RegionInstanceGroupManagersResizeCall) doRequest(alt string) (*http.Res reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/instanceGroupManagers/{instanceGroupManager}/resize") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -67400,7 +80641,7 @@ func (c *RegionInstanceGroupManagersResizeCall) Do(opts ...googleapi.CallOption) } return ret, nil // { - // "description": "Changes the intended size for the managed instance group. If you increase the size, the group schedules actions to create new instances using the current instance template. If you decrease the size, the group schedules delete actions on one or more instances. The resize operation is marked DONE when the resize actions are scheduled even if the group has not yet added or deleted any instances. You must separately verify the status of the creating or deleting actions with the listmanagedinstances method.\n\nIf the group is part of a backend service that has enabled connection draining, it can take up to 60 seconds after the connection draining duration has elapsed before the VM instance is removed or deleted.", + // "description": "Changes the intended size of the managed instance group. If you increase the size, the group creates new instances using the current instance template. If you decrease the size, the group deletes one or more instances.\n\nThe resize operation is marked DONE if the resize request is successful. The underlying actions take additional time. You must separately verify the status of the creating or deleting actions with the listmanagedinstances method.\n\nIf the group is part of a backend service that has enabled connection draining, it can take up to 60 seconds after the connection draining duration has elapsed before the VM instance is removed or deleted.", // "httpMethod": "POST", // "id": "compute.regionInstanceGroupManagers.resize", // "parameterOrder": [ @@ -67537,9 +80778,13 @@ func (c *RegionInstanceGroupManagersSetInstanceTemplateCall) doRequest(alt strin } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/instanceGroupManagers/{instanceGroupManager}/setInstanceTemplate") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -67718,9 +80963,13 @@ func (c *RegionInstanceGroupManagersSetTargetPoolsCall) doRequest(alt string) (* } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/instanceGroupManagers/{instanceGroupManager}/setTargetPools") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -67885,9 +81134,13 @@ func (c *RegionInstanceGroupsGetCall) doRequest(alt string) (*http.Response, err } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/instanceGroups/{instanceGroup}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -68107,9 +81360,13 @@ func (c *RegionInstanceGroupsListCall) doRequest(alt string) (*http.Response, er } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/instanceGroups") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -68362,9 +81619,13 @@ func (c *RegionInstanceGroupsListInstancesCall) doRequest(alt string) (*http.Res } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/instanceGroups/{instanceGroup}/listInstances") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -68583,9 +81844,13 @@ func (c *RegionInstanceGroupsSetNamedPortsCall) doRequest(alt string) (*http.Res } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/instanceGroups/{instanceGroup}/setNamedPorts") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -68737,9 +82002,13 @@ func (c *RegionOperationsDeleteCall) doRequest(alt string) (*http.Response, erro reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/operations/{operation}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -68871,9 +82140,13 @@ func (c *RegionOperationsGetCall) doRequest(alt string) (*http.Response, error) } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/operations/{operation}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -69096,9 +82369,13 @@ func (c *RegionOperationsListCall) doRequest(alt string) (*http.Response, error) } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/operations") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -69293,9 +82570,13 @@ func (c *RegionsGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -69507,9 +82788,13 @@ func (c *RegionsListCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -69754,9 +83039,13 @@ func (c *RoutersAggregatedListCall) doRequest(alt string) (*http.Response, error } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/aggregated/routers") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -69947,9 +83236,13 @@ func (c *RoutersDeleteCall) doRequest(alt string) (*http.Response, error) { reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/routers/{router}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -70114,9 +83407,13 @@ func (c *RoutersGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/routers/{router}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -70208,6 +83505,280 @@ func (c *RoutersGetCall) Do(opts ...googleapi.CallOption) (*Router, error) { } +// method id "compute.routers.getNatMappingInfo": + +type RoutersGetNatMappingInfoCall struct { + s *Service + project string + region string + router string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// GetNatMappingInfo: Retrieves runtime Nat mapping information of VM +// endpoints. +func (r *RoutersService) GetNatMappingInfo(project string, region string, router string) *RoutersGetNatMappingInfoCall { + c := &RoutersGetNatMappingInfoCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.region = region + c.router = router + return c +} + +// Filter sets the optional parameter "filter": A filter expression that +// filters resources listed in the response. The expression must specify +// the field name, a comparison operator, and the value that you want to +// use for filtering. The value must be a string, a number, or a +// boolean. The comparison operator must be either =, !=, >, or <. +// +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. +// +// You can also filter nested fields. For example, you could specify +// scheduling.automaticRestart = false to include instances only if they +// are not scheduled for automatic restarts. You can use filtering on +// nested fields to filter based on resource labels. +// +// To filter on multiple expressions, provide each separate expression +// within parentheses. For example, (scheduling.automaticRestart = true) +// (cpuPlatform = "Intel Skylake"). By default, each expression is an +// AND expression. However, you can include AND and OR expressions +// explicitly. For example, (cpuPlatform = "Intel Skylake") OR +// (cpuPlatform = "Intel Broadwell") AND (scheduling.automaticRestart = +// true). +func (c *RoutersGetNatMappingInfoCall) Filter(filter string) *RoutersGetNatMappingInfoCall { + c.urlParams_.Set("filter", filter) + return c +} + +// MaxResults sets the optional parameter "maxResults": The maximum +// number of results per page that should be returned. If the number of +// available results is larger than maxResults, Compute Engine returns a +// nextPageToken that can be used to get the next page of results in +// subsequent list requests. Acceptable values are 0 to 500, inclusive. +// (Default: 500) +func (c *RoutersGetNatMappingInfoCall) MaxResults(maxResults int64) *RoutersGetNatMappingInfoCall { + c.urlParams_.Set("maxResults", fmt.Sprint(maxResults)) + return c +} + +// OrderBy sets the optional parameter "orderBy": Sorts list results by +// a certain order. By default, results are returned in alphanumerical +// order based on the resource name. +// +// You can also sort results in descending order based on the creation +// timestamp using orderBy="creationTimestamp desc". This sorts results +// based on the creationTimestamp field in reverse chronological order +// (newest result first). Use this to sort resources like operations so +// that the newest operation is returned first. +// +// Currently, only sorting by name or creationTimestamp desc is +// supported. +func (c *RoutersGetNatMappingInfoCall) OrderBy(orderBy string) *RoutersGetNatMappingInfoCall { + c.urlParams_.Set("orderBy", orderBy) + return c +} + +// PageToken sets the optional parameter "pageToken": Specifies a page +// token to use. Set pageToken to the nextPageToken returned by a +// previous list request to get the next page of results. +func (c *RoutersGetNatMappingInfoCall) PageToken(pageToken string) *RoutersGetNatMappingInfoCall { + c.urlParams_.Set("pageToken", pageToken) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *RoutersGetNatMappingInfoCall) Fields(s ...googleapi.Field) *RoutersGetNatMappingInfoCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// IfNoneMatch sets the optional parameter which makes the operation +// fail if the object's ETag matches the given value. This is useful for +// getting updates only after the object has changed since the last +// request. Use googleapi.IsNotModified to check whether the response +// error from Do is the result of In-None-Match. +func (c *RoutersGetNatMappingInfoCall) IfNoneMatch(entityTag string) *RoutersGetNatMappingInfoCall { + c.ifNoneMatch_ = entityTag + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *RoutersGetNatMappingInfoCall) Context(ctx context.Context) *RoutersGetNatMappingInfoCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *RoutersGetNatMappingInfoCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *RoutersGetNatMappingInfoCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + if c.ifNoneMatch_ != "" { + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) + } + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/routers/{router}/getNatMappingInfo") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "region": c.region, + "router": c.router, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.routers.getNatMappingInfo" call. +// Exactly one of *VmEndpointNatMappingsList or error will be non-nil. +// Any non-2xx status code is an error. Response headers are in either +// *VmEndpointNatMappingsList.ServerResponse.Header or (if a response +// was returned at all) in error.(*googleapi.Error).Header. Use +// googleapi.IsNotModified to check whether the returned error was +// because http.StatusNotModified was returned. +func (c *RoutersGetNatMappingInfoCall) Do(opts ...googleapi.CallOption) (*VmEndpointNatMappingsList, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &VmEndpointNatMappingsList{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Retrieves runtime Nat mapping information of VM endpoints.", + // "httpMethod": "GET", + // "id": "compute.routers.getNatMappingInfo", + // "parameterOrder": [ + // "project", + // "region", + // "router" + // ], + // "parameters": { + // "filter": { + // "description": "A filter expression that filters resources listed in the response. The expression must specify the field name, a comparison operator, and the value that you want to use for filtering. The value must be a string, a number, or a boolean. The comparison operator must be either =, !=, \u003e, or \u003c.\n\nFor example, if you are filtering Compute Engine instances, you can exclude instances named example-instance by specifying name != example-instance.\n\nYou can also filter nested fields. For example, you could specify scheduling.automaticRestart = false to include instances only if they are not scheduled for automatic restarts. You can use filtering on nested fields to filter based on resource labels.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart = true) (cpuPlatform = \"Intel Skylake\"). By default, each expression is an AND expression. However, you can include AND and OR expressions explicitly. For example, (cpuPlatform = \"Intel Skylake\") OR (cpuPlatform = \"Intel Broadwell\") AND (scheduling.automaticRestart = true).", + // "location": "query", + // "type": "string" + // }, + // "maxResults": { + // "default": "500", + // "description": "The maximum number of results per page that should be returned. If the number of available results is larger than maxResults, Compute Engine returns a nextPageToken that can be used to get the next page of results in subsequent list requests. Acceptable values are 0 to 500, inclusive. (Default: 500)", + // "format": "uint32", + // "location": "query", + // "minimum": "0", + // "type": "integer" + // }, + // "orderBy": { + // "description": "Sorts list results by a certain order. By default, results are returned in alphanumerical order based on the resource name.\n\nYou can also sort results in descending order based on the creation timestamp using orderBy=\"creationTimestamp desc\". This sorts results based on the creationTimestamp field in reverse chronological order (newest result first). Use this to sort resources like operations so that the newest operation is returned first.\n\nCurrently, only sorting by name or creationTimestamp desc is supported.", + // "location": "query", + // "type": "string" + // }, + // "pageToken": { + // "description": "Specifies a page token to use. Set pageToken to the nextPageToken returned by a previous list request to get the next page of results.", + // "location": "query", + // "type": "string" + // }, + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "region": { + // "description": "Name of the region for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // }, + // "router": { + // "description": "Name of the Router resource to query for Nat Mapping information of VM endpoints.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/regions/{region}/routers/{router}/getNatMappingInfo", + // "response": { + // "$ref": "VmEndpointNatMappingsList" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute", + // "https://www.googleapis.com/auth/compute.readonly" + // ] + // } + +} + +// Pages invokes f for each page of results. +// A non-nil error returned from f will halt the iteration. +// The provided context supersedes any context provided to the Context method. +func (c *RoutersGetNatMappingInfoCall) Pages(ctx context.Context, f func(*VmEndpointNatMappingsList) error) error { + c.ctx_ = ctx + defer c.PageToken(c.urlParams_.Get("pageToken")) // reset paging to original point + for { + x, err := c.Do() + if err != nil { + return err + } + if err := f(x); err != nil { + return err + } + if x.NextPageToken == "" { + return nil + } + c.PageToken(x.NextPageToken) + } +} + // method id "compute.routers.getRouterStatus": type RoutersGetRouterStatusCall struct { @@ -70277,9 +83848,13 @@ func (c *RoutersGetRouterStatusCall) doRequest(alt string) (*http.Response, erro } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/routers/{router}/getRouterStatus") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -70450,9 +84025,13 @@ func (c *RoutersInsertCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/routers") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -70672,9 +84251,13 @@ func (c *RoutersListCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/routers") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -70883,9 +84466,13 @@ func (c *RoutersPatchCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/routers/{router}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PATCH", urls, body) + req, err := http.NewRequest("PATCH", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -71047,9 +84634,13 @@ func (c *RoutersPreviewCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/routers/{router}/preview") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -71225,9 +84816,13 @@ func (c *RoutersUpdateCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/routers/{router}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PUT", urls, body) + req, err := http.NewRequest("PUT", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -71398,9 +84993,13 @@ func (c *RoutesDeleteCall) doRequest(alt string) (*http.Response, error) { reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/routes/{route}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -71470,7 +85069,7 @@ func (c *RoutesDeleteCall) Do(opts ...googleapi.CallOption) (*Operation, error) // "route": { // "description": "Name of the Route resource to delete.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -71555,9 +85154,13 @@ func (c *RoutesGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/routes/{route}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -71622,7 +85225,7 @@ func (c *RoutesGetCall) Do(opts ...googleapi.CallOption) (*Route, error) { // "route": { // "description": "Name of the Route resource to return.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -71718,9 +85321,13 @@ func (c *RoutesInsertCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/routes") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -71930,9 +85537,13 @@ func (c *RoutesListCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/routes") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -72050,6 +85661,1551 @@ func (c *RoutesListCall) Pages(ctx context.Context, f func(*RouteList) error) er } } +// method id "compute.securityPolicies.addRule": + +type SecurityPoliciesAddRuleCall struct { + s *Service + project string + securityPolicy string + securitypolicyrule *SecurityPolicyRule + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// AddRule: Inserts a rule into a security policy. +func (r *SecurityPoliciesService) AddRule(project string, securityPolicy string, securitypolicyrule *SecurityPolicyRule) *SecurityPoliciesAddRuleCall { + c := &SecurityPoliciesAddRuleCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.securityPolicy = securityPolicy + c.securitypolicyrule = securitypolicyrule + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *SecurityPoliciesAddRuleCall) Fields(s ...googleapi.Field) *SecurityPoliciesAddRuleCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *SecurityPoliciesAddRuleCall) Context(ctx context.Context) *SecurityPoliciesAddRuleCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *SecurityPoliciesAddRuleCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *SecurityPoliciesAddRuleCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.securitypolicyrule) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/securityPolicies/{securityPolicy}/addRule") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "securityPolicy": c.securityPolicy, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.securityPolicies.addRule" call. +// Exactly one of *Operation or error will be non-nil. Any non-2xx +// status code is an error. Response headers are in either +// *Operation.ServerResponse.Header or (if a response was returned at +// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified +// to check whether the returned error was because +// http.StatusNotModified was returned. +func (c *SecurityPoliciesAddRuleCall) Do(opts ...googleapi.CallOption) (*Operation, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Operation{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Inserts a rule into a security policy.", + // "httpMethod": "POST", + // "id": "compute.securityPolicies.addRule", + // "parameterOrder": [ + // "project", + // "securityPolicy" + // ], + // "parameters": { + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "securityPolicy": { + // "description": "Name of the security policy to update.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/global/securityPolicies/{securityPolicy}/addRule", + // "request": { + // "$ref": "SecurityPolicyRule" + // }, + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + +// method id "compute.securityPolicies.delete": + +type SecurityPoliciesDeleteCall struct { + s *Service + project string + securityPolicy string + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// Delete: Deletes the specified policy. +func (r *SecurityPoliciesService) Delete(project string, securityPolicy string) *SecurityPoliciesDeleteCall { + c := &SecurityPoliciesDeleteCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.securityPolicy = securityPolicy + return c +} + +// RequestId sets the optional parameter "requestId": An optional +// request ID to identify requests. Specify a unique request ID so that +// if you must retry your request, the server will know to ignore the +// request if it has already been completed. +// +// For example, consider a situation where you make an initial request +// and the request times out. If you make the request again with the +// same request ID, the server can check if original operation with the +// same request ID was received, and if so, will ignore the second +// request. This prevents clients from accidentally creating duplicate +// commitments. +// +// The request ID must be a valid UUID with the exception that zero UUID +// is not supported (00000000-0000-0000-0000-000000000000). +func (c *SecurityPoliciesDeleteCall) RequestId(requestId string) *SecurityPoliciesDeleteCall { + c.urlParams_.Set("requestId", requestId) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *SecurityPoliciesDeleteCall) Fields(s ...googleapi.Field) *SecurityPoliciesDeleteCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *SecurityPoliciesDeleteCall) Context(ctx context.Context) *SecurityPoliciesDeleteCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *SecurityPoliciesDeleteCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *SecurityPoliciesDeleteCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/securityPolicies/{securityPolicy}") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "securityPolicy": c.securityPolicy, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.securityPolicies.delete" call. +// Exactly one of *Operation or error will be non-nil. Any non-2xx +// status code is an error. Response headers are in either +// *Operation.ServerResponse.Header or (if a response was returned at +// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified +// to check whether the returned error was because +// http.StatusNotModified was returned. +func (c *SecurityPoliciesDeleteCall) Do(opts ...googleapi.CallOption) (*Operation, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Operation{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Deletes the specified policy.", + // "httpMethod": "DELETE", + // "id": "compute.securityPolicies.delete", + // "parameterOrder": [ + // "project", + // "securityPolicy" + // ], + // "parameters": { + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "requestId": { + // "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", + // "location": "query", + // "type": "string" + // }, + // "securityPolicy": { + // "description": "Name of the security policy to delete.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/global/securityPolicies/{securityPolicy}", + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + +// method id "compute.securityPolicies.get": + +type SecurityPoliciesGetCall struct { + s *Service + project string + securityPolicy string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// Get: List all of the ordered rules present in a single specified +// policy. +func (r *SecurityPoliciesService) Get(project string, securityPolicy string) *SecurityPoliciesGetCall { + c := &SecurityPoliciesGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.securityPolicy = securityPolicy + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *SecurityPoliciesGetCall) Fields(s ...googleapi.Field) *SecurityPoliciesGetCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// IfNoneMatch sets the optional parameter which makes the operation +// fail if the object's ETag matches the given value. This is useful for +// getting updates only after the object has changed since the last +// request. Use googleapi.IsNotModified to check whether the response +// error from Do is the result of In-None-Match. +func (c *SecurityPoliciesGetCall) IfNoneMatch(entityTag string) *SecurityPoliciesGetCall { + c.ifNoneMatch_ = entityTag + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *SecurityPoliciesGetCall) Context(ctx context.Context) *SecurityPoliciesGetCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *SecurityPoliciesGetCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *SecurityPoliciesGetCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + if c.ifNoneMatch_ != "" { + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) + } + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/securityPolicies/{securityPolicy}") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "securityPolicy": c.securityPolicy, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.securityPolicies.get" call. +// Exactly one of *SecurityPolicy or error will be non-nil. Any non-2xx +// status code is an error. Response headers are in either +// *SecurityPolicy.ServerResponse.Header or (if a response was returned +// at all) in error.(*googleapi.Error).Header. Use +// googleapi.IsNotModified to check whether the returned error was +// because http.StatusNotModified was returned. +func (c *SecurityPoliciesGetCall) Do(opts ...googleapi.CallOption) (*SecurityPolicy, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &SecurityPolicy{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "List all of the ordered rules present in a single specified policy.", + // "httpMethod": "GET", + // "id": "compute.securityPolicies.get", + // "parameterOrder": [ + // "project", + // "securityPolicy" + // ], + // "parameters": { + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "securityPolicy": { + // "description": "Name of the security policy to get.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/global/securityPolicies/{securityPolicy}", + // "response": { + // "$ref": "SecurityPolicy" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute", + // "https://www.googleapis.com/auth/compute.readonly" + // ] + // } + +} + +// method id "compute.securityPolicies.getRule": + +type SecurityPoliciesGetRuleCall struct { + s *Service + project string + securityPolicy string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// GetRule: Gets a rule at the specified priority. +func (r *SecurityPoliciesService) GetRule(project string, securityPolicy string) *SecurityPoliciesGetRuleCall { + c := &SecurityPoliciesGetRuleCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.securityPolicy = securityPolicy + return c +} + +// Priority sets the optional parameter "priority": The priority of the +// rule to get from the security policy. +func (c *SecurityPoliciesGetRuleCall) Priority(priority int64) *SecurityPoliciesGetRuleCall { + c.urlParams_.Set("priority", fmt.Sprint(priority)) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *SecurityPoliciesGetRuleCall) Fields(s ...googleapi.Field) *SecurityPoliciesGetRuleCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// IfNoneMatch sets the optional parameter which makes the operation +// fail if the object's ETag matches the given value. This is useful for +// getting updates only after the object has changed since the last +// request. Use googleapi.IsNotModified to check whether the response +// error from Do is the result of In-None-Match. +func (c *SecurityPoliciesGetRuleCall) IfNoneMatch(entityTag string) *SecurityPoliciesGetRuleCall { + c.ifNoneMatch_ = entityTag + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *SecurityPoliciesGetRuleCall) Context(ctx context.Context) *SecurityPoliciesGetRuleCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *SecurityPoliciesGetRuleCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *SecurityPoliciesGetRuleCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + if c.ifNoneMatch_ != "" { + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) + } + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/securityPolicies/{securityPolicy}/getRule") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "securityPolicy": c.securityPolicy, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.securityPolicies.getRule" call. +// Exactly one of *SecurityPolicyRule or error will be non-nil. Any +// non-2xx status code is an error. Response headers are in either +// *SecurityPolicyRule.ServerResponse.Header or (if a response was +// returned at all) in error.(*googleapi.Error).Header. Use +// googleapi.IsNotModified to check whether the returned error was +// because http.StatusNotModified was returned. +func (c *SecurityPoliciesGetRuleCall) Do(opts ...googleapi.CallOption) (*SecurityPolicyRule, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &SecurityPolicyRule{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Gets a rule at the specified priority.", + // "httpMethod": "GET", + // "id": "compute.securityPolicies.getRule", + // "parameterOrder": [ + // "project", + // "securityPolicy" + // ], + // "parameters": { + // "priority": { + // "description": "The priority of the rule to get from the security policy.", + // "format": "int32", + // "location": "query", + // "type": "integer" + // }, + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "securityPolicy": { + // "description": "Name of the security policy to which the queried rule belongs.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/global/securityPolicies/{securityPolicy}/getRule", + // "response": { + // "$ref": "SecurityPolicyRule" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute", + // "https://www.googleapis.com/auth/compute.readonly" + // ] + // } + +} + +// method id "compute.securityPolicies.insert": + +type SecurityPoliciesInsertCall struct { + s *Service + project string + securitypolicy *SecurityPolicy + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// Insert: Creates a new policy in the specified project using the data +// included in the request. +func (r *SecurityPoliciesService) Insert(project string, securitypolicy *SecurityPolicy) *SecurityPoliciesInsertCall { + c := &SecurityPoliciesInsertCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.securitypolicy = securitypolicy + return c +} + +// RequestId sets the optional parameter "requestId": An optional +// request ID to identify requests. Specify a unique request ID so that +// if you must retry your request, the server will know to ignore the +// request if it has already been completed. +// +// For example, consider a situation where you make an initial request +// and the request times out. If you make the request again with the +// same request ID, the server can check if original operation with the +// same request ID was received, and if so, will ignore the second +// request. This prevents clients from accidentally creating duplicate +// commitments. +// +// The request ID must be a valid UUID with the exception that zero UUID +// is not supported (00000000-0000-0000-0000-000000000000). +func (c *SecurityPoliciesInsertCall) RequestId(requestId string) *SecurityPoliciesInsertCall { + c.urlParams_.Set("requestId", requestId) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *SecurityPoliciesInsertCall) Fields(s ...googleapi.Field) *SecurityPoliciesInsertCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *SecurityPoliciesInsertCall) Context(ctx context.Context) *SecurityPoliciesInsertCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *SecurityPoliciesInsertCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *SecurityPoliciesInsertCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.securitypolicy) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/securityPolicies") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.securityPolicies.insert" call. +// Exactly one of *Operation or error will be non-nil. Any non-2xx +// status code is an error. Response headers are in either +// *Operation.ServerResponse.Header or (if a response was returned at +// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified +// to check whether the returned error was because +// http.StatusNotModified was returned. +func (c *SecurityPoliciesInsertCall) Do(opts ...googleapi.CallOption) (*Operation, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Operation{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Creates a new policy in the specified project using the data included in the request.", + // "httpMethod": "POST", + // "id": "compute.securityPolicies.insert", + // "parameterOrder": [ + // "project" + // ], + // "parameters": { + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "requestId": { + // "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", + // "location": "query", + // "type": "string" + // } + // }, + // "path": "{project}/global/securityPolicies", + // "request": { + // "$ref": "SecurityPolicy" + // }, + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + +// method id "compute.securityPolicies.list": + +type SecurityPoliciesListCall struct { + s *Service + project string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// List: List all the policies that have been configured for the +// specified project. +func (r *SecurityPoliciesService) List(project string) *SecurityPoliciesListCall { + c := &SecurityPoliciesListCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + return c +} + +// Filter sets the optional parameter "filter": A filter expression that +// filters resources listed in the response. The expression must specify +// the field name, a comparison operator, and the value that you want to +// use for filtering. The value must be a string, a number, or a +// boolean. The comparison operator must be either =, !=, >, or <. +// +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. +// +// You can also filter nested fields. For example, you could specify +// scheduling.automaticRestart = false to include instances only if they +// are not scheduled for automatic restarts. You can use filtering on +// nested fields to filter based on resource labels. +// +// To filter on multiple expressions, provide each separate expression +// within parentheses. For example, (scheduling.automaticRestart = true) +// (cpuPlatform = "Intel Skylake"). By default, each expression is an +// AND expression. However, you can include AND and OR expressions +// explicitly. For example, (cpuPlatform = "Intel Skylake") OR +// (cpuPlatform = "Intel Broadwell") AND (scheduling.automaticRestart = +// true). +func (c *SecurityPoliciesListCall) Filter(filter string) *SecurityPoliciesListCall { + c.urlParams_.Set("filter", filter) + return c +} + +// MaxResults sets the optional parameter "maxResults": The maximum +// number of results per page that should be returned. If the number of +// available results is larger than maxResults, Compute Engine returns a +// nextPageToken that can be used to get the next page of results in +// subsequent list requests. Acceptable values are 0 to 500, inclusive. +// (Default: 500) +func (c *SecurityPoliciesListCall) MaxResults(maxResults int64) *SecurityPoliciesListCall { + c.urlParams_.Set("maxResults", fmt.Sprint(maxResults)) + return c +} + +// OrderBy sets the optional parameter "orderBy": Sorts list results by +// a certain order. By default, results are returned in alphanumerical +// order based on the resource name. +// +// You can also sort results in descending order based on the creation +// timestamp using orderBy="creationTimestamp desc". This sorts results +// based on the creationTimestamp field in reverse chronological order +// (newest result first). Use this to sort resources like operations so +// that the newest operation is returned first. +// +// Currently, only sorting by name or creationTimestamp desc is +// supported. +func (c *SecurityPoliciesListCall) OrderBy(orderBy string) *SecurityPoliciesListCall { + c.urlParams_.Set("orderBy", orderBy) + return c +} + +// PageToken sets the optional parameter "pageToken": Specifies a page +// token to use. Set pageToken to the nextPageToken returned by a +// previous list request to get the next page of results. +func (c *SecurityPoliciesListCall) PageToken(pageToken string) *SecurityPoliciesListCall { + c.urlParams_.Set("pageToken", pageToken) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *SecurityPoliciesListCall) Fields(s ...googleapi.Field) *SecurityPoliciesListCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// IfNoneMatch sets the optional parameter which makes the operation +// fail if the object's ETag matches the given value. This is useful for +// getting updates only after the object has changed since the last +// request. Use googleapi.IsNotModified to check whether the response +// error from Do is the result of In-None-Match. +func (c *SecurityPoliciesListCall) IfNoneMatch(entityTag string) *SecurityPoliciesListCall { + c.ifNoneMatch_ = entityTag + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *SecurityPoliciesListCall) Context(ctx context.Context) *SecurityPoliciesListCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *SecurityPoliciesListCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *SecurityPoliciesListCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + if c.ifNoneMatch_ != "" { + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) + } + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/securityPolicies") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.securityPolicies.list" call. +// Exactly one of *SecurityPolicyList or error will be non-nil. Any +// non-2xx status code is an error. Response headers are in either +// *SecurityPolicyList.ServerResponse.Header or (if a response was +// returned at all) in error.(*googleapi.Error).Header. Use +// googleapi.IsNotModified to check whether the returned error was +// because http.StatusNotModified was returned. +func (c *SecurityPoliciesListCall) Do(opts ...googleapi.CallOption) (*SecurityPolicyList, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &SecurityPolicyList{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "List all the policies that have been configured for the specified project.", + // "httpMethod": "GET", + // "id": "compute.securityPolicies.list", + // "parameterOrder": [ + // "project" + // ], + // "parameters": { + // "filter": { + // "description": "A filter expression that filters resources listed in the response. The expression must specify the field name, a comparison operator, and the value that you want to use for filtering. The value must be a string, a number, or a boolean. The comparison operator must be either =, !=, \u003e, or \u003c.\n\nFor example, if you are filtering Compute Engine instances, you can exclude instances named example-instance by specifying name != example-instance.\n\nYou can also filter nested fields. For example, you could specify scheduling.automaticRestart = false to include instances only if they are not scheduled for automatic restarts. You can use filtering on nested fields to filter based on resource labels.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart = true) (cpuPlatform = \"Intel Skylake\"). By default, each expression is an AND expression. However, you can include AND and OR expressions explicitly. For example, (cpuPlatform = \"Intel Skylake\") OR (cpuPlatform = \"Intel Broadwell\") AND (scheduling.automaticRestart = true).", + // "location": "query", + // "type": "string" + // }, + // "maxResults": { + // "default": "500", + // "description": "The maximum number of results per page that should be returned. If the number of available results is larger than maxResults, Compute Engine returns a nextPageToken that can be used to get the next page of results in subsequent list requests. Acceptable values are 0 to 500, inclusive. (Default: 500)", + // "format": "uint32", + // "location": "query", + // "minimum": "0", + // "type": "integer" + // }, + // "orderBy": { + // "description": "Sorts list results by a certain order. By default, results are returned in alphanumerical order based on the resource name.\n\nYou can also sort results in descending order based on the creation timestamp using orderBy=\"creationTimestamp desc\". This sorts results based on the creationTimestamp field in reverse chronological order (newest result first). Use this to sort resources like operations so that the newest operation is returned first.\n\nCurrently, only sorting by name or creationTimestamp desc is supported.", + // "location": "query", + // "type": "string" + // }, + // "pageToken": { + // "description": "Specifies a page token to use. Set pageToken to the nextPageToken returned by a previous list request to get the next page of results.", + // "location": "query", + // "type": "string" + // }, + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/global/securityPolicies", + // "response": { + // "$ref": "SecurityPolicyList" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute", + // "https://www.googleapis.com/auth/compute.readonly" + // ] + // } + +} + +// Pages invokes f for each page of results. +// A non-nil error returned from f will halt the iteration. +// The provided context supersedes any context provided to the Context method. +func (c *SecurityPoliciesListCall) Pages(ctx context.Context, f func(*SecurityPolicyList) error) error { + c.ctx_ = ctx + defer c.PageToken(c.urlParams_.Get("pageToken")) // reset paging to original point + for { + x, err := c.Do() + if err != nil { + return err + } + if err := f(x); err != nil { + return err + } + if x.NextPageToken == "" { + return nil + } + c.PageToken(x.NextPageToken) + } +} + +// method id "compute.securityPolicies.patch": + +type SecurityPoliciesPatchCall struct { + s *Service + project string + securityPolicy string + securitypolicy *SecurityPolicy + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// Patch: Patches the specified policy with the data included in the +// request. +func (r *SecurityPoliciesService) Patch(project string, securityPolicy string, securitypolicy *SecurityPolicy) *SecurityPoliciesPatchCall { + c := &SecurityPoliciesPatchCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.securityPolicy = securityPolicy + c.securitypolicy = securitypolicy + return c +} + +// RequestId sets the optional parameter "requestId": An optional +// request ID to identify requests. Specify a unique request ID so that +// if you must retry your request, the server will know to ignore the +// request if it has already been completed. +// +// For example, consider a situation where you make an initial request +// and the request times out. If you make the request again with the +// same request ID, the server can check if original operation with the +// same request ID was received, and if so, will ignore the second +// request. This prevents clients from accidentally creating duplicate +// commitments. +// +// The request ID must be a valid UUID with the exception that zero UUID +// is not supported (00000000-0000-0000-0000-000000000000). +func (c *SecurityPoliciesPatchCall) RequestId(requestId string) *SecurityPoliciesPatchCall { + c.urlParams_.Set("requestId", requestId) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *SecurityPoliciesPatchCall) Fields(s ...googleapi.Field) *SecurityPoliciesPatchCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *SecurityPoliciesPatchCall) Context(ctx context.Context) *SecurityPoliciesPatchCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *SecurityPoliciesPatchCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *SecurityPoliciesPatchCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.securitypolicy) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/securityPolicies/{securityPolicy}") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("PATCH", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "securityPolicy": c.securityPolicy, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.securityPolicies.patch" call. +// Exactly one of *Operation or error will be non-nil. Any non-2xx +// status code is an error. Response headers are in either +// *Operation.ServerResponse.Header or (if a response was returned at +// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified +// to check whether the returned error was because +// http.StatusNotModified was returned. +func (c *SecurityPoliciesPatchCall) Do(opts ...googleapi.CallOption) (*Operation, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Operation{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Patches the specified policy with the data included in the request.", + // "httpMethod": "PATCH", + // "id": "compute.securityPolicies.patch", + // "parameterOrder": [ + // "project", + // "securityPolicy" + // ], + // "parameters": { + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "requestId": { + // "description": "An optional request ID to identify requests. Specify a unique request ID so that if you must retry your request, the server will know to ignore the request if it has already been completed.\n\nFor example, consider a situation where you make an initial request and the request times out. If you make the request again with the same request ID, the server can check if original operation with the same request ID was received, and if so, will ignore the second request. This prevents clients from accidentally creating duplicate commitments.\n\nThe request ID must be a valid UUID with the exception that zero UUID is not supported (00000000-0000-0000-0000-000000000000).", + // "location": "query", + // "type": "string" + // }, + // "securityPolicy": { + // "description": "Name of the security policy to update.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/global/securityPolicies/{securityPolicy}", + // "request": { + // "$ref": "SecurityPolicy" + // }, + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + +// method id "compute.securityPolicies.patchRule": + +type SecurityPoliciesPatchRuleCall struct { + s *Service + project string + securityPolicy string + securitypolicyrule *SecurityPolicyRule + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// PatchRule: Patches a rule at the specified priority. +func (r *SecurityPoliciesService) PatchRule(project string, securityPolicy string, securitypolicyrule *SecurityPolicyRule) *SecurityPoliciesPatchRuleCall { + c := &SecurityPoliciesPatchRuleCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.securityPolicy = securityPolicy + c.securitypolicyrule = securitypolicyrule + return c +} + +// Priority sets the optional parameter "priority": The priority of the +// rule to patch. +func (c *SecurityPoliciesPatchRuleCall) Priority(priority int64) *SecurityPoliciesPatchRuleCall { + c.urlParams_.Set("priority", fmt.Sprint(priority)) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *SecurityPoliciesPatchRuleCall) Fields(s ...googleapi.Field) *SecurityPoliciesPatchRuleCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *SecurityPoliciesPatchRuleCall) Context(ctx context.Context) *SecurityPoliciesPatchRuleCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *SecurityPoliciesPatchRuleCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *SecurityPoliciesPatchRuleCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.securitypolicyrule) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/securityPolicies/{securityPolicy}/patchRule") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "securityPolicy": c.securityPolicy, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.securityPolicies.patchRule" call. +// Exactly one of *Operation or error will be non-nil. Any non-2xx +// status code is an error. Response headers are in either +// *Operation.ServerResponse.Header or (if a response was returned at +// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified +// to check whether the returned error was because +// http.StatusNotModified was returned. +func (c *SecurityPoliciesPatchRuleCall) Do(opts ...googleapi.CallOption) (*Operation, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Operation{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Patches a rule at the specified priority.", + // "httpMethod": "POST", + // "id": "compute.securityPolicies.patchRule", + // "parameterOrder": [ + // "project", + // "securityPolicy" + // ], + // "parameters": { + // "priority": { + // "description": "The priority of the rule to patch.", + // "format": "int32", + // "location": "query", + // "type": "integer" + // }, + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "securityPolicy": { + // "description": "Name of the security policy to update.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/global/securityPolicies/{securityPolicy}/patchRule", + // "request": { + // "$ref": "SecurityPolicyRule" + // }, + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + +// method id "compute.securityPolicies.removeRule": + +type SecurityPoliciesRemoveRuleCall struct { + s *Service + project string + securityPolicy string + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// RemoveRule: Deletes a rule at the specified priority. +func (r *SecurityPoliciesService) RemoveRule(project string, securityPolicy string) *SecurityPoliciesRemoveRuleCall { + c := &SecurityPoliciesRemoveRuleCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.securityPolicy = securityPolicy + return c +} + +// Priority sets the optional parameter "priority": The priority of the +// rule to remove from the security policy. +func (c *SecurityPoliciesRemoveRuleCall) Priority(priority int64) *SecurityPoliciesRemoveRuleCall { + c.urlParams_.Set("priority", fmt.Sprint(priority)) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *SecurityPoliciesRemoveRuleCall) Fields(s ...googleapi.Field) *SecurityPoliciesRemoveRuleCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *SecurityPoliciesRemoveRuleCall) Context(ctx context.Context) *SecurityPoliciesRemoveRuleCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *SecurityPoliciesRemoveRuleCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *SecurityPoliciesRemoveRuleCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/securityPolicies/{securityPolicy}/removeRule") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "securityPolicy": c.securityPolicy, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.securityPolicies.removeRule" call. +// Exactly one of *Operation or error will be non-nil. Any non-2xx +// status code is an error. Response headers are in either +// *Operation.ServerResponse.Header or (if a response was returned at +// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified +// to check whether the returned error was because +// http.StatusNotModified was returned. +func (c *SecurityPoliciesRemoveRuleCall) Do(opts ...googleapi.CallOption) (*Operation, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Operation{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Deletes a rule at the specified priority.", + // "httpMethod": "POST", + // "id": "compute.securityPolicies.removeRule", + // "parameterOrder": [ + // "project", + // "securityPolicy" + // ], + // "parameters": { + // "priority": { + // "description": "The priority of the rule to remove from the security policy.", + // "format": "int32", + // "location": "query", + // "type": "integer" + // }, + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "securityPolicy": { + // "description": "Name of the security policy to update.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/global/securityPolicies/{securityPolicy}/removeRule", + // "response": { + // "$ref": "Operation" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + // method id "compute.snapshots.delete": type SnapshotsDeleteCall struct { @@ -72067,7 +87223,7 @@ type SnapshotsDeleteCall struct { // deletion is needed for subsequent snapshots, the data will be moved // to the next corresponding snapshot. // -// For more information, see Deleting snaphots. +// For more information, see Deleting snapshots. // For details, see https://cloud.google.com/compute/docs/reference/latest/snapshots/delete func (r *SnapshotsService) Delete(project string, snapshot string) *SnapshotsDeleteCall { c := &SnapshotsDeleteCall{s: r.s, urlParams_: make(gensupport.URLParams)} @@ -72128,9 +87284,13 @@ func (c *SnapshotsDeleteCall) doRequest(alt string) (*http.Response, error) { reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/snapshots/{snapshot}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -72177,7 +87337,7 @@ func (c *SnapshotsDeleteCall) Do(opts ...googleapi.CallOption) (*Operation, erro } return ret, nil // { - // "description": "Deletes the specified Snapshot resource. Keep in mind that deleting a single snapshot might not necessarily delete all the data on that snapshot. If any data on the snapshot that is marked for deletion is needed for subsequent snapshots, the data will be moved to the next corresponding snapshot.\n\nFor more information, see Deleting snaphots.", + // "description": "Deletes the specified Snapshot resource. Keep in mind that deleting a single snapshot might not necessarily delete all the data on that snapshot. If any data on the snapshot that is marked for deletion is needed for subsequent snapshots, the data will be moved to the next corresponding snapshot.\n\nFor more information, see Deleting snapshots.", // "httpMethod": "DELETE", // "id": "compute.snapshots.delete", // "parameterOrder": [ @@ -72200,7 +87360,7 @@ func (c *SnapshotsDeleteCall) Do(opts ...googleapi.CallOption) (*Operation, erro // "snapshot": { // "description": "Name of the Snapshot resource to delete.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -72285,9 +87445,13 @@ func (c *SnapshotsGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/snapshots/{snapshot}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -72352,7 +87516,7 @@ func (c *SnapshotsGetCall) Do(opts ...googleapi.CallOption) (*Snapshot, error) { // "snapshot": { // "description": "Name of the Snapshot resource to return.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -72370,6 +87534,162 @@ func (c *SnapshotsGetCall) Do(opts ...googleapi.CallOption) (*Snapshot, error) { } +// method id "compute.snapshots.getIamPolicy": + +type SnapshotsGetIamPolicyCall struct { + s *Service + project string + resource string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// GetIamPolicy: Gets the access control policy for a resource. May be +// empty if no such policy or resource exists. +func (r *SnapshotsService) GetIamPolicy(project string, resource string) *SnapshotsGetIamPolicyCall { + c := &SnapshotsGetIamPolicyCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.resource = resource + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *SnapshotsGetIamPolicyCall) Fields(s ...googleapi.Field) *SnapshotsGetIamPolicyCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// IfNoneMatch sets the optional parameter which makes the operation +// fail if the object's ETag matches the given value. This is useful for +// getting updates only after the object has changed since the last +// request. Use googleapi.IsNotModified to check whether the response +// error from Do is the result of In-None-Match. +func (c *SnapshotsGetIamPolicyCall) IfNoneMatch(entityTag string) *SnapshotsGetIamPolicyCall { + c.ifNoneMatch_ = entityTag + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *SnapshotsGetIamPolicyCall) Context(ctx context.Context) *SnapshotsGetIamPolicyCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *SnapshotsGetIamPolicyCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *SnapshotsGetIamPolicyCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + if c.ifNoneMatch_ != "" { + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) + } + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/snapshots/{resource}/getIamPolicy") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "resource": c.resource, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.snapshots.getIamPolicy" call. +// Exactly one of *Policy or error will be non-nil. Any non-2xx status +// code is an error. Response headers are in either +// *Policy.ServerResponse.Header or (if a response was returned at all) +// in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to +// check whether the returned error was because http.StatusNotModified +// was returned. +func (c *SnapshotsGetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Policy, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Policy{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Gets the access control policy for a resource. May be empty if no such policy or resource exists.", + // "httpMethod": "GET", + // "id": "compute.snapshots.getIamPolicy", + // "parameterOrder": [ + // "project", + // "resource" + // ], + // "parameters": { + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "resource": { + // "description": "Name or id of the resource for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/global/snapshots/{resource}/getIamPolicy", + // "response": { + // "$ref": "Policy" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute", + // "https://www.googleapis.com/auth/compute.readonly" + // ] + // } + +} + // method id "compute.snapshots.list": type SnapshotsListCall struct { @@ -72499,9 +87819,13 @@ func (c *SnapshotsListCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/snapshots") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -72619,6 +87943,157 @@ func (c *SnapshotsListCall) Pages(ctx context.Context, f func(*SnapshotList) err } } +// method id "compute.snapshots.setIamPolicy": + +type SnapshotsSetIamPolicyCall struct { + s *Service + project string + resource string + globalsetpolicyrequest *GlobalSetPolicyRequest + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// SetIamPolicy: Sets the access control policy on the specified +// resource. Replaces any existing policy. +func (r *SnapshotsService) SetIamPolicy(project string, resource string, globalsetpolicyrequest *GlobalSetPolicyRequest) *SnapshotsSetIamPolicyCall { + c := &SnapshotsSetIamPolicyCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.resource = resource + c.globalsetpolicyrequest = globalsetpolicyrequest + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *SnapshotsSetIamPolicyCall) Fields(s ...googleapi.Field) *SnapshotsSetIamPolicyCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *SnapshotsSetIamPolicyCall) Context(ctx context.Context) *SnapshotsSetIamPolicyCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *SnapshotsSetIamPolicyCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *SnapshotsSetIamPolicyCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.globalsetpolicyrequest) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/snapshots/{resource}/setIamPolicy") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "resource": c.resource, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.snapshots.setIamPolicy" call. +// Exactly one of *Policy or error will be non-nil. Any non-2xx status +// code is an error. Response headers are in either +// *Policy.ServerResponse.Header or (if a response was returned at all) +// in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to +// check whether the returned error was because http.StatusNotModified +// was returned. +func (c *SnapshotsSetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Policy, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Policy{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Sets the access control policy on the specified resource. Replaces any existing policy.", + // "httpMethod": "POST", + // "id": "compute.snapshots.setIamPolicy", + // "parameterOrder": [ + // "project", + // "resource" + // ], + // "parameters": { + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "resource": { + // "description": "Name or id of the resource for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/global/snapshots/{resource}/setIamPolicy", + // "request": { + // "$ref": "GlobalSetPolicyRequest" + // }, + // "response": { + // "$ref": "Policy" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + // method id "compute.snapshots.setLabels": type SnapshotsSetLabelsCall struct { @@ -72679,9 +88154,13 @@ func (c *SnapshotsSetLabelsCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/snapshots/{resource}/setLabels") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -72744,9 +88223,9 @@ func (c *SnapshotsSetLabelsCall) Do(opts ...googleapi.CallOption) (*Operation, e // "type": "string" // }, // "resource": { - // "description": "Name of the resource for this request.", + // "description": "Name or id of the resource for this request.", // "location": "path", - // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?", + // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", // "required": true, // "type": "string" // } @@ -72766,6 +88245,158 @@ func (c *SnapshotsSetLabelsCall) Do(opts ...googleapi.CallOption) (*Operation, e } +// method id "compute.snapshots.testIamPermissions": + +type SnapshotsTestIamPermissionsCall struct { + s *Service + project string + resource string + testpermissionsrequest *TestPermissionsRequest + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// TestIamPermissions: Returns permissions that a caller has on the +// specified resource. +func (r *SnapshotsService) TestIamPermissions(project string, resource string, testpermissionsrequest *TestPermissionsRequest) *SnapshotsTestIamPermissionsCall { + c := &SnapshotsTestIamPermissionsCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.resource = resource + c.testpermissionsrequest = testpermissionsrequest + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *SnapshotsTestIamPermissionsCall) Fields(s ...googleapi.Field) *SnapshotsTestIamPermissionsCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *SnapshotsTestIamPermissionsCall) Context(ctx context.Context) *SnapshotsTestIamPermissionsCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *SnapshotsTestIamPermissionsCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *SnapshotsTestIamPermissionsCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.testpermissionsrequest) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/snapshots/{resource}/testIamPermissions") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "resource": c.resource, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.snapshots.testIamPermissions" call. +// Exactly one of *TestPermissionsResponse or error will be non-nil. Any +// non-2xx status code is an error. Response headers are in either +// *TestPermissionsResponse.ServerResponse.Header or (if a response was +// returned at all) in error.(*googleapi.Error).Header. Use +// googleapi.IsNotModified to check whether the returned error was +// because http.StatusNotModified was returned. +func (c *SnapshotsTestIamPermissionsCall) Do(opts ...googleapi.CallOption) (*TestPermissionsResponse, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &TestPermissionsResponse{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Returns permissions that a caller has on the specified resource.", + // "httpMethod": "POST", + // "id": "compute.snapshots.testIamPermissions", + // "parameterOrder": [ + // "project", + // "resource" + // ], + // "parameters": { + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "resource": { + // "description": "Name or id of the resource for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9_]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/global/snapshots/{resource}/testIamPermissions", + // "request": { + // "$ref": "TestPermissionsRequest" + // }, + // "response": { + // "$ref": "TestPermissionsResponse" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute", + // "https://www.googleapis.com/auth/compute.readonly" + // ] + // } + +} + // method id "compute.sslCertificates.delete": type SslCertificatesDeleteCall struct { @@ -72837,9 +88468,13 @@ func (c *SslCertificatesDeleteCall) doRequest(alt string) (*http.Response, error reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/sslCertificates/{sslCertificate}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -72993,9 +88628,13 @@ func (c *SslCertificatesGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/sslCertificates/{sslCertificate}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -73155,9 +88794,13 @@ func (c *SslCertificatesInsertCall) doRequest(alt string) (*http.Response, error } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/sslCertificates") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -73366,9 +89009,13 @@ func (c *SslCertificatesListCall) doRequest(alt string) (*http.Response, error) } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/sslCertificates") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -73559,9 +89206,13 @@ func (c *SslPoliciesDeleteCall) doRequest(alt string) (*http.Response, error) { reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/sslPolicies/{sslPolicy}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -73714,9 +89365,13 @@ func (c *SslPoliciesGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/sslPolicies/{sslPolicy}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -73875,9 +89530,13 @@ func (c *SslPoliciesInsertCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/sslPolicies") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -74086,9 +89745,13 @@ func (c *SslPoliciesListCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/sslPolicies") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -74334,9 +89997,13 @@ func (c *SslPoliciesListAvailableFeaturesCall) doRequest(alt string) (*http.Resp } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/sslPolicies/listAvailableFeatures") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -74514,9 +90181,13 @@ func (c *SslPoliciesPatchCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/sslPolicies/{sslPolicy}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PATCH", urls, body) + req, err := http.NewRequest("PATCH", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -74732,9 +90403,13 @@ func (c *SubnetworksAggregatedListCall) doRequest(alt string) (*http.Response, e } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/aggregated/subnetworks") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -74925,9 +90600,13 @@ func (c *SubnetworksDeleteCall) doRequest(alt string) (*http.Response, error) { reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/subnetworks/{subnetwork}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -75104,9 +90783,13 @@ func (c *SubnetworksExpandIpCidrRangeCall) doRequest(alt string) (*http.Response } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/subnetworks/{subnetwork}/expandIpCidrRange") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -75274,9 +90957,13 @@ func (c *SubnetworksGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/subnetworks/{subnetwork}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -75368,6 +91055,173 @@ func (c *SubnetworksGetCall) Do(opts ...googleapi.CallOption) (*Subnetwork, erro } +// method id "compute.subnetworks.getIamPolicy": + +type SubnetworksGetIamPolicyCall struct { + s *Service + project string + region string + resource string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// GetIamPolicy: Gets the access control policy for a resource. May be +// empty if no such policy or resource exists. +func (r *SubnetworksService) GetIamPolicy(project string, region string, resource string) *SubnetworksGetIamPolicyCall { + c := &SubnetworksGetIamPolicyCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.region = region + c.resource = resource + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *SubnetworksGetIamPolicyCall) Fields(s ...googleapi.Field) *SubnetworksGetIamPolicyCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// IfNoneMatch sets the optional parameter which makes the operation +// fail if the object's ETag matches the given value. This is useful for +// getting updates only after the object has changed since the last +// request. Use googleapi.IsNotModified to check whether the response +// error from Do is the result of In-None-Match. +func (c *SubnetworksGetIamPolicyCall) IfNoneMatch(entityTag string) *SubnetworksGetIamPolicyCall { + c.ifNoneMatch_ = entityTag + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *SubnetworksGetIamPolicyCall) Context(ctx context.Context) *SubnetworksGetIamPolicyCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *SubnetworksGetIamPolicyCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *SubnetworksGetIamPolicyCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + if c.ifNoneMatch_ != "" { + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) + } + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/subnetworks/{resource}/getIamPolicy") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "region": c.region, + "resource": c.resource, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.subnetworks.getIamPolicy" call. +// Exactly one of *Policy or error will be non-nil. Any non-2xx status +// code is an error. Response headers are in either +// *Policy.ServerResponse.Header or (if a response was returned at all) +// in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to +// check whether the returned error was because http.StatusNotModified +// was returned. +func (c *SubnetworksGetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Policy, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Policy{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Gets the access control policy for a resource. May be empty if no such policy or resource exists.", + // "httpMethod": "GET", + // "id": "compute.subnetworks.getIamPolicy", + // "parameterOrder": [ + // "project", + // "region", + // "resource" + // ], + // "parameters": { + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "region": { + // "description": "The name of the region for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // }, + // "resource": { + // "description": "Name or id of the resource for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/regions/{region}/subnetworks/{resource}/getIamPolicy", + // "response": { + // "$ref": "Policy" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute", + // "https://www.googleapis.com/auth/compute.readonly" + // ] + // } + +} + // method id "compute.subnetworks.insert": type SubnetworksInsertCall struct { @@ -75447,9 +91301,13 @@ func (c *SubnetworksInsertCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/subnetworks") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -75669,9 +91527,13 @@ func (c *SubnetworksListCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/subnetworks") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -75798,6 +91660,257 @@ func (c *SubnetworksListCall) Pages(ctx context.Context, f func(*SubnetworkList) } } +// method id "compute.subnetworks.listUsable": + +type SubnetworksListUsableCall struct { + s *Service + project string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// ListUsable: Retrieves an aggregated list of usable subnetworks. +func (r *SubnetworksService) ListUsable(project string) *SubnetworksListUsableCall { + c := &SubnetworksListUsableCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + return c +} + +// Filter sets the optional parameter "filter": A filter expression that +// filters resources listed in the response. The expression must specify +// the field name, a comparison operator, and the value that you want to +// use for filtering. The value must be a string, a number, or a +// boolean. The comparison operator must be either =, !=, >, or <. +// +// For example, if you are filtering Compute Engine instances, you can +// exclude instances named example-instance by specifying name != +// example-instance. +// +// You can also filter nested fields. For example, you could specify +// scheduling.automaticRestart = false to include instances only if they +// are not scheduled for automatic restarts. You can use filtering on +// nested fields to filter based on resource labels. +// +// To filter on multiple expressions, provide each separate expression +// within parentheses. For example, (scheduling.automaticRestart = true) +// (cpuPlatform = "Intel Skylake"). By default, each expression is an +// AND expression. However, you can include AND and OR expressions +// explicitly. For example, (cpuPlatform = "Intel Skylake") OR +// (cpuPlatform = "Intel Broadwell") AND (scheduling.automaticRestart = +// true). +func (c *SubnetworksListUsableCall) Filter(filter string) *SubnetworksListUsableCall { + c.urlParams_.Set("filter", filter) + return c +} + +// MaxResults sets the optional parameter "maxResults": The maximum +// number of results per page that should be returned. If the number of +// available results is larger than maxResults, Compute Engine returns a +// nextPageToken that can be used to get the next page of results in +// subsequent list requests. Acceptable values are 0 to 500, inclusive. +// (Default: 500) +func (c *SubnetworksListUsableCall) MaxResults(maxResults int64) *SubnetworksListUsableCall { + c.urlParams_.Set("maxResults", fmt.Sprint(maxResults)) + return c +} + +// OrderBy sets the optional parameter "orderBy": Sorts list results by +// a certain order. By default, results are returned in alphanumerical +// order based on the resource name. +// +// You can also sort results in descending order based on the creation +// timestamp using orderBy="creationTimestamp desc". This sorts results +// based on the creationTimestamp field in reverse chronological order +// (newest result first). Use this to sort resources like operations so +// that the newest operation is returned first. +// +// Currently, only sorting by name or creationTimestamp desc is +// supported. +func (c *SubnetworksListUsableCall) OrderBy(orderBy string) *SubnetworksListUsableCall { + c.urlParams_.Set("orderBy", orderBy) + return c +} + +// PageToken sets the optional parameter "pageToken": Specifies a page +// token to use. Set pageToken to the nextPageToken returned by a +// previous list request to get the next page of results. +func (c *SubnetworksListUsableCall) PageToken(pageToken string) *SubnetworksListUsableCall { + c.urlParams_.Set("pageToken", pageToken) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *SubnetworksListUsableCall) Fields(s ...googleapi.Field) *SubnetworksListUsableCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// IfNoneMatch sets the optional parameter which makes the operation +// fail if the object's ETag matches the given value. This is useful for +// getting updates only after the object has changed since the last +// request. Use googleapi.IsNotModified to check whether the response +// error from Do is the result of In-None-Match. +func (c *SubnetworksListUsableCall) IfNoneMatch(entityTag string) *SubnetworksListUsableCall { + c.ifNoneMatch_ = entityTag + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *SubnetworksListUsableCall) Context(ctx context.Context) *SubnetworksListUsableCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *SubnetworksListUsableCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *SubnetworksListUsableCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + if c.ifNoneMatch_ != "" { + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) + } + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/aggregated/subnetworks/listUsable") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.subnetworks.listUsable" call. +// Exactly one of *UsableSubnetworksAggregatedList or error will be +// non-nil. Any non-2xx status code is an error. Response headers are in +// either *UsableSubnetworksAggregatedList.ServerResponse.Header or (if +// a response was returned at all) in error.(*googleapi.Error).Header. +// Use googleapi.IsNotModified to check whether the returned error was +// because http.StatusNotModified was returned. +func (c *SubnetworksListUsableCall) Do(opts ...googleapi.CallOption) (*UsableSubnetworksAggregatedList, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &UsableSubnetworksAggregatedList{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Retrieves an aggregated list of usable subnetworks.", + // "httpMethod": "GET", + // "id": "compute.subnetworks.listUsable", + // "parameterOrder": [ + // "project" + // ], + // "parameters": { + // "filter": { + // "description": "A filter expression that filters resources listed in the response. The expression must specify the field name, a comparison operator, and the value that you want to use for filtering. The value must be a string, a number, or a boolean. The comparison operator must be either =, !=, \u003e, or \u003c.\n\nFor example, if you are filtering Compute Engine instances, you can exclude instances named example-instance by specifying name != example-instance.\n\nYou can also filter nested fields. For example, you could specify scheduling.automaticRestart = false to include instances only if they are not scheduled for automatic restarts. You can use filtering on nested fields to filter based on resource labels.\n\nTo filter on multiple expressions, provide each separate expression within parentheses. For example, (scheduling.automaticRestart = true) (cpuPlatform = \"Intel Skylake\"). By default, each expression is an AND expression. However, you can include AND and OR expressions explicitly. For example, (cpuPlatform = \"Intel Skylake\") OR (cpuPlatform = \"Intel Broadwell\") AND (scheduling.automaticRestart = true).", + // "location": "query", + // "type": "string" + // }, + // "maxResults": { + // "default": "500", + // "description": "The maximum number of results per page that should be returned. If the number of available results is larger than maxResults, Compute Engine returns a nextPageToken that can be used to get the next page of results in subsequent list requests. Acceptable values are 0 to 500, inclusive. (Default: 500)", + // "format": "uint32", + // "location": "query", + // "minimum": "0", + // "type": "integer" + // }, + // "orderBy": { + // "description": "Sorts list results by a certain order. By default, results are returned in alphanumerical order based on the resource name.\n\nYou can also sort results in descending order based on the creation timestamp using orderBy=\"creationTimestamp desc\". This sorts results based on the creationTimestamp field in reverse chronological order (newest result first). Use this to sort resources like operations so that the newest operation is returned first.\n\nCurrently, only sorting by name or creationTimestamp desc is supported.", + // "location": "query", + // "type": "string" + // }, + // "pageToken": { + // "description": "Specifies a page token to use. Set pageToken to the nextPageToken returned by a previous list request to get the next page of results.", + // "location": "query", + // "type": "string" + // }, + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/aggregated/subnetworks/listUsable", + // "response": { + // "$ref": "UsableSubnetworksAggregatedList" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute", + // "https://www.googleapis.com/auth/compute.readonly" + // ] + // } + +} + +// Pages invokes f for each page of results. +// A non-nil error returned from f will halt the iteration. +// The provided context supersedes any context provided to the Context method. +func (c *SubnetworksListUsableCall) Pages(ctx context.Context, f func(*UsableSubnetworksAggregatedList) error) error { + c.ctx_ = ctx + defer c.PageToken(c.urlParams_.Get("pageToken")) // reset paging to original point + for { + x, err := c.Do() + if err != nil { + return err + } + if err := f(x); err != nil { + return err + } + if x.NextPageToken == "" { + return nil + } + c.PageToken(x.NextPageToken) + } +} + // method id "compute.subnetworks.patch": type SubnetworksPatchCall struct { @@ -75812,11 +91925,9 @@ type SubnetworksPatchCall struct { } // Patch: Patches the specified subnetwork with the data included in the -// request. Only the following fields within the subnetwork resource can -// be specified in the request: secondary_ip_range, -// allow_subnet_cidr_routes_overlap and role. It is also mandatory to -// specify the current fingeprint of the subnetwork resource being -// patched. +// request. Only certain fields can up updated with a patch request as +// indicated in the field descriptions. You must specify the current +// fingeprint of the subnetwork resource being patched. func (r *SubnetworksService) Patch(project string, region string, subnetwork string, subnetwork2 *Subnetwork) *SubnetworksPatchCall { c := &SubnetworksPatchCall{s: r.s, urlParams_: make(gensupport.URLParams)} c.project = project @@ -75883,9 +91994,13 @@ func (c *SubnetworksPatchCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/subnetworks/{subnetwork}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PATCH", urls, body) + req, err := http.NewRequest("PATCH", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -75933,7 +92048,7 @@ func (c *SubnetworksPatchCall) Do(opts ...googleapi.CallOption) (*Operation, err } return ret, nil // { - // "description": "Patches the specified subnetwork with the data included in the request. Only the following fields within the subnetwork resource can be specified in the request: secondary_ip_range, allow_subnet_cidr_routes_overlap and role. It is also mandatory to specify the current fingeprint of the subnetwork resource being patched.", + // "description": "Patches the specified subnetwork with the data included in the request. Only certain fields can up updated with a patch request as indicated in the field descriptions. You must specify the current fingeprint of the subnetwork resource being patched.", // "httpMethod": "PATCH", // "id": "compute.subnetworks.patch", // "parameterOrder": [ @@ -75984,6 +92099,168 @@ func (c *SubnetworksPatchCall) Do(opts ...googleapi.CallOption) (*Operation, err } +// method id "compute.subnetworks.setIamPolicy": + +type SubnetworksSetIamPolicyCall struct { + s *Service + project string + region string + resource string + regionsetpolicyrequest *RegionSetPolicyRequest + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// SetIamPolicy: Sets the access control policy on the specified +// resource. Replaces any existing policy. +func (r *SubnetworksService) SetIamPolicy(project string, region string, resource string, regionsetpolicyrequest *RegionSetPolicyRequest) *SubnetworksSetIamPolicyCall { + c := &SubnetworksSetIamPolicyCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.region = region + c.resource = resource + c.regionsetpolicyrequest = regionsetpolicyrequest + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *SubnetworksSetIamPolicyCall) Fields(s ...googleapi.Field) *SubnetworksSetIamPolicyCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *SubnetworksSetIamPolicyCall) Context(ctx context.Context) *SubnetworksSetIamPolicyCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *SubnetworksSetIamPolicyCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *SubnetworksSetIamPolicyCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.regionsetpolicyrequest) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/subnetworks/{resource}/setIamPolicy") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "region": c.region, + "resource": c.resource, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.subnetworks.setIamPolicy" call. +// Exactly one of *Policy or error will be non-nil. Any non-2xx status +// code is an error. Response headers are in either +// *Policy.ServerResponse.Header or (if a response was returned at all) +// in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to +// check whether the returned error was because http.StatusNotModified +// was returned. +func (c *SubnetworksSetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Policy, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Policy{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Sets the access control policy on the specified resource. Replaces any existing policy.", + // "httpMethod": "POST", + // "id": "compute.subnetworks.setIamPolicy", + // "parameterOrder": [ + // "project", + // "region", + // "resource" + // ], + // "parameters": { + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "region": { + // "description": "The name of the region for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // }, + // "resource": { + // "description": "Name or id of the resource for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/regions/{region}/subnetworks/{resource}/setIamPolicy", + // "request": { + // "$ref": "RegionSetPolicyRequest" + // }, + // "response": { + // "$ref": "Policy" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute" + // ] + // } + +} + // method id "compute.subnetworks.setPrivateIpGoogleAccess": type SubnetworksSetPrivateIpGoogleAccessCall struct { @@ -76066,9 +92343,13 @@ func (c *SubnetworksSetPrivateIpGoogleAccessCall) doRequest(alt string) (*http.R } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/subnetworks/{subnetwork}/setPrivateIpGoogleAccess") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -76167,6 +92448,169 @@ func (c *SubnetworksSetPrivateIpGoogleAccessCall) Do(opts ...googleapi.CallOptio } +// method id "compute.subnetworks.testIamPermissions": + +type SubnetworksTestIamPermissionsCall struct { + s *Service + project string + region string + resource string + testpermissionsrequest *TestPermissionsRequest + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// TestIamPermissions: Returns permissions that a caller has on the +// specified resource. +func (r *SubnetworksService) TestIamPermissions(project string, region string, resource string, testpermissionsrequest *TestPermissionsRequest) *SubnetworksTestIamPermissionsCall { + c := &SubnetworksTestIamPermissionsCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.project = project + c.region = region + c.resource = resource + c.testpermissionsrequest = testpermissionsrequest + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *SubnetworksTestIamPermissionsCall) Fields(s ...googleapi.Field) *SubnetworksTestIamPermissionsCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *SubnetworksTestIamPermissionsCall) Context(ctx context.Context) *SubnetworksTestIamPermissionsCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *SubnetworksTestIamPermissionsCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *SubnetworksTestIamPermissionsCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.testpermissionsrequest) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/subnetworks/{resource}/testIamPermissions") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "project": c.project, + "region": c.region, + "resource": c.resource, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "compute.subnetworks.testIamPermissions" call. +// Exactly one of *TestPermissionsResponse or error will be non-nil. Any +// non-2xx status code is an error. Response headers are in either +// *TestPermissionsResponse.ServerResponse.Header or (if a response was +// returned at all) in error.(*googleapi.Error).Header. Use +// googleapi.IsNotModified to check whether the returned error was +// because http.StatusNotModified was returned. +func (c *SubnetworksTestIamPermissionsCall) Do(opts ...googleapi.CallOption) (*TestPermissionsResponse, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &TestPermissionsResponse{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Returns permissions that a caller has on the specified resource.", + // "httpMethod": "POST", + // "id": "compute.subnetworks.testIamPermissions", + // "parameterOrder": [ + // "project", + // "region", + // "resource" + // ], + // "parameters": { + // "project": { + // "description": "Project ID for this request.", + // "location": "path", + // "pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?))", + // "required": true, + // "type": "string" + // }, + // "region": { + // "description": "The name of the region for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?", + // "required": true, + // "type": "string" + // }, + // "resource": { + // "description": "Name or id of the resource for this request.", + // "location": "path", + // "pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}", + // "required": true, + // "type": "string" + // } + // }, + // "path": "{project}/regions/{region}/subnetworks/{resource}/testIamPermissions", + // "request": { + // "$ref": "TestPermissionsRequest" + // }, + // "response": { + // "$ref": "TestPermissionsResponse" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/compute", + // "https://www.googleapis.com/auth/compute.readonly" + // ] + // } + +} + // method id "compute.targetHttpProxies.delete": type TargetHttpProxiesDeleteCall struct { @@ -76239,9 +92683,13 @@ func (c *TargetHttpProxiesDeleteCall) doRequest(alt string) (*http.Response, err reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/targetHttpProxies/{targetHttpProxy}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -76396,9 +92844,13 @@ func (c *TargetHttpProxiesGetCall) doRequest(alt string) (*http.Response, error) } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/targetHttpProxies/{targetHttpProxy}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -76559,9 +93011,13 @@ func (c *TargetHttpProxiesInsertCall) doRequest(alt string) (*http.Response, err } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/targetHttpProxies") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -76771,9 +93227,13 @@ func (c *TargetHttpProxiesListCall) doRequest(alt string) (*http.Response, error } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/targetHttpProxies") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -76970,9 +93430,13 @@ func (c *TargetHttpProxiesSetUrlMapCall) doRequest(alt string) (*http.Response, } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/targetHttpProxies/{targetHttpProxy}/setUrlMap") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -77133,9 +93597,13 @@ func (c *TargetHttpsProxiesDeleteCall) doRequest(alt string) (*http.Response, er reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/targetHttpsProxies/{targetHttpsProxy}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -77289,9 +93757,13 @@ func (c *TargetHttpsProxiesGetCall) doRequest(alt string) (*http.Response, error } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/targetHttpsProxies/{targetHttpsProxy}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -77451,9 +93923,13 @@ func (c *TargetHttpsProxiesInsertCall) doRequest(alt string) (*http.Response, er } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/targetHttpsProxies") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -77662,9 +94138,13 @@ func (c *TargetHttpsProxiesListCall) doRequest(alt string) (*http.Response, erro } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/targetHttpsProxies") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -77860,9 +94340,13 @@ func (c *TargetHttpsProxiesSetQuicOverrideCall) doRequest(alt string) (*http.Res } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/targetHttpsProxies/{targetHttpsProxy}/setQuicOverride") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -78029,9 +94513,13 @@ func (c *TargetHttpsProxiesSetSslCertificatesCall) doRequest(alt string) (*http. } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/targetHttpsProxies/{targetHttpsProxy}/setSslCertificates") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -78203,9 +94691,13 @@ func (c *TargetHttpsProxiesSetSslPolicyCall) doRequest(alt string) (*http.Respon } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/targetHttpsProxies/{targetHttpsProxy}/setSslPolicy") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -78372,9 +94864,13 @@ func (c *TargetHttpsProxiesSetUrlMapCall) doRequest(alt string) (*http.Response, } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/targetHttpsProxies/{targetHttpsProxy}/setUrlMap") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -78592,9 +95088,13 @@ func (c *TargetInstancesAggregatedListCall) doRequest(alt string) (*http.Respons } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/aggregated/targetInstances") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -78786,9 +95286,13 @@ func (c *TargetInstancesDeleteCall) doRequest(alt string) (*http.Response, error reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/targetInstances/{targetInstance}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -78954,9 +95458,13 @@ func (c *TargetInstancesGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/targetInstances/{targetInstance}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -79128,9 +95636,13 @@ func (c *TargetInstancesInsertCall) doRequest(alt string) (*http.Response, error } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/targetInstances") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -79351,9 +95863,13 @@ func (c *TargetInstancesListCall) doRequest(alt string) (*http.Response, error) } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/targetInstances") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -79561,9 +96077,13 @@ func (c *TargetPoolsAddHealthCheckCall) doRequest(alt string) (*http.Response, e } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/targetPools/{targetPool}/addHealthCheck") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -79743,9 +96263,13 @@ func (c *TargetPoolsAddInstanceCall) doRequest(alt string) (*http.Response, erro } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/targetPools/{targetPool}/addInstance") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -79972,9 +96496,13 @@ func (c *TargetPoolsAggregatedListCall) doRequest(alt string) (*http.Response, e } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/aggregated/targetPools") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -80166,9 +96694,13 @@ func (c *TargetPoolsDeleteCall) doRequest(alt string) (*http.Response, error) { reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/targetPools/{targetPool}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -80334,9 +96866,13 @@ func (c *TargetPoolsGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/targetPools/{targetPool}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -80491,9 +97027,13 @@ func (c *TargetPoolsGetHealthCall) doRequest(alt string) (*http.Response, error) } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/targetPools/{targetPool}/getHealth") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -80668,9 +97208,13 @@ func (c *TargetPoolsInsertCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/targetPools") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -80891,9 +97435,13 @@ func (c *TargetPoolsListCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/targetPools") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -81101,9 +97649,13 @@ func (c *TargetPoolsRemoveHealthCheckCall) doRequest(alt string) (*http.Response } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/targetPools/{targetPool}/removeHealthCheck") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -81283,9 +97835,13 @@ func (c *TargetPoolsRemoveInstanceCall) doRequest(alt string) (*http.Response, e } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/targetPools/{targetPool}/removeInstance") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -81472,9 +98028,13 @@ func (c *TargetPoolsSetBackupCall) doRequest(alt string) (*http.Response, error) } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/targetPools/{targetPool}/setBackup") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -81650,9 +98210,13 @@ func (c *TargetSslProxiesDeleteCall) doRequest(alt string) (*http.Response, erro reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/targetSslProxies/{targetSslProxy}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -81806,9 +98370,13 @@ func (c *TargetSslProxiesGetCall) doRequest(alt string) (*http.Response, error) } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/targetSslProxies/{targetSslProxy}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -81968,9 +98536,13 @@ func (c *TargetSslProxiesInsertCall) doRequest(alt string) (*http.Response, erro } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/targetSslProxies") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -82179,9 +98751,13 @@ func (c *TargetSslProxiesListCall) doRequest(alt string) (*http.Response, error) } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/targetSslProxies") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -82377,9 +98953,13 @@ func (c *TargetSslProxiesSetBackendServiceCall) doRequest(alt string) (*http.Res } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/targetSslProxies/{targetSslProxy}/setBackendService") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -82547,9 +99127,13 @@ func (c *TargetSslProxiesSetProxyHeaderCall) doRequest(alt string) (*http.Respon } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/targetSslProxies/{targetSslProxy}/setProxyHeader") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -82717,9 +99301,13 @@ func (c *TargetSslProxiesSetSslCertificatesCall) doRequest(alt string) (*http.Re } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/targetSslProxies/{targetSslProxy}/setSslCertificates") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -82890,9 +99478,13 @@ func (c *TargetSslProxiesSetSslPolicyCall) doRequest(alt string) (*http.Response } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/targetSslProxies/{targetSslProxy}/setSslPolicy") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -83052,9 +99644,13 @@ func (c *TargetTcpProxiesDeleteCall) doRequest(alt string) (*http.Response, erro reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/targetTcpProxies/{targetTcpProxy}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -83208,9 +99804,13 @@ func (c *TargetTcpProxiesGetCall) doRequest(alt string) (*http.Response, error) } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/targetTcpProxies/{targetTcpProxy}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -83370,9 +99970,13 @@ func (c *TargetTcpProxiesInsertCall) doRequest(alt string) (*http.Response, erro } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/targetTcpProxies") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -83581,9 +100185,13 @@ func (c *TargetTcpProxiesListCall) doRequest(alt string) (*http.Response, error) } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/targetTcpProxies") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -83779,9 +100387,13 @@ func (c *TargetTcpProxiesSetBackendServiceCall) doRequest(alt string) (*http.Res } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/targetTcpProxies/{targetTcpProxy}/setBackendService") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -83949,9 +100561,13 @@ func (c *TargetTcpProxiesSetProxyHeaderCall) doRequest(alt string) (*http.Respon } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/targetTcpProxies/{targetTcpProxy}/setProxyHeader") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -84168,9 +100784,13 @@ func (c *TargetVpnGatewaysAggregatedListCall) doRequest(alt string) (*http.Respo } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/aggregated/targetVpnGateways") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -84361,9 +100981,13 @@ func (c *TargetVpnGatewaysDeleteCall) doRequest(alt string) (*http.Response, err reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/targetVpnGateways/{targetVpnGateway}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -84528,9 +101152,13 @@ func (c *TargetVpnGatewaysGetCall) doRequest(alt string) (*http.Response, error) } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/targetVpnGateways/{targetVpnGateway}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -84701,9 +101329,13 @@ func (c *TargetVpnGatewaysInsertCall) doRequest(alt string) (*http.Response, err } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/targetVpnGateways") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -84923,9 +101555,13 @@ func (c *TargetVpnGatewaysListCall) doRequest(alt string) (*http.Response, error } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/targetVpnGateways") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -85124,9 +101760,13 @@ func (c *UrlMapsDeleteCall) doRequest(alt string) (*http.Response, error) { reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/urlMaps/{urlMap}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -85281,9 +101921,13 @@ func (c *UrlMapsGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/urlMaps/{urlMap}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -85444,9 +102088,13 @@ func (c *UrlMapsInsertCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/urlMaps") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -85606,9 +102254,13 @@ func (c *UrlMapsInvalidateCacheCall) doRequest(alt string) (*http.Response, erro } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/urlMaps/{urlMap}/invalidateCache") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -85827,9 +102479,13 @@ func (c *UrlMapsListCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/urlMaps") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -86028,9 +102684,13 @@ func (c *UrlMapsPatchCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/urlMaps/{urlMap}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PATCH", urls, body) + req, err := http.NewRequest("PATCH", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -86200,9 +102860,13 @@ func (c *UrlMapsUpdateCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/urlMaps/{urlMap}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PUT", urls, body) + req, err := http.NewRequest("PUT", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -86354,9 +103018,13 @@ func (c *UrlMapsValidateCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/global/urlMaps/{urlMap}/validate") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -86568,9 +103236,13 @@ func (c *VpnTunnelsAggregatedListCall) doRequest(alt string) (*http.Response, er } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/aggregated/vpnTunnels") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -86761,9 +103433,13 @@ func (c *VpnTunnelsDeleteCall) doRequest(alt string) (*http.Response, error) { reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/vpnTunnels/{vpnTunnel}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -86928,9 +103604,13 @@ func (c *VpnTunnelsGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/vpnTunnels/{vpnTunnel}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -87101,9 +103781,13 @@ func (c *VpnTunnelsInsertCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/vpnTunnels") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -87323,9 +104007,13 @@ func (c *VpnTunnelsListCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/regions/{region}/vpnTunnels") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -87507,9 +104195,13 @@ func (c *ZoneOperationsDeleteCall) doRequest(alt string) (*http.Response, error) reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/operations/{operation}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -87641,9 +104333,13 @@ func (c *ZoneOperationsGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/operations/{operation}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -87866,9 +104562,13 @@ func (c *ZoneOperationsListCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}/operations") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -88063,9 +104763,13 @@ func (c *ZonesGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones/{zone}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -88277,9 +104981,13 @@ func (c *ZonesListCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "{project}/zones") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, diff --git a/vendor/google.golang.org/api/container/v1/BUILD b/vendor/google.golang.org/api/container/v1/BUILD index 2ef4ef67a55..0da28e68c48 100644 --- a/vendor/google.golang.org/api/container/v1/BUILD +++ b/vendor/google.golang.org/api/container/v1/BUILD @@ -7,8 +7,6 @@ go_library( importpath = "google.golang.org/api/container/v1", visibility = ["//visibility:public"], deps = [ - "//vendor/golang.org/x/net/context:go_default_library", - "//vendor/golang.org/x/net/context/ctxhttp:go_default_library", "//vendor/google.golang.org/api/gensupport:go_default_library", "//vendor/google.golang.org/api/googleapi:go_default_library", ], diff --git a/vendor/google.golang.org/api/container/v1/container-api.json b/vendor/google.golang.org/api/container/v1/container-api.json index a7e01b0b1df..e8718f8f348 100644 --- a/vendor/google.golang.org/api/container/v1/container-api.json +++ b/vendor/google.golang.org/api/container/v1/container-api.json @@ -12,7 +12,7 @@ "baseUrl": "https://container.googleapis.com/", "batchPath": "batch", "canonicalName": "Container", - "description": "The Google Kubernetes Engine API is used for building and managing container based applications, powered by the open source Kubernetes technology.", + "description": "Builds and manages container-based applications, powered by the open source Kubernetes technology.", "discoveryVersion": "v1", "documentationLink": "https://cloud.google.com/container-engine/", "fullyEncodeReservedExpansion": true, @@ -668,7 +668,7 @@ ], "parameters": { "parent": { - "description": "The parent (project, location, cluster id) where the node pool will be\ncreated. Specified in the format\n'projects/*/locations/*/clusters/*/nodePools/*'.", + "description": "The parent (project, location, cluster id) where the node pool will be\ncreated. Specified in the format\n'projects/*/locations/*/clusters/*'.", "location": "path", "pattern": "^projects/[^/]+/locations/[^/]+/clusters/[^/]+$", "required": true, @@ -2361,7 +2361,7 @@ } } }, - "revision": "20180607", + "revision": "20181109", "rootUrl": "https://container.googleapis.com/", "schemas": { "AcceleratorConfig": { @@ -2479,6 +2479,13 @@ "description": "The IP address range of the container pods in this cluster, in\n[CIDR](http://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing)\nnotation (e.g. `10.96.0.0/14`). Leave blank to have\none automatically chosen or specify a `/14` block in `10.0.0.0/8`.", "type": "string" }, + "conditions": { + "description": "Which conditions caused the current cluster state.", + "items": { + "$ref": "StatusCondition" + }, + "type": "array" + }, "createTime": { "description": "[Output only] The time the cluster was created, in\n[RFC3339](https://www.ietf.org/rfc/rfc3339.txt) text format.", "type": "string" @@ -2488,12 +2495,12 @@ "type": "string" }, "currentNodeCount": { - "description": "[Output only] The number of nodes currently in the cluster.", + "description": "[Output only] The number of nodes currently in the cluster. Deprecated.\nCall Kubernetes API directly to retrieve node information.", "format": "int32", "type": "integer" }, "currentNodeVersion": { - "description": "[Output only] The current version of the node software components.\nIf they are currently at multiple versions because they're in the process\nof being upgraded, this reflects the minimum version of all nodes.", + "description": "[Output only] Deprecated, use\n[NodePool.version](/kubernetes-engine/docs/reference/rest/v1/projects.zones.clusters.nodePool)\ninstead. The current version of the node software components. If they are\ncurrently at multiple versions because they're in the process of being\nupgraded, this reflects the minimum version of all nodes.", "type": "string" }, "description": { @@ -2545,7 +2552,7 @@ "type": "string" }, "locations": { - "description": "The list of Google Compute Engine\n[locations](/compute/docs/zones#available) in which the cluster's nodes\nshould be located.", + "description": "The list of Google Compute Engine\n[zones](/compute/docs/zones#available) in which the cluster's nodes\nshould be located.", "items": { "type": "string" }, @@ -2561,7 +2568,7 @@ }, "masterAuth": { "$ref": "MasterAuth", - "description": "The authentication information for accessing the master endpoint." + "description": "The authentication information for accessing the master endpoint.\nIf unspecified, the defaults are used:\nFor clusters before v1.12, if master_auth is unspecified, `username` will\nbe set to \"admin\", a random password will be generated, and a client\ncertificate will be issued." }, "masterAuthorizedNetworksConfig": { "$ref": "MasterAuthorizedNetworksConfig", @@ -2579,6 +2586,10 @@ "description": "The name of the Google Compute Engine\n[network](/compute/docs/networks-and-firewalls#networks) to which the\ncluster is connected. If left unspecified, the `default` network\nwill be used.", "type": "string" }, + "networkConfig": { + "$ref": "NetworkConfig", + "description": "Configuration for cluster networking." + }, "networkPolicy": { "$ref": "NetworkPolicy", "description": "Configuration options for the NetworkPolicy feature." @@ -2599,6 +2610,10 @@ }, "type": "array" }, + "privateClusterConfig": { + "$ref": "PrivateClusterConfig", + "description": "Configuration for private cluster." + }, "resourceLabels": { "additionalProperties": { "type": "string" @@ -2664,7 +2679,7 @@ "type": "string" }, "desiredLocations": { - "description": "The desired list of Google Compute Engine\n[locations](/compute/docs/zones#available) in which the cluster's nodes\nshould be located. Changing the locations a cluster is in will result\nin nodes being either created or removed from the cluster, depending on\nwhether locations are being added or removed.\n\nThis list must always include the cluster's primary zone.", + "description": "The desired list of Google Compute Engine\n[zones](/compute/docs/zones#available) in which the cluster's nodes\nshould be located. Changing the locations a cluster is in will result\nin nodes being either created or removed from the cluster, depending on\nwhether locations are being added or removed.\n\nThis list must always include the cluster's primary zone.", "items": { "type": "string" }, @@ -2756,7 +2771,7 @@ "description": "The node pool to create." }, "parent": { - "description": "The parent (project, location, cluster id) where the node pool will be\ncreated. Specified in the format\n'projects/*/locations/*/clusters/*/nodePools/*'.", + "description": "The parent (project, location, cluster id) where the node pool will be\ncreated. Specified in the format\n'projects/*/locations/*/clusters/*'.", "type": "string" }, "projectId": { @@ -2974,7 +2989,7 @@ }, "clientCertificateConfig": { "$ref": "ClientCertificateConfig", - "description": "Configuration for client certificate authentication on the cluster. If no\nconfiguration is specified, a client certificate is issued." + "description": "Configuration for client certificate authentication on the cluster. For\nclusters before v1.12, if no configuration is specified, a client\ncertificate is issued." }, "clientKey": { "description": "[Output only] Base64-encoded private key used by clients to authenticate\nto the cluster endpoint.", @@ -2989,7 +3004,7 @@ "type": "string" }, "username": { - "description": "The username to use for HTTP basic authentication to the master endpoint.\nFor clusters v1.6.0 and later, you can disable basic authentication by\nproviding an empty username.", + "description": "The username to use for HTTP basic authentication to the master endpoint.\nFor clusters v1.6.0 and later, basic authentication can be disabled by\nleaving username unspecified (or setting it to the empty string).", "type": "string" } }, @@ -3013,6 +3028,21 @@ }, "type": "object" }, + "NetworkConfig": { + "description": "NetworkConfig reports the relative names of network \u0026 subnetwork.", + "id": "NetworkConfig", + "properties": { + "network": { + "description": "Output only. The relative name of the Google Compute Engine\nnetwork(/compute/docs/networks-and-firewalls#networks) to which\nthe cluster is connected.\nExample: projects/my-project/global/networks/my-network", + "type": "string" + }, + "subnetwork": { + "description": "Output only. The relative name of the Google Compute Engine\n[subnetwork](/compute/docs/vpc) to which the cluster is connected.\nExample: projects/my-project/regions/us-central1/subnetworks/my-subnet", + "type": "string" + } + }, + "type": "object" + }, "NetworkPolicy": { "description": "Configuration options for the NetworkPolicy feature.\nhttps://kubernetes.io/docs/concepts/services-networking/networkpolicies/", "id": "NetworkPolicy", @@ -3063,6 +3093,10 @@ "format": "int32", "type": "integer" }, + "diskType": { + "description": "Type of the disk attached to each node (e.g. 'pd-standard' or 'pd-ssd')\n\nIf unspecified, the default disk type is 'pd-standard'", + "type": "string" + }, "imageType": { "description": "The image type to use for this node. Note that for a given image type,\nthe latest version of it will be used.", "type": "string" @@ -3087,7 +3121,7 @@ "additionalProperties": { "type": "string" }, - "description": "The metadata key/value pairs assigned to instances in the cluster.\n\nKeys must conform to the regexp [a-zA-Z0-9-_]+ and be less than 128 bytes\nin length. These are reflected as part of a URL in the metadata server.\nAdditionally, to avoid ambiguity, keys must not conflict with any other\nmetadata keys for the project or be one of the reserved keys:\n \"cluster-location\"\n \"cluster-name\"\n \"cluster-uid\"\n \"configure-sh\"\n \"gci-update-strategy\"\n \"gci-ensure-gke-docker\"\n \"instance-template\"\n \"kube-env\"\n \"startup-script\"\n \"user-data\"\n\nValues are free-form strings, and only have meaning as interpreted by\nthe image running in the instance. The only restriction placed on them is\nthat each value's size must be less than or equal to 32 KB.\n\nThe total size of all keys and values must be less than 512 KB.", + "description": "The metadata key/value pairs assigned to instances in the cluster.\n\nKeys must conform to the regexp [a-zA-Z0-9-_]+ and be less than 128 bytes\nin length. These are reflected as part of a URL in the metadata server.\nAdditionally, to avoid ambiguity, keys must not conflict with any other\nmetadata keys for the project or be one of the reserved keys:\n \"cluster-location\"\n \"cluster-name\"\n \"cluster-uid\"\n \"configure-sh\"\n \"enable-os-login\"\n \"gci-update-strategy\"\n \"gci-ensure-gke-docker\"\n \"instance-template\"\n \"kube-env\"\n \"startup-script\"\n \"user-data\"\n\nValues are free-form strings, and only have meaning as interpreted by\nthe image running in the instance. The only restriction placed on them is\nthat each value's size must be less than or equal to 32 KB.\n\nThe total size of all keys and values must be less than 512 KB.", "type": "object" }, "minCpuPlatform": { @@ -3115,6 +3149,13 @@ "type": "string" }, "type": "array" + }, + "taints": { + "description": "List of kubernetes taints to be applied to each node.\n\nFor more information, including usage and the valid values, see:\nhttps://kubernetes.io/docs/concepts/configuration/taint-and-toleration/", + "items": { + "$ref": "NodeTaint" + }, + "type": "array" } }, "type": "object" @@ -3146,6 +3187,13 @@ "$ref": "NodePoolAutoscaling", "description": "Autoscaler configuration for this NodePool. Autoscaler is enabled\nonly if a valid configuration is present." }, + "conditions": { + "description": "Which conditions caused the current node pool state.", + "items": { + "$ref": "StatusCondition" + }, + "type": "array" + }, "config": { "$ref": "NodeConfig", "description": "The node configuration of the pool." @@ -3228,10 +3276,48 @@ }, "type": "object" }, + "NodeTaint": { + "description": "Kubernetes taint is comprised of three fields: key, value, and effect. Effect\ncan only be one of three types: NoSchedule, PreferNoSchedule or NoExecute.\n\nFor more information, including usage and the valid values, see:\nhttps://kubernetes.io/docs/concepts/configuration/taint-and-toleration/", + "id": "NodeTaint", + "properties": { + "effect": { + "description": "Effect for taint.", + "enum": [ + "EFFECT_UNSPECIFIED", + "NO_SCHEDULE", + "PREFER_NO_SCHEDULE", + "NO_EXECUTE" + ], + "enumDescriptions": [ + "Not set", + "NoSchedule", + "PreferNoSchedule", + "NoExecute" + ], + "type": "string" + }, + "key": { + "description": "Key for taint.", + "type": "string" + }, + "value": { + "description": "Value for taint.", + "type": "string" + } + }, + "type": "object" + }, "Operation": { "description": "This operation resource represents operations that may have happened or are\nhappening on the cluster. All fields are output only.", "id": "Operation", "properties": { + "clusterConditions": { + "description": "Which conditions caused the current cluster state.", + "items": { + "$ref": "StatusCondition" + }, + "type": "array" + }, "detail": { "description": "Detailed operation progress, if available.", "type": "string" @@ -3248,6 +3334,13 @@ "description": "The server-assigned ID for the operation.", "type": "string" }, + "nodepoolConditions": { + "description": "Which conditions caused the current node pool state.", + "items": { + "$ref": "StatusCondition" + }, + "type": "array" + }, "operationType": { "description": "The operation type.", "enum": [ @@ -3331,6 +3424,33 @@ }, "type": "object" }, + "PrivateClusterConfig": { + "description": "Configuration options for private clusters.", + "id": "PrivateClusterConfig", + "properties": { + "enablePrivateEndpoint": { + "description": "Whether the master's internal IP address is used as the cluster endpoint.", + "type": "boolean" + }, + "enablePrivateNodes": { + "description": "Whether nodes have internal IP addresses only. If enabled, all nodes are\ngiven only RFC 1918 private addresses and communicate with the master via\nprivate networking.", + "type": "boolean" + }, + "masterIpv4CidrBlock": { + "description": "The IP range in CIDR notation to use for the hosted master network. This\nrange will be used for assigning internal IP addresses to the master or\nset of masters, as well as the ILB VIP. This range must not overlap with\nany other ranges in use within the cluster's network.", + "type": "string" + }, + "privateEndpoint": { + "description": "Output only. The internal IP address of this cluster's master endpoint.", + "type": "string" + }, + "publicEndpoint": { + "description": "Output only. The external IP address of this cluster's master endpoint.", + "type": "string" + } + }, + "type": "object" + }, "RollbackNodePoolUpgradeRequest": { "description": "RollbackNodePoolUpgradeRequest rollbacks the previously Aborted or Failed\nNodePool upgrade. This will be an no-op if the last upgrade successfully\ncompleted.", "id": "RollbackNodePoolUpgradeRequest", @@ -3491,7 +3611,7 @@ "type": "string" }, "locations": { - "description": "The desired list of Google Compute Engine\n[locations](/compute/docs/zones#available) in which the cluster's nodes\nshould be located. Changing the locations a cluster is in will result\nin nodes being either created or removed from the cluster, depending on\nwhether locations are being added or removed.\n\nThis list must always include the cluster's primary zone.", + "description": "The desired list of Google Compute Engine\n[zones](/compute/docs/zones#available) in which the cluster's nodes\nshould be located. Changing the locations a cluster is in will result\nin nodes being either created or removed from the cluster, depending on\nwhether locations are being added or removed.\n\nThis list must always include the cluster's primary zone.", "items": { "type": "string" }, @@ -3784,6 +3904,35 @@ }, "type": "object" }, + "StatusCondition": { + "description": "StatusCondition describes why a cluster or a node pool has a certain status\n(e.g., ERROR or DEGRADED).", + "id": "StatusCondition", + "properties": { + "code": { + "description": "Machine-friendly representation of the condition", + "enum": [ + "UNKNOWN", + "GCE_STOCKOUT", + "GKE_SERVICE_ACCOUNT_DELETED", + "GCE_QUOTA_EXCEEDED", + "SET_BY_OPERATOR" + ], + "enumDescriptions": [ + "UNKNOWN indicates a generic condition.", + "GCE_STOCKOUT indicates a Google Compute Engine stockout.", + "GKE_SERVICE_ACCOUNT_DELETED indicates that the user deleted their robot\nservice account.", + "Google Compute Engine quota was exceeded.", + "Cluster state was manually changed by an SRE due to a system logic error.\nMore codes TBA" + ], + "type": "string" + }, + "message": { + "description": "Human-friendly representation of the condition", + "type": "string" + } + }, + "type": "object" + }, "UpdateClusterRequest": { "description": "UpdateClusterRequest updates the settings of a cluster.", "id": "UpdateClusterRequest", diff --git a/vendor/google.golang.org/api/container/v1/container-gen.go b/vendor/google.golang.org/api/container/v1/container-gen.go index 0650b9387c7..f6ff6af90f4 100644 --- a/vendor/google.golang.org/api/container/v1/container-gen.go +++ b/vendor/google.golang.org/api/container/v1/container-gen.go @@ -1,3 +1,9 @@ +// Copyright 2018 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Code generated file. DO NOT EDIT. + // Package container provides access to the Kubernetes Engine API. // // See https://cloud.google.com/container-engine/ @@ -11,18 +17,18 @@ package container import ( "bytes" + "context" "encoding/json" "errors" "fmt" - context "golang.org/x/net/context" - ctxhttp "golang.org/x/net/context/ctxhttp" - gensupport "google.golang.org/api/gensupport" - googleapi "google.golang.org/api/googleapi" "io" "net/http" "net/url" "strconv" "strings" + + gensupport "google.golang.org/api/gensupport" + googleapi "google.golang.org/api/googleapi" ) // Always reference these packages, just in case the auto-generated code @@ -38,7 +44,6 @@ var _ = googleapi.Version var _ = errors.New var _ = strings.Replace var _ = context.Canceled -var _ = ctxhttp.Do const apiId = "container:v1" const apiName = "container" @@ -437,6 +442,9 @@ type Cluster struct { // one automatically chosen or specify a `/14` block in `10.0.0.0/8`. ClusterIpv4Cidr string `json:"clusterIpv4Cidr,omitempty"` + // Conditions: Which conditions caused the current cluster state. + Conditions []*StatusCondition `json:"conditions,omitempty"` + // CreateTime: [Output only] The time the cluster was created, // in // [RFC3339](https://www.ietf.org/rfc/rfc3339.txt) text format. @@ -446,15 +454,20 @@ type Cluster struct { // the master endpoint. CurrentMasterVersion string `json:"currentMasterVersion,omitempty"` - // CurrentNodeCount: [Output only] The number of nodes currently in the - // cluster. + // CurrentNodeCount: [Output only] The number of nodes currently in the + // cluster. Deprecated. + // Call Kubernetes API directly to retrieve node information. CurrentNodeCount int64 `json:"currentNodeCount,omitempty"` - // CurrentNodeVersion: [Output only] The current version of the node - // software components. - // If they are currently at multiple versions because they're in the - // process - // of being upgraded, this reflects the minimum version of all nodes. + // CurrentNodeVersion: [Output only] Deprecated, + // use + // [NodePool.version](/kubernetes-engine/docs/reference/rest/v1/proje + // cts.zones.clusters.nodePool) + // instead. The current version of the node software components. If they + // are + // currently at multiple versions because they're in the process of + // being + // upgraded, this reflects the minimum version of all nodes. CurrentNodeVersion string `json:"currentNodeVersion,omitempty"` // Description: An optional description of this cluster. @@ -549,7 +562,7 @@ type Cluster struct { // Locations: The list of Google Compute // Engine - // [locations](/compute/docs/zones#available) in which the cluster's + // [zones](/compute/docs/zones#available) in which the cluster's // nodes // should be located. Locations []string `json:"locations,omitempty"` @@ -568,6 +581,12 @@ type Cluster struct { // MasterAuth: The authentication information for accessing the master // endpoint. + // If unspecified, the defaults are used: + // For clusters before v1.12, if master_auth is unspecified, `username` + // will + // be set to "admin", a random password will be generated, and a + // client + // certificate will be issued. MasterAuth *MasterAuth `json:"masterAuth,omitempty"` // MasterAuthorizedNetworksConfig: The configuration options for master @@ -603,6 +622,9 @@ type Cluster struct { // will be used. Network string `json:"network,omitempty"` + // NetworkConfig: Configuration for cluster networking. + NetworkConfig *NetworkConfig `json:"networkConfig,omitempty"` + // NetworkPolicy: Configuration options for the NetworkPolicy feature. NetworkPolicy *NetworkPolicy `json:"networkPolicy,omitempty"` @@ -635,6 +657,9 @@ type Cluster struct { // specified. NodePools []*NodePool `json:"nodePools,omitempty"` + // PrivateClusterConfig: Configuration for private cluster. + PrivateClusterConfig *PrivateClusterConfig `json:"privateClusterConfig,omitempty"` + // ResourceLabels: The resource labels for the cluster to use to // annotate any related // Google Compute Engine resources. @@ -740,7 +765,7 @@ type ClusterUpdate struct { // DesiredLocations: The desired list of Google Compute // Engine - // [locations](/compute/docs/zones#available) in which the cluster's + // [zones](/compute/docs/zones#available) in which the cluster's // nodes // should be located. Changing the locations a cluster is in will // result @@ -948,9 +973,8 @@ type CreateNodePoolRequest struct { // Parent: The parent (project, location, cluster id) where the node // pool will be - // created. Specified in the - // format - // 'projects/*/locations/*/clusters/*/nodePools/*'. + // created. Specified in the format + // 'projects/*/locations/*/clusters/*'. Parent string `json:"parent,omitempty"` // ProjectId: Deprecated. The Google Developers Console [project ID or @@ -1517,8 +1541,10 @@ type MasterAuth struct { ClientCertificate string `json:"clientCertificate,omitempty"` // ClientCertificateConfig: Configuration for client certificate - // authentication on the cluster. If no - // configuration is specified, a client certificate is issued. + // authentication on the cluster. For + // clusters before v1.12, if no configuration is specified, a + // client + // certificate is issued. ClientCertificateConfig *ClientCertificateConfig `json:"clientCertificateConfig,omitempty"` // ClientKey: [Output only] Base64-encoded private key used by clients @@ -1542,9 +1568,9 @@ type MasterAuth struct { // Username: The username to use for HTTP basic authentication to the // master endpoint. - // For clusters v1.6.0 and later, you can disable basic authentication + // For clusters v1.6.0 and later, basic authentication can be disabled // by - // providing an empty username. + // leaving username unspecified (or setting it to the empty string). Username string `json:"username,omitempty"` // ForceSendFields is a list of field names (e.g. "ClientCertificate") @@ -1610,6 +1636,47 @@ func (s *MasterAuthorizedNetworksConfig) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +// NetworkConfig: NetworkConfig reports the relative names of network & +// subnetwork. +type NetworkConfig struct { + // Network: Output only. The relative name of the Google Compute + // Engine + // network(/compute/docs/networks-and-firewalls#networks) to which + // the cluster is connected. + // Example: projects/my-project/global/networks/my-network + Network string `json:"network,omitempty"` + + // Subnetwork: Output only. The relative name of the Google Compute + // Engine + // [subnetwork](/compute/docs/vpc) to which the cluster is + // connected. + // Example: + // projects/my-project/regions/us-central1/subnetworks/my-subnet + Subnetwork string `json:"subnetwork,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Network") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Network") to include in + // API requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *NetworkConfig) MarshalJSON() ([]byte, error) { + type NoMethod NetworkConfig + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + // NetworkPolicy: Configuration options for the NetworkPolicy // feature. // https://kubernetes.io/docs/concepts/services-networking/netwo @@ -1696,6 +1763,12 @@ type NodeConfig struct { // If unspecified, the default disk size is 100GB. DiskSizeGb int64 `json:"diskSizeGb,omitempty"` + // DiskType: Type of the disk attached to each node (e.g. 'pd-standard' + // or 'pd-ssd') + // + // If unspecified, the default disk type is 'pd-standard' + DiskType string `json:"diskType,omitempty"` + // ImageType: The image type to use for this node. Note that for a given // image type, // the latest version of it will be used. @@ -1751,6 +1824,7 @@ type NodeConfig struct { // "cluster-name" // "cluster-uid" // "configure-sh" + // "enable-os-login" // "gci-update-strategy" // "gci-ensure-gke-docker" // "instance-template" @@ -1827,6 +1901,14 @@ type NodeConfig struct { // must comply with RFC1035. Tags []string `json:"tags,omitempty"` + // Taints: List of kubernetes taints to be applied to each node. + // + // For more information, including usage and the valid values, + // see: + // https://kubernetes.io/docs/concepts/configuration/taint-and-toler + // ation/ + Taints []*NodeTaint `json:"taints,omitempty"` + // ForceSendFields is a list of field names (e.g. "Accelerators") to // unconditionally include in API requests. By default, fields with // empty values are omitted from API requests. However, any non-pointer, @@ -1913,6 +1995,9 @@ type NodePool struct { // only if a valid configuration is present. Autoscaling *NodePoolAutoscaling `json:"autoscaling,omitempty"` + // Conditions: Which conditions caused the current node pool state. + Conditions []*StatusCondition `json:"conditions,omitempty"` + // Config: The node configuration of the pool. Config *NodeConfig `json:"config,omitempty"` @@ -2043,10 +2128,61 @@ func (s *NodePoolAutoscaling) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +// NodeTaint: Kubernetes taint is comprised of three fields: key, value, +// and effect. Effect +// can only be one of three types: NoSchedule, PreferNoSchedule or +// NoExecute. +// +// For more information, including usage and the valid values, +// see: +// https://kubernetes.io/docs/concepts/configuration/taint-and-toler +// ation/ +type NodeTaint struct { + // Effect: Effect for taint. + // + // Possible values: + // "EFFECT_UNSPECIFIED" - Not set + // "NO_SCHEDULE" - NoSchedule + // "PREFER_NO_SCHEDULE" - PreferNoSchedule + // "NO_EXECUTE" - NoExecute + Effect string `json:"effect,omitempty"` + + // Key: Key for taint. + Key string `json:"key,omitempty"` + + // Value: Value for taint. + Value string `json:"value,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Effect") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Effect") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *NodeTaint) MarshalJSON() ([]byte, error) { + type NoMethod NodeTaint + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + // Operation: This operation resource represents operations that may // have happened or are // happening on the cluster. All fields are output only. type Operation struct { + // ClusterConditions: Which conditions caused the current cluster state. + ClusterConditions []*StatusCondition `json:"clusterConditions,omitempty"` + // Detail: Detailed operation progress, if available. Detail string `json:"detail,omitempty"` @@ -2067,6 +2203,10 @@ type Operation struct { // Name: The server-assigned ID for the operation. Name string `json:"name,omitempty"` + // NodepoolConditions: Which conditions caused the current node pool + // state. + NodepoolConditions []*StatusCondition `json:"nodepoolConditions,omitempty"` + // OperationType: The operation type. // // Possible values: @@ -2125,20 +2265,21 @@ type Operation struct { // server. googleapi.ServerResponse `json:"-"` - // ForceSendFields is a list of field names (e.g. "Detail") to - // unconditionally include in API requests. By default, fields with + // ForceSendFields is a list of field names (e.g. "ClusterConditions") + // to unconditionally include in API requests. By default, fields with // empty values are omitted from API requests. However, any non-pointer, // non-interface field appearing in ForceSendFields will be sent to the // server regardless of whether the field is empty or not. This may be // used to include empty fields in Patch requests. ForceSendFields []string `json:"-"` - // NullFields is a list of field names (e.g. "Detail") to include in API - // requests with the JSON null value. By default, fields with empty - // values are omitted from API requests. However, any field with an - // empty value appearing in NullFields will be sent to the server as - // null. It is an error if a field in this list has a non-empty value. - // This may be used to include null fields in Patch requests. + // NullFields is a list of field names (e.g. "ClusterConditions") to + // include in API requests with the JSON null value. By default, fields + // with empty values are omitted from API requests. However, any field + // with an empty value appearing in NullFields will be sent to the + // server as null. It is an error if a field in this list has a + // non-empty value. This may be used to include null fields in Patch + // requests. NullFields []string `json:"-"` } @@ -2148,6 +2289,61 @@ func (s *Operation) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +// PrivateClusterConfig: Configuration options for private clusters. +type PrivateClusterConfig struct { + // EnablePrivateEndpoint: Whether the master's internal IP address is + // used as the cluster endpoint. + EnablePrivateEndpoint bool `json:"enablePrivateEndpoint,omitempty"` + + // EnablePrivateNodes: Whether nodes have internal IP addresses only. If + // enabled, all nodes are + // given only RFC 1918 private addresses and communicate with the master + // via + // private networking. + EnablePrivateNodes bool `json:"enablePrivateNodes,omitempty"` + + // MasterIpv4CidrBlock: The IP range in CIDR notation to use for the + // hosted master network. This + // range will be used for assigning internal IP addresses to the master + // or + // set of masters, as well as the ILB VIP. This range must not overlap + // with + // any other ranges in use within the cluster's network. + MasterIpv4CidrBlock string `json:"masterIpv4CidrBlock,omitempty"` + + // PrivateEndpoint: Output only. The internal IP address of this + // cluster's master endpoint. + PrivateEndpoint string `json:"privateEndpoint,omitempty"` + + // PublicEndpoint: Output only. The external IP address of this + // cluster's master endpoint. + PublicEndpoint string `json:"publicEndpoint,omitempty"` + + // ForceSendFields is a list of field names (e.g. + // "EnablePrivateEndpoint") to unconditionally include in API requests. + // By default, fields with empty values are omitted from API requests. + // However, any non-pointer, non-interface field appearing in + // ForceSendFields will be sent to the server regardless of whether the + // field is empty or not. This may be used to include empty fields in + // Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "EnablePrivateEndpoint") to + // include in API requests with the JSON null value. By default, fields + // with empty values are omitted from API requests. However, any field + // with an empty value appearing in NullFields will be sent to the + // server as null. It is an error if a field in this list has a + // non-empty value. This may be used to include null fields in Patch + // requests. + NullFields []string `json:"-"` +} + +func (s *PrivateClusterConfig) MarshalJSON() ([]byte, error) { + type NoMethod PrivateClusterConfig + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + // RollbackNodePoolUpgradeRequest: RollbackNodePoolUpgradeRequest // rollbacks the previously Aborted or Failed // NodePool upgrade. This will be an no-op if the last upgrade @@ -2441,7 +2637,7 @@ type SetLocationsRequest struct { // Locations: The desired list of Google Compute // Engine - // [locations](/compute/docs/zones#available) in which the cluster's + // [zones](/compute/docs/zones#available) in which the cluster's // nodes // should be located. Changing the locations a cluster is in will // result @@ -3017,6 +3213,51 @@ func (s *StartIPRotationRequest) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +// StatusCondition: StatusCondition describes why a cluster or a node +// pool has a certain status +// (e.g., ERROR or DEGRADED). +type StatusCondition struct { + // Code: Machine-friendly representation of the condition + // + // Possible values: + // "UNKNOWN" - UNKNOWN indicates a generic condition. + // "GCE_STOCKOUT" - GCE_STOCKOUT indicates a Google Compute Engine + // stockout. + // "GKE_SERVICE_ACCOUNT_DELETED" - GKE_SERVICE_ACCOUNT_DELETED + // indicates that the user deleted their robot + // service account. + // "GCE_QUOTA_EXCEEDED" - Google Compute Engine quota was exceeded. + // "SET_BY_OPERATOR" - Cluster state was manually changed by an SRE + // due to a system logic error. + // More codes TBA + Code string `json:"code,omitempty"` + + // Message: Human-friendly representation of the condition + Message string `json:"message,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Code") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Code") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *StatusCondition) MarshalJSON() ([]byte, error) { + type NoMethod StatusCondition + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + // UpdateClusterRequest: UpdateClusterRequest updates the settings of a // cluster. type UpdateClusterRequest struct { @@ -3294,9 +3535,13 @@ func (c *ProjectsLocationsGetServerConfigCall) doRequest(alt string) (*http.Resp } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}/serverConfig") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "name": c.name, @@ -3436,9 +3681,13 @@ func (c *ProjectsLocationsClustersCompleteIpRotationCall) doRequest(alt string) } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}:completeIpRotation") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "name": c.name, @@ -3587,9 +3836,13 @@ func (c *ProjectsLocationsClustersCreateCall) doRequest(alt string) (*http.Respo } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+parent}/clusters") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "parent": c.parent, @@ -3756,9 +4009,13 @@ func (c *ProjectsLocationsClustersDeleteCall) doRequest(alt string) (*http.Respo reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "name": c.name, @@ -3940,9 +4197,13 @@ func (c *ProjectsLocationsClustersGetCall) doRequest(alt string) (*http.Response } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "name": c.name, @@ -4117,9 +4378,13 @@ func (c *ProjectsLocationsClustersListCall) doRequest(alt string) (*http.Respons } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+parent}/clusters") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "parent": c.parent, @@ -4259,9 +4524,13 @@ func (c *ProjectsLocationsClustersSetAddonsCall) doRequest(alt string) (*http.Re } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}:setAddons") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "name": c.name, @@ -4395,9 +4664,13 @@ func (c *ProjectsLocationsClustersSetLegacyAbacCall) doRequest(alt string) (*htt } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}:setLegacyAbac") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "name": c.name, @@ -4530,9 +4803,13 @@ func (c *ProjectsLocationsClustersSetLocationsCall) doRequest(alt string) (*http } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}:setLocations") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "name": c.name, @@ -4665,9 +4942,13 @@ func (c *ProjectsLocationsClustersSetLoggingCall) doRequest(alt string) (*http.R } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}:setLogging") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "name": c.name, @@ -4800,9 +5081,13 @@ func (c *ProjectsLocationsClustersSetMaintenancePolicyCall) doRequest(alt string } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}:setMaintenancePolicy") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "name": c.name, @@ -4939,9 +5224,13 @@ func (c *ProjectsLocationsClustersSetMasterAuthCall) doRequest(alt string) (*htt } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}:setMasterAuth") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "name": c.name, @@ -5074,9 +5363,13 @@ func (c *ProjectsLocationsClustersSetMonitoringCall) doRequest(alt string) (*htt } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}:setMonitoring") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "name": c.name, @@ -5209,9 +5502,13 @@ func (c *ProjectsLocationsClustersSetNetworkPolicyCall) doRequest(alt string) (* } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}:setNetworkPolicy") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "name": c.name, @@ -5344,9 +5641,13 @@ func (c *ProjectsLocationsClustersSetResourceLabelsCall) doRequest(alt string) ( } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}:setResourceLabels") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "name": c.name, @@ -5479,9 +5780,13 @@ func (c *ProjectsLocationsClustersStartIpRotationCall) doRequest(alt string) (*h } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}:startIpRotation") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "name": c.name, @@ -5614,9 +5919,13 @@ func (c *ProjectsLocationsClustersUpdateCall) doRequest(alt string) (*http.Respo } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PUT", urls, body) + req, err := http.NewRequest("PUT", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "name": c.name, @@ -5749,9 +6058,13 @@ func (c *ProjectsLocationsClustersUpdateMasterCall) doRequest(alt string) (*http } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}:updateMaster") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "name": c.name, @@ -5884,9 +6197,13 @@ func (c *ProjectsLocationsClustersNodePoolsCreateCall) doRequest(alt string) (*h } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+parent}/nodePools") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "parent": c.parent, @@ -5941,7 +6258,7 @@ func (c *ProjectsLocationsClustersNodePoolsCreateCall) Do(opts ...googleapi.Call // ], // "parameters": { // "parent": { - // "description": "The parent (project, location, cluster id) where the node pool will be\ncreated. Specified in the format\n'projects/*/locations/*/clusters/*/nodePools/*'.", + // "description": "The parent (project, location, cluster id) where the node pool will be\ncreated. Specified in the format\n'projects/*/locations/*/clusters/*'.", // "location": "path", // "pattern": "^projects/[^/]+/locations/[^/]+/clusters/[^/]+$", // "required": true, @@ -6050,9 +6367,13 @@ func (c *ProjectsLocationsClustersNodePoolsDeleteCall) doRequest(alt string) (*h reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "name": c.name, @@ -6247,9 +6568,13 @@ func (c *ProjectsLocationsClustersNodePoolsGetCall) doRequest(alt string) (*http } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "name": c.name, @@ -6436,9 +6761,13 @@ func (c *ProjectsLocationsClustersNodePoolsListCall) doRequest(alt string) (*htt } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+parent}/nodePools") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "parent": c.parent, @@ -6585,9 +6914,13 @@ func (c *ProjectsLocationsClustersNodePoolsRollbackCall) doRequest(alt string) ( } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}:rollback") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "name": c.name, @@ -6721,9 +7054,13 @@ func (c *ProjectsLocationsClustersNodePoolsSetAutoscalingCall) doRequest(alt str } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}:setAutoscaling") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "name": c.name, @@ -6856,9 +7193,13 @@ func (c *ProjectsLocationsClustersNodePoolsSetManagementCall) doRequest(alt stri } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}:setManagement") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "name": c.name, @@ -6991,9 +7332,13 @@ func (c *ProjectsLocationsClustersNodePoolsSetSizeCall) doRequest(alt string) (* } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}:setSize") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "name": c.name, @@ -7127,9 +7472,13 @@ func (c *ProjectsLocationsClustersNodePoolsUpdateCall) doRequest(alt string) (*h } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PUT", urls, body) + req, err := http.NewRequest("PUT", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "name": c.name, @@ -7262,9 +7611,13 @@ func (c *ProjectsLocationsOperationsCancelCall) doRequest(alt string) (*http.Res } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}:cancel") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "name": c.name, @@ -7434,9 +7787,13 @@ func (c *ProjectsLocationsOperationsGetCall) doRequest(alt string) (*http.Respon } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "name": c.name, @@ -7611,9 +7968,13 @@ func (c *ProjectsLocationsOperationsListCall) doRequest(alt string) (*http.Respo } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+parent}/operations") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "parent": c.parent, @@ -7771,9 +8132,13 @@ func (c *ProjectsZonesGetServerconfigCall) doRequest(alt string) (*http.Response } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/projects/{projectId}/zones/{zone}/serverconfig") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "projectId": c.projectId, @@ -7919,9 +8284,13 @@ func (c *ProjectsZonesClustersAddonsCall) doRequest(alt string) (*http.Response, } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/projects/{projectId}/zones/{zone}/clusters/{clusterId}/addons") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "projectId": c.projectId, @@ -8073,9 +8442,13 @@ func (c *ProjectsZonesClustersCompleteIpRotationCall) doRequest(alt string) (*ht } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/projects/{projectId}/zones/{zone}/clusters/{clusterId}:completeIpRotation") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "projectId": c.projectId, @@ -8241,9 +8614,13 @@ func (c *ProjectsZonesClustersCreateCall) doRequest(alt string) (*http.Response, } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/projects/{projectId}/zones/{zone}/clusters") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "projectId": c.projectId, @@ -8399,9 +8776,13 @@ func (c *ProjectsZonesClustersDeleteCall) doRequest(alt string) (*http.Response, reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/projects/{projectId}/zones/{zone}/clusters/{clusterId}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "projectId": c.projectId, @@ -8570,9 +8951,13 @@ func (c *ProjectsZonesClustersGetCall) doRequest(alt string) (*http.Response, er } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/projects/{projectId}/zones/{zone}/clusters/{clusterId}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "projectId": c.projectId, @@ -8727,9 +9112,13 @@ func (c *ProjectsZonesClustersLegacyAbacCall) doRequest(alt string) (*http.Respo } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/projects/{projectId}/zones/{zone}/clusters/{clusterId}/legacyAbac") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "projectId": c.projectId, @@ -8897,9 +9286,13 @@ func (c *ProjectsZonesClustersListCall) doRequest(alt string) (*http.Response, e } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/projects/{projectId}/zones/{zone}/clusters") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "projectId": c.projectId, @@ -9045,9 +9438,13 @@ func (c *ProjectsZonesClustersLocationsCall) doRequest(alt string) (*http.Respon } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/projects/{projectId}/zones/{zone}/clusters/{clusterId}/locations") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "projectId": c.projectId, @@ -9199,9 +9596,13 @@ func (c *ProjectsZonesClustersLoggingCall) doRequest(alt string) (*http.Response } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/projects/{projectId}/zones/{zone}/clusters/{clusterId}/logging") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "projectId": c.projectId, @@ -9353,9 +9754,13 @@ func (c *ProjectsZonesClustersMasterCall) doRequest(alt string) (*http.Response, } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/projects/{projectId}/zones/{zone}/clusters/{clusterId}/master") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "projectId": c.projectId, @@ -9507,9 +9912,13 @@ func (c *ProjectsZonesClustersMonitoringCall) doRequest(alt string) (*http.Respo } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/projects/{projectId}/zones/{zone}/clusters/{clusterId}/monitoring") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "projectId": c.projectId, @@ -9661,9 +10070,13 @@ func (c *ProjectsZonesClustersResourceLabelsCall) doRequest(alt string) (*http.R } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/projects/{projectId}/zones/{zone}/clusters/{clusterId}/resourceLabels") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "projectId": c.projectId, @@ -9815,9 +10228,13 @@ func (c *ProjectsZonesClustersSetMaintenancePolicyCall) doRequest(alt string) (* } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/projects/{projectId}/zones/{zone}/clusters/{clusterId}:setMaintenancePolicy") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "projectId": c.projectId, @@ -9973,9 +10390,13 @@ func (c *ProjectsZonesClustersSetMasterAuthCall) doRequest(alt string) (*http.Re } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/projects/{projectId}/zones/{zone}/clusters/{clusterId}:setMasterAuth") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "projectId": c.projectId, @@ -10127,9 +10548,13 @@ func (c *ProjectsZonesClustersSetNetworkPolicyCall) doRequest(alt string) (*http } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/projects/{projectId}/zones/{zone}/clusters/{clusterId}:setNetworkPolicy") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "projectId": c.projectId, @@ -10281,9 +10706,13 @@ func (c *ProjectsZonesClustersStartIpRotationCall) doRequest(alt string) (*http. } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/projects/{projectId}/zones/{zone}/clusters/{clusterId}:startIpRotation") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "projectId": c.projectId, @@ -10435,9 +10864,13 @@ func (c *ProjectsZonesClustersUpdateCall) doRequest(alt string) (*http.Response, } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/projects/{projectId}/zones/{zone}/clusters/{clusterId}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PUT", urls, body) + req, err := http.NewRequest("PUT", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "projectId": c.projectId, @@ -10591,9 +11024,13 @@ func (c *ProjectsZonesClustersNodePoolsAutoscalingCall) doRequest(alt string) (* } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/projects/{projectId}/zones/{zone}/clusters/{clusterId}/nodePools/{nodePoolId}/autoscaling") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "projectId": c.projectId, @@ -10753,9 +11190,13 @@ func (c *ProjectsZonesClustersNodePoolsCreateCall) doRequest(alt string) (*http. } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/projects/{projectId}/zones/{zone}/clusters/{clusterId}/nodePools") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "projectId": c.projectId, @@ -10912,9 +11353,13 @@ func (c *ProjectsZonesClustersNodePoolsDeleteCall) doRequest(alt string) (*http. reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/projects/{projectId}/zones/{zone}/clusters/{clusterId}/nodePools/{nodePoolId}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "projectId": c.projectId, @@ -11095,9 +11540,13 @@ func (c *ProjectsZonesClustersNodePoolsGetCall) doRequest(alt string) (*http.Res } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/projects/{projectId}/zones/{zone}/clusters/{clusterId}/nodePools/{nodePoolId}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "projectId": c.projectId, @@ -11274,9 +11723,13 @@ func (c *ProjectsZonesClustersNodePoolsListCall) doRequest(alt string) (*http.Re } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/projects/{projectId}/zones/{zone}/clusters/{clusterId}/nodePools") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "projectId": c.projectId, @@ -11434,9 +11887,13 @@ func (c *ProjectsZonesClustersNodePoolsRollbackCall) doRequest(alt string) (*htt } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/projects/{projectId}/zones/{zone}/clusters/{clusterId}/nodePools/{nodePoolId}:rollback") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "projectId": c.projectId, @@ -11598,9 +12055,13 @@ func (c *ProjectsZonesClustersNodePoolsSetManagementCall) doRequest(alt string) } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/projects/{projectId}/zones/{zone}/clusters/{clusterId}/nodePools/{nodePoolId}/setManagement") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "projectId": c.projectId, @@ -11762,9 +12223,13 @@ func (c *ProjectsZonesClustersNodePoolsSetSizeCall) doRequest(alt string) (*http } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/projects/{projectId}/zones/{zone}/clusters/{clusterId}/nodePools/{nodePoolId}/setSize") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "projectId": c.projectId, @@ -11927,9 +12392,13 @@ func (c *ProjectsZonesClustersNodePoolsUpdateCall) doRequest(alt string) (*http. } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/projects/{projectId}/zones/{zone}/clusters/{clusterId}/nodePools/{nodePoolId}/update") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "projectId": c.projectId, @@ -12089,9 +12558,13 @@ func (c *ProjectsZonesOperationsCancelCall) doRequest(alt string) (*http.Respons } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/projects/{projectId}/zones/{zone}/operations/{operationId}:cancel") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "projectId": c.projectId, @@ -12258,9 +12731,13 @@ func (c *ProjectsZonesOperationsGetCall) doRequest(alt string) (*http.Response, } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/projects/{projectId}/zones/{zone}/operations/{operationId}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "projectId": c.projectId, @@ -12429,9 +12906,13 @@ func (c *ProjectsZonesOperationsListCall) doRequest(alt string) (*http.Response, } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/projects/{projectId}/zones/{zone}/operations") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "projectId": c.projectId, diff --git a/vendor/google.golang.org/api/gensupport/BUILD b/vendor/google.golang.org/api/gensupport/BUILD index cd7119f750c..50d626bf609 100644 --- a/vendor/google.golang.org/api/gensupport/BUILD +++ b/vendor/google.golang.org/api/gensupport/BUILD @@ -6,12 +6,10 @@ go_library( "backoff.go", "buffer.go", "doc.go", - "go18.go", "header.go", "json.go", "jsonfloat.go", "media.go", - "not_go18.go", "params.go", "resumable.go", "retry.go", @@ -20,11 +18,7 @@ go_library( importmap = "k8s.io/kubernetes/vendor/google.golang.org/api/gensupport", importpath = "google.golang.org/api/gensupport", visibility = ["//visibility:public"], - deps = [ - "//vendor/golang.org/x/net/context:go_default_library", - "//vendor/golang.org/x/net/context/ctxhttp:go_default_library", - "//vendor/google.golang.org/api/googleapi:go_default_library", - ], + deps = ["//vendor/google.golang.org/api/googleapi:go_default_library"], ) filegroup( diff --git a/vendor/google.golang.org/api/gensupport/backoff.go b/vendor/google.golang.org/api/gensupport/backoff.go index 1356140472a..94b7789eea7 100644 --- a/vendor/google.golang.org/api/gensupport/backoff.go +++ b/vendor/google.golang.org/api/gensupport/backoff.go @@ -9,6 +9,8 @@ import ( "time" ) +// BackoffStrategy defines the set of functions that a backoff-er must +// implement. type BackoffStrategy interface { // Pause returns the duration of the next pause and true if the operation should be // retried, or false if no further retries should be attempted. @@ -28,6 +30,7 @@ type ExponentialBackoff struct { n uint } +// Pause returns the amount of time the caller should wait. func (eb *ExponentialBackoff) Pause() (time.Duration, bool) { if eb.total > eb.Max { return 0, false @@ -40,6 +43,8 @@ func (eb *ExponentialBackoff) Pause() (time.Duration, bool) { return d, true } +// Reset resets the backoff strategy such that the next Pause call will begin +// counting from the start. It is not safe to call concurrently with Pause. func (eb *ExponentialBackoff) Reset() { eb.n = 0 eb.total = 0 diff --git a/vendor/google.golang.org/api/gensupport/buffer.go b/vendor/google.golang.org/api/gensupport/buffer.go index 99210491153..3d0817ede98 100644 --- a/vendor/google.golang.org/api/gensupport/buffer.go +++ b/vendor/google.golang.org/api/gensupport/buffer.go @@ -11,7 +11,8 @@ import ( "google.golang.org/api/googleapi" ) -// MediaBuffer buffers data from an io.Reader to support uploading media in retryable chunks. +// MediaBuffer buffers data from an io.Reader to support uploading media in +// retryable chunks. It should be created with NewMediaBuffer. type MediaBuffer struct { media io.Reader @@ -22,6 +23,7 @@ type MediaBuffer struct { off int64 } +// NewMediaBuffer initializes a MediaBuffer. func NewMediaBuffer(media io.Reader, chunkSize int) *MediaBuffer { return &MediaBuffer{media: media, chunk: make([]byte, 0, chunkSize)} } diff --git a/vendor/google.golang.org/api/gensupport/go18.go b/vendor/google.golang.org/api/gensupport/go18.go deleted file mode 100644 index c76cb8f20bb..00000000000 --- a/vendor/google.golang.org/api/gensupport/go18.go +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build go1.8 - -package gensupport - -import ( - "io" - "net/http" -) - -// SetGetBody sets the GetBody field of req to f. -func SetGetBody(req *http.Request, f func() (io.ReadCloser, error)) { - req.GetBody = f -} diff --git a/vendor/google.golang.org/api/gensupport/jsonfloat.go b/vendor/google.golang.org/api/gensupport/jsonfloat.go index cb02335d22d..8377850811f 100644 --- a/vendor/google.golang.org/api/gensupport/jsonfloat.go +++ b/vendor/google.golang.org/api/gensupport/jsonfloat.go @@ -1,4 +1,4 @@ -// Copyright 2016 Google Inc. All Rights Reserved. +// Copyright 2016 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/vendor/google.golang.org/api/gensupport/media.go b/vendor/google.golang.org/api/gensupport/media.go index 5895fef8896..4cef4adbb66 100644 --- a/vendor/google.golang.org/api/gensupport/media.go +++ b/vendor/google.golang.org/api/gensupport/media.go @@ -242,6 +242,7 @@ func NewInfoFromResumableMedia(r io.ReaderAt, size int64, mediaType string) *Med } } +// SetProgressUpdater sets the progress updater for the media info. func (mi *MediaInfo) SetProgressUpdater(pu googleapi.ProgressUpdater) { if mi != nil { mi.progressUpdater = pu @@ -334,3 +335,8 @@ func (mi *MediaInfo) ResumableUpload(locURI string) *ResumableUpload { }, } } + +// SetGetBody sets the GetBody field of req to f. +func SetGetBody(req *http.Request, f func() (io.ReadCloser, error)) { + req.GetBody = f +} diff --git a/vendor/google.golang.org/api/gensupport/not_go18.go b/vendor/google.golang.org/api/gensupport/not_go18.go deleted file mode 100644 index 2536501cecf..00000000000 --- a/vendor/google.golang.org/api/gensupport/not_go18.go +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build !go1.8 - -package gensupport - -import ( - "io" - "net/http" -) - -func SetGetBody(req *http.Request, f func() (io.ReadCloser, error)) {} diff --git a/vendor/google.golang.org/api/gensupport/params.go b/vendor/google.golang.org/api/gensupport/params.go index 3b3c743967e..0e878a4255b 100644 --- a/vendor/google.golang.org/api/gensupport/params.go +++ b/vendor/google.golang.org/api/gensupport/params.go @@ -43,6 +43,7 @@ func (u URLParams) Encode() string { return url.Values(u).Encode() } +// SetOptions sets the URL params and any additional call options. func SetOptions(u URLParams, opts ...googleapi.CallOption) { for _, o := range opts { u.Set(o.Get()) diff --git a/vendor/google.golang.org/api/gensupport/resumable.go b/vendor/google.golang.org/api/gensupport/resumable.go index dcd591f7ff6..2552a6acaca 100644 --- a/vendor/google.golang.org/api/gensupport/resumable.go +++ b/vendor/google.golang.org/api/gensupport/resumable.go @@ -5,14 +5,13 @@ package gensupport import ( + "context" "errors" "fmt" "io" "net/http" "sync" "time" - - "golang.org/x/net/context" ) const ( diff --git a/vendor/google.golang.org/api/gensupport/retry.go b/vendor/google.golang.org/api/gensupport/retry.go index c60b3c394b3..fdde3f42c69 100644 --- a/vendor/google.golang.org/api/gensupport/retry.go +++ b/vendor/google.golang.org/api/gensupport/retry.go @@ -1,4 +1,4 @@ -// Copyright 2017 Google Inc. All Rights Reserved. +// Copyright 2017 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -15,12 +15,11 @@ package gensupport import ( + "context" "io" "net" "net/http" "time" - - "golang.org/x/net/context" ) // Retry invokes the given function, retrying it multiple times if the connection failed or diff --git a/vendor/google.golang.org/api/gensupport/send.go b/vendor/google.golang.org/api/gensupport/send.go index 0f75aa86792..5799393093d 100644 --- a/vendor/google.golang.org/api/gensupport/send.go +++ b/vendor/google.golang.org/api/gensupport/send.go @@ -5,12 +5,10 @@ package gensupport import ( + "context" "encoding/json" "errors" "net/http" - - "golang.org/x/net/context" - "golang.org/x/net/context/ctxhttp" ) // Hook is the type of a function that is called once before each HTTP request @@ -32,7 +30,8 @@ func RegisterHook(h Hook) { // SendRequest sends a single HTTP request using the given client. // If ctx is non-nil, it calls all hooks, then sends the request with -// ctxhttp.Do, then calls any functions returned by the hooks in reverse order. +// req.WithContext, then calls any functions returned by the hooks in +// reverse order. func SendRequest(ctx context.Context, client *http.Client, req *http.Request) (*http.Response, error) { // Disallow Accept-Encoding because it interferes with the automatic gzip handling // done by the default http.Transport. See https://github.com/google/google-api-go-client/issues/219. @@ -50,7 +49,7 @@ func SendRequest(ctx context.Context, client *http.Client, req *http.Request) (* } // Send request. - resp, err := ctxhttp.Do(ctx, client, req) + resp, err := send(ctx, client, req) // Call returned funcs in reverse order. for i := len(post) - 1; i >= 0; i-- { @@ -61,6 +60,23 @@ func SendRequest(ctx context.Context, client *http.Client, req *http.Request) (* return resp, err } +func send(ctx context.Context, client *http.Client, req *http.Request) (*http.Response, error) { + if client == nil { + client = http.DefaultClient + } + resp, err := client.Do(req.WithContext(ctx)) + // If we got an error, and the context has been canceled, + // the context's error is probably more useful. + if err != nil { + select { + case <-ctx.Done(): + err = ctx.Err() + default: + } + } + return resp, err +} + // DecodeResponse decodes the body of res into target. If there is no body, // target is unchanged. func DecodeResponse(target interface{}, res *http.Response) error { diff --git a/vendor/google.golang.org/api/googleapi/googleapi.go b/vendor/google.golang.org/api/googleapi/googleapi.go index 3d970ee11be..2b892ff3462 100644 --- a/vendor/google.golang.org/api/googleapi/googleapi.go +++ b/vendor/google.golang.org/api/googleapi/googleapi.go @@ -37,24 +37,28 @@ type SizeReaderAt interface { // ServerResponse is embedded in each Do response and // provides the HTTP status code and header sent by the server. type ServerResponse struct { - // HTTPStatusCode is the server's response status code. - // When using a resource method's Do call, this will always be in the 2xx range. + // HTTPStatusCode is the server's response status code. When using a + // resource method's Do call, this will always be in the 2xx range. HTTPStatusCode int // Header contains the response header fields from the server. Header http.Header } const ( + // Version defines the gax version being used. This is typically sent + // in an HTTP header to services. Version = "0.5" // UserAgent is the header string used to identify this package. UserAgent = "google-api-go-client/" + Version - // The default chunk size to use for resumable uploads if not specified by the user. + // DefaultUploadChunkSize is the default chunk size to use for resumable + // uploads if not specified by the user. DefaultUploadChunkSize = 8 * 1024 * 1024 - // The minimum chunk size that can be used for resumable uploads. All - // user-specified chunk sizes must be multiple of this value. + // MinUploadChunkSize is the minimum chunk size that can be used for + // resumable uploads. All user-specified chunk sizes must be multiple of + // this value. MinUploadChunkSize = 256 * 1024 ) @@ -161,9 +165,13 @@ func CheckMediaResponse(res *http.Response) error { } } +// MarshalStyle defines whether to marshal JSON with a {"data": ...} wrapper. type MarshalStyle bool +// WithDataWrapper marshals JSON with a {"data": ...} wrapper. var WithDataWrapper = MarshalStyle(true) + +// WithoutDataWrapper marshals JSON without a {"data": ...} wrapper. var WithoutDataWrapper = MarshalStyle(false) func (wrap MarshalStyle) JSONReader(v interface{}) (io.Reader, error) { @@ -212,6 +220,7 @@ func (w countingWriter) Write(p []byte) (int, error) { // The remaining usable pieces of resumable uploads is exposed in each auto-generated API. type ProgressUpdater func(current, total int64) +// MediaOption defines the interface for setting media options. type MediaOption interface { setOptions(o *MediaOptions) } @@ -268,6 +277,11 @@ func ProcessMediaOptions(opts []MediaOption) *MediaOptions { return mo } +// ResolveRelative resolves relatives such as "http://www.golang.org/" and +// "topics/myproject/mytopic" into a single string, such as +// "http://www.golang.org/topics/myproject/mytopic". It strips all parent +// references (e.g. ../..) as well as anything after the host +// (e.g. /bar/gaz gets stripped out of foo.com/bar/gaz). func ResolveRelative(basestr, relstr string) string { u, _ := url.Parse(basestr) afterColonPath := "" diff --git a/vendor/google.golang.org/api/googleapi/types.go b/vendor/google.golang.org/api/googleapi/types.go index c8fdd541611..a280e3021a1 100644 --- a/vendor/google.golang.org/api/googleapi/types.go +++ b/vendor/google.golang.org/api/googleapi/types.go @@ -120,33 +120,33 @@ func quotedList(n int, fn func(dst []byte, i int) []byte) ([]byte, error) { return dst, nil } -func (s Int64s) MarshalJSON() ([]byte, error) { - return quotedList(len(s), func(dst []byte, i int) []byte { - return strconv.AppendInt(dst, s[i], 10) +func (q Int64s) MarshalJSON() ([]byte, error) { + return quotedList(len(q), func(dst []byte, i int) []byte { + return strconv.AppendInt(dst, q[i], 10) }) } -func (s Int32s) MarshalJSON() ([]byte, error) { - return quotedList(len(s), func(dst []byte, i int) []byte { - return strconv.AppendInt(dst, int64(s[i]), 10) +func (q Int32s) MarshalJSON() ([]byte, error) { + return quotedList(len(q), func(dst []byte, i int) []byte { + return strconv.AppendInt(dst, int64(q[i]), 10) }) } -func (s Uint64s) MarshalJSON() ([]byte, error) { - return quotedList(len(s), func(dst []byte, i int) []byte { - return strconv.AppendUint(dst, s[i], 10) +func (q Uint64s) MarshalJSON() ([]byte, error) { + return quotedList(len(q), func(dst []byte, i int) []byte { + return strconv.AppendUint(dst, q[i], 10) }) } -func (s Uint32s) MarshalJSON() ([]byte, error) { - return quotedList(len(s), func(dst []byte, i int) []byte { - return strconv.AppendUint(dst, uint64(s[i]), 10) +func (q Uint32s) MarshalJSON() ([]byte, error) { + return quotedList(len(q), func(dst []byte, i int) []byte { + return strconv.AppendUint(dst, uint64(q[i]), 10) }) } -func (s Float64s) MarshalJSON() ([]byte, error) { - return quotedList(len(s), func(dst []byte, i int) []byte { - return strconv.AppendFloat(dst, s[i], 'g', -1, 64) +func (q Float64s) MarshalJSON() ([]byte, error) { + return quotedList(len(q), func(dst []byte, i int) []byte { + return strconv.AppendFloat(dst, q[i], 'g', -1, 64) }) } diff --git a/vendor/google.golang.org/api/logging/v2beta1/BUILD b/vendor/google.golang.org/api/logging/v2beta1/BUILD index 26105cc9dd2..8b23d0c7e57 100644 --- a/vendor/google.golang.org/api/logging/v2beta1/BUILD +++ b/vendor/google.golang.org/api/logging/v2beta1/BUILD @@ -7,8 +7,6 @@ go_library( importpath = "google.golang.org/api/logging/v2beta1", visibility = ["//visibility:public"], deps = [ - "//vendor/golang.org/x/net/context:go_default_library", - "//vendor/golang.org/x/net/context/ctxhttp:go_default_library", "//vendor/google.golang.org/api/gensupport:go_default_library", "//vendor/google.golang.org/api/googleapi:go_default_library", ], diff --git a/vendor/google.golang.org/api/logging/v2beta1/logging-api.json b/vendor/google.golang.org/api/logging/v2beta1/logging-api.json index 80c939831ea..31c5d26da77 100644 --- a/vendor/google.golang.org/api/logging/v2beta1/logging-api.json +++ b/vendor/google.golang.org/api/logging/v2beta1/logging-api.json @@ -24,7 +24,7 @@ "baseUrl": "https://logging.googleapis.com/", "batchPath": "batch", "canonicalName": "Logging", - "description": "Writes log entries and manages your Stackdriver Logging configuration.", + "description": "Writes log entries and manages your Logging configuration.", "discoveryVersion": "v1", "documentationLink": "https://cloud.google.com/logging/docs/", "fullyEncodeReservedExpansion": true, @@ -116,83 +116,10 @@ }, "protocol": "rest", "resources": { - "billingAccounts": { - "resources": { - "logs": { - "methods": { - "delete": { - "description": "Deletes all the log entries in a log. The log reappears if it receives new entries. Log entries written shortly before the delete operation might not be deleted.", - "flatPath": "v2beta1/billingAccounts/{billingAccountsId}/logs/{logsId}", - "httpMethod": "DELETE", - "id": "logging.billingAccounts.logs.delete", - "parameterOrder": [ - "logName" - ], - "parameters": { - "logName": { - "description": "Required. The resource name of the log to delete:\n\"projects/[PROJECT_ID]/logs/[LOG_ID]\"\n\"organizations/[ORGANIZATION_ID]/logs/[LOG_ID]\"\n\"billingAccounts/[BILLING_ACCOUNT_ID]/logs/[LOG_ID]\"\n\"folders/[FOLDER_ID]/logs/[LOG_ID]\"\n[LOG_ID] must be URL-encoded. For example, \"projects/my-project-id/logs/syslog\", \"organizations/1234567890/logs/cloudresourcemanager.googleapis.com%2Factivity\". For more information about log names, see LogEntry.", - "location": "path", - "pattern": "^billingAccounts/[^/]+/logs/[^/]+$", - "required": true, - "type": "string" - } - }, - "path": "v2beta1/{+logName}", - "response": { - "$ref": "Empty" - }, - "scopes": [ - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/logging.admin" - ] - }, - "list": { - "description": "Lists the logs in projects, organizations, folders, or billing accounts. Only logs that have entries are listed.", - "flatPath": "v2beta1/billingAccounts/{billingAccountsId}/logs", - "httpMethod": "GET", - "id": "logging.billingAccounts.logs.list", - "parameterOrder": [ - "parent" - ], - "parameters": { - "pageSize": { - "description": "Optional. The maximum number of results to return from this request. Non-positive values are ignored. The presence of nextPageToken in the response indicates that more results might be available.", - "format": "int32", - "location": "query", - "type": "integer" - }, - "pageToken": { - "description": "Optional. If present, then retrieve the next batch of results from the preceding call to this method. pageToken must be the value of nextPageToken from the previous response. The values of other method parameters should be identical to those in the previous call.", - "location": "query", - "type": "string" - }, - "parent": { - "description": "Required. The resource name that owns the logs:\n\"projects/[PROJECT_ID]\"\n\"organizations/[ORGANIZATION_ID]\"\n\"billingAccounts/[BILLING_ACCOUNT_ID]\"\n\"folders/[FOLDER_ID]\"\n", - "location": "path", - "pattern": "^billingAccounts/[^/]+$", - "required": true, - "type": "string" - } - }, - "path": "v2beta1/{+parent}/logs", - "response": { - "$ref": "ListLogsResponse" - }, - "scopes": [ - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/cloud-platform.read-only", - "https://www.googleapis.com/auth/logging.admin", - "https://www.googleapis.com/auth/logging.read" - ] - } - } - } - } - }, "entries": { "methods": { "list": { - "description": "Lists log entries. Use this method to retrieve log entries from Stackdriver Logging. For ways to export log entries, see Exporting Logs.", + "description": "Lists log entries. Use this method to retrieve log entries from Logging. For ways to export log entries, see Exporting Logs.", "flatPath": "v2beta1/entries:list", "httpMethod": "POST", "id": "logging.entries.list", @@ -213,7 +140,7 @@ ] }, "write": { - "description": "Writes log entries to Stackdriver Logging. This API method is the only way to send log entries to Stackdriver Logging. This method is used, directly or indirectly, by the Stackdriver Logging agent (fluentd) and all logging libraries configured to use Stackdriver Logging. A single request may contain log entries for a maximum of 1000 different resources (projects, organizations, billing accounts or folders)", + "description": "Writes log entries to Logging. This API method is the only way to send log entries to Logging. This method is used, directly or indirectly, by the Logging agent (fluentd) and all logging libraries configured to use Logging. A single request may contain log entries for a maximum of 1000 different resources (projects, organizations, billing accounts or folders)", "flatPath": "v2beta1/entries:write", "httpMethod": "POST", "id": "logging.entries.write", @@ -237,7 +164,7 @@ "monitoredResourceDescriptors": { "methods": { "list": { - "description": "Lists the descriptors for monitored resource types used by Stackdriver Logging.", + "description": "Lists the descriptors for monitored resource types used by Logging.", "flatPath": "v2beta1/monitoredResourceDescriptors", "httpMethod": "GET", "id": "logging.monitoredResourceDescriptors.list", @@ -268,150 +195,8 @@ } } }, - "organizations": { - "resources": { - "logs": { - "methods": { - "delete": { - "description": "Deletes all the log entries in a log. The log reappears if it receives new entries. Log entries written shortly before the delete operation might not be deleted.", - "flatPath": "v2beta1/organizations/{organizationsId}/logs/{logsId}", - "httpMethod": "DELETE", - "id": "logging.organizations.logs.delete", - "parameterOrder": [ - "logName" - ], - "parameters": { - "logName": { - "description": "Required. The resource name of the log to delete:\n\"projects/[PROJECT_ID]/logs/[LOG_ID]\"\n\"organizations/[ORGANIZATION_ID]/logs/[LOG_ID]\"\n\"billingAccounts/[BILLING_ACCOUNT_ID]/logs/[LOG_ID]\"\n\"folders/[FOLDER_ID]/logs/[LOG_ID]\"\n[LOG_ID] must be URL-encoded. For example, \"projects/my-project-id/logs/syslog\", \"organizations/1234567890/logs/cloudresourcemanager.googleapis.com%2Factivity\". For more information about log names, see LogEntry.", - "location": "path", - "pattern": "^organizations/[^/]+/logs/[^/]+$", - "required": true, - "type": "string" - } - }, - "path": "v2beta1/{+logName}", - "response": { - "$ref": "Empty" - }, - "scopes": [ - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/logging.admin" - ] - }, - "list": { - "description": "Lists the logs in projects, organizations, folders, or billing accounts. Only logs that have entries are listed.", - "flatPath": "v2beta1/organizations/{organizationsId}/logs", - "httpMethod": "GET", - "id": "logging.organizations.logs.list", - "parameterOrder": [ - "parent" - ], - "parameters": { - "pageSize": { - "description": "Optional. The maximum number of results to return from this request. Non-positive values are ignored. The presence of nextPageToken in the response indicates that more results might be available.", - "format": "int32", - "location": "query", - "type": "integer" - }, - "pageToken": { - "description": "Optional. If present, then retrieve the next batch of results from the preceding call to this method. pageToken must be the value of nextPageToken from the previous response. The values of other method parameters should be identical to those in the previous call.", - "location": "query", - "type": "string" - }, - "parent": { - "description": "Required. The resource name that owns the logs:\n\"projects/[PROJECT_ID]\"\n\"organizations/[ORGANIZATION_ID]\"\n\"billingAccounts/[BILLING_ACCOUNT_ID]\"\n\"folders/[FOLDER_ID]\"\n", - "location": "path", - "pattern": "^organizations/[^/]+$", - "required": true, - "type": "string" - } - }, - "path": "v2beta1/{+parent}/logs", - "response": { - "$ref": "ListLogsResponse" - }, - "scopes": [ - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/cloud-platform.read-only", - "https://www.googleapis.com/auth/logging.admin", - "https://www.googleapis.com/auth/logging.read" - ] - } - } - } - } - }, "projects": { "resources": { - "logs": { - "methods": { - "delete": { - "description": "Deletes all the log entries in a log. The log reappears if it receives new entries. Log entries written shortly before the delete operation might not be deleted.", - "flatPath": "v2beta1/projects/{projectsId}/logs/{logsId}", - "httpMethod": "DELETE", - "id": "logging.projects.logs.delete", - "parameterOrder": [ - "logName" - ], - "parameters": { - "logName": { - "description": "Required. The resource name of the log to delete:\n\"projects/[PROJECT_ID]/logs/[LOG_ID]\"\n\"organizations/[ORGANIZATION_ID]/logs/[LOG_ID]\"\n\"billingAccounts/[BILLING_ACCOUNT_ID]/logs/[LOG_ID]\"\n\"folders/[FOLDER_ID]/logs/[LOG_ID]\"\n[LOG_ID] must be URL-encoded. For example, \"projects/my-project-id/logs/syslog\", \"organizations/1234567890/logs/cloudresourcemanager.googleapis.com%2Factivity\". For more information about log names, see LogEntry.", - "location": "path", - "pattern": "^projects/[^/]+/logs/[^/]+$", - "required": true, - "type": "string" - } - }, - "path": "v2beta1/{+logName}", - "response": { - "$ref": "Empty" - }, - "scopes": [ - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/logging.admin" - ] - }, - "list": { - "description": "Lists the logs in projects, organizations, folders, or billing accounts. Only logs that have entries are listed.", - "flatPath": "v2beta1/projects/{projectsId}/logs", - "httpMethod": "GET", - "id": "logging.projects.logs.list", - "parameterOrder": [ - "parent" - ], - "parameters": { - "pageSize": { - "description": "Optional. The maximum number of results to return from this request. Non-positive values are ignored. The presence of nextPageToken in the response indicates that more results might be available.", - "format": "int32", - "location": "query", - "type": "integer" - }, - "pageToken": { - "description": "Optional. If present, then retrieve the next batch of results from the preceding call to this method. pageToken must be the value of nextPageToken from the previous response. The values of other method parameters should be identical to those in the previous call.", - "location": "query", - "type": "string" - }, - "parent": { - "description": "Required. The resource name that owns the logs:\n\"projects/[PROJECT_ID]\"\n\"organizations/[ORGANIZATION_ID]\"\n\"billingAccounts/[BILLING_ACCOUNT_ID]\"\n\"folders/[FOLDER_ID]\"\n", - "location": "path", - "pattern": "^projects/[^/]+$", - "required": true, - "type": "string" - } - }, - "path": "v2beta1/{+parent}/logs", - "response": { - "$ref": "ListLogsResponse" - }, - "scopes": [ - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/cloud-platform.read-only", - "https://www.googleapis.com/auth/logging.admin", - "https://www.googleapis.com/auth/logging.read" - ] - } - } - }, "metrics": { "methods": { "create": { @@ -589,7 +374,7 @@ "type": "string" }, "uniqueWriterIdentity": { - "description": "Optional. Determines the kind of IAM identity returned as writer_identity in the new sink. If this value is omitted or set to false, and if the sink's parent is a project, then the value returned as writer_identity is the same group or service account used by Stackdriver Logging before the addition of writer identities to this API. The sink's destination must be in the same project as the sink itself.If this field is set to true, or if the sink is owned by a non-project resource such as an organization, then the value of writer_identity will be a unique service account used only for exports from the new sink. For more information, see writer_identity in LogSink.", + "description": "Optional. Determines the kind of IAM identity returned as writer_identity in the new sink. If this value is omitted or set to false, and if the sink's parent is a project, then the value returned as writer_identity is the same group or service account used by Logging before the addition of writer identities to this API. The sink's destination must be in the same project as the sink itself.If this field is set to true, or if the sink is owned by a non-project resource such as an organization, then the value of writer_identity will be a unique service account used only for exports from the new sink. For more information, see writer_identity in LogSink.", "location": "query", "type": "boolean" } @@ -721,7 +506,7 @@ "type": "boolean" }, "updateMask": { - "description": "Optional. Field mask that specifies the fields in sink that need an update. A sink field will be overwritten if, and only if, it is in the update mask. name and output only fields cannot be updated.An empty updateMask is temporarily treated as using the following mask for backwards compatibility purposes: destination,filter,includeChildren At some point in the future, behavior will be removed and specifying an empty updateMask will be an error.For a detailed FieldMask definition, see https://developers.google.com/protocol-buffers/docs/reference/google.protobuf#fieldmaskExample: updateMask=filter.", + "description": "Optional. Field mask that specifies the fields in sink that need an update. A sink field will be overwritten if, and only if, it is in the update mask. name and output only fields cannot be updated.An empty updateMask is temporarily treated as using the following mask for backwards compatibility purposes: destination,filter,includeChildren At some point in the future, behavior will be removed and specifying an empty updateMask will be an error.For a detailed FieldMask definition, see https://developers.google.com/protocol-buffers/docs/reference/google.protobuf#google.protobuf.FieldMaskExample: updateMask=filter.", "format": "google-fieldmask", "location": "query", "type": "string" @@ -744,7 +529,7 @@ } } }, - "revision": "20180604", + "revision": "20181020", "rootUrl": "https://logging.googleapis.com/", "schemas": { "BucketOptions": { @@ -1006,24 +791,6 @@ }, "type": "object" }, - "ListLogsResponse": { - "description": "Result returned from ListLogs.", - "id": "ListLogsResponse", - "properties": { - "logNames": { - "description": "A list of log names. For example, \"projects/my-project/syslog\" or \"organizations/123/cloudresourcemanager.googleapis.com%2Factivity\".", - "items": { - "type": "string" - }, - "type": "array" - }, - "nextPageToken": { - "description": "If there might be more results than those appearing in this response, then nextPageToken is included. To get the next set of results, call this method again using the value of nextPageToken as pageToken.", - "type": "string" - } - }, - "type": "object" - }, "ListMonitoredResourceDescriptorsResponse": { "description": "Result returned from ListMonitoredResourceDescriptors.", "id": "ListMonitoredResourceDescriptorsResponse", @@ -1069,7 +836,7 @@ "description": "Optional. Information about the HTTP request associated with this log entry, if applicable." }, "insertId": { - "description": "Optional. A unique identifier for the log entry. If you provide a value, then Stackdriver Logging considers other log entries in the same project, with the same timestamp, and with the same insert_id to be duplicates which can be removed. If omitted in new log entries, then Stackdriver Logging assigns its own unique identifier. The insert_id is also used to order log entries that have the same timestamp value.", + "description": "Optional. A unique identifier for the log entry. If you provide a value, then Logging considers other log entries in the same project, with the same timestamp, and with the same insert_id to be duplicates which can be removed. If omitted in new log entries, then Logging assigns its own unique identifier. The insert_id is also used to order log entries that have the same timestamp value.", "type": "string" }, "jsonPayload": { @@ -1108,7 +875,7 @@ "type": "object" }, "receiveTimestamp": { - "description": "Output only. The time the log entry was received by Stackdriver Logging.", + "description": "Output only. The time the log entry was received by Logging.", "format": "google-datetime", "type": "string" }, @@ -1147,7 +914,7 @@ "description": "Optional. Source code location information associated with the log entry, if any." }, "spanId": { - "description": "Optional. The span ID within the trace associated with the log entry. For Stackdriver Trace spans, this is the same format that the Stackdriver Trace API v2 uses: a 16-character hexadecimal encoding of an 8-byte array, such as \u003ccode\u003e\"000000000000004a\"\u003c/code\u003e.", + "description": "Optional. The span ID within the trace associated with the log entry. For Trace spans, this is the same format that the Trace API v2 uses: a 16-character hexadecimal encoding of an 8-byte array, such as \u003ccode\u003e\"000000000000004a\"\u003c/code\u003e.", "type": "string" }, "textPayload": { @@ -1155,13 +922,17 @@ "type": "string" }, "timestamp": { - "description": "Optional. The time the event described by the log entry occurred. This time is used to compute the log entry's age and to enforce the logs retention period. If this field is omitted in a new log entry, then Stackdriver Logging assigns it the current time. Timestamps have nanosecond accuracy, but trailing zeros in the fractional seconds might be omitted when the timestamp is displayed.Incoming log entries should have timestamps that are no more than the logs retention period in the past, and no more than 24 hours in the future. Log entries outside those time boundaries will not be available when calling entries.list, but those log entries can still be exported with LogSinks.", + "description": "Optional. The time the event described by the log entry occurred. This time is used to compute the log entry's age and to enforce the logs retention period. If this field is omitted in a new log entry, then Logging assigns it the current time. Timestamps have nanosecond accuracy, but trailing zeros in the fractional seconds might be omitted when the timestamp is displayed.Incoming log entries should have timestamps that are no more than the logs retention period in the past, and no more than 24 hours in the future. Log entries outside those time boundaries will not be available when calling entries.list, but those log entries can still be exported with LogSinks.", "format": "google-datetime", "type": "string" }, "trace": { "description": "Optional. Resource name of the trace associated with the log entry, if any. If it contains a relative resource name, the name is assumed to be relative to //tracing.googleapis.com. Example: projects/my-projectid/traces/06796866738c859f2f19b7cfb3214824", "type": "string" + }, + "traceSampled": { + "description": "Optional. The sampling decision of the trace associated with the log entry. True means that the trace resource name in the trace field was sampled for storage in a trace backend. False means that the trace was not sampled for storage when this log entry was written, or the sampling decision was unknown at the time. A non-sampled trace value is still useful as a request correlation identifier. The default is False.", + "type": "boolean" } }, "type": "object" @@ -1264,7 +1035,7 @@ "description": "Optional. The bucket_options are required when the logs-based metric is using a DISTRIBUTION value type and it describes the bucket boundaries used to create a histogram of the extracted values." }, "description": { - "description": "Optional. A description of this metric, which is used in documentation.", + "description": "Optional. A description of this metric, which is used in documentation. The maximum length of the description is 8000 characters.", "type": "string" }, "filter": { @@ -1297,8 +1068,8 @@ "V1" ], "enumDescriptions": [ - "Stackdriver Logging API v2.", - "Stackdriver Logging API v1." + "Logging API v2.", + "Logging API v1." ], "type": "string" } @@ -1313,11 +1084,6 @@ "description": "Required. The export destination:\n\"storage.googleapis.com/[GCS_BUCKET]\"\n\"bigquery.googleapis.com/projects/[PROJECT_ID]/datasets/[DATASET]\"\n\"pubsub.googleapis.com/projects/[PROJECT_ID]/topics/[TOPIC_ID]\"\nThe sink's writer_identity, set when the sink is created, must have permission to write to the destination or else the log entries are not exported. For more information, see Exporting Logs With Sinks.", "type": "string" }, - "endTime": { - "description": "Deprecated. This field is ignored when creating or updating sinks.", - "format": "google-datetime", - "type": "string" - }, "filter": { "description": "Optional. An advanced logs filter. The only exported log entries are those that are in the resource owning the sink and that match the filter. For example:\nlogName=\"projects/[PROJECT_ID]/logs/[LOG_ID]\" AND severity\u003e=ERROR\n", "type": "string" @@ -1344,13 +1110,8 @@ ], "type": "string" }, - "startTime": { - "description": "Deprecated. This field is ignored when creating or updating sinks.", - "format": "google-datetime", - "type": "string" - }, "writerIdentity": { - "description": "Output only. An IAM identity\u0026mdash;a service account or group\u0026mdash;under which Stackdriver Logging writes the exported log entries to the sink's destination. This field is set by sinks.create and sinks.update, based on the setting of unique_writer_identity in those methods.Until you grant this identity write-access to the destination, log entry exports from this sink will fail. For more information, see Granting access for a resource. Consult the destination service's documentation to determine the appropriate IAM roles to assign to the identity.", + "description": "Output only. An IAM identity\u0026mdash;a service account or group\u0026mdash;under which Logging writes the exported log entries to the sink's destination. This field is set by sinks.create and sinks.update, based on the setting of unique_writer_identity in those methods.Until you grant this identity write-access to the destination, log entry exports from this sink will fail. For more information, see Granting access for a resource. Consult the destination service's documentation to determine the appropriate IAM roles to assign to the identity.", "type": "string" } }, @@ -1375,6 +1136,10 @@ }, "type": "array" }, + "metadata": { + "$ref": "MetricDescriptorMetadata", + "description": "Optional. Metadata which can be used to guide usage of the metric." + }, "metricKind": { "description": "Whether the metric records instantaneous values, changes to a value, etc. Some combinations of metric_kind and value_type might not be supported.", "enum": [ @@ -1396,7 +1161,7 @@ "type": "string" }, "type": { - "description": "The metric type, including its DNS name prefix. The type is not URL-encoded. All user-defined custom metric types have the DNS name custom.googleapis.com. Metric types should use a natural hierarchical grouping. For example:\n\"custom.googleapis.com/invoice/paid/amount\"\n\"appengine.googleapis.com/http/server/response_latencies\"\n", + "description": "The metric type, including its DNS name prefix. The type is not URL-encoded. All user-defined metric types have the DNS name custom.googleapis.com or external.googleapis.com. Metric types should use a natural hierarchical grouping. For example:\n\"custom.googleapis.com/invoice/paid/amount\"\n\"external.googleapis.com/prometheus/up\"\n\"appengine.googleapis.com/http/server/response_latencies\"\n", "type": "string" }, "unit": { @@ -1428,6 +1193,43 @@ }, "type": "object" }, + "MetricDescriptorMetadata": { + "description": "Additional annotations that can be used to guide the usage of a metric.", + "id": "MetricDescriptorMetadata", + "properties": { + "ingestDelay": { + "description": "The delay of data points caused by ingestion. Data points older than this age are guaranteed to be ingested and available to be read, excluding data loss due to errors.", + "format": "google-duration", + "type": "string" + }, + "launchStage": { + "description": "The launch stage of the metric definition.", + "enum": [ + "LAUNCH_STAGE_UNSPECIFIED", + "EARLY_ACCESS", + "ALPHA", + "BETA", + "GA", + "DEPRECATED" + ], + "enumDescriptions": [ + "Do not use this default value.", + "Early Access features are limited to a closed group of testers. To use these features, you must sign up in advance and sign a Trusted Tester agreement (which includes confidentiality provisions). These features may be unstable, changed in backward-incompatible ways, and are not guaranteed to be released.", + "Alpha is a limited availability test for releases before they are cleared for widespread use. By Alpha, all significant design issues are resolved and we are in the process of verifying functionality. Alpha customers need to apply for access, agree to applicable terms, and have their projects whitelisted. Alpha releases don’t have to be feature complete, no SLAs are provided, and there are no technical support obligations, but they will be far enough along that customers can actually use them in test environments or for limited-use tests -- just like they would in normal production cases.", + "Beta is the point at which we are ready to open a release for any customer to use. There are no SLA or technical support obligations in a Beta release. Products will be complete from a feature perspective, but may have some open outstanding issues. Beta releases are suitable for limited production use cases.", + "GA features are open to all developers and are considered stable and fully qualified for production use.", + "Deprecated features are scheduled to be shut down and removed. For more information, see the “Deprecation Policy” section of our Terms of Service (https://cloud.google.com/terms/) and the Google Cloud Platform Subject to the Deprecation Policy (https://cloud.google.com/terms/deprecation) documentation." + ], + "type": "string" + }, + "samplePeriod": { + "description": "The sampling period of metric data points. For metrics which are written periodically, consecutive data points are stored at this time interval, excluding data loss due to errors. Metrics with a higher granularity have a smaller sampling period.", + "format": "google-duration", + "type": "string" + } + }, + "type": "object" + }, "MonitoredResource": { "description": "An object representing a resource that can be used for monitoring, logging, billing, or other purposes. Examples include virtual machine instances, databases, and storage devices such as disks. The type field identifies a MonitoredResourceDescriptor object that describes the resource's schema. Information in the labels field identifies the actual resource and its attributes according to the schema. For example, a particular Compute Engine VM instance could be represented by the following object, because the MonitoredResourceDescriptor for \"gce_instance\" has labels \"instance_id\" and \"zone\":\n{ \"type\": \"gce_instance\",\n \"labels\": { \"instance_id\": \"12345678901234\",\n \"zone\": \"us-central1-a\" }}\n", "id": "MonitoredResource", @@ -1477,7 +1279,7 @@ "type": "object" }, "MonitoredResourceMetadata": { - "description": "Auxiliary metadata for a MonitoredResource object. MonitoredResource objects contain the minimum set of information to uniquely identify a monitored resource instance. There is some other useful auxiliary metadata. Google Stackdriver Monitoring \u0026 Logging uses an ingestion pipeline to extract metadata for cloud resources of all types , and stores the metadata in this message.", + "description": "Auxiliary metadata for a MonitoredResource object. MonitoredResource objects contain the minimum set of information to uniquely identify a monitored resource instance. There is some other useful auxiliary metadata. Monitoring and Logging use an ingestion pipeline to extract metadata for cloud resources of all types, and store the metadata in this message.", "id": "MonitoredResourceMetadata", "properties": { "systemLabels": { @@ -1485,7 +1287,7 @@ "description": "Properties of the object.", "type": "any" }, - "description": "Output only. Values for predefined system metadata labels. System labels are a kind of metadata extracted by Google Stackdriver. Stackdriver determines what system labels are useful and how to obtain their values. Some examples: \"machine_image\", \"vpc\", \"subnet_id\", \"security_group\", \"name\", etc. System label values can be only strings, Boolean values, or a list of strings. For example:\n{ \"name\": \"my-test-instance\",\n \"security_group\": [\"a\", \"b\", \"c\"],\n \"spot_instance\": false }\n", + "description": "Output only. Values for predefined system metadata labels. System labels are a kind of metadata extracted by Google, including \"machine_image\", \"vpc\", \"subnet_id\", \"security_group\", \"name\", etc. System label values can be only strings, Boolean values, or a list of strings. For example:\n{ \"name\": \"my-test-instance\",\n \"security_group\": [\"a\", \"b\", \"c\"],\n \"spot_instance\": false }\n", "type": "object" }, "userLabels": { @@ -1629,6 +1431,10 @@ "description": "Stackdriver Trace identifier for this request.", "type": "string" }, + "traceSampled": { + "description": "If true, the value in the 'trace_id' field was sampled for storage in a trace backend.", + "type": "boolean" + }, "urlMapEntry": { "description": "File or class that handled the request.", "type": "string" @@ -1692,7 +1498,7 @@ "type": "boolean" }, "entries": { - "description": "Required. The log entries to send to Stackdriver Logging. The order of log entries in this list does not matter. Values supplied in this method's log_name, resource, and labels fields are copied into those log entries in this list that do not include values for their corresponding fields. For more information, see the LogEntry type.If the timestamp or insert_id fields are missing in log entries, then this method supplies the current time or a unique identifier, respectively. The supplied values are chosen so that, among the log entries that did not supply their own values, the entries earlier in the list will sort before the entries later in the list. See the entries.list method.Log entries with timestamps that are more than the logs retention period in the past or more than 24 hours in the future will not be available when calling entries.list. However, those log entries can still be exported with LogSinks.To improve throughput and to avoid exceeding the quota limit for calls to entries.write, you should try to include several log entries in this list, rather than calling this method for each individual log entry.", + "description": "Required. The log entries to send to Logging. The order of log entries in this list does not matter. Values supplied in this method's log_name, resource, and labels fields are copied into those log entries in this list that do not include values for their corresponding fields. For more information, see the LogEntry type.If the timestamp or insert_id fields are missing in log entries, then this method supplies the current time or a unique identifier, respectively. The supplied values are chosen so that, among the log entries that did not supply their own values, the entries earlier in the list will sort before the entries later in the list. See the entries.list method.Log entries with timestamps that are more than the logs retention period in the past or more than 24 hours in the future will not be available when calling entries.list. However, those log entries can still be exported with LogSinks.To improve throughput and to avoid exceeding the quota limit for calls to entries.write, you should try to include several log entries in this list, rather than calling this method for each individual log entry.", "items": { "$ref": "LogEntry" }, @@ -1706,7 +1512,7 @@ "type": "object" }, "logName": { - "description": "Optional. A default log resource name that is assigned to all log entries in entries that do not specify a value for log_name:\n\"projects/[PROJECT_ID]/logs/[LOG_ID]\"\n\"organizations/[ORGANIZATION_ID]/logs/[LOG_ID]\"\n\"billingAccounts/[BILLING_ACCOUNT_ID]/logs/[LOG_ID]\"\n\"folders/[FOLDER_ID]/logs/[LOG_ID]\"\n[LOG_ID] must be URL-encoded. For example, \"projects/my-project-id/logs/syslog\" or \"organizations/1234567890/logs/cloudresourcemanager.googleapis.com%2Factivity\". For more information about log names, see LogEntry.", + "description": "Optional. A default log resource name that is assigned to all log entries in entries that do not specify a value for log_name:\n\"projects/[PROJECT_ID]/logs/[LOG_ID]\"\n\"organizations/[ORGANIZATION_ID]/logs/[LOG_ID]\"\n\"billingAccounts/[BILLING_ACCOUNT_ID]/logs/[LOG_ID]\"\n\"folders/[FOLDER_ID]/logs/[LOG_ID]\"\n[LOG_ID] must be URL-encoded. For example:\n\"projects/my-project-id/logs/syslog\"\n\"organizations/1234567890/logs/cloudresourcemanager.googleapis.com%2Factivity\"\nThe permission \u003ccode\u003elogging.logEntries.create\u003c/code\u003e is needed on each project, organization, billing account, or folder that is receiving new log entries, whether the resource is specified in \u003ccode\u003elogName\u003c/code\u003e or in an individual log entry.", "type": "string" }, "partialSuccess": { diff --git a/vendor/google.golang.org/api/logging/v2beta1/logging-gen.go b/vendor/google.golang.org/api/logging/v2beta1/logging-gen.go index 12a8cef8706..c2dc86a8667 100644 --- a/vendor/google.golang.org/api/logging/v2beta1/logging-gen.go +++ b/vendor/google.golang.org/api/logging/v2beta1/logging-gen.go @@ -1,5 +1,13 @@ +// Copyright 2018 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Code generated file. DO NOT EDIT. + // Package logging provides access to the Stackdriver Logging API. // +// This package is DEPRECATED. Use package cloud.google.com/go/logging instead. +// // See https://cloud.google.com/logging/docs/ // // Usage example: @@ -11,18 +19,18 @@ package logging import ( "bytes" + "context" "encoding/json" "errors" "fmt" - context "golang.org/x/net/context" - ctxhttp "golang.org/x/net/context/ctxhttp" - gensupport "google.golang.org/api/gensupport" - googleapi "google.golang.org/api/googleapi" "io" "net/http" "net/url" "strconv" "strings" + + gensupport "google.golang.org/api/gensupport" + googleapi "google.golang.org/api/googleapi" ) // Always reference these packages, just in case the auto-generated code @@ -38,7 +46,6 @@ var _ = googleapi.Version var _ = errors.New var _ = strings.Replace var _ = context.Canceled -var _ = ctxhttp.Do const apiId = "logging:v2beta1" const apiName = "logging" @@ -68,10 +75,8 @@ func New(client *http.Client) (*Service, error) { return nil, errors.New("client is nil") } s := &Service{client: client, BasePath: basePath} - s.BillingAccounts = NewBillingAccountsService(s) s.Entries = NewEntriesService(s) s.MonitoredResourceDescriptors = NewMonitoredResourceDescriptorsService(s) - s.Organizations = NewOrganizationsService(s) s.Projects = NewProjectsService(s) return s, nil } @@ -81,14 +86,10 @@ type Service struct { BasePath string // API endpoint base URL UserAgent string // optional additional User-Agent fragment - BillingAccounts *BillingAccountsService - Entries *EntriesService MonitoredResourceDescriptors *MonitoredResourceDescriptorsService - Organizations *OrganizationsService - Projects *ProjectsService } @@ -99,27 +100,6 @@ func (s *Service) userAgent() string { return googleapi.UserAgent + " " + s.UserAgent } -func NewBillingAccountsService(s *Service) *BillingAccountsService { - rs := &BillingAccountsService{s: s} - rs.Logs = NewBillingAccountsLogsService(s) - return rs -} - -type BillingAccountsService struct { - s *Service - - Logs *BillingAccountsLogsService -} - -func NewBillingAccountsLogsService(s *Service) *BillingAccountsLogsService { - rs := &BillingAccountsLogsService{s: s} - return rs -} - -type BillingAccountsLogsService struct { - s *Service -} - func NewEntriesService(s *Service) *EntriesService { rs := &EntriesService{s: s} return rs @@ -138,30 +118,8 @@ type MonitoredResourceDescriptorsService struct { s *Service } -func NewOrganizationsService(s *Service) *OrganizationsService { - rs := &OrganizationsService{s: s} - rs.Logs = NewOrganizationsLogsService(s) - return rs -} - -type OrganizationsService struct { - s *Service - - Logs *OrganizationsLogsService -} - -func NewOrganizationsLogsService(s *Service) *OrganizationsLogsService { - rs := &OrganizationsLogsService{s: s} - return rs -} - -type OrganizationsLogsService struct { - s *Service -} - func NewProjectsService(s *Service) *ProjectsService { rs := &ProjectsService{s: s} - rs.Logs = NewProjectsLogsService(s) rs.Metrics = NewProjectsMetricsService(s) rs.Sinks = NewProjectsSinksService(s) return rs @@ -170,22 +128,11 @@ func NewProjectsService(s *Service) *ProjectsService { type ProjectsService struct { s *Service - Logs *ProjectsLogsService - Metrics *ProjectsMetricsService Sinks *ProjectsSinksService } -func NewProjectsLogsService(s *Service) *ProjectsLogsService { - rs := &ProjectsLogsService{s: s} - return rs -} - -type ProjectsLogsService struct { - s *Service -} - func NewProjectsMetricsService(s *Service) *ProjectsMetricsService { rs := &ProjectsMetricsService{s: s} return rs @@ -701,46 +648,6 @@ func (s *ListLogMetricsResponse) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } -// ListLogsResponse: Result returned from ListLogs. -type ListLogsResponse struct { - // LogNames: A list of log names. For example, - // "projects/my-project/syslog" or - // "organizations/123/cloudresourcemanager.googleapis.com%2Factivity". - LogNames []string `json:"logNames,omitempty"` - - // NextPageToken: If there might be more results than those appearing in - // this response, then nextPageToken is included. To get the next set of - // results, call this method again using the value of nextPageToken as - // pageToken. - NextPageToken string `json:"nextPageToken,omitempty"` - - // ServerResponse contains the HTTP response code and headers from the - // server. - googleapi.ServerResponse `json:"-"` - - // ForceSendFields is a list of field names (e.g. "LogNames") to - // unconditionally include in API requests. By default, fields with - // empty values are omitted from API requests. However, any non-pointer, - // non-interface field appearing in ForceSendFields will be sent to the - // server regardless of whether the field is empty or not. This may be - // used to include empty fields in Patch requests. - ForceSendFields []string `json:"-"` - - // NullFields is a list of field names (e.g. "LogNames") to include in - // API requests with the JSON null value. By default, fields with empty - // values are omitted from API requests. However, any field with an - // empty value appearing in NullFields will be sent to the server as - // null. It is an error if a field in this list has a non-empty value. - // This may be used to include null fields in Patch requests. - NullFields []string `json:"-"` -} - -func (s *ListLogsResponse) MarshalJSON() ([]byte, error) { - type NoMethod ListLogsResponse - raw := NoMethod(*s) - return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) -} - // ListMonitoredResourceDescriptorsResponse: Result returned from // ListMonitoredResourceDescriptors. type ListMonitoredResourceDescriptorsResponse struct { @@ -825,12 +732,11 @@ type LogEntry struct { HttpRequest *HttpRequest `json:"httpRequest,omitempty"` // InsertId: Optional. A unique identifier for the log entry. If you - // provide a value, then Stackdriver Logging considers other log entries - // in the same project, with the same timestamp, and with the same - // insert_id to be duplicates which can be removed. If omitted in new - // log entries, then Stackdriver Logging assigns its own unique - // identifier. The insert_id is also used to order log entries that have - // the same timestamp value. + // provide a value, then Logging considers other log entries in the same + // project, with the same timestamp, and with the same insert_id to be + // duplicates which can be removed. If omitted in new log entries, then + // Logging assigns its own unique identifier. The insert_id is also used + // to order log entries that have the same timestamp value. InsertId string `json:"insertId,omitempty"` // JsonPayload: The log entry payload, represented as a structure that @@ -880,7 +786,7 @@ type LogEntry struct { ProtoPayload googleapi.RawMessage `json:"protoPayload,omitempty"` // ReceiveTimestamp: Output only. The time the log entry was received by - // Stackdriver Logging. + // Logging. ReceiveTimestamp string `json:"receiveTimestamp,omitempty"` // Resource: Required. The primary monitored resource associated with @@ -912,9 +818,9 @@ type LogEntry struct { SourceLocation *LogEntrySourceLocation `json:"sourceLocation,omitempty"` // SpanId: Optional. The span ID within the trace associated with the - // log entry. For Stackdriver Trace spans, this is the same format that - // the Stackdriver Trace API v2 uses: a 16-character hexadecimal - // encoding of an 8-byte array, such as "000000000000004a". + // log entry. For Trace spans, this is the same format that the Trace + // API v2 uses: a 16-character hexadecimal encoding of an 8-byte array, + // such as "000000000000004a". SpanId string `json:"spanId,omitempty"` // TextPayload: The log entry payload, represented as a Unicode string @@ -924,14 +830,14 @@ type LogEntry struct { // Timestamp: Optional. The time the event described by the log entry // occurred. This time is used to compute the log entry's age and to // enforce the logs retention period. If this field is omitted in a new - // log entry, then Stackdriver Logging assigns it the current time. - // Timestamps have nanosecond accuracy, but trailing zeros in the - // fractional seconds might be omitted when the timestamp is - // displayed.Incoming log entries should have timestamps that are no - // more than the logs retention period in the past, and no more than 24 - // hours in the future. Log entries outside those time boundaries will - // not be available when calling entries.list, but those log entries can - // still be exported with LogSinks. + // log entry, then Logging assigns it the current time. Timestamps have + // nanosecond accuracy, but trailing zeros in the fractional seconds + // might be omitted when the timestamp is displayed.Incoming log entries + // should have timestamps that are no more than the logs retention + // period in the past, and no more than 24 hours in the future. Log + // entries outside those time boundaries will not be available when + // calling entries.list, but those log entries can still be exported + // with LogSinks. Timestamp string `json:"timestamp,omitempty"` // Trace: Optional. Resource name of the trace associated with the log @@ -940,6 +846,15 @@ type LogEntry struct { // projects/my-projectid/traces/06796866738c859f2f19b7cfb3214824 Trace string `json:"trace,omitempty"` + // TraceSampled: Optional. The sampling decision of the trace associated + // with the log entry. True means that the trace resource name in the + // trace field was sampled for storage in a trace backend. False means + // that the trace was not sampled for storage when this log entry was + // written, or the sampling decision was unknown at the time. A + // non-sampled trace value is still useful as a request correlation + // identifier. The default is False. + TraceSampled bool `json:"traceSampled,omitempty"` + // ForceSendFields is a list of field names (e.g. "HttpRequest") to // unconditionally include in API requests. By default, fields with // empty values are omitted from API requests. However, any non-pointer, @@ -1114,7 +1029,8 @@ type LogMetric struct { BucketOptions *BucketOptions `json:"bucketOptions,omitempty"` // Description: Optional. A description of this metric, which is used in - // documentation. + // documentation. The maximum length of the description is 8000 + // characters. Description string `json:"description,omitempty"` // Filter: Required. An advanced logs filter which is used to match log @@ -1190,8 +1106,8 @@ type LogMetric struct { // metric. The v2 format is used by default and cannot be changed. // // Possible values: - // "V2" - Stackdriver Logging API v2. - // "V1" - Stackdriver Logging API v1. + // "V2" - Logging API v2. + // "V1" - Logging API v1. Version string `json:"version,omitempty"` // ServerResponse contains the HTTP response code and headers from the @@ -1239,10 +1155,6 @@ type LogSink struct { // not exported. For more information, see Exporting Logs With Sinks. Destination string `json:"destination,omitempty"` - // EndTime: Deprecated. This field is ignored when creating or updating - // sinks. - EndTime string `json:"endTime,omitempty"` - // Filter: Optional. An advanced logs filter. The only exported log // entries are those that are in the resource owning the sink and that // match the filter. For @@ -1287,19 +1199,15 @@ type LogSink struct { // "V1" - LogEntry version 1 format. OutputVersionFormat string `json:"outputVersionFormat,omitempty"` - // StartTime: Deprecated. This field is ignored when creating or - // updating sinks. - StartTime string `json:"startTime,omitempty"` - // WriterIdentity: Output only. An IAM identity—a service account - // or group—under which Stackdriver Logging writes the exported - // log entries to the sink's destination. This field is set by - // sinks.create and sinks.update, based on the setting of - // unique_writer_identity in those methods.Until you grant this identity - // write-access to the destination, log entry exports from this sink - // will fail. For more information, see Granting access for a resource. - // Consult the destination service's documentation to determine the - // appropriate IAM roles to assign to the identity. + // or group—under which Logging writes the exported log entries to + // the sink's destination. This field is set by sinks.create and + // sinks.update, based on the setting of unique_writer_identity in those + // methods.Until you grant this identity write-access to the + // destination, log entry exports from this sink will fail. For more + // information, see Granting access for a resource. Consult the + // destination service's documentation to determine the appropriate IAM + // roles to assign to the identity. WriterIdentity string `json:"writerIdentity,omitempty"` // ServerResponse contains the HTTP response code and headers from the @@ -1352,6 +1260,10 @@ type MetricDescriptor struct { // failed. Labels []*LabelDescriptor `json:"labels,omitempty"` + // Metadata: Optional. Metadata which can be used to guide usage of the + // metric. + Metadata *MetricDescriptorMetadata `json:"metadata,omitempty"` + // MetricKind: Whether the metric records instantaneous values, changes // to a value, etc. Some combinations of metric_kind and value_type // might not be supported. @@ -1370,13 +1282,15 @@ type MetricDescriptor struct { Name string `json:"name,omitempty"` // Type: The metric type, including its DNS name prefix. The type is not - // URL-encoded. All user-defined custom metric types have the DNS name - // custom.googleapis.com. Metric types should use a natural hierarchical - // grouping. For + // URL-encoded. All user-defined metric types have the DNS name + // custom.googleapis.com or external.googleapis.com. Metric types should + // use a natural hierarchical grouping. For // example: // "custom.googleapis.com/invoice/paid/amount" - // "appengine.google - // apis.com/http/server/response_latencies" + // "external.googlea + // pis.com/prometheus/up" + // "appengine.googleapis.com/http/server/response_ + // latencies" // Type string `json:"type,omitempty"` @@ -1472,6 +1386,76 @@ func (s *MetricDescriptor) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +// MetricDescriptorMetadata: Additional annotations that can be used to +// guide the usage of a metric. +type MetricDescriptorMetadata struct { + // IngestDelay: The delay of data points caused by ingestion. Data + // points older than this age are guaranteed to be ingested and + // available to be read, excluding data loss due to errors. + IngestDelay string `json:"ingestDelay,omitempty"` + + // LaunchStage: The launch stage of the metric definition. + // + // Possible values: + // "LAUNCH_STAGE_UNSPECIFIED" - Do not use this default value. + // "EARLY_ACCESS" - Early Access features are limited to a closed + // group of testers. To use these features, you must sign up in advance + // and sign a Trusted Tester agreement (which includes confidentiality + // provisions). These features may be unstable, changed in + // backward-incompatible ways, and are not guaranteed to be released. + // "ALPHA" - Alpha is a limited availability test for releases before + // they are cleared for widespread use. By Alpha, all significant design + // issues are resolved and we are in the process of verifying + // functionality. Alpha customers need to apply for access, agree to + // applicable terms, and have their projects whitelisted. Alpha releases + // don’t have to be feature complete, no SLAs are provided, and there + // are no technical support obligations, but they will be far enough + // along that customers can actually use them in test environments or + // for limited-use tests -- just like they would in normal production + // cases. + // "BETA" - Beta is the point at which we are ready to open a release + // for any customer to use. There are no SLA or technical support + // obligations in a Beta release. Products will be complete from a + // feature perspective, but may have some open outstanding issues. Beta + // releases are suitable for limited production use cases. + // "GA" - GA features are open to all developers and are considered + // stable and fully qualified for production use. + // "DEPRECATED" - Deprecated features are scheduled to be shut down + // and removed. For more information, see the “Deprecation Policy” + // section of our Terms of Service (https://cloud.google.com/terms/) and + // the Google Cloud Platform Subject to the Deprecation Policy + // (https://cloud.google.com/terms/deprecation) documentation. + LaunchStage string `json:"launchStage,omitempty"` + + // SamplePeriod: The sampling period of metric data points. For metrics + // which are written periodically, consecutive data points are stored at + // this time interval, excluding data loss due to errors. Metrics with a + // higher granularity have a smaller sampling period. + SamplePeriod string `json:"samplePeriod,omitempty"` + + // ForceSendFields is a list of field names (e.g. "IngestDelay") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "IngestDelay") to include + // in API requests with the JSON null value. By default, fields with + // empty values are omitted from API requests. However, any field with + // an empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *MetricDescriptorMetadata) MarshalJSON() ([]byte, error) { + type NoMethod MetricDescriptorMetadata + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + // MonitoredResource: An object representing a resource that can be used // for monitoring, logging, billing, or other purposes. Examples include // virtual machine instances, databases, and storage devices such as @@ -1585,17 +1569,15 @@ func (s *MonitoredResourceDescriptor) MarshalJSON() ([]byte, error) { // MonitoredResourceMetadata: Auxiliary metadata for a MonitoredResource // object. MonitoredResource objects contain the minimum set of // information to uniquely identify a monitored resource instance. There -// is some other useful auxiliary metadata. Google Stackdriver -// Monitoring & Logging uses an ingestion pipeline to extract metadata -// for cloud resources of all types , and stores the metadata in this -// message. +// is some other useful auxiliary metadata. Monitoring and Logging use +// an ingestion pipeline to extract metadata for cloud resources of all +// types, and store the metadata in this message. type MonitoredResourceMetadata struct { // SystemLabels: Output only. Values for predefined system metadata - // labels. System labels are a kind of metadata extracted by Google - // Stackdriver. Stackdriver determines what system labels are useful and - // how to obtain their values. Some examples: "machine_image", "vpc", - // "subnet_id", "security_group", "name", etc. System label values can - // be only strings, Boolean values, or a list of strings. For example: + // labels. System labels are a kind of metadata extracted by Google, + // including "machine_image", "vpc", "subnet_id", "security_group", + // "name", etc. System label values can be only strings, Boolean values, + // or a list of strings. For example: // { "name": "my-test-instance", // "security_group": ["a", "b", "c"], // "spot_instance": false } @@ -1738,6 +1720,10 @@ type RequestLog struct { // TraceId: Stackdriver Trace identifier for this request. TraceId string `json:"traceId,omitempty"` + // TraceSampled: If true, the value in the 'trace_id' field was sampled + // for storage in a trace backend. + TraceSampled bool `json:"traceSampled,omitempty"` + // UrlMapEntry: File or class that handled the request. UrlMapEntry string `json:"urlMapEntry,omitempty"` @@ -1871,24 +1857,23 @@ type WriteLogEntriesRequest struct { // valuable data. DryRun bool `json:"dryRun,omitempty"` - // Entries: Required. The log entries to send to Stackdriver Logging. - // The order of log entries in this list does not matter. Values - // supplied in this method's log_name, resource, and labels fields are - // copied into those log entries in this list that do not include values - // for their corresponding fields. For more information, see the - // LogEntry type.If the timestamp or insert_id fields are missing in log - // entries, then this method supplies the current time or a unique - // identifier, respectively. The supplied values are chosen so that, - // among the log entries that did not supply their own values, the - // entries earlier in the list will sort before the entries later in the - // list. See the entries.list method.Log entries with timestamps that - // are more than the logs retention period in the past or more than 24 - // hours in the future will not be available when calling entries.list. - // However, those log entries can still be exported with LogSinks.To - // improve throughput and to avoid exceeding the quota limit for calls - // to entries.write, you should try to include several log entries in - // this list, rather than calling this method for each individual log - // entry. + // Entries: Required. The log entries to send to Logging. The order of + // log entries in this list does not matter. Values supplied in this + // method's log_name, resource, and labels fields are copied into those + // log entries in this list that do not include values for their + // corresponding fields. For more information, see the LogEntry type.If + // the timestamp or insert_id fields are missing in log entries, then + // this method supplies the current time or a unique identifier, + // respectively. The supplied values are chosen so that, among the log + // entries that did not supply their own values, the entries earlier in + // the list will sort before the entries later in the list. See the + // entries.list method.Log entries with timestamps that are more than + // the logs retention period in the past or more than 24 hours in the + // future will not be available when calling entries.list. However, + // those log entries can still be exported with LogSinks.To improve + // throughput and to avoid exceeding the quota limit for calls to + // entries.write, you should try to include several log entries in this + // list, rather than calling this method for each individual log entry. Entries []*LogEntry `json:"entries,omitempty"` // Labels: Optional. Default labels that are added to the labels field @@ -1906,10 +1891,15 @@ type WriteLogEntriesRequest struct { // "billingAccounts/[BILLING_ACCOUNT_ID]/logs/[ // LOG_ID]" // "folders/[FOLDER_ID]/logs/[LOG_ID]" - // [LOG_ID] must be URL-encoded. For example, - // "projects/my-project-id/logs/syslog" or - // "organizations/1234567890/logs/cloudresourcemanager.googleapis.com%2Fa - // ctivity". For more information about log names, see LogEntry. + // [LOG_ID] must be URL-encoded. For + // example: + // "projects/my-project-id/logs/syslog" + // "organizations/123456789 + // 0/logs/cloudresourcemanager.googleapis.com%2Factivity" + // The permission logging.logEntries.create is needed on + // each project, organization, billing account, or folder that is + // receiving new log entries, whether the resource is specified in + // logName or in an individual log entry. LogName string `json:"logName,omitempty"` // PartialSuccess: Optional. Whether valid entries should be written @@ -1960,328 +1950,6 @@ type WriteLogEntriesResponse struct { googleapi.ServerResponse `json:"-"` } -// method id "logging.billingAccounts.logs.delete": - -type BillingAccountsLogsDeleteCall struct { - s *Service - logName string - urlParams_ gensupport.URLParams - ctx_ context.Context - header_ http.Header -} - -// Delete: Deletes all the log entries in a log. The log reappears if it -// receives new entries. Log entries written shortly before the delete -// operation might not be deleted. -func (r *BillingAccountsLogsService) Delete(logName string) *BillingAccountsLogsDeleteCall { - c := &BillingAccountsLogsDeleteCall{s: r.s, urlParams_: make(gensupport.URLParams)} - c.logName = logName - return c -} - -// Fields allows partial responses to be retrieved. See -// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse -// for more information. -func (c *BillingAccountsLogsDeleteCall) Fields(s ...googleapi.Field) *BillingAccountsLogsDeleteCall { - c.urlParams_.Set("fields", googleapi.CombineFields(s)) - return c -} - -// Context sets the context to be used in this call's Do method. Any -// pending HTTP request will be aborted if the provided context is -// canceled. -func (c *BillingAccountsLogsDeleteCall) Context(ctx context.Context) *BillingAccountsLogsDeleteCall { - c.ctx_ = ctx - return c -} - -// Header returns an http.Header that can be modified by the caller to -// add HTTP headers to the request. -func (c *BillingAccountsLogsDeleteCall) Header() http.Header { - if c.header_ == nil { - c.header_ = make(http.Header) - } - return c.header_ -} - -func (c *BillingAccountsLogsDeleteCall) doRequest(alt string) (*http.Response, error) { - reqHeaders := make(http.Header) - for k, v := range c.header_ { - reqHeaders[k] = v - } - reqHeaders.Set("User-Agent", c.s.userAgent()) - var body io.Reader = nil - c.urlParams_.Set("alt", alt) - urls := googleapi.ResolveRelative(c.s.BasePath, "v2beta1/{+logName}") - urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) - req.Header = reqHeaders - googleapi.Expand(req.URL, map[string]string{ - "logName": c.logName, - }) - return gensupport.SendRequest(c.ctx_, c.s.client, req) -} - -// Do executes the "logging.billingAccounts.logs.delete" call. -// Exactly one of *Empty or error will be non-nil. Any non-2xx status -// code is an error. Response headers are in either -// *Empty.ServerResponse.Header or (if a response was returned at all) -// in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to -// check whether the returned error was because http.StatusNotModified -// was returned. -func (c *BillingAccountsLogsDeleteCall) Do(opts ...googleapi.CallOption) (*Empty, error) { - gensupport.SetOptions(c.urlParams_, opts...) - res, err := c.doRequest("json") - if res != nil && res.StatusCode == http.StatusNotModified { - if res.Body != nil { - res.Body.Close() - } - return nil, &googleapi.Error{ - Code: res.StatusCode, - Header: res.Header, - } - } - if err != nil { - return nil, err - } - defer googleapi.CloseBody(res) - if err := googleapi.CheckResponse(res); err != nil { - return nil, err - } - ret := &Empty{ - ServerResponse: googleapi.ServerResponse{ - Header: res.Header, - HTTPStatusCode: res.StatusCode, - }, - } - target := &ret - if err := gensupport.DecodeResponse(target, res); err != nil { - return nil, err - } - return ret, nil - // { - // "description": "Deletes all the log entries in a log. The log reappears if it receives new entries. Log entries written shortly before the delete operation might not be deleted.", - // "flatPath": "v2beta1/billingAccounts/{billingAccountsId}/logs/{logsId}", - // "httpMethod": "DELETE", - // "id": "logging.billingAccounts.logs.delete", - // "parameterOrder": [ - // "logName" - // ], - // "parameters": { - // "logName": { - // "description": "Required. The resource name of the log to delete:\n\"projects/[PROJECT_ID]/logs/[LOG_ID]\"\n\"organizations/[ORGANIZATION_ID]/logs/[LOG_ID]\"\n\"billingAccounts/[BILLING_ACCOUNT_ID]/logs/[LOG_ID]\"\n\"folders/[FOLDER_ID]/logs/[LOG_ID]\"\n[LOG_ID] must be URL-encoded. For example, \"projects/my-project-id/logs/syslog\", \"organizations/1234567890/logs/cloudresourcemanager.googleapis.com%2Factivity\". For more information about log names, see LogEntry.", - // "location": "path", - // "pattern": "^billingAccounts/[^/]+/logs/[^/]+$", - // "required": true, - // "type": "string" - // } - // }, - // "path": "v2beta1/{+logName}", - // "response": { - // "$ref": "Empty" - // }, - // "scopes": [ - // "https://www.googleapis.com/auth/cloud-platform", - // "https://www.googleapis.com/auth/logging.admin" - // ] - // } - -} - -// method id "logging.billingAccounts.logs.list": - -type BillingAccountsLogsListCall struct { - s *Service - parent string - urlParams_ gensupport.URLParams - ifNoneMatch_ string - ctx_ context.Context - header_ http.Header -} - -// List: Lists the logs in projects, organizations, folders, or billing -// accounts. Only logs that have entries are listed. -func (r *BillingAccountsLogsService) List(parent string) *BillingAccountsLogsListCall { - c := &BillingAccountsLogsListCall{s: r.s, urlParams_: make(gensupport.URLParams)} - c.parent = parent - return c -} - -// PageSize sets the optional parameter "pageSize": The maximum number -// of results to return from this request. Non-positive values are -// ignored. The presence of nextPageToken in the response indicates that -// more results might be available. -func (c *BillingAccountsLogsListCall) PageSize(pageSize int64) *BillingAccountsLogsListCall { - c.urlParams_.Set("pageSize", fmt.Sprint(pageSize)) - return c -} - -// PageToken sets the optional parameter "pageToken": If present, then -// retrieve the next batch of results from the preceding call to this -// method. pageToken must be the value of nextPageToken from the -// previous response. The values of other method parameters should be -// identical to those in the previous call. -func (c *BillingAccountsLogsListCall) PageToken(pageToken string) *BillingAccountsLogsListCall { - c.urlParams_.Set("pageToken", pageToken) - return c -} - -// Fields allows partial responses to be retrieved. See -// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse -// for more information. -func (c *BillingAccountsLogsListCall) Fields(s ...googleapi.Field) *BillingAccountsLogsListCall { - c.urlParams_.Set("fields", googleapi.CombineFields(s)) - return c -} - -// IfNoneMatch sets the optional parameter which makes the operation -// fail if the object's ETag matches the given value. This is useful for -// getting updates only after the object has changed since the last -// request. Use googleapi.IsNotModified to check whether the response -// error from Do is the result of In-None-Match. -func (c *BillingAccountsLogsListCall) IfNoneMatch(entityTag string) *BillingAccountsLogsListCall { - c.ifNoneMatch_ = entityTag - return c -} - -// Context sets the context to be used in this call's Do method. Any -// pending HTTP request will be aborted if the provided context is -// canceled. -func (c *BillingAccountsLogsListCall) Context(ctx context.Context) *BillingAccountsLogsListCall { - c.ctx_ = ctx - return c -} - -// Header returns an http.Header that can be modified by the caller to -// add HTTP headers to the request. -func (c *BillingAccountsLogsListCall) Header() http.Header { - if c.header_ == nil { - c.header_ = make(http.Header) - } - return c.header_ -} - -func (c *BillingAccountsLogsListCall) doRequest(alt string) (*http.Response, error) { - reqHeaders := make(http.Header) - for k, v := range c.header_ { - reqHeaders[k] = v - } - reqHeaders.Set("User-Agent", c.s.userAgent()) - if c.ifNoneMatch_ != "" { - reqHeaders.Set("If-None-Match", c.ifNoneMatch_) - } - var body io.Reader = nil - c.urlParams_.Set("alt", alt) - urls := googleapi.ResolveRelative(c.s.BasePath, "v2beta1/{+parent}/logs") - urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) - req.Header = reqHeaders - googleapi.Expand(req.URL, map[string]string{ - "parent": c.parent, - }) - return gensupport.SendRequest(c.ctx_, c.s.client, req) -} - -// Do executes the "logging.billingAccounts.logs.list" call. -// Exactly one of *ListLogsResponse or error will be non-nil. Any -// non-2xx status code is an error. Response headers are in either -// *ListLogsResponse.ServerResponse.Header or (if a response was -// returned at all) in error.(*googleapi.Error).Header. Use -// googleapi.IsNotModified to check whether the returned error was -// because http.StatusNotModified was returned. -func (c *BillingAccountsLogsListCall) Do(opts ...googleapi.CallOption) (*ListLogsResponse, error) { - gensupport.SetOptions(c.urlParams_, opts...) - res, err := c.doRequest("json") - if res != nil && res.StatusCode == http.StatusNotModified { - if res.Body != nil { - res.Body.Close() - } - return nil, &googleapi.Error{ - Code: res.StatusCode, - Header: res.Header, - } - } - if err != nil { - return nil, err - } - defer googleapi.CloseBody(res) - if err := googleapi.CheckResponse(res); err != nil { - return nil, err - } - ret := &ListLogsResponse{ - ServerResponse: googleapi.ServerResponse{ - Header: res.Header, - HTTPStatusCode: res.StatusCode, - }, - } - target := &ret - if err := gensupport.DecodeResponse(target, res); err != nil { - return nil, err - } - return ret, nil - // { - // "description": "Lists the logs in projects, organizations, folders, or billing accounts. Only logs that have entries are listed.", - // "flatPath": "v2beta1/billingAccounts/{billingAccountsId}/logs", - // "httpMethod": "GET", - // "id": "logging.billingAccounts.logs.list", - // "parameterOrder": [ - // "parent" - // ], - // "parameters": { - // "pageSize": { - // "description": "Optional. The maximum number of results to return from this request. Non-positive values are ignored. The presence of nextPageToken in the response indicates that more results might be available.", - // "format": "int32", - // "location": "query", - // "type": "integer" - // }, - // "pageToken": { - // "description": "Optional. If present, then retrieve the next batch of results from the preceding call to this method. pageToken must be the value of nextPageToken from the previous response. The values of other method parameters should be identical to those in the previous call.", - // "location": "query", - // "type": "string" - // }, - // "parent": { - // "description": "Required. The resource name that owns the logs:\n\"projects/[PROJECT_ID]\"\n\"organizations/[ORGANIZATION_ID]\"\n\"billingAccounts/[BILLING_ACCOUNT_ID]\"\n\"folders/[FOLDER_ID]\"\n", - // "location": "path", - // "pattern": "^billingAccounts/[^/]+$", - // "required": true, - // "type": "string" - // } - // }, - // "path": "v2beta1/{+parent}/logs", - // "response": { - // "$ref": "ListLogsResponse" - // }, - // "scopes": [ - // "https://www.googleapis.com/auth/cloud-platform", - // "https://www.googleapis.com/auth/cloud-platform.read-only", - // "https://www.googleapis.com/auth/logging.admin", - // "https://www.googleapis.com/auth/logging.read" - // ] - // } - -} - -// Pages invokes f for each page of results. -// A non-nil error returned from f will halt the iteration. -// The provided context supersedes any context provided to the Context method. -func (c *BillingAccountsLogsListCall) Pages(ctx context.Context, f func(*ListLogsResponse) error) error { - c.ctx_ = ctx - defer c.PageToken(c.urlParams_.Get("pageToken")) // reset paging to original point - for { - x, err := c.Do() - if err != nil { - return err - } - if err := f(x); err != nil { - return err - } - if x.NextPageToken == "" { - return nil - } - c.PageToken(x.NextPageToken) - } -} - // method id "logging.entries.list": type EntriesListCall struct { @@ -2293,8 +1961,7 @@ type EntriesListCall struct { } // List: Lists log entries. Use this method to retrieve log entries from -// Stackdriver Logging. For ways to export log entries, see Exporting -// Logs. +// Logging. For ways to export log entries, see Exporting Logs. func (r *EntriesService) List(listlogentriesrequest *ListLogEntriesRequest) *EntriesListCall { c := &EntriesListCall{s: r.s, urlParams_: make(gensupport.URLParams)} c.listlogentriesrequest = listlogentriesrequest @@ -2339,9 +2006,13 @@ func (c *EntriesListCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v2beta1/entries:list") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders return gensupport.SendRequest(c.ctx_, c.s.client, req) } @@ -2384,7 +2055,7 @@ func (c *EntriesListCall) Do(opts ...googleapi.CallOption) (*ListLogEntriesRespo } return ret, nil // { - // "description": "Lists log entries. Use this method to retrieve log entries from Stackdriver Logging. For ways to export log entries, see Exporting Logs.", + // "description": "Lists log entries. Use this method to retrieve log entries from Logging. For ways to export log entries, see Exporting Logs.", // "flatPath": "v2beta1/entries:list", // "httpMethod": "POST", // "id": "logging.entries.list", @@ -2438,13 +2109,12 @@ type EntriesWriteCall struct { header_ http.Header } -// Write: Writes log entries to Stackdriver Logging. This API method is -// the only way to send log entries to Stackdriver Logging. This method -// is used, directly or indirectly, by the Stackdriver Logging agent -// (fluentd) and all logging libraries configured to use Stackdriver -// Logging. A single request may contain log entries for a maximum of -// 1000 different resources (projects, organizations, billing accounts -// or folders) +// Write: Writes log entries to Logging. This API method is the only way +// to send log entries to Logging. This method is used, directly or +// indirectly, by the Logging agent (fluentd) and all logging libraries +// configured to use Logging. A single request may contain log entries +// for a maximum of 1000 different resources (projects, organizations, +// billing accounts or folders) func (r *EntriesService) Write(writelogentriesrequest *WriteLogEntriesRequest) *EntriesWriteCall { c := &EntriesWriteCall{s: r.s, urlParams_: make(gensupport.URLParams)} c.writelogentriesrequest = writelogentriesrequest @@ -2489,9 +2159,13 @@ func (c *EntriesWriteCall) doRequest(alt string) (*http.Response, error) { } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v2beta1/entries:write") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders return gensupport.SendRequest(c.ctx_, c.s.client, req) } @@ -2534,7 +2208,7 @@ func (c *EntriesWriteCall) Do(opts ...googleapi.CallOption) (*WriteLogEntriesRes } return ret, nil // { - // "description": "Writes log entries to Stackdriver Logging. This API method is the only way to send log entries to Stackdriver Logging. This method is used, directly or indirectly, by the Stackdriver Logging agent (fluentd) and all logging libraries configured to use Stackdriver Logging. A single request may contain log entries for a maximum of 1000 different resources (projects, organizations, billing accounts or folders)", + // "description": "Writes log entries to Logging. This API method is the only way to send log entries to Logging. This method is used, directly or indirectly, by the Logging agent (fluentd) and all logging libraries configured to use Logging. A single request may contain log entries for a maximum of 1000 different resources (projects, organizations, billing accounts or folders)", // "flatPath": "v2beta1/entries:write", // "httpMethod": "POST", // "id": "logging.entries.write", @@ -2567,7 +2241,7 @@ type MonitoredResourceDescriptorsListCall struct { } // List: Lists the descriptors for monitored resource types used by -// Stackdriver Logging. +// Logging. func (r *MonitoredResourceDescriptorsService) List() *MonitoredResourceDescriptorsListCall { c := &MonitoredResourceDescriptorsListCall{s: r.s, urlParams_: make(gensupport.URLParams)} return c @@ -2638,9 +2312,13 @@ func (c *MonitoredResourceDescriptorsListCall) doRequest(alt string) (*http.Resp } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v2beta1/monitoredResourceDescriptors") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders return gensupport.SendRequest(c.ctx_, c.s.client, req) } @@ -2685,7 +2363,7 @@ func (c *MonitoredResourceDescriptorsListCall) Do(opts ...googleapi.CallOption) } return ret, nil // { - // "description": "Lists the descriptors for monitored resource types used by Stackdriver Logging.", + // "description": "Lists the descriptors for monitored resource types used by Logging.", // "flatPath": "v2beta1/monitoredResourceDescriptors", // "httpMethod": "GET", // "id": "logging.monitoredResourceDescriptors.list", @@ -2738,650 +2416,6 @@ func (c *MonitoredResourceDescriptorsListCall) Pages(ctx context.Context, f func } } -// method id "logging.organizations.logs.delete": - -type OrganizationsLogsDeleteCall struct { - s *Service - logName string - urlParams_ gensupport.URLParams - ctx_ context.Context - header_ http.Header -} - -// Delete: Deletes all the log entries in a log. The log reappears if it -// receives new entries. Log entries written shortly before the delete -// operation might not be deleted. -func (r *OrganizationsLogsService) Delete(logName string) *OrganizationsLogsDeleteCall { - c := &OrganizationsLogsDeleteCall{s: r.s, urlParams_: make(gensupport.URLParams)} - c.logName = logName - return c -} - -// Fields allows partial responses to be retrieved. See -// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse -// for more information. -func (c *OrganizationsLogsDeleteCall) Fields(s ...googleapi.Field) *OrganizationsLogsDeleteCall { - c.urlParams_.Set("fields", googleapi.CombineFields(s)) - return c -} - -// Context sets the context to be used in this call's Do method. Any -// pending HTTP request will be aborted if the provided context is -// canceled. -func (c *OrganizationsLogsDeleteCall) Context(ctx context.Context) *OrganizationsLogsDeleteCall { - c.ctx_ = ctx - return c -} - -// Header returns an http.Header that can be modified by the caller to -// add HTTP headers to the request. -func (c *OrganizationsLogsDeleteCall) Header() http.Header { - if c.header_ == nil { - c.header_ = make(http.Header) - } - return c.header_ -} - -func (c *OrganizationsLogsDeleteCall) doRequest(alt string) (*http.Response, error) { - reqHeaders := make(http.Header) - for k, v := range c.header_ { - reqHeaders[k] = v - } - reqHeaders.Set("User-Agent", c.s.userAgent()) - var body io.Reader = nil - c.urlParams_.Set("alt", alt) - urls := googleapi.ResolveRelative(c.s.BasePath, "v2beta1/{+logName}") - urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) - req.Header = reqHeaders - googleapi.Expand(req.URL, map[string]string{ - "logName": c.logName, - }) - return gensupport.SendRequest(c.ctx_, c.s.client, req) -} - -// Do executes the "logging.organizations.logs.delete" call. -// Exactly one of *Empty or error will be non-nil. Any non-2xx status -// code is an error. Response headers are in either -// *Empty.ServerResponse.Header or (if a response was returned at all) -// in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to -// check whether the returned error was because http.StatusNotModified -// was returned. -func (c *OrganizationsLogsDeleteCall) Do(opts ...googleapi.CallOption) (*Empty, error) { - gensupport.SetOptions(c.urlParams_, opts...) - res, err := c.doRequest("json") - if res != nil && res.StatusCode == http.StatusNotModified { - if res.Body != nil { - res.Body.Close() - } - return nil, &googleapi.Error{ - Code: res.StatusCode, - Header: res.Header, - } - } - if err != nil { - return nil, err - } - defer googleapi.CloseBody(res) - if err := googleapi.CheckResponse(res); err != nil { - return nil, err - } - ret := &Empty{ - ServerResponse: googleapi.ServerResponse{ - Header: res.Header, - HTTPStatusCode: res.StatusCode, - }, - } - target := &ret - if err := gensupport.DecodeResponse(target, res); err != nil { - return nil, err - } - return ret, nil - // { - // "description": "Deletes all the log entries in a log. The log reappears if it receives new entries. Log entries written shortly before the delete operation might not be deleted.", - // "flatPath": "v2beta1/organizations/{organizationsId}/logs/{logsId}", - // "httpMethod": "DELETE", - // "id": "logging.organizations.logs.delete", - // "parameterOrder": [ - // "logName" - // ], - // "parameters": { - // "logName": { - // "description": "Required. The resource name of the log to delete:\n\"projects/[PROJECT_ID]/logs/[LOG_ID]\"\n\"organizations/[ORGANIZATION_ID]/logs/[LOG_ID]\"\n\"billingAccounts/[BILLING_ACCOUNT_ID]/logs/[LOG_ID]\"\n\"folders/[FOLDER_ID]/logs/[LOG_ID]\"\n[LOG_ID] must be URL-encoded. For example, \"projects/my-project-id/logs/syslog\", \"organizations/1234567890/logs/cloudresourcemanager.googleapis.com%2Factivity\". For more information about log names, see LogEntry.", - // "location": "path", - // "pattern": "^organizations/[^/]+/logs/[^/]+$", - // "required": true, - // "type": "string" - // } - // }, - // "path": "v2beta1/{+logName}", - // "response": { - // "$ref": "Empty" - // }, - // "scopes": [ - // "https://www.googleapis.com/auth/cloud-platform", - // "https://www.googleapis.com/auth/logging.admin" - // ] - // } - -} - -// method id "logging.organizations.logs.list": - -type OrganizationsLogsListCall struct { - s *Service - parent string - urlParams_ gensupport.URLParams - ifNoneMatch_ string - ctx_ context.Context - header_ http.Header -} - -// List: Lists the logs in projects, organizations, folders, or billing -// accounts. Only logs that have entries are listed. -func (r *OrganizationsLogsService) List(parent string) *OrganizationsLogsListCall { - c := &OrganizationsLogsListCall{s: r.s, urlParams_: make(gensupport.URLParams)} - c.parent = parent - return c -} - -// PageSize sets the optional parameter "pageSize": The maximum number -// of results to return from this request. Non-positive values are -// ignored. The presence of nextPageToken in the response indicates that -// more results might be available. -func (c *OrganizationsLogsListCall) PageSize(pageSize int64) *OrganizationsLogsListCall { - c.urlParams_.Set("pageSize", fmt.Sprint(pageSize)) - return c -} - -// PageToken sets the optional parameter "pageToken": If present, then -// retrieve the next batch of results from the preceding call to this -// method. pageToken must be the value of nextPageToken from the -// previous response. The values of other method parameters should be -// identical to those in the previous call. -func (c *OrganizationsLogsListCall) PageToken(pageToken string) *OrganizationsLogsListCall { - c.urlParams_.Set("pageToken", pageToken) - return c -} - -// Fields allows partial responses to be retrieved. See -// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse -// for more information. -func (c *OrganizationsLogsListCall) Fields(s ...googleapi.Field) *OrganizationsLogsListCall { - c.urlParams_.Set("fields", googleapi.CombineFields(s)) - return c -} - -// IfNoneMatch sets the optional parameter which makes the operation -// fail if the object's ETag matches the given value. This is useful for -// getting updates only after the object has changed since the last -// request. Use googleapi.IsNotModified to check whether the response -// error from Do is the result of In-None-Match. -func (c *OrganizationsLogsListCall) IfNoneMatch(entityTag string) *OrganizationsLogsListCall { - c.ifNoneMatch_ = entityTag - return c -} - -// Context sets the context to be used in this call's Do method. Any -// pending HTTP request will be aborted if the provided context is -// canceled. -func (c *OrganizationsLogsListCall) Context(ctx context.Context) *OrganizationsLogsListCall { - c.ctx_ = ctx - return c -} - -// Header returns an http.Header that can be modified by the caller to -// add HTTP headers to the request. -func (c *OrganizationsLogsListCall) Header() http.Header { - if c.header_ == nil { - c.header_ = make(http.Header) - } - return c.header_ -} - -func (c *OrganizationsLogsListCall) doRequest(alt string) (*http.Response, error) { - reqHeaders := make(http.Header) - for k, v := range c.header_ { - reqHeaders[k] = v - } - reqHeaders.Set("User-Agent", c.s.userAgent()) - if c.ifNoneMatch_ != "" { - reqHeaders.Set("If-None-Match", c.ifNoneMatch_) - } - var body io.Reader = nil - c.urlParams_.Set("alt", alt) - urls := googleapi.ResolveRelative(c.s.BasePath, "v2beta1/{+parent}/logs") - urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) - req.Header = reqHeaders - googleapi.Expand(req.URL, map[string]string{ - "parent": c.parent, - }) - return gensupport.SendRequest(c.ctx_, c.s.client, req) -} - -// Do executes the "logging.organizations.logs.list" call. -// Exactly one of *ListLogsResponse or error will be non-nil. Any -// non-2xx status code is an error. Response headers are in either -// *ListLogsResponse.ServerResponse.Header or (if a response was -// returned at all) in error.(*googleapi.Error).Header. Use -// googleapi.IsNotModified to check whether the returned error was -// because http.StatusNotModified was returned. -func (c *OrganizationsLogsListCall) Do(opts ...googleapi.CallOption) (*ListLogsResponse, error) { - gensupport.SetOptions(c.urlParams_, opts...) - res, err := c.doRequest("json") - if res != nil && res.StatusCode == http.StatusNotModified { - if res.Body != nil { - res.Body.Close() - } - return nil, &googleapi.Error{ - Code: res.StatusCode, - Header: res.Header, - } - } - if err != nil { - return nil, err - } - defer googleapi.CloseBody(res) - if err := googleapi.CheckResponse(res); err != nil { - return nil, err - } - ret := &ListLogsResponse{ - ServerResponse: googleapi.ServerResponse{ - Header: res.Header, - HTTPStatusCode: res.StatusCode, - }, - } - target := &ret - if err := gensupport.DecodeResponse(target, res); err != nil { - return nil, err - } - return ret, nil - // { - // "description": "Lists the logs in projects, organizations, folders, or billing accounts. Only logs that have entries are listed.", - // "flatPath": "v2beta1/organizations/{organizationsId}/logs", - // "httpMethod": "GET", - // "id": "logging.organizations.logs.list", - // "parameterOrder": [ - // "parent" - // ], - // "parameters": { - // "pageSize": { - // "description": "Optional. The maximum number of results to return from this request. Non-positive values are ignored. The presence of nextPageToken in the response indicates that more results might be available.", - // "format": "int32", - // "location": "query", - // "type": "integer" - // }, - // "pageToken": { - // "description": "Optional. If present, then retrieve the next batch of results from the preceding call to this method. pageToken must be the value of nextPageToken from the previous response. The values of other method parameters should be identical to those in the previous call.", - // "location": "query", - // "type": "string" - // }, - // "parent": { - // "description": "Required. The resource name that owns the logs:\n\"projects/[PROJECT_ID]\"\n\"organizations/[ORGANIZATION_ID]\"\n\"billingAccounts/[BILLING_ACCOUNT_ID]\"\n\"folders/[FOLDER_ID]\"\n", - // "location": "path", - // "pattern": "^organizations/[^/]+$", - // "required": true, - // "type": "string" - // } - // }, - // "path": "v2beta1/{+parent}/logs", - // "response": { - // "$ref": "ListLogsResponse" - // }, - // "scopes": [ - // "https://www.googleapis.com/auth/cloud-platform", - // "https://www.googleapis.com/auth/cloud-platform.read-only", - // "https://www.googleapis.com/auth/logging.admin", - // "https://www.googleapis.com/auth/logging.read" - // ] - // } - -} - -// Pages invokes f for each page of results. -// A non-nil error returned from f will halt the iteration. -// The provided context supersedes any context provided to the Context method. -func (c *OrganizationsLogsListCall) Pages(ctx context.Context, f func(*ListLogsResponse) error) error { - c.ctx_ = ctx - defer c.PageToken(c.urlParams_.Get("pageToken")) // reset paging to original point - for { - x, err := c.Do() - if err != nil { - return err - } - if err := f(x); err != nil { - return err - } - if x.NextPageToken == "" { - return nil - } - c.PageToken(x.NextPageToken) - } -} - -// method id "logging.projects.logs.delete": - -type ProjectsLogsDeleteCall struct { - s *Service - logName string - urlParams_ gensupport.URLParams - ctx_ context.Context - header_ http.Header -} - -// Delete: Deletes all the log entries in a log. The log reappears if it -// receives new entries. Log entries written shortly before the delete -// operation might not be deleted. -func (r *ProjectsLogsService) Delete(logName string) *ProjectsLogsDeleteCall { - c := &ProjectsLogsDeleteCall{s: r.s, urlParams_: make(gensupport.URLParams)} - c.logName = logName - return c -} - -// Fields allows partial responses to be retrieved. See -// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse -// for more information. -func (c *ProjectsLogsDeleteCall) Fields(s ...googleapi.Field) *ProjectsLogsDeleteCall { - c.urlParams_.Set("fields", googleapi.CombineFields(s)) - return c -} - -// Context sets the context to be used in this call's Do method. Any -// pending HTTP request will be aborted if the provided context is -// canceled. -func (c *ProjectsLogsDeleteCall) Context(ctx context.Context) *ProjectsLogsDeleteCall { - c.ctx_ = ctx - return c -} - -// Header returns an http.Header that can be modified by the caller to -// add HTTP headers to the request. -func (c *ProjectsLogsDeleteCall) Header() http.Header { - if c.header_ == nil { - c.header_ = make(http.Header) - } - return c.header_ -} - -func (c *ProjectsLogsDeleteCall) doRequest(alt string) (*http.Response, error) { - reqHeaders := make(http.Header) - for k, v := range c.header_ { - reqHeaders[k] = v - } - reqHeaders.Set("User-Agent", c.s.userAgent()) - var body io.Reader = nil - c.urlParams_.Set("alt", alt) - urls := googleapi.ResolveRelative(c.s.BasePath, "v2beta1/{+logName}") - urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) - req.Header = reqHeaders - googleapi.Expand(req.URL, map[string]string{ - "logName": c.logName, - }) - return gensupport.SendRequest(c.ctx_, c.s.client, req) -} - -// Do executes the "logging.projects.logs.delete" call. -// Exactly one of *Empty or error will be non-nil. Any non-2xx status -// code is an error. Response headers are in either -// *Empty.ServerResponse.Header or (if a response was returned at all) -// in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to -// check whether the returned error was because http.StatusNotModified -// was returned. -func (c *ProjectsLogsDeleteCall) Do(opts ...googleapi.CallOption) (*Empty, error) { - gensupport.SetOptions(c.urlParams_, opts...) - res, err := c.doRequest("json") - if res != nil && res.StatusCode == http.StatusNotModified { - if res.Body != nil { - res.Body.Close() - } - return nil, &googleapi.Error{ - Code: res.StatusCode, - Header: res.Header, - } - } - if err != nil { - return nil, err - } - defer googleapi.CloseBody(res) - if err := googleapi.CheckResponse(res); err != nil { - return nil, err - } - ret := &Empty{ - ServerResponse: googleapi.ServerResponse{ - Header: res.Header, - HTTPStatusCode: res.StatusCode, - }, - } - target := &ret - if err := gensupport.DecodeResponse(target, res); err != nil { - return nil, err - } - return ret, nil - // { - // "description": "Deletes all the log entries in a log. The log reappears if it receives new entries. Log entries written shortly before the delete operation might not be deleted.", - // "flatPath": "v2beta1/projects/{projectsId}/logs/{logsId}", - // "httpMethod": "DELETE", - // "id": "logging.projects.logs.delete", - // "parameterOrder": [ - // "logName" - // ], - // "parameters": { - // "logName": { - // "description": "Required. The resource name of the log to delete:\n\"projects/[PROJECT_ID]/logs/[LOG_ID]\"\n\"organizations/[ORGANIZATION_ID]/logs/[LOG_ID]\"\n\"billingAccounts/[BILLING_ACCOUNT_ID]/logs/[LOG_ID]\"\n\"folders/[FOLDER_ID]/logs/[LOG_ID]\"\n[LOG_ID] must be URL-encoded. For example, \"projects/my-project-id/logs/syslog\", \"organizations/1234567890/logs/cloudresourcemanager.googleapis.com%2Factivity\". For more information about log names, see LogEntry.", - // "location": "path", - // "pattern": "^projects/[^/]+/logs/[^/]+$", - // "required": true, - // "type": "string" - // } - // }, - // "path": "v2beta1/{+logName}", - // "response": { - // "$ref": "Empty" - // }, - // "scopes": [ - // "https://www.googleapis.com/auth/cloud-platform", - // "https://www.googleapis.com/auth/logging.admin" - // ] - // } - -} - -// method id "logging.projects.logs.list": - -type ProjectsLogsListCall struct { - s *Service - parent string - urlParams_ gensupport.URLParams - ifNoneMatch_ string - ctx_ context.Context - header_ http.Header -} - -// List: Lists the logs in projects, organizations, folders, or billing -// accounts. Only logs that have entries are listed. -func (r *ProjectsLogsService) List(parent string) *ProjectsLogsListCall { - c := &ProjectsLogsListCall{s: r.s, urlParams_: make(gensupport.URLParams)} - c.parent = parent - return c -} - -// PageSize sets the optional parameter "pageSize": The maximum number -// of results to return from this request. Non-positive values are -// ignored. The presence of nextPageToken in the response indicates that -// more results might be available. -func (c *ProjectsLogsListCall) PageSize(pageSize int64) *ProjectsLogsListCall { - c.urlParams_.Set("pageSize", fmt.Sprint(pageSize)) - return c -} - -// PageToken sets the optional parameter "pageToken": If present, then -// retrieve the next batch of results from the preceding call to this -// method. pageToken must be the value of nextPageToken from the -// previous response. The values of other method parameters should be -// identical to those in the previous call. -func (c *ProjectsLogsListCall) PageToken(pageToken string) *ProjectsLogsListCall { - c.urlParams_.Set("pageToken", pageToken) - return c -} - -// Fields allows partial responses to be retrieved. See -// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse -// for more information. -func (c *ProjectsLogsListCall) Fields(s ...googleapi.Field) *ProjectsLogsListCall { - c.urlParams_.Set("fields", googleapi.CombineFields(s)) - return c -} - -// IfNoneMatch sets the optional parameter which makes the operation -// fail if the object's ETag matches the given value. This is useful for -// getting updates only after the object has changed since the last -// request. Use googleapi.IsNotModified to check whether the response -// error from Do is the result of In-None-Match. -func (c *ProjectsLogsListCall) IfNoneMatch(entityTag string) *ProjectsLogsListCall { - c.ifNoneMatch_ = entityTag - return c -} - -// Context sets the context to be used in this call's Do method. Any -// pending HTTP request will be aborted if the provided context is -// canceled. -func (c *ProjectsLogsListCall) Context(ctx context.Context) *ProjectsLogsListCall { - c.ctx_ = ctx - return c -} - -// Header returns an http.Header that can be modified by the caller to -// add HTTP headers to the request. -func (c *ProjectsLogsListCall) Header() http.Header { - if c.header_ == nil { - c.header_ = make(http.Header) - } - return c.header_ -} - -func (c *ProjectsLogsListCall) doRequest(alt string) (*http.Response, error) { - reqHeaders := make(http.Header) - for k, v := range c.header_ { - reqHeaders[k] = v - } - reqHeaders.Set("User-Agent", c.s.userAgent()) - if c.ifNoneMatch_ != "" { - reqHeaders.Set("If-None-Match", c.ifNoneMatch_) - } - var body io.Reader = nil - c.urlParams_.Set("alt", alt) - urls := googleapi.ResolveRelative(c.s.BasePath, "v2beta1/{+parent}/logs") - urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) - req.Header = reqHeaders - googleapi.Expand(req.URL, map[string]string{ - "parent": c.parent, - }) - return gensupport.SendRequest(c.ctx_, c.s.client, req) -} - -// Do executes the "logging.projects.logs.list" call. -// Exactly one of *ListLogsResponse or error will be non-nil. Any -// non-2xx status code is an error. Response headers are in either -// *ListLogsResponse.ServerResponse.Header or (if a response was -// returned at all) in error.(*googleapi.Error).Header. Use -// googleapi.IsNotModified to check whether the returned error was -// because http.StatusNotModified was returned. -func (c *ProjectsLogsListCall) Do(opts ...googleapi.CallOption) (*ListLogsResponse, error) { - gensupport.SetOptions(c.urlParams_, opts...) - res, err := c.doRequest("json") - if res != nil && res.StatusCode == http.StatusNotModified { - if res.Body != nil { - res.Body.Close() - } - return nil, &googleapi.Error{ - Code: res.StatusCode, - Header: res.Header, - } - } - if err != nil { - return nil, err - } - defer googleapi.CloseBody(res) - if err := googleapi.CheckResponse(res); err != nil { - return nil, err - } - ret := &ListLogsResponse{ - ServerResponse: googleapi.ServerResponse{ - Header: res.Header, - HTTPStatusCode: res.StatusCode, - }, - } - target := &ret - if err := gensupport.DecodeResponse(target, res); err != nil { - return nil, err - } - return ret, nil - // { - // "description": "Lists the logs in projects, organizations, folders, or billing accounts. Only logs that have entries are listed.", - // "flatPath": "v2beta1/projects/{projectsId}/logs", - // "httpMethod": "GET", - // "id": "logging.projects.logs.list", - // "parameterOrder": [ - // "parent" - // ], - // "parameters": { - // "pageSize": { - // "description": "Optional. The maximum number of results to return from this request. Non-positive values are ignored. The presence of nextPageToken in the response indicates that more results might be available.", - // "format": "int32", - // "location": "query", - // "type": "integer" - // }, - // "pageToken": { - // "description": "Optional. If present, then retrieve the next batch of results from the preceding call to this method. pageToken must be the value of nextPageToken from the previous response. The values of other method parameters should be identical to those in the previous call.", - // "location": "query", - // "type": "string" - // }, - // "parent": { - // "description": "Required. The resource name that owns the logs:\n\"projects/[PROJECT_ID]\"\n\"organizations/[ORGANIZATION_ID]\"\n\"billingAccounts/[BILLING_ACCOUNT_ID]\"\n\"folders/[FOLDER_ID]\"\n", - // "location": "path", - // "pattern": "^projects/[^/]+$", - // "required": true, - // "type": "string" - // } - // }, - // "path": "v2beta1/{+parent}/logs", - // "response": { - // "$ref": "ListLogsResponse" - // }, - // "scopes": [ - // "https://www.googleapis.com/auth/cloud-platform", - // "https://www.googleapis.com/auth/cloud-platform.read-only", - // "https://www.googleapis.com/auth/logging.admin", - // "https://www.googleapis.com/auth/logging.read" - // ] - // } - -} - -// Pages invokes f for each page of results. -// A non-nil error returned from f will halt the iteration. -// The provided context supersedes any context provided to the Context method. -func (c *ProjectsLogsListCall) Pages(ctx context.Context, f func(*ListLogsResponse) error) error { - c.ctx_ = ctx - defer c.PageToken(c.urlParams_.Get("pageToken")) // reset paging to original point - for { - x, err := c.Do() - if err != nil { - return err - } - if err := f(x); err != nil { - return err - } - if x.NextPageToken == "" { - return nil - } - c.PageToken(x.NextPageToken) - } -} - // method id "logging.projects.metrics.create": type ProjectsMetricsCreateCall struct { @@ -3439,9 +2473,13 @@ func (c *ProjectsMetricsCreateCall) doRequest(alt string) (*http.Response, error } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v2beta1/{+parent}/metrics") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "parent": c.parent, @@ -3569,9 +2607,13 @@ func (c *ProjectsMetricsDeleteCall) doRequest(alt string) (*http.Response, error reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v2beta1/{+metricName}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "metricName": c.metricName, @@ -3710,9 +2752,13 @@ func (c *ProjectsMetricsGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v2beta1/{+metricName}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "metricName": c.metricName, @@ -3871,9 +2917,13 @@ func (c *ProjectsMetricsListCall) doRequest(alt string) (*http.Response, error) } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v2beta1/{+parent}/metrics") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "parent": c.parent, @@ -4038,9 +3088,13 @@ func (c *ProjectsMetricsUpdateCall) doRequest(alt string) (*http.Response, error } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v2beta1/{+metricName}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PUT", urls, body) + req, err := http.NewRequest("PUT", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "metricName": c.metricName, @@ -4146,13 +3200,12 @@ func (r *ProjectsSinksService) Create(parent string, logsink *LogSink) *Projects // as writer_identity in the new sink. If this value is omitted or set // to false, and if the sink's parent is a project, then the value // returned as writer_identity is the same group or service account used -// by Stackdriver Logging before the addition of writer identities to -// this API. The sink's destination must be in the same project as the -// sink itself.If this field is set to true, or if the sink is owned by -// a non-project resource such as an organization, then the value of -// writer_identity will be a unique service account used only for -// exports from the new sink. For more information, see writer_identity -// in LogSink. +// by Logging before the addition of writer identities to this API. The +// sink's destination must be in the same project as the sink itself.If +// this field is set to true, or if the sink is owned by a non-project +// resource such as an organization, then the value of writer_identity +// will be a unique service account used only for exports from the new +// sink. For more information, see writer_identity in LogSink. func (c *ProjectsSinksCreateCall) UniqueWriterIdentity(uniqueWriterIdentity bool) *ProjectsSinksCreateCall { c.urlParams_.Set("uniqueWriterIdentity", fmt.Sprint(uniqueWriterIdentity)) return c @@ -4196,9 +3249,13 @@ func (c *ProjectsSinksCreateCall) doRequest(alt string) (*http.Response, error) } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v2beta1/{+parent}/sinks") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "parent": c.parent, @@ -4260,7 +3317,7 @@ func (c *ProjectsSinksCreateCall) Do(opts ...googleapi.CallOption) (*LogSink, er // "type": "string" // }, // "uniqueWriterIdentity": { - // "description": "Optional. Determines the kind of IAM identity returned as writer_identity in the new sink. If this value is omitted or set to false, and if the sink's parent is a project, then the value returned as writer_identity is the same group or service account used by Stackdriver Logging before the addition of writer identities to this API. The sink's destination must be in the same project as the sink itself.If this field is set to true, or if the sink is owned by a non-project resource such as an organization, then the value of writer_identity will be a unique service account used only for exports from the new sink. For more information, see writer_identity in LogSink.", + // "description": "Optional. Determines the kind of IAM identity returned as writer_identity in the new sink. If this value is omitted or set to false, and if the sink's parent is a project, then the value returned as writer_identity is the same group or service account used by Logging before the addition of writer identities to this API. The sink's destination must be in the same project as the sink itself.If this field is set to true, or if the sink is owned by a non-project resource such as an organization, then the value of writer_identity will be a unique service account used only for exports from the new sink. For more information, see writer_identity in LogSink.", // "location": "query", // "type": "boolean" // } @@ -4331,9 +3388,13 @@ func (c *ProjectsSinksDeleteCall) doRequest(alt string) (*http.Response, error) reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v2beta1/{+sinkName}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "sinkName": c.sinkNameid, @@ -4471,9 +3532,13 @@ func (c *ProjectsSinksGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v2beta1/{+sinkName}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "sinkName": c.sinkName, @@ -4632,9 +3697,13 @@ func (c *ProjectsSinksListCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v2beta1/{+parent}/sinks") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "parent": c.parent, @@ -4788,7 +3857,7 @@ func (c *ProjectsSinksUpdateCall) UniqueWriterIdentity(uniqueWriterIdentity bool // compatibility purposes: destination,filter,includeChildren At some // point in the future, behavior will be removed and specifying an empty // updateMask will be an error.For a detailed FieldMask definition, see -// https://developers.google.com/protocol-buffers/docs/reference/google.protobuf#fieldmaskExample: +// https://developers.google.com/protocol-buffers/docs/reference/google.protobuf#google.protobuf.FieldMaskExample: // updateMask=filter. func (c *ProjectsSinksUpdateCall) UpdateMask(updateMask string) *ProjectsSinksUpdateCall { c.urlParams_.Set("updateMask", updateMask) @@ -4833,9 +3902,13 @@ func (c *ProjectsSinksUpdateCall) doRequest(alt string) (*http.Response, error) } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v2beta1/{+sinkName}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PUT", urls, body) + req, err := http.NewRequest("PUT", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "sinkName": c.sinkNameid, @@ -4902,7 +3975,7 @@ func (c *ProjectsSinksUpdateCall) Do(opts ...googleapi.CallOption) (*LogSink, er // "type": "boolean" // }, // "updateMask": { - // "description": "Optional. Field mask that specifies the fields in sink that need an update. A sink field will be overwritten if, and only if, it is in the update mask. name and output only fields cannot be updated.An empty updateMask is temporarily treated as using the following mask for backwards compatibility purposes: destination,filter,includeChildren At some point in the future, behavior will be removed and specifying an empty updateMask will be an error.For a detailed FieldMask definition, see https://developers.google.com/protocol-buffers/docs/reference/google.protobuf#fieldmaskExample: updateMask=filter.", + // "description": "Optional. Field mask that specifies the fields in sink that need an update. A sink field will be overwritten if, and only if, it is in the update mask. name and output only fields cannot be updated.An empty updateMask is temporarily treated as using the following mask for backwards compatibility purposes: destination,filter,includeChildren At some point in the future, behavior will be removed and specifying an empty updateMask will be an error.For a detailed FieldMask definition, see https://developers.google.com/protocol-buffers/docs/reference/google.protobuf#google.protobuf.FieldMaskExample: updateMask=filter.", // "format": "google-fieldmask", // "location": "query", // "type": "string" diff --git a/vendor/google.golang.org/api/monitoring/v3/BUILD b/vendor/google.golang.org/api/monitoring/v3/BUILD index 9b5cd30c58c..d0c61d6f1a9 100644 --- a/vendor/google.golang.org/api/monitoring/v3/BUILD +++ b/vendor/google.golang.org/api/monitoring/v3/BUILD @@ -7,8 +7,6 @@ go_library( importpath = "google.golang.org/api/monitoring/v3", visibility = ["//visibility:public"], deps = [ - "//vendor/golang.org/x/net/context:go_default_library", - "//vendor/golang.org/x/net/context/ctxhttp:go_default_library", "//vendor/google.golang.org/api/gensupport:go_default_library", "//vendor/google.golang.org/api/googleapi:go_default_library", ], diff --git a/vendor/google.golang.org/api/monitoring/v3/monitoring-api.json b/vendor/google.golang.org/api/monitoring/v3/monitoring-api.json index 3062670955e..a6600d72672 100644 --- a/vendor/google.golang.org/api/monitoring/v3/monitoring-api.json +++ b/vendor/google.golang.org/api/monitoring/v3/monitoring-api.json @@ -837,7 +837,7 @@ "notificationChannels": { "methods": { "create": { - "description": "Creates a new notification channel, representing a single notification endpoint such as an email address, SMS number, or pagerduty service.", + "description": "Creates a new notification channel, representing a single notification endpoint such as an email address, SMS number, or PagerDuty service.", "flatPath": "v3/projects/{projectsId}/notificationChannels", "httpMethod": "POST", "id": "monitoring.projects.notificationChannels.create", @@ -1452,7 +1452,7 @@ } } }, - "revision": "20180603", + "revision": "20181211", "rootUrl": "https://monitoring.googleapis.com/", "schemas": { "Aggregation": { @@ -1801,11 +1801,11 @@ "type": "object" }, "ContentMatcher": { - "description": "Used to perform string matching. Currently, this matches on the exact content. In the future, it can be expanded to allow for regular expressions and more complex matching.", + "description": "Used to perform string matching. It allows substring and regular expressions, together with their negations.", "id": "ContentMatcher", "properties": { "content": { - "description": "String content to match (max 1024 bytes)", + "description": "String or regex content to match (max 1024 bytes)", "type": "string" } }, @@ -1852,7 +1852,7 @@ "id": "CreateTimeSeriesRequest", "properties": { "timeSeries": { - "description": "The new data to be added to a list of time series. Adds at most one data point to each of several time series. The new data point must be more recent than any other point in its time series. Each TimeSeries value must fully specify a unique time series by supplying all label values for the metric and the monitored resource.", + "description": "The new data to be added to a list of time series. Adds at most one data point to each of several time series. The new data point must be more recent than any other point in its time series. Each TimeSeries value must fully specify a unique time series by supplying all label values for the metric and the monitored resource.The maximum number of TimeSeries objects per Create request is 200.", "items": { "$ref": "TimeSeries" }, @@ -1921,6 +1921,20 @@ }, "type": "object" }, + "DroppedLabels": { + "description": "A set of (label, value) pairs which were dropped during aggregation, attached to google.api.Distribution.Exemplars in google.api.Distribution values during aggregation.These values are used in combination with the label values that remain on the aggregated Distribution timeseries to construct the full label set for the exemplar values. The resulting full label set may be used to identify the specific task/job/instance (for example) which may be contributing to a long-tail, while allowing the storage savings of only storing aggregated distribution values for a large group.Note that there are no guarantees on ordering of the labels from exemplar-to-exemplar and from distribution-to-distribution in the same stream, and there may be duplicates. It is up to clients to resolve any ambiguities.", + "id": "DroppedLabels", + "properties": { + "label": { + "additionalProperties": { + "type": "string" + }, + "description": "Map from label to its value, for all labels dropped in any aggregation.", + "type": "object" + } + }, + "type": "object" + }, "Empty": { "description": "A generic empty message that you can re-use to avoid defining duplicated empty messages in your APIs. A typical example is to use it as the request or the response type of an API method. For instance:\nservice Foo {\n rpc Bar(google.protobuf.Empty) returns (google.protobuf.Empty);\n}\nThe JSON representation for Empty is empty JSON object {}.", "id": "Empty", @@ -2189,27 +2203,41 @@ "type": "object" }, "InternalChecker": { - "description": "Nimbus InternalCheckers.", + "description": "An internal checker allows uptime checks to run on private/internal GCP resources.", "id": "InternalChecker", "properties": { - "checkerId": { - "description": "The checker ID.", - "type": "string" - }, "displayName": { - "description": "The checker's human-readable name.", + "description": "The checker's human-readable name. The display name should be unique within a Stackdriver Workspace in order to make it easier to identify; however, uniqueness is not enforced.", "type": "string" }, "gcpZone": { "description": "The GCP zone the uptime check should egress from. Only respected for internal uptime checks, where internal_network is specified.", "type": "string" }, - "network": { - "description": "The internal network to perform this uptime check on.", + "name": { + "description": "A unique resource name for this InternalChecker. The format is:projects/[PROJECT_ID]/internalCheckers/[INTERNAL_CHECKER_ID].PROJECT_ID is the stackdriver workspace project for the uptime check config associated with the internal checker.", "type": "string" }, - "projectId": { - "description": "The GCP project ID. Not necessarily the same as the project_id for the config.", + "network": { + "description": "The GCP VPC network (https://cloud.google.com/vpc/docs/vpc) where the internal resource lives (ex: \"default\").", + "type": "string" + }, + "peerProjectId": { + "description": "The GCP project_id where the internal checker lives. Not necessary the same as the workspace project.", + "type": "string" + }, + "state": { + "description": "The current operational state of the internal checker.", + "enum": [ + "UNSPECIFIED", + "CREATING", + "RUNNING" + ], + "enumDescriptions": [ + "An internal checker should never be in the unspecified state.", + "The checker is being created, provisioned, and configured. A checker in this state can be returned by ListInternalCheckers or GetInternalChecker, as well as by examining the longrunning.Operation that created it.", + "The checker is running and available for use. A checker in this state can be returned by ListInternalCheckers or GetInternalChecker as well as by examining the longrunning.Operation that created it. If a checker is being torn down, it is neither visible nor usable, so there is no \"deleting\" or \"down\" state." + ], "type": "string" } }, @@ -2527,6 +2555,10 @@ }, "type": "array" }, + "metadata": { + "$ref": "MetricDescriptorMetadata", + "description": "Optional. Metadata which can be used to guide usage of the metric." + }, "metricKind": { "description": "Whether the metric records instantaneous values, changes to a value, etc. Some combinations of metric_kind and value_type might not be supported.", "enum": [ @@ -2548,11 +2580,11 @@ "type": "string" }, "type": { - "description": "The metric type, including its DNS name prefix. The type is not URL-encoded. All user-defined custom metric types have the DNS name custom.googleapis.com. Metric types should use a natural hierarchical grouping. For example:\n\"custom.googleapis.com/invoice/paid/amount\"\n\"appengine.googleapis.com/http/server/response_latencies\"\n", + "description": "The metric type, including its DNS name prefix. The type is not URL-encoded. All user-defined metric types have the DNS name custom.googleapis.com or external.googleapis.com. Metric types should use a natural hierarchical grouping. For example:\n\"custom.googleapis.com/invoice/paid/amount\"\n\"external.googleapis.com/prometheus/up\"\n\"appengine.googleapis.com/http/server/response_latencies\"\n", "type": "string" }, "unit": { - "description": "Optional. The unit in which the metric value is reported. For example, kBy/s means kilobytes/sec, and 1 is the dimensionless unit. The supported units are a subset of The Unified Code for Units of Measure standard (http://unitsofmeasure.org/ucum.html).\u003cbr\u003e\u003cbr\u003e This field is part of the metric's documentation, but it is ignored by Stackdriver.", + "description": "The unit in which the metric value is reported. It is only applicable if the value_type is INT64, DOUBLE, or DISTRIBUTION. The supported units are a subset of The Unified Code for Units of Measure (http://unitsofmeasure.org/ucum.html) standard:Basic units (UNIT)\nbit bit\nBy byte\ns second\nmin minute\nh hour\nd dayPrefixes (PREFIX)\nk kilo (10**3)\nM mega (10**6)\nG giga (10**9)\nT tera (10**12)\nP peta (10**15)\nE exa (10**18)\nZ zetta (10**21)\nY yotta (10**24)\nm milli (10**-3)\nu micro (10**-6)\nn nano (10**-9)\np pico (10**-12)\nf femto (10**-15)\na atto (10**-18)\nz zepto (10**-21)\ny yocto (10**-24)\nKi kibi (2**10)\nMi mebi (2**20)\nGi gibi (2**30)\nTi tebi (2**40)GrammarThe grammar also includes these connectors:\n/ division (as an infix operator, e.g. 1/s).\n. multiplication (as an infix operator, e.g. GBy.d)The grammar for a unit is as follows:\nExpression = Component { \".\" Component } { \"/\" Component } ;\n\nComponent = ( [ PREFIX ] UNIT | \"%\" ) [ Annotation ]\n | Annotation\n | \"1\"\n ;\n\nAnnotation = \"{\" NAME \"}\" ;\nNotes:\nAnnotation is just a comment if it follows a UNIT and is equivalent to 1 if it is used alone. For examples, {requests}/s == 1/s, By{transmitted}/s == By/s.\nNAME is a sequence of non-blank printable ASCII characters not containing '{' or '}'.\n1 represents dimensionless value 1, such as in 1/s.\n% represents dimensionless value 1/100, and annotates values giving a percentage.", "type": "string" }, "valueType": { @@ -2580,6 +2612,43 @@ }, "type": "object" }, + "MetricDescriptorMetadata": { + "description": "Additional annotations that can be used to guide the usage of a metric.", + "id": "MetricDescriptorMetadata", + "properties": { + "ingestDelay": { + "description": "The delay of data points caused by ingestion. Data points older than this age are guaranteed to be ingested and available to be read, excluding data loss due to errors.", + "format": "google-duration", + "type": "string" + }, + "launchStage": { + "description": "The launch stage of the metric definition.", + "enum": [ + "LAUNCH_STAGE_UNSPECIFIED", + "EARLY_ACCESS", + "ALPHA", + "BETA", + "GA", + "DEPRECATED" + ], + "enumDescriptions": [ + "Do not use this default value.", + "Early Access features are limited to a closed group of testers. To use these features, you must sign up in advance and sign a Trusted Tester agreement (which includes confidentiality provisions). These features may be unstable, changed in backward-incompatible ways, and are not guaranteed to be released.", + "Alpha is a limited availability test for releases before they are cleared for widespread use. By Alpha, all significant design issues are resolved and we are in the process of verifying functionality. Alpha customers need to apply for access, agree to applicable terms, and have their projects whitelisted. Alpha releases don’t have to be feature complete, no SLAs are provided, and there are no technical support obligations, but they will be far enough along that customers can actually use them in test environments or for limited-use tests -- just like they would in normal production cases.", + "Beta is the point at which we are ready to open a release for any customer to use. There are no SLA or technical support obligations in a Beta release. Products will be complete from a feature perspective, but may have some open outstanding issues. Beta releases are suitable for limited production use cases.", + "GA features are open to all developers and are considered stable and fully qualified for production use.", + "Deprecated features are scheduled to be shut down and removed. For more information, see the “Deprecation Policy” section of our Terms of Service (https://cloud.google.com/terms/) and the Google Cloud Platform Subject to the Deprecation Policy (https://cloud.google.com/terms/deprecation) documentation." + ], + "type": "string" + }, + "samplePeriod": { + "description": "The sampling period of metric data points. For metrics which are written periodically, consecutive data points are stored at this time interval, excluding data loss due to errors. Metrics with a higher granularity have a smaller sampling period.", + "format": "google-duration", + "type": "string" + } + }, + "type": "object" + }, "MetricThreshold": { "description": "A condition type that compares a collection of time series against a threshold.", "id": "MetricThreshold", @@ -2657,7 +2726,7 @@ "type": "object" }, "type": { - "description": "Required. The monitored resource type. This field must match the type field of a MonitoredResourceDescriptor object. For example, the type of a Compute Engine VM instance is gce_instance.", + "description": "Required. The monitored resource type. This field must match the type field of a MonitoredResourceDescriptor object. For example, the type of a Compute Engine VM instance is gce_instance. For a list of types, see Monitoring resource types and Logging resource types.", "type": "string" } }, @@ -2694,7 +2763,7 @@ "type": "object" }, "MonitoredResourceMetadata": { - "description": "Auxiliary metadata for a MonitoredResource object. MonitoredResource objects contain the minimum set of information to uniquely identify a monitored resource instance. There is some other useful auxiliary metadata. Google Stackdriver Monitoring \u0026 Logging uses an ingestion pipeline to extract metadata for cloud resources of all types , and stores the metadata in this message.", + "description": "Auxiliary metadata for a MonitoredResource object. MonitoredResource objects contain the minimum set of information to uniquely identify a monitored resource instance. There is some other useful auxiliary metadata. Monitoring and Logging use an ingestion pipeline to extract metadata for cloud resources of all types, and store the metadata in this message.", "id": "MonitoredResourceMetadata", "properties": { "systemLabels": { @@ -2702,7 +2771,7 @@ "description": "Properties of the object.", "type": "any" }, - "description": "Output only. Values for predefined system metadata labels. System labels are a kind of metadata extracted by Google Stackdriver. Stackdriver determines what system labels are useful and how to obtain their values. Some examples: \"machine_image\", \"vpc\", \"subnet_id\", \"security_group\", \"name\", etc. System label values can be only strings, Boolean values, or a list of strings. For example:\n{ \"name\": \"my-test-instance\",\n \"security_group\": [\"a\", \"b\", \"c\"],\n \"spot_instance\": false }\n", + "description": "Output only. Values for predefined system metadata labels. System labels are a kind of metadata extracted by Google, including \"machine_image\", \"vpc\", \"subnet_id\", \"security_group\", \"name\", etc. System label values can be only strings, Boolean values, or a list of strings. For example:\n{ \"name\": \"my-test-instance\",\n \"security_group\": [\"a\", \"b\", \"c\"],\n \"spot_instance\": false }\n", "type": "object" }, "userLabels": { @@ -2813,8 +2882,8 @@ "description": "The tiers that support this notification channel; the project service tier must be one of the supported_tiers.", "enumDescriptions": [ "An invalid sentinel value, used to indicate that a tier has not been provided explicitly.", - "The Stackdriver Basic tier, a free tier of service that provides basic features, a moderate allotment of logs, and access to built-in metrics. A number of features are not available in this tier. For more details, see the service tiers documentation (https://cloud.google.com/monitoring/accounts/tiers).", - "The Stackdriver Premium tier, a higher, more expensive tier of service that provides access to all Stackdriver features, lets you use Stackdriver with AWS accounts, and has a larger allotments for logs and metrics. For more details, see the service tiers documentation (https://cloud.google.com/monitoring/accounts/tiers)." + "The Stackdriver Basic tier, a free tier of service that provides basic features, a moderate allotment of logs, and access to built-in metrics. A number of features are not available in this tier. For more details, see the service tiers documentation (https://cloud.google.com/monitoring/workspaces/tiers).", + "The Stackdriver Premium tier, a higher, more expensive tier of service that provides access to all Stackdriver features, lets you use Stackdriver with AWS accounts, and has a larger allotments for logs and metrics. For more details, see the service tiers documentation (https://cloud.google.com/monitoring/workspaces/tiers)." ], "items": { "enum": [ @@ -2926,6 +2995,17 @@ }, "type": "object" }, + "SpanContext": { + "description": "The context of a span, attached to google.api.Distribution.Exemplars in google.api.Distribution values during aggregation.It contains the name of a span with format: projects/PROJECT_ID/traces/TRACE_ID/spans/SPAN_ID", + "id": "SpanContext", + "properties": { + "spanName": { + "description": "The resource name of the span in the following format:\nprojects/[PROJECT_ID]/traces/[TRACE_ID]/spans/[SPAN_ID]\nTRACE_ID is a unique identifier for a trace within a project; it is a 32-character hexadecimal encoding of a 16-byte array.SPAN_ID is a unique identifier for a span within a trace; it is a 16-character hexadecimal encoding of an 8-byte array.", + "type": "string" + } + }, + "type": "object" + }, "Status": { "description": "The Status type defines a logical error model that is suitable for different programming environments, including REST APIs and RPC APIs. It is used by gRPC (https://github.com/grpc). The error model is designed to be:\nSimple to use and understand for most users\nFlexible enough to meet unexpected needsOverviewThe Status message contains three pieces of data: error code, error message, and error details. The error code should be an enum value of google.rpc.Code, but it may accept additional error codes if needed. The error message should be a developer-facing English message that helps developers understand and resolve the error. If a localized user-facing error message is needed, put the localized message in the error details or localize it in the client. The optional error details may contain arbitrary information about the error. There is a predefined set of error detail types in the package google.rpc that can be used for common error conditions.Language mappingThe Status message is the logical representation of the error model, but it is not necessarily the actual wire format. When the Status message is exposed in different client libraries and different wire protocols, it can be mapped differently. For example, it will likely be mapped to some exceptions in Java, but more likely mapped to some error codes in C.Other usesThe error model and the Status message can be used in a variety of environments, either with or without APIs, to provide a consistent developer experience across different environments.Example uses of this error model include:\nPartial errors. If a service needs to return partial errors to the client, it may embed the Status in the normal response to indicate the partial errors.\nWorkflow errors. A typical workflow has multiple steps. Each step may have a Status message for error reporting.\nBatch operations. If a client uses batch request and batch response, the Status message should be used directly inside batch response, one for each error sub-response.\nAsynchronous operations. If an API call embeds asynchronous operation results in its response, the status of those operations should be represented directly using the Status message.\nLogging. If some API errors are stored in logs, the message Status could be used directly after any stripping needed for security/privacy reasons.", "id": "Status", @@ -2966,7 +3046,7 @@ "type": "object" }, "TimeInterval": { - "description": "A time interval extending just after a start time through an end time. If the start time is the same as the end time, then the interval represents a single point in time.", + "description": "A time interval extending just after a start time through an end time. The start time must not be later than the end time. The default start time is the end time, making the startTime value technically optional. Whether this is useful depends on the MetricKind. If the start and end times are the same, the interval represents a point in time. This is appropriate for GAUGE metrics, but not for DELTA and CUMULATIVE metrics, which cover a span of time.", "id": "TimeInterval", "properties": { "endTime": { @@ -3152,7 +3232,7 @@ "type": "array" }, "displayName": { - "description": "A human-friendly name for the uptime check configuration. The display name should be unique within a Stackdriver Account in order to make it easier to identify; however, uniqueness is not enforced. Required.", + "description": "A human-friendly name for the uptime check configuration. The display name should be unique within a Stackdriver Workspace in order to make it easier to identify; however, uniqueness is not enforced. Required.", "type": "string" }, "httpCheck": { @@ -3160,14 +3240,14 @@ "description": "Contains information needed to make an HTTP or HTTPS check." }, "internalCheckers": { - "description": "The internal checkers that this check will egress from. If is_internal is true and this list is empty, the check will egress from all InternalCheckers configured for the project that owns this CheckConfig.", + "description": "The internal checkers that this check will egress from. If is_internal is true and this list is empty, the check will egress from all the InternalCheckers configured for the project that owns this CheckConfig.", "items": { "$ref": "InternalChecker" }, "type": "array" }, "isInternal": { - "description": "Denotes whether this is a check that egresses from InternalCheckers.", + "description": "If this is true, then checks are made only from the 'internal_checkers'. If it is false, then checks are made only from the 'selected_regions'. It is an error to provide 'selected_regions' when is_internal is true, or to provide 'internal_checkers' when is_internal is false.", "type": "boolean" }, "monitoredResource": { @@ -3188,7 +3268,7 @@ "description": "The group resource associated with the configuration." }, "selectedRegions": { - "description": "The list of regions from which the check will be run. If this field is specified, enough regions to include a minimum of 3 locations must be provided, or an error message is returned. Not specifying this field will result in uptime checks running from all regions.", + "description": "The list of regions from which the check will be run. Some regions contain one location, and others contain more than one. If this field is specified, enough regions to include a minimum of 3 locations must be provided, or an error message is returned. Not specifying this field will result in uptime checks running from all regions.", "enumDescriptions": [ "Default value if no region is specified. Will result in uptime checks running from all regions.", "Allows checks to run from locations within the United States of America.", diff --git a/vendor/google.golang.org/api/monitoring/v3/monitoring-gen.go b/vendor/google.golang.org/api/monitoring/v3/monitoring-gen.go index a738a418ee9..e898a0f499e 100644 --- a/vendor/google.golang.org/api/monitoring/v3/monitoring-gen.go +++ b/vendor/google.golang.org/api/monitoring/v3/monitoring-gen.go @@ -1,5 +1,13 @@ +// Copyright 2018 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Code generated file. DO NOT EDIT. + // Package monitoring provides access to the Stackdriver Monitoring API. // +// This package is DEPRECATED. Use package cloud.google.com/go/monitoring/apiv3 instead. +// // See https://cloud.google.com/monitoring/api/ // // Usage example: @@ -11,18 +19,18 @@ package monitoring import ( "bytes" + "context" "encoding/json" "errors" "fmt" - context "golang.org/x/net/context" - ctxhttp "golang.org/x/net/context/ctxhttp" - gensupport "google.golang.org/api/gensupport" - googleapi "google.golang.org/api/googleapi" "io" "net/http" "net/url" "strconv" "strings" + + gensupport "google.golang.org/api/gensupport" + googleapi "google.golang.org/api/googleapi" ) // Always reference these packages, just in case the auto-generated code @@ -38,7 +46,6 @@ var _ = googleapi.Version var _ = errors.New var _ = strings.Replace var _ = context.Canceled -var _ = ctxhttp.Do const apiId = "monitoring:v3" const apiName = "monitoring" @@ -898,11 +905,10 @@ func (s *Condition) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } -// ContentMatcher: Used to perform string matching. Currently, this -// matches on the exact content. In the future, it can be expanded to -// allow for regular expressions and more complex matching. +// ContentMatcher: Used to perform string matching. It allows substring +// and regular expressions, together with their negations. type ContentMatcher struct { - // Content: String content to match (max 1024 bytes) + // Content: String or regex content to match (max 1024 bytes) Content string `json:"content,omitempty"` // ForceSendFields is a list of field names (e.g. "Content") to @@ -1009,7 +1015,9 @@ type CreateTimeSeriesRequest struct { // at most one data point to each of several time series. The new data // point must be more recent than any other point in its time series. // Each TimeSeries value must fully specify a unique time series by - // supplying all label values for the metric and the monitored resource. + // supplying all label values for the metric and the monitored + // resource.The maximum number of TimeSeries objects per Create request + // is 200. TimeSeries []*TimeSeries `json:"timeSeries,omitempty"` // ForceSendFields is a list of field names (e.g. "TimeSeries") to @@ -1165,6 +1173,47 @@ func (s *Documentation) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +// DroppedLabels: A set of (label, value) pairs which were dropped +// during aggregation, attached to google.api.Distribution.Exemplars in +// google.api.Distribution values during aggregation.These values are +// used in combination with the label values that remain on the +// aggregated Distribution timeseries to construct the full label set +// for the exemplar values. The resulting full label set may be used to +// identify the specific task/job/instance (for example) which may be +// contributing to a long-tail, while allowing the storage savings of +// only storing aggregated distribution values for a large group.Note +// that there are no guarantees on ordering of the labels from +// exemplar-to-exemplar and from distribution-to-distribution in the +// same stream, and there may be duplicates. It is up to clients to +// resolve any ambiguities. +type DroppedLabels struct { + // Label: Map from label to its value, for all labels dropped in any + // aggregation. + Label map[string]string `json:"label,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Label") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Label") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *DroppedLabels) MarshalJSON() ([]byte, error) { + type NoMethod DroppedLabels + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + // Empty: A generic empty message that you can re-use to avoid defining // duplicated empty messages in your APIs. A typical example is to use // it as the request or the response type of an API method. For @@ -1637,12 +1686,12 @@ func (s *HttpCheck) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } -// InternalChecker: Nimbus InternalCheckers. +// InternalChecker: An internal checker allows uptime checks to run on +// private/internal GCP resources. type InternalChecker struct { - // CheckerId: The checker ID. - CheckerId string `json:"checkerId,omitempty"` - - // DisplayName: The checker's human-readable name. + // DisplayName: The checker's human-readable name. The display name + // should be unique within a Stackdriver Workspace in order to make it + // easier to identify; however, uniqueness is not enforced. DisplayName string `json:"displayName,omitempty"` // GcpZone: The GCP zone the uptime check should egress from. Only @@ -1650,14 +1699,37 @@ type InternalChecker struct { // specified. GcpZone string `json:"gcpZone,omitempty"` - // Network: The internal network to perform this uptime check on. + // Name: A unique resource name for this InternalChecker. The format + // is:projects/[PROJECT_ID]/internalCheckers/[INTERNAL_CHECKER_ID].PROJEC + // T_ID is the stackdriver workspace project for the uptime check config + // associated with the internal checker. + Name string `json:"name,omitempty"` + + // Network: The GCP VPC network (https://cloud.google.com/vpc/docs/vpc) + // where the internal resource lives (ex: "default"). Network string `json:"network,omitempty"` - // ProjectId: The GCP project ID. Not necessarily the same as the - // project_id for the config. - ProjectId string `json:"projectId,omitempty"` + // PeerProjectId: The GCP project_id where the internal checker lives. + // Not necessary the same as the workspace project. + PeerProjectId string `json:"peerProjectId,omitempty"` - // ForceSendFields is a list of field names (e.g. "CheckerId") to + // State: The current operational state of the internal checker. + // + // Possible values: + // "UNSPECIFIED" - An internal checker should never be in the + // unspecified state. + // "CREATING" - The checker is being created, provisioned, and + // configured. A checker in this state can be returned by + // ListInternalCheckers or GetInternalChecker, as well as by examining + // the longrunning.Operation that created it. + // "RUNNING" - The checker is running and available for use. A checker + // in this state can be returned by ListInternalCheckers or + // GetInternalChecker as well as by examining the longrunning.Operation + // that created it. If a checker is being torn down, it is neither + // visible nor usable, so there is no "deleting" or "down" state. + State string `json:"state,omitempty"` + + // ForceSendFields is a list of field names (e.g. "DisplayName") to // unconditionally include in API requests. By default, fields with // empty values are omitted from API requests. However, any non-pointer, // non-interface field appearing in ForceSendFields will be sent to the @@ -1665,10 +1737,10 @@ type InternalChecker struct { // used to include empty fields in Patch requests. ForceSendFields []string `json:"-"` - // NullFields is a list of field names (e.g. "CheckerId") to include in - // API requests with the JSON null value. By default, fields with empty - // values are omitted from API requests. However, any field with an - // empty value appearing in NullFields will be sent to the server as + // NullFields is a list of field names (e.g. "DisplayName") to include + // in API requests with the JSON null value. By default, fields with + // empty values are omitted from API requests. However, any field with + // an empty value appearing in NullFields will be sent to the server as // null. It is an error if a field in this list has a non-empty value. // This may be used to include null fields in Patch requests. NullFields []string `json:"-"` @@ -2296,6 +2368,10 @@ type MetricDescriptor struct { // failed. Labels []*LabelDescriptor `json:"labels,omitempty"` + // Metadata: Optional. Metadata which can be used to guide usage of the + // metric. + Metadata *MetricDescriptorMetadata `json:"metadata,omitempty"` + // MetricKind: Whether the metric records instantaneous values, changes // to a value, etc. Some combinations of metric_kind and value_type // might not be supported. @@ -2314,22 +2390,69 @@ type MetricDescriptor struct { Name string `json:"name,omitempty"` // Type: The metric type, including its DNS name prefix. The type is not - // URL-encoded. All user-defined custom metric types have the DNS name - // custom.googleapis.com. Metric types should use a natural hierarchical - // grouping. For + // URL-encoded. All user-defined metric types have the DNS name + // custom.googleapis.com or external.googleapis.com. Metric types should + // use a natural hierarchical grouping. For // example: // "custom.googleapis.com/invoice/paid/amount" - // "appengine.google - // apis.com/http/server/response_latencies" + // "external.googlea + // pis.com/prometheus/up" + // "appengine.googleapis.com/http/server/response_ + // latencies" // Type string `json:"type,omitempty"` - // Unit: Optional. The unit in which the metric value is reported. For - // example, kBy/s means kilobytes/sec, and 1 is the dimensionless unit. - // The supported units are a subset of The Unified Code for Units of - // Measure standard (http://unitsofmeasure.org/ucum.html).

This - // field is part of the metric's documentation, but it is ignored by - // Stackdriver. + // Unit: The unit in which the metric value is reported. It is only + // applicable if the value_type is INT64, DOUBLE, or DISTRIBUTION. The + // supported units are a subset of The Unified Code for Units of Measure + // (http://unitsofmeasure.org/ucum.html) standard:Basic units (UNIT) + // bit bit + // By byte + // s second + // min minute + // h hour + // d dayPrefixes (PREFIX) + // k kilo (10**3) + // M mega (10**6) + // G giga (10**9) + // T tera (10**12) + // P peta (10**15) + // E exa (10**18) + // Z zetta (10**21) + // Y yotta (10**24) + // m milli (10**-3) + // u micro (10**-6) + // n nano (10**-9) + // p pico (10**-12) + // f femto (10**-15) + // a atto (10**-18) + // z zepto (10**-21) + // y yocto (10**-24) + // Ki kibi (2**10) + // Mi mebi (2**20) + // Gi gibi (2**30) + // Ti tebi (2**40)GrammarThe grammar also includes these connectors: + // / division (as an infix operator, e.g. 1/s). + // . multiplication (as an infix operator, e.g. GBy.d)The grammar for a + // unit is as follows: + // Expression = Component { "." Component } { "/" Component } + // ; + // + // Component = ( [ PREFIX ] UNIT | "%" ) [ Annotation ] + // | Annotation + // | "1" + // ; + // + // Annotation = "{" NAME "}" ; + // Notes: + // Annotation is just a comment if it follows a UNIT and is equivalent + // to 1 if it is used alone. For examples, {requests}/s == 1/s, + // By{transmitted}/s == By/s. + // NAME is a sequence of non-blank printable ASCII characters not + // containing '{' or '}'. + // 1 represents dimensionless value 1, such as in 1/s. + // % represents dimensionless value 1/100, and annotates values giving + // a percentage. Unit string `json:"unit,omitempty"` // ValueType: Whether the measurement is an integer, a floating-point @@ -2375,6 +2498,76 @@ func (s *MetricDescriptor) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +// MetricDescriptorMetadata: Additional annotations that can be used to +// guide the usage of a metric. +type MetricDescriptorMetadata struct { + // IngestDelay: The delay of data points caused by ingestion. Data + // points older than this age are guaranteed to be ingested and + // available to be read, excluding data loss due to errors. + IngestDelay string `json:"ingestDelay,omitempty"` + + // LaunchStage: The launch stage of the metric definition. + // + // Possible values: + // "LAUNCH_STAGE_UNSPECIFIED" - Do not use this default value. + // "EARLY_ACCESS" - Early Access features are limited to a closed + // group of testers. To use these features, you must sign up in advance + // and sign a Trusted Tester agreement (which includes confidentiality + // provisions). These features may be unstable, changed in + // backward-incompatible ways, and are not guaranteed to be released. + // "ALPHA" - Alpha is a limited availability test for releases before + // they are cleared for widespread use. By Alpha, all significant design + // issues are resolved and we are in the process of verifying + // functionality. Alpha customers need to apply for access, agree to + // applicable terms, and have their projects whitelisted. Alpha releases + // don’t have to be feature complete, no SLAs are provided, and there + // are no technical support obligations, but they will be far enough + // along that customers can actually use them in test environments or + // for limited-use tests -- just like they would in normal production + // cases. + // "BETA" - Beta is the point at which we are ready to open a release + // for any customer to use. There are no SLA or technical support + // obligations in a Beta release. Products will be complete from a + // feature perspective, but may have some open outstanding issues. Beta + // releases are suitable for limited production use cases. + // "GA" - GA features are open to all developers and are considered + // stable and fully qualified for production use. + // "DEPRECATED" - Deprecated features are scheduled to be shut down + // and removed. For more information, see the “Deprecation Policy” + // section of our Terms of Service (https://cloud.google.com/terms/) and + // the Google Cloud Platform Subject to the Deprecation Policy + // (https://cloud.google.com/terms/deprecation) documentation. + LaunchStage string `json:"launchStage,omitempty"` + + // SamplePeriod: The sampling period of metric data points. For metrics + // which are written periodically, consecutive data points are stored at + // this time interval, excluding data loss due to errors. Metrics with a + // higher granularity have a smaller sampling period. + SamplePeriod string `json:"samplePeriod,omitempty"` + + // ForceSendFields is a list of field names (e.g. "IngestDelay") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "IngestDelay") to include + // in API requests with the JSON null value. By default, fields with + // empty values are omitted from API requests. However, any field with + // an empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *MetricDescriptorMetadata) MarshalJSON() ([]byte, error) { + type NoMethod MetricDescriptorMetadata + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + // MetricThreshold: A condition type that compares a collection of time // series against a threshold. type MetricThreshold struct { @@ -2526,7 +2719,8 @@ type MonitoredResource struct { // Type: Required. The monitored resource type. This field must match // the type field of a MonitoredResourceDescriptor object. For example, - // the type of a Compute Engine VM instance is gce_instance. + // the type of a Compute Engine VM instance is gce_instance. For a list + // of types, see Monitoring resource types and Logging resource types. Type string `json:"type,omitempty"` // ForceSendFields is a list of field names (e.g. "Labels") to @@ -2621,17 +2815,15 @@ func (s *MonitoredResourceDescriptor) MarshalJSON() ([]byte, error) { // MonitoredResourceMetadata: Auxiliary metadata for a MonitoredResource // object. MonitoredResource objects contain the minimum set of // information to uniquely identify a monitored resource instance. There -// is some other useful auxiliary metadata. Google Stackdriver -// Monitoring & Logging uses an ingestion pipeline to extract metadata -// for cloud resources of all types , and stores the metadata in this -// message. +// is some other useful auxiliary metadata. Monitoring and Logging use +// an ingestion pipeline to extract metadata for cloud resources of all +// types, and store the metadata in this message. type MonitoredResourceMetadata struct { // SystemLabels: Output only. Values for predefined system metadata - // labels. System labels are a kind of metadata extracted by Google - // Stackdriver. Stackdriver determines what system labels are useful and - // how to obtain their values. Some examples: "machine_image", "vpc", - // "subnet_id", "security_group", "name", etc. System label values can - // be only strings, Boolean values, or a list of strings. For example: + // labels. System labels are a kind of metadata extracted by Google, + // including "machine_image", "vpc", "subnet_id", "security_group", + // "name", etc. System label values can be only strings, Boolean values, + // or a list of strings. For example: // { "name": "my-test-instance", // "security_group": ["a", "b", "c"], // "spot_instance": false } @@ -2840,13 +3032,13 @@ type NotificationChannelDescriptor struct { // service that provides basic features, a moderate allotment of logs, // and access to built-in metrics. A number of features are not // available in this tier. For more details, see the service tiers - // documentation (https://cloud.google.com/monitoring/accounts/tiers). + // documentation (https://cloud.google.com/monitoring/workspaces/tiers). // "SERVICE_TIER_PREMIUM" - The Stackdriver Premium tier, a higher, // more expensive tier of service that provides access to all // Stackdriver features, lets you use Stackdriver with AWS accounts, and // has a larger allotments for logs and metrics. For more details, see // the service tiers documentation - // (https://cloud.google.com/monitoring/accounts/tiers). + // (https://cloud.google.com/monitoring/workspaces/tiers). SupportedTiers []string `json:"supportedTiers,omitempty"` // Type: The type of notification channel, such as "email", "sms", etc. @@ -3081,6 +3273,44 @@ func (s *SourceContext) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +// SpanContext: The context of a span, attached to +// google.api.Distribution.Exemplars in google.api.Distribution values +// during aggregation.It contains the name of a span with format: +// projects/PROJECT_ID/traces/TRACE_ID/spans/SPAN_ID +type SpanContext struct { + // SpanName: The resource name of the span in the following + // format: + // projects/[PROJECT_ID]/traces/[TRACE_ID]/spans/[SPAN_ID] + // TRACE_ + // ID is a unique identifier for a trace within a project; it is a + // 32-character hexadecimal encoding of a 16-byte array.SPAN_ID is a + // unique identifier for a span within a trace; it is a 16-character + // hexadecimal encoding of an 8-byte array. + SpanName string `json:"spanName,omitempty"` + + // ForceSendFields is a list of field names (e.g. "SpanName") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "SpanName") to include in + // API requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *SpanContext) MarshalJSON() ([]byte, error) { + type NoMethod SpanContext + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + // Status: The Status type defines a logical error model that is // suitable for different programming environments, including REST APIs // and RPC APIs. It is used by gRPC (https://github.com/grpc). The error @@ -3188,8 +3418,12 @@ func (s *TcpCheck) MarshalJSON() ([]byte, error) { } // TimeInterval: A time interval extending just after a start time -// through an end time. If the start time is the same as the end time, -// then the interval represents a single point in time. +// through an end time. The start time must not be later than the end +// time. The default start time is the end time, making the startTime +// value technically optional. Whether this is useful depends on the +// MetricKind. If the start and end times are the same, the interval +// represents a point in time. This is appropriate for GAUGE metrics, +// but not for DELTA and CUMULATIVE metrics, which cover a span of time. type TimeInterval struct { // EndTime: Required. The end of the time interval. EndTime string `json:"endTime,omitempty"` @@ -3480,7 +3714,7 @@ type UptimeCheckConfig struct { // DisplayName: A human-friendly name for the uptime check // configuration. The display name should be unique within a Stackdriver - // Account in order to make it easier to identify; however, uniqueness + // Workspace in order to make it easier to identify; however, uniqueness // is not enforced. Required. DisplayName string `json:"displayName,omitempty"` @@ -3490,12 +3724,15 @@ type UptimeCheckConfig struct { // InternalCheckers: The internal checkers that this check will egress // from. If is_internal is true and this list is empty, the check will - // egress from all InternalCheckers configured for the project that owns - // this CheckConfig. + // egress from all the InternalCheckers configured for the project that + // owns this CheckConfig. InternalCheckers []*InternalChecker `json:"internalCheckers,omitempty"` - // IsInternal: Denotes whether this is a check that egresses from - // InternalCheckers. + // IsInternal: If this is true, then checks are made only from the + // 'internal_checkers'. If it is false, then checks are made only from + // the 'selected_regions'. It is an error to provide 'selected_regions' + // when is_internal is true, or to provide 'internal_checkers' when + // is_internal is false. IsInternal bool `json:"isInternal,omitempty"` // MonitoredResource: The monitored resource @@ -3522,7 +3759,8 @@ type UptimeCheckConfig struct { ResourceGroup *ResourceGroup `json:"resourceGroup,omitempty"` // SelectedRegions: The list of regions from which the check will be - // run. If this field is specified, enough regions to include a minimum + // run. Some regions contain one location, and others contain more than + // one. If this field is specified, enough regions to include a minimum // of 3 locations must be provided, or an error message is returned. Not // specifying this field will result in uptime checks running from all // regions. @@ -3722,9 +3960,13 @@ func (c *ProjectsAlertPoliciesCreateCall) doRequest(alt string) (*http.Response, } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v3/{+name}/alertPolicies") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "name": c.name, @@ -3851,9 +4093,13 @@ func (c *ProjectsAlertPoliciesDeleteCall) doRequest(alt string) (*http.Response, reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v3/{+name}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "name": c.name, @@ -3991,9 +4237,13 @@ func (c *ProjectsAlertPoliciesGetCall) doRequest(alt string) (*http.Response, er } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v3/{+name}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "name": c.name, @@ -4166,9 +4416,13 @@ func (c *ProjectsAlertPoliciesListCall) doRequest(alt string) (*http.Response, e } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v3/{+name}/alertPolicies") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "name": c.name, @@ -4369,9 +4623,13 @@ func (c *ProjectsAlertPoliciesPatchCall) doRequest(alt string) (*http.Response, } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v3/{+name}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PATCH", urls, body) + req, err := http.NewRequest("PATCH", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "name": c.name, @@ -4514,9 +4772,13 @@ func (c *ProjectsCollectdTimeSeriesCreateCall) doRequest(alt string) (*http.Resp } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v3/{+name}/collectdTimeSeries") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "name": c.name, @@ -4658,9 +4920,13 @@ func (c *ProjectsGroupsCreateCall) doRequest(alt string) (*http.Response, error) } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v3/{+name}/groups") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "name": c.name, @@ -4792,9 +5058,13 @@ func (c *ProjectsGroupsDeleteCall) doRequest(alt string) (*http.Response, error) reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v3/{+name}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "name": c.name, @@ -4932,9 +5202,13 @@ func (c *ProjectsGroupsGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v3/{+name}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "name": c.name, @@ -5119,9 +5393,13 @@ func (c *ProjectsGroupsListCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v3/{+name}/groups") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "name": c.name, @@ -5308,9 +5586,13 @@ func (c *ProjectsGroupsUpdateCall) doRequest(alt string) (*http.Response, error) } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v3/{+name}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PUT", urls, body) + req, err := http.NewRequest("PUT", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "name": c.name, @@ -5499,9 +5781,13 @@ func (c *ProjectsGroupsMembersListCall) doRequest(alt string) (*http.Response, e } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v3/{+name}/members") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "name": c.name, @@ -5683,9 +5969,13 @@ func (c *ProjectsMetricDescriptorsCreateCall) doRequest(alt string) (*http.Respo } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v3/{+name}/metricDescriptors") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "name": c.name, @@ -5814,9 +6104,13 @@ func (c *ProjectsMetricDescriptorsDeleteCall) doRequest(alt string) (*http.Respo reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v3/{+name}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "name": c.name, @@ -5955,9 +6249,13 @@ func (c *ProjectsMetricDescriptorsGetCall) doRequest(alt string) (*http.Response } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v3/{+name}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "name": c.name, @@ -6125,9 +6423,13 @@ func (c *ProjectsMetricDescriptorsListCall) doRequest(alt string) (*http.Respons } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v3/{+name}/metricDescriptors") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "name": c.name, @@ -6305,9 +6607,13 @@ func (c *ProjectsMonitoredResourceDescriptorsGetCall) doRequest(alt string) (*ht } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v3/{+name}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "name": c.name, @@ -6475,9 +6781,13 @@ func (c *ProjectsMonitoredResourceDescriptorsListCall) doRequest(alt string) (*h } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v3/{+name}/monitoredResourceDescriptors") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "name": c.name, @@ -6658,9 +6968,13 @@ func (c *ProjectsNotificationChannelDescriptorsGetCall) doRequest(alt string) (* } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v3/{+name}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "name": c.name, @@ -6817,9 +7131,13 @@ func (c *ProjectsNotificationChannelDescriptorsListCall) doRequest(alt string) ( } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v3/{+name}/notificationChannelDescriptors") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "name": c.name, @@ -6941,7 +7259,7 @@ type ProjectsNotificationChannelsCreateCall struct { // Create: Creates a new notification channel, representing a single // notification endpoint such as an email address, SMS number, or -// pagerduty service. +// PagerDuty service. func (r *ProjectsNotificationChannelsService) Create(name string, notificationchannel *NotificationChannel) *ProjectsNotificationChannelsCreateCall { c := &ProjectsNotificationChannelsCreateCall{s: r.s, urlParams_: make(gensupport.URLParams)} c.name = name @@ -6987,9 +7305,13 @@ func (c *ProjectsNotificationChannelsCreateCall) doRequest(alt string) (*http.Re } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v3/{+name}/notificationChannels") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "name": c.name, @@ -7035,7 +7357,7 @@ func (c *ProjectsNotificationChannelsCreateCall) Do(opts ...googleapi.CallOption } return ret, nil // { - // "description": "Creates a new notification channel, representing a single notification endpoint such as an email address, SMS number, or pagerduty service.", + // "description": "Creates a new notification channel, representing a single notification endpoint such as an email address, SMS number, or PagerDuty service.", // "flatPath": "v3/projects/{projectsId}/notificationChannels", // "httpMethod": "POST", // "id": "monitoring.projects.notificationChannels.create", @@ -7126,9 +7448,13 @@ func (c *ProjectsNotificationChannelsDeleteCall) doRequest(alt string) (*http.Re reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v3/{+name}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "name": c.name, @@ -7276,9 +7602,13 @@ func (c *ProjectsNotificationChannelsGetCall) doRequest(alt string) (*http.Respo } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v3/{+name}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "name": c.name, @@ -7430,9 +7760,13 @@ func (c *ProjectsNotificationChannelsGetVerificationCodeCall) doRequest(alt stri } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v3/{+name}:getVerificationCode") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "name": c.name, @@ -7611,9 +7945,13 @@ func (c *ProjectsNotificationChannelsListCall) doRequest(alt string) (*http.Resp } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v3/{+name}/notificationChannels") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "name": c.name, @@ -7795,9 +8133,13 @@ func (c *ProjectsNotificationChannelsPatchCall) doRequest(alt string) (*http.Res } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v3/{+name}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PATCH", urls, body) + req, err := http.NewRequest("PATCH", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "name": c.name, @@ -7939,9 +8281,13 @@ func (c *ProjectsNotificationChannelsSendVerificationCodeCall) doRequest(alt str } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v3/{+name}:sendVerificationCode") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "name": c.name, @@ -8077,9 +8423,13 @@ func (c *ProjectsNotificationChannelsVerifyCall) doRequest(alt string) (*http.Re } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v3/{+name}:verify") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "name": c.name, @@ -8216,9 +8566,13 @@ func (c *ProjectsTimeSeriesCreateCall) doRequest(alt string) (*http.Response, er } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v3/{+name}/timeSeries") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "name": c.name, @@ -8527,9 +8881,13 @@ func (c *ProjectsTimeSeriesListCall) doRequest(alt string) (*http.Response, erro } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v3/{+name}/timeSeries") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "name": c.name, @@ -8783,9 +9141,13 @@ func (c *ProjectsUptimeCheckConfigsCreateCall) doRequest(alt string) (*http.Resp } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v3/{+parent}/uptimeCheckConfigs") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "parent": c.parent, @@ -8915,9 +9277,13 @@ func (c *ProjectsUptimeCheckConfigsDeleteCall) doRequest(alt string) (*http.Resp reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v3/{+name}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "name": c.name, @@ -9055,9 +9421,13 @@ func (c *ProjectsUptimeCheckConfigsGetCall) doRequest(alt string) (*http.Respons } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v3/{+name}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "name": c.name, @@ -9216,9 +9586,13 @@ func (c *ProjectsUptimeCheckConfigsListCall) doRequest(alt string) (*http.Respon } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v3/{+parent}/uptimeCheckConfigs") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "parent": c.parent, @@ -9395,9 +9769,13 @@ func (c *ProjectsUptimeCheckConfigsPatchCall) doRequest(alt string) (*http.Respo } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v3/{+name}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PATCH", urls, body) + req, err := http.NewRequest("PATCH", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "name": c.name, @@ -9562,9 +9940,13 @@ func (c *UptimeCheckIpsListCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v3/uptimeCheckIps") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders return gensupport.SendRequest(c.ctx_, c.s.client, req) } diff --git a/vendor/google.golang.org/api/pubsub/v1/BUILD b/vendor/google.golang.org/api/pubsub/v1/BUILD index a02f93d5f77..b499669eb9b 100644 --- a/vendor/google.golang.org/api/pubsub/v1/BUILD +++ b/vendor/google.golang.org/api/pubsub/v1/BUILD @@ -7,8 +7,6 @@ go_library( importpath = "google.golang.org/api/pubsub/v1", visibility = ["//visibility:public"], deps = [ - "//vendor/golang.org/x/net/context:go_default_library", - "//vendor/golang.org/x/net/context/ctxhttp:go_default_library", "//vendor/google.golang.org/api/gensupport:go_default_library", "//vendor/google.golang.org/api/googleapi:go_default_library", ], diff --git a/vendor/google.golang.org/api/pubsub/v1/pubsub-api.json b/vendor/google.golang.org/api/pubsub/v1/pubsub-api.json index 2a2e03dedc6..b341ffba514 100644 --- a/vendor/google.golang.org/api/pubsub/v1/pubsub-api.json +++ b/vendor/google.golang.org/api/pubsub/v1/pubsub-api.json @@ -111,7 +111,7 @@ "snapshots": { "methods": { "create": { - "description": "Creates a snapshot from the requested subscription.\u003cbr\u003e\u003cbr\u003e\n\u003cb\u003eALPHA:\u003c/b\u003e This feature is part of an alpha release. This API might be\nchanged in backward-incompatible ways and is not recommended for production\nuse. It is not subject to any SLA or deprecation policy.\nIf the snapshot already exists, returns `ALREADY_EXISTS`.\nIf the requested subscription doesn't exist, returns `NOT_FOUND`.\nIf the backlog in the subscription is too old -- and the resulting snapshot\nwould expire in less than 1 hour -- then `FAILED_PRECONDITION` is returned.\nSee also the `Snapshot.expire_time` field. If the name is not provided in\nthe request, the server will assign a random\nname for this snapshot on the same project as the subscription, conforming\nto the [resource name format](https://cloud.google.com/pubsub/docs/overview#names).\nThe generated\nname is populated in the returned Snapshot object. Note that for REST API\nrequests, you must specify a name in the request.", + "description": "Creates a snapshot from the requested subscription. Snapshots are used in\n\u003ca href=\"https://cloud.google.com/pubsub/docs/replay-overview\"\u003eSeek\u003c/a\u003e\noperations, which allow\nyou to manage message acknowledgments in bulk. That is, you can set the\nacknowledgment state of messages in an existing subscription to the state\ncaptured by a snapshot.\n\u003cbr\u003e\u003cbr\u003e\n\u003cb\u003eBETA:\u003c/b\u003e This feature is part of a beta release. This API might be\nchanged in backward-incompatible ways and is not recommended for production\nuse. It is not subject to any SLA or deprecation policy.\u003cbr\u003e\u003cbr\u003e\nIf the snapshot already exists, returns `ALREADY_EXISTS`.\nIf the requested subscription doesn't exist, returns `NOT_FOUND`.\nIf the backlog in the subscription is too old -- and the resulting snapshot\nwould expire in less than 1 hour -- then `FAILED_PRECONDITION` is returned.\nSee also the `Snapshot.expire_time` field. If the name is not provided in\nthe request, the server will assign a random\nname for this snapshot on the same project as the subscription, conforming\nto the\n[resource name format](https://cloud.google.com/pubsub/docs/overview#names).\nThe generated name is populated in the returned Snapshot object. Note that\nfor REST API requests, you must specify a name in the request.", "flatPath": "v1/projects/{projectsId}/snapshots/{snapshotsId}", "httpMethod": "PUT", "id": "pubsub.projects.snapshots.create", @@ -120,7 +120,7 @@ ], "parameters": { "name": { - "description": "Optional user-provided name for this snapshot.\nIf the name is not provided in the request, the server will assign a random\nname for this snapshot on the same project as the subscription.\nNote that for REST API requests, you must specify a name.\nFormat is `projects/{project}/snapshots/{snap}`.", + "description": "Optional user-provided name for this snapshot.\nIf the name is not provided in the request, the server will assign a random\nname for this snapshot on the same project as the subscription.\nNote that for REST API requests, you must specify a name. See the\n\u003ca href=\"https://cloud.google.com/pubsub/docs/admin#resource_names\"\u003e\nresource name rules\u003c/a\u003e.\nFormat is `projects/{project}/snapshots/{snap}`.", "location": "path", "pattern": "^projects/[^/]+/snapshots/[^/]+$", "required": true, @@ -140,7 +140,7 @@ ] }, "delete": { - "description": "Removes an existing snapshot. \u003cbr\u003e\u003cbr\u003e\n\u003cb\u003eALPHA:\u003c/b\u003e This feature is part of an alpha release. This API might be\nchanged in backward-incompatible ways and is not recommended for production\nuse. It is not subject to any SLA or deprecation policy.\nWhen the snapshot is deleted, all messages retained in the snapshot\nare immediately dropped. After a snapshot is deleted, a new one may be\ncreated with the same name, but the new one has no association with the old\nsnapshot or its subscription, unless the same subscription is specified.", + "description": "Removes an existing snapshot. Snapshots are used in\n\u003ca href=\"https://cloud.google.com/pubsub/docs/replay-overview\"\u003eSeek\u003c/a\u003e\noperations, which allow\nyou to manage message acknowledgments in bulk. That is, you can set the\nacknowledgment state of messages in an existing subscription to the state\ncaptured by a snapshot.\u003cbr\u003e\u003cbr\u003e\n\u003cb\u003eBETA:\u003c/b\u003e This feature is part of a beta release. This API might be\nchanged in backward-incompatible ways and is not recommended for production\nuse. It is not subject to any SLA or deprecation policy.\nWhen the snapshot is deleted, all messages retained in the snapshot\nare immediately dropped. After a snapshot is deleted, a new one may be\ncreated with the same name, but the new one has no association with the old\nsnapshot or its subscription, unless the same subscription is specified.", "flatPath": "v1/projects/{projectsId}/snapshots/{snapshotsId}", "httpMethod": "DELETE", "id": "pubsub.projects.snapshots.delete", @@ -166,7 +166,7 @@ ] }, "get": { - "description": "Gets the configuration details of a snapshot.\u003cbr\u003e\u003cbr\u003e\n\u003cb\u003eALPHA:\u003c/b\u003e This feature is part of an alpha release. This API might be\nchanged in backward-incompatible ways and is not recommended for production\nuse. It is not subject to any SLA or deprecation policy.", + "description": "Gets the configuration details of a snapshot. Snapshots are used in\n\u003ca href=\"https://cloud.google.com/pubsub/docs/replay-overview\"\u003eSeek\u003c/a\u003e\noperations, which allow you to manage message acknowledgments in bulk. That\nis, you can set the acknowledgment state of messages in an existing\nsubscription to the state captured by a snapshot.\u003cbr\u003e\u003cbr\u003e\n\u003cb\u003eBETA:\u003c/b\u003e This feature is part of a beta release. This API might be\nchanged in backward-incompatible ways and is not recommended for production\nuse. It is not subject to any SLA or deprecation policy.", "flatPath": "v1/projects/{projectsId}/snapshots/{snapshotsId}", "httpMethod": "GET", "id": "pubsub.projects.snapshots.get", @@ -218,7 +218,7 @@ ] }, "list": { - "description": "Lists the existing snapshots.\u003cbr\u003e\u003cbr\u003e\n\u003cb\u003eALPHA:\u003c/b\u003e This feature is part of an alpha release. This API might be\nchanged in backward-incompatible ways and is not recommended for production\nuse. It is not subject to any SLA or deprecation policy.", + "description": "Lists the existing snapshots. Snapshots are used in\n\u003ca href=\"https://cloud.google.com/pubsub/docs/replay-overview\"\u003eSeek\u003c/a\u003e\noperations, which allow\nyou to manage message acknowledgments in bulk. That is, you can set the\nacknowledgment state of messages in an existing subscription to the state\ncaptured by a snapshot.\u003cbr\u003e\u003cbr\u003e\n\u003cb\u003eBETA:\u003c/b\u003e This feature is part of a beta release. This API might be\nchanged in backward-incompatible ways and is not recommended for production\nuse. It is not subject to any SLA or deprecation policy.", "flatPath": "v1/projects/{projectsId}/snapshots", "httpMethod": "GET", "id": "pubsub.projects.snapshots.list", @@ -238,7 +238,7 @@ "type": "string" }, "project": { - "description": "The name of the cloud project that snapshots belong to.\nFormat is `projects/{project}`.", + "description": "The name of the project in which to list snapshots.\nFormat is `projects/{project-id}`.", "location": "path", "pattern": "^projects/[^/]+$", "required": true, @@ -255,7 +255,7 @@ ] }, "patch": { - "description": "Updates an existing snapshot.\u003cbr\u003e\u003cbr\u003e\n\u003cb\u003eALPHA:\u003c/b\u003e This feature is part of an alpha release. This API might be\nchanged in backward-incompatible ways and is not recommended for production\nuse. It is not subject to any SLA or deprecation policy.\nNote that certain properties of a snapshot are not modifiable.", + "description": "Updates an existing snapshot. Snapshots are used in\n\u003ca href=\"https://cloud.google.com/pubsub/docs/replay-overview\"\u003eSeek\u003c/a\u003e\noperations, which allow\nyou to manage message acknowledgments in bulk. That is, you can set the\nacknowledgment state of messages in an existing subscription to the state\ncaptured by a snapshot.\u003cbr\u003e\u003cbr\u003e\n\u003cb\u003eBETA:\u003c/b\u003e This feature is part of a beta release. This API might be\nchanged in backward-incompatible ways and is not recommended for production\nuse. It is not subject to any SLA or deprecation policy.\nNote that certain properties of a snapshot are not modifiable.", "flatPath": "v1/projects/{projectsId}/snapshots/{snapshotsId}", "httpMethod": "PATCH", "id": "pubsub.projects.snapshots.patch", @@ -375,7 +375,7 @@ ] }, "create": { - "description": "Creates a subscription to a given topic. See the\n\u003ca href=\"/pubsub/docs/admin#resource_names\"\u003e resource name rules\u003c/a\u003e.\nIf the subscription already exists, returns `ALREADY_EXISTS`.\nIf the corresponding topic doesn't exist, returns `NOT_FOUND`.\n\nIf the name is not provided in the request, the server will assign a random\nname for this subscription on the same project as the topic, conforming\nto the\n[resource name format](https://cloud.google.com/pubsub/docs/overview#names).\nThe generated name is populated in the returned Subscription object.\nNote that for REST API requests, you must specify a name in the request.", + "description": "Creates a subscription to a given topic. See the\n\u003ca href=\"https://cloud.google.com/pubsub/docs/admin#resource_names\"\u003e\nresource name rules\u003c/a\u003e.\nIf the subscription already exists, returns `ALREADY_EXISTS`.\nIf the corresponding topic doesn't exist, returns `NOT_FOUND`.\n\nIf the name is not provided in the request, the server will assign a random\nname for this subscription on the same project as the topic, conforming\nto the\n[resource name format](https://cloud.google.com/pubsub/docs/overview#names).\nThe generated name is populated in the returned Subscription object.\nNote that for REST API requests, you must specify a name in the request.", "flatPath": "v1/projects/{projectsId}/subscriptions/{subscriptionsId}", "httpMethod": "PUT", "id": "pubsub.projects.subscriptions.create", @@ -502,7 +502,7 @@ "type": "string" }, "project": { - "description": "The name of the cloud project that subscriptions belong to.\nFormat is `projects/{project}`.", + "description": "The name of the project in which to list subscriptions.\nFormat is `projects/{project-id}`.", "location": "path", "pattern": "^projects/[^/]+$", "required": true, @@ -606,7 +606,7 @@ ] }, "pull": { - "description": "Pulls messages from the server. Returns an empty list if there are no\nmessages available in the backlog. The server may return `UNAVAILABLE` if\nthere are too many concurrent pull requests pending for the given\nsubscription.", + "description": "Pulls messages from the server. The server may return `UNAVAILABLE` if\nthere are too many concurrent pull requests pending for the given\nsubscription.", "flatPath": "v1/projects/{projectsId}/subscriptions/{subscriptionsId}:pull", "httpMethod": "POST", "id": "pubsub.projects.subscriptions.pull", @@ -635,7 +635,7 @@ ] }, "seek": { - "description": "Seeks an existing subscription to a point in time or to a given snapshot,\nwhichever is provided in the request.\u003cbr\u003e\u003cbr\u003e\n\u003cb\u003eALPHA:\u003c/b\u003e This feature is part of an alpha release. This API might be\nchanged in backward-incompatible ways and is not recommended for production\nuse. It is not subject to any SLA or deprecation policy.", + "description": "Seeks an existing subscription to a point in time or to a given snapshot,\nwhichever is provided in the request. Snapshots are used in\n\u003ca href=\"https://cloud.google.com/pubsub/docs/replay-overview\"\u003eSeek\u003c/a\u003e\noperations, which allow\nyou to manage message acknowledgments in bulk. That is, you can set the\nacknowledgment state of messages in an existing subscription to the state\ncaptured by a snapshot. Note that both the subscription and the snapshot\nmust be on the same topic.\u003cbr\u003e\u003cbr\u003e\n\u003cb\u003eBETA:\u003c/b\u003e This feature is part of a beta release. This API might be\nchanged in backward-incompatible ways and is not recommended for production\nuse. It is not subject to any SLA or deprecation policy.", "flatPath": "v1/projects/{projectsId}/subscriptions/{subscriptionsId}:seek", "httpMethod": "POST", "id": "pubsub.projects.subscriptions.seek", @@ -726,7 +726,7 @@ "topics": { "methods": { "create": { - "description": "Creates the given topic with the given name. See the\n\u003ca href=\"/pubsub/docs/admin#resource_names\"\u003e resource name rules\u003c/a\u003e.", + "description": "Creates the given topic with the given name. See the\n\u003ca href=\"https://cloud.google.com/pubsub/docs/admin#resource_names\"\u003e\nresource name rules\u003c/a\u003e.", "flatPath": "v1/projects/{projectsId}/topics/{topicsId}", "httpMethod": "PUT", "id": "pubsub.projects.topics.create", @@ -853,7 +853,7 @@ "type": "string" }, "project": { - "description": "The name of the cloud project that topics belong to.\nFormat is `projects/{project}`.", + "description": "The name of the project in which to list topics.\nFormat is `projects/{project-id}`.", "location": "path", "pattern": "^projects/[^/]+$", "required": true, @@ -869,8 +869,37 @@ "https://www.googleapis.com/auth/pubsub" ] }, + "patch": { + "description": "Updates an existing topic. Note that certain properties of a\ntopic are not modifiable.", + "flatPath": "v1/projects/{projectsId}/topics/{topicsId}", + "httpMethod": "PATCH", + "id": "pubsub.projects.topics.patch", + "parameterOrder": [ + "name" + ], + "parameters": { + "name": { + "description": "The name of the topic. It must have the format\n`\"projects/{project}/topics/{topic}\"`. `{topic}` must start with a letter,\nand contain only letters (`[A-Za-z]`), numbers (`[0-9]`), dashes (`-`),\nunderscores (`_`), periods (`.`), tildes (`~`), plus (`+`) or percent\nsigns (`%`). It must be between 3 and 255 characters in length, and it\nmust not start with `\"goog\"`.", + "location": "path", + "pattern": "^projects/[^/]+/topics/[^/]+$", + "required": true, + "type": "string" + } + }, + "path": "v1/{+name}", + "request": { + "$ref": "UpdateTopicRequest" + }, + "response": { + "$ref": "Topic" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/pubsub" + ] + }, "publish": { - "description": "Adds one or more messages to the topic. Returns `NOT_FOUND` if the topic\ndoes not exist. The message payload must not be empty; it must contain\n either a non-empty data field, or at least one attribute.", + "description": "Adds one or more messages to the topic. Returns `NOT_FOUND` if the topic\ndoes not exist.", "flatPath": "v1/projects/{projectsId}/topics/{topicsId}:publish", "httpMethod": "POST", "id": "pubsub.projects.topics.publish", @@ -961,7 +990,7 @@ "snapshots": { "methods": { "list": { - "description": "Lists the names of the snapshots on this topic.\u003cbr\u003e\u003cbr\u003e\n\u003cb\u003eALPHA:\u003c/b\u003e This feature is part of an alpha release. This API might be\nchanged in backward-incompatible ways and is not recommended for production\nuse. It is not subject to any SLA or deprecation policy.", + "description": "Lists the names of the snapshots on this topic. Snapshots are used in\n\u003ca href=\"https://cloud.google.com/pubsub/docs/replay-overview\"\u003eSeek\u003c/a\u003e\noperations, which allow\nyou to manage message acknowledgments in bulk. That is, you can set the\nacknowledgment state of messages in an existing subscription to the state\ncaptured by a snapshot.\u003cbr\u003e\u003cbr\u003e\n\u003cb\u003eBETA:\u003c/b\u003e This feature is part of a beta release. This API might be\nchanged in backward-incompatible ways and is not recommended for production\nuse. It is not subject to any SLA or deprecation policy.", "flatPath": "v1/projects/{projectsId}/topics/{topicsId}/snapshots", "httpMethod": "GET", "id": "pubsub.projects.topics.snapshots.list", @@ -1045,7 +1074,7 @@ } } }, - "revision": "20180604", + "revision": "20181213", "rootUrl": "https://pubsub.googleapis.com/", "schemas": { "AcknowledgeRequest": { @@ -1066,6 +1095,10 @@ "description": "Associates `members` with a `role`.", "id": "Binding", "properties": { + "condition": { + "$ref": "Expr", + "description": "Unimplemented. The condition that is associated with this binding.\nNOTE: an unsatisfied condition will not allow user access via current\nbinding. Different bindings, including their conditions, are examined\nindependently." + }, "members": { "description": "Specifies the identities requesting access for a Cloud Platform resource.\n`members` can have the following values:\n\n* `allUsers`: A special identifier that represents anyone who is\n on the internet; with or without a Google account.\n\n* `allAuthenticatedUsers`: A special identifier that represents anyone\n who is authenticated with a Google account or a service account.\n\n* `user:{emailid}`: An email address that represents a specific Google\n account. For example, `alice@gmail.com` .\n\n\n* `serviceAccount:{emailid}`: An email address that represents a service\n account. For example, `my-other-app@appspot.gserviceaccount.com`.\n\n* `group:{emailid}`: An email address that represents a Google group.\n For example, `admins@example.com`.\n\n\n* `domain:{domain}`: A Google Apps domain name that represents all the\n users of that domain. For example, `google.com` or `example.com`.\n\n", "items": { @@ -1074,16 +1107,23 @@ "type": "array" }, "role": { - "description": "Role that is assigned to `members`.\nFor example, `roles/viewer`, `roles/editor`, or `roles/owner`.\nRequired", + "description": "Role that is assigned to `members`.\nFor example, `roles/viewer`, `roles/editor`, or `roles/owner`.", "type": "string" } }, "type": "object" }, "CreateSnapshotRequest": { - "description": "Request for the `CreateSnapshot` method.\u003cbr\u003e\u003cbr\u003e\n\u003cb\u003eALPHA:\u003c/b\u003e This feature is part of an alpha release. This API might be changed in\nbackward-incompatible ways and is not recommended for production use.\nIt is not subject to any SLA or deprecation policy.", + "description": "Request for the `CreateSnapshot` method.\u003cbr\u003e\u003cbr\u003e\n\u003cb\u003eBETA:\u003c/b\u003e This feature is part of a beta release. This API might be changed in\nbackward-incompatible ways and is not recommended for production use.\nIt is not subject to any SLA or deprecation policy.", "id": "CreateSnapshotRequest", "properties": { + "labels": { + "additionalProperties": { + "type": "string" + }, + "description": "See \u003ca href=\"https://cloud.google.com/pubsub/docs/labels\"\u003e Creating and\nmanaging labels\u003c/a\u003e.", + "type": "object" + }, "subscription": { "description": "The subscription whose backlog the snapshot retains.\nSpecifically, the created snapshot is guaranteed to retain:\n (a) The existing backlog on the subscription. More precisely, this is\n defined as the messages in the subscription's backlog that are\n unacknowledged upon the successful completion of the\n `CreateSnapshot` request; as well as:\n (b) Any messages published to the subscription's topic following the\n successful completion of the CreateSnapshot request.\nFormat is `projects/{project}/subscriptions/{sub}`.", "type": "string" @@ -1097,8 +1137,43 @@ "properties": {}, "type": "object" }, + "ExpirationPolicy": { + "description": "A policy that specifies the conditions for resource expiration (i.e.,\nautomatic resource deletion).", + "id": "ExpirationPolicy", + "properties": { + "ttl": { + "description": "Specifies the \"time-to-live\" duration for an associated resource. The\nresource expires if it is not active for a period of `ttl`. The definition\nof \"activity\" depends on the type of the associated resource. The minimum\nand maximum allowed values for `ttl` depend on the type of the associated\nresource, as well. If `ttl` is not set, the associated resource never\nexpires.", + "format": "google-duration", + "type": "string" + } + }, + "type": "object" + }, + "Expr": { + "description": "Represents an expression text. Example:\n\n title: \"User account presence\"\n description: \"Determines whether the request has a user account\"\n expression: \"size(request.user) \u003e 0\"", + "id": "Expr", + "properties": { + "description": { + "description": "An optional description of the expression. This is a longer text which\ndescribes the expression, e.g. when hovered over it in a UI.", + "type": "string" + }, + "expression": { + "description": "Textual representation of an expression in\nCommon Expression Language syntax.\n\nThe application context of the containing message determines which\nwell-known feature set of CEL is supported.", + "type": "string" + }, + "location": { + "description": "An optional string indicating the location of the expression for error\nreporting, e.g. a file name and a position in the file.", + "type": "string" + }, + "title": { + "description": "An optional title for the expression, i.e. a short string describing\nits purpose. This can be used e.g. in UIs which allow to enter the\nexpression.", + "type": "string" + } + }, + "type": "object" + }, "ListSnapshotsResponse": { - "description": "Response for the `ListSnapshots` method.\u003cbr\u003e\u003cbr\u003e\n\u003cb\u003eALPHA:\u003c/b\u003e This feature is part of an alpha release. This API might be\nchanged in backward-incompatible ways and is not recommended for production\nuse. It is not subject to any SLA or deprecation policy.", + "description": "Response for the `ListSnapshots` method.\u003cbr\u003e\u003cbr\u003e\n\u003cb\u003eBETA:\u003c/b\u003e This feature is part of a beta release. This API might be\nchanged in backward-incompatible ways and is not recommended for production\nuse. It is not subject to any SLA or deprecation policy.", "id": "ListSnapshotsResponse", "properties": { "nextPageToken": { @@ -1134,7 +1209,7 @@ "type": "object" }, "ListTopicSnapshotsResponse": { - "description": "Response for the `ListTopicSnapshots` method.\u003cbr\u003e\u003cbr\u003e\n\u003cb\u003eALPHA:\u003c/b\u003e This feature is part of an alpha release. This API might be\nchanged in backward-incompatible ways and is not recommended for production\nuse. It is not subject to any SLA or deprecation policy.", + "description": "Response for the `ListTopicSnapshots` method.\u003cbr\u003e\u003cbr\u003e\n\u003cb\u003eBETA:\u003c/b\u003e This feature is part of a beta release. This API might be\nchanged in backward-incompatible ways and is not recommended for production\nuse. It is not subject to any SLA or deprecation policy.", "id": "ListTopicSnapshotsResponse", "properties": { "nextPageToken": { @@ -1192,7 +1267,7 @@ "id": "ModifyAckDeadlineRequest", "properties": { "ackDeadlineSeconds": { - "description": "The new ack deadline with respect to the time this request was sent to\nthe Pub/Sub system. For example, if the value is 10, the new\nack deadline will expire 10 seconds after the `ModifyAckDeadline` call\nwas made. Specifying zero may immediately make the message available for\nanother pull request.\nThe minimum deadline you can specify is 0 seconds.\nThe maximum deadline you can specify is 600 seconds (10 minutes).", + "description": "The new ack deadline with respect to the time this request was sent to\nthe Pub/Sub system. For example, if the value is 10, the new\nack deadline will expire 10 seconds after the `ModifyAckDeadline` call\nwas made. Specifying zero might immediately make the message available for\ndelivery to another subscriber client. This typically results in an\nincrease in the rate of message redeliveries (that is, duplicates).\nThe minimum deadline you can specify is 0 seconds.\nThe maximum deadline you can specify is 600 seconds (10 minutes).", "format": "int32", "type": "integer" }, @@ -1270,7 +1345,7 @@ "type": "object" }, "PubsubMessage": { - "description": "A message data and its attributes. The message payload must not be empty;\nit must contain either a non-empty data field, or at least one attribute.", + "description": "A message that is published by publishers and consumed by subscribers. The\nmessage must contain either a non-empty data field or at least one attribute.\nNote that client libraries represent this object differently\ndepending on the language. See the corresponding\n\u003ca href=\"https://cloud.google.com/pubsub/docs/reference/libraries\"\u003eclient\nlibrary documentation\u003c/a\u003e for more information. See\n\u003ca href=\"https://cloud.google.com/pubsub/quotas\"\u003eQuotas and limits\u003c/a\u003e\nfor more information about message limits.", "id": "PubsubMessage", "properties": { "attributes": { @@ -1281,7 +1356,7 @@ "type": "object" }, "data": { - "description": "The message payload.", + "description": "The message data field. If this field is empty, the message must contain\nat least one attribute.", "format": "byte", "type": "string" }, @@ -1307,7 +1382,7 @@ "type": "integer" }, "returnImmediately": { - "description": "If this field set to true, the system will respond immediately even if\nit there are no messages available to return in the `Pull` response.\nOtherwise, the system may wait (for a bounded amount of time) until at\nleast one message is available, rather than returning no messages. The\nclient may cancel the request if it does not wish to wait any longer for\nthe response.", + "description": "If this field set to true, the system will respond immediately even if\nit there are no messages available to return in the `Pull` response.\nOtherwise, the system may wait (for a bounded amount of time) until at\nleast one message is available, rather than returning no messages.", "type": "boolean" } }, @@ -1318,7 +1393,7 @@ "id": "PullResponse", "properties": { "receivedMessages": { - "description": "Received Pub/Sub messages. The Pub/Sub system will return zero messages if\nthere are no more available in the backlog. The Pub/Sub system may return\nfewer than the `maxMessages` requested even if there are more messages\navailable in the backlog.", + "description": "Received Pub/Sub messages. The list will be empty if there are no more\nmessages available in the backlog. For JSON, the response can be entirely\nempty. The Pub/Sub system may return fewer than the `maxMessages` requested\neven if there are more messages available in the backlog.", "items": { "$ref": "ReceivedMessage" }, @@ -1361,7 +1436,7 @@ "type": "object" }, "SeekRequest": { - "description": "Request for the `Seek` method.\u003cbr\u003e\u003cbr\u003e\n\u003cb\u003eALPHA:\u003c/b\u003e This feature is part of an alpha release. This API might be\nchanged in backward-incompatible ways and is not recommended for production\nuse. It is not subject to any SLA or deprecation policy.", + "description": "Request for the `Seek` method. \u003cbr\u003e\u003cbr\u003e\n\u003cb\u003eBETA:\u003c/b\u003e This feature is part of a beta release. This API might be\nchanged in backward-incompatible ways and is not recommended for production\nuse. It is not subject to any SLA or deprecation policy.", "id": "SeekRequest", "properties": { "snapshot": { @@ -1377,6 +1452,7 @@ "type": "object" }, "SeekResponse": { + "description": "Response for the `Seek` method (this response is empty).", "id": "SeekResponse", "properties": {}, "type": "object" @@ -1393,7 +1469,7 @@ "type": "object" }, "Snapshot": { - "description": "A snapshot resource.\u003cbr\u003e\u003cbr\u003e\n\u003cb\u003eALPHA:\u003c/b\u003e This feature is part of an alpha release. This API might be\nchanged in backward-incompatible ways and is not recommended for production\nuse. It is not subject to any SLA or deprecation policy.", + "description": "A snapshot resource. Snapshots are used in\n\u003ca href=\"https://cloud.google.com/pubsub/docs/replay-overview\"\u003eSeek\u003c/a\u003e\noperations, which allow\nyou to manage message acknowledgments in bulk. That is, you can set the\nacknowledgment state of messages in an existing subscription to the state\ncaptured by a snapshot.\u003cbr\u003e\u003cbr\u003e\n\u003cb\u003eBETA:\u003c/b\u003e This feature is part of a beta release. This API might be\nchanged in backward-incompatible ways and is not recommended for production\nuse. It is not subject to any SLA or deprecation policy.", "id": "Snapshot", "properties": { "expireTime": { @@ -1401,6 +1477,13 @@ "format": "google-datetime", "type": "string" }, + "labels": { + "additionalProperties": { + "type": "string" + }, + "description": "See \u003ca href=\"https://cloud.google.com/pubsub/docs/labels\"\u003e Creating and\nmanaging labels\u003c/a\u003e.", + "type": "object" + }, "name": { "description": "The name of the snapshot.", "type": "string" @@ -1417,12 +1500,23 @@ "id": "Subscription", "properties": { "ackDeadlineSeconds": { - "description": "This value is the maximum time after a subscriber receives a message\nbefore the subscriber should acknowledge the message. After message\ndelivery but before the ack deadline expires and before the message is\nacknowledged, it is an outstanding message and will not be delivered\nagain during that time (on a best-effort basis).\n\nFor pull subscriptions, this value is used as the initial value for the ack\ndeadline. To override this value for a given message, call\n`ModifyAckDeadline` with the corresponding `ack_id` if using\nnon-streaming pull or send the `ack_id` in a\n`StreamingModifyAckDeadlineRequest` if using streaming pull.\nThe minimum custom deadline you can specify is 10 seconds.\nThe maximum custom deadline you can specify is 600 seconds (10 minutes).\nIf this parameter is 0, a default value of 10 seconds is used.\n\nFor push delivery, this value is also used to set the request timeout for\nthe call to the push endpoint.\n\nIf the subscriber never acknowledges the message, the Pub/Sub\nsystem will eventually redeliver the message.", + "description": "The approximate amount of time (on a best-effort basis) Pub/Sub waits for\nthe subscriber to acknowledge receipt before resending the message. In the\ninterval after the message is delivered and before it is acknowledged, it\nis considered to be \u003ci\u003eoutstanding\u003c/i\u003e. During that time period, the\nmessage will not be redelivered (on a best-effort basis).\n\nFor pull subscriptions, this value is used as the initial value for the ack\ndeadline. To override this value for a given message, call\n`ModifyAckDeadline` with the corresponding `ack_id` if using\nnon-streaming pull or send the `ack_id` in a\n`StreamingModifyAckDeadlineRequest` if using streaming pull.\nThe minimum custom deadline you can specify is 10 seconds.\nThe maximum custom deadline you can specify is 600 seconds (10 minutes).\nIf this parameter is 0, a default value of 10 seconds is used.\n\nFor push delivery, this value is also used to set the request timeout for\nthe call to the push endpoint.\n\nIf the subscriber never acknowledges the message, the Pub/Sub\nsystem will eventually redeliver the message.", "format": "int32", "type": "integer" }, + "expirationPolicy": { + "$ref": "ExpirationPolicy", + "description": "A policy that specifies the conditions for this subscription's expiration.\nA subscription is considered active as long as any connected subscriber is\nsuccessfully consuming messages from the subscription or is issuing\noperations on the subscription. If `expiration_policy` is not set, a\n*default policy* with `ttl` of 31 days will be used. The minimum allowed\nvalue for `expiration_policy.ttl` is 1 day.\n\u003cb\u003eBETA:\u003c/b\u003e This feature is part of a beta release. This API might be\nchanged in backward-incompatible ways and is not recommended for production\nuse. It is not subject to any SLA or deprecation policy." + }, + "labels": { + "additionalProperties": { + "type": "string" + }, + "description": "See \u003ca href=\"https://cloud.google.com/pubsub/docs/labels\"\u003e Creating and\nmanaging labels\u003c/a\u003e.", + "type": "object" + }, "messageRetentionDuration": { - "description": "How long to retain unacknowledged messages in the subscription's backlog,\nfrom the moment a message is published.\nIf `retain_acked_messages` is true, then this also configures the retention\nof acknowledged messages, and thus configures how far back in time a `Seek`\ncan be done. Defaults to 7 days. Cannot be more than 7 days or less than 10\nminutes.\u003cbr\u003e\u003cbr\u003e\n\u003cb\u003eALPHA:\u003c/b\u003e This feature is part of an alpha release. This API might be\nchanged in backward-incompatible ways and is not recommended for production\nuse. It is not subject to any SLA or deprecation policy.", + "description": "How long to retain unacknowledged messages in the subscription's backlog,\nfrom the moment a message is published.\nIf `retain_acked_messages` is true, then this also configures the retention\nof acknowledged messages, and thus configures how far back in time a `Seek`\ncan be done. Defaults to 7 days. Cannot be more than 7 days or less than 10\nminutes.\u003cbr\u003e\u003cbr\u003e\n\u003cb\u003eBETA:\u003c/b\u003e This feature is part of a beta release. This API might be\nchanged in backward-incompatible ways and is not recommended for production\nuse. It is not subject to any SLA or deprecation policy.", "format": "google-duration", "type": "string" }, @@ -1435,7 +1529,7 @@ "description": "If push delivery is used with this subscription, this field is\nused to configure it. An empty `pushConfig` signifies that the subscriber\nwill pull and ack messages using API methods." }, "retainAckedMessages": { - "description": "Indicates whether to retain acknowledged messages. If true, then\nmessages are not expunged from the subscription's backlog, even if they are\nacknowledged, until they fall out of the `message_retention_duration`\nwindow.\u003cbr\u003e\u003cbr\u003e\n\u003cb\u003eALPHA:\u003c/b\u003e This feature is part of an alpha release. This API might be\nchanged in backward-incompatible ways and is not recommended for production\nuse. It is not subject to any SLA or deprecation policy.", + "description": "Indicates whether to retain acknowledged messages. If true, then\nmessages are not expunged from the subscription's backlog, even if they are\nacknowledged, until they fall out of the `message_retention_duration`\nwindow. This must be true if you would like to\n\u003ca href=\"https://cloud.google.com/pubsub/docs/replay-overview#seek_to_a_time\"\u003e\nSeek to a timestamp\u003c/a\u003e.\n\u003cbr\u003e\u003cbr\u003e\n\u003cb\u003eBETA:\u003c/b\u003e This feature is part of a beta release. This API might be\nchanged in backward-incompatible ways and is not recommended for production\nuse. It is not subject to any SLA or deprecation policy.", "type": "boolean" }, "topic": { @@ -1477,6 +1571,13 @@ "description": "A topic resource.", "id": "Topic", "properties": { + "labels": { + "additionalProperties": { + "type": "string" + }, + "description": "See \u003ca href=\"https://cloud.google.com/pubsub/docs/labels\"\u003e Creating and\nmanaging labels\u003c/a\u003e.", + "type": "object" + }, "name": { "description": "The name of the topic. It must have the format\n`\"projects/{project}/topics/{topic}\"`. `{topic}` must start with a letter,\nand contain only letters (`[A-Za-z]`), numbers (`[0-9]`), dashes (`-`),\nunderscores (`_`), periods (`.`), tildes (`~`), plus (`+`) or percent\nsigns (`%`). It must be between 3 and 255 characters in length, and it\nmust not start with `\"goog\"`.", "type": "string" @@ -1485,7 +1586,7 @@ "type": "object" }, "UpdateSnapshotRequest": { - "description": "Request for the UpdateSnapshot method.\u003cbr\u003e\u003cbr\u003e\n\u003cb\u003eALPHA:\u003c/b\u003e This feature is part of an alpha release. This API might be\nchanged in backward-incompatible ways and is not recommended for production\nuse. It is not subject to any SLA or deprecation policy.", + "description": "Request for the UpdateSnapshot method.\u003cbr\u003e\u003cbr\u003e\n\u003cb\u003eBETA:\u003c/b\u003e This feature is part of a beta release. This API might be\nchanged in backward-incompatible ways and is not recommended for production\nuse. It is not subject to any SLA or deprecation policy.", "id": "UpdateSnapshotRequest", "properties": { "snapshot": { @@ -1515,6 +1616,22 @@ } }, "type": "object" + }, + "UpdateTopicRequest": { + "description": "Request for the UpdateTopic method.", + "id": "UpdateTopicRequest", + "properties": { + "topic": { + "$ref": "Topic", + "description": "The updated topic object." + }, + "updateMask": { + "description": "Indicates which fields in the provided topic to update. Must be specified\nand non-empty. Note that if `update_mask` contains\n\"message_storage_policy\" then the new value will be determined based on the\npolicy configured at the project or organization level. The\n`message_storage_policy` must not be set in the `topic` provided above.", + "format": "google-fieldmask", + "type": "string" + } + }, + "type": "object" } }, "servicePath": "", diff --git a/vendor/google.golang.org/api/pubsub/v1/pubsub-gen.go b/vendor/google.golang.org/api/pubsub/v1/pubsub-gen.go index d44985ffeeb..114ada3f42c 100644 --- a/vendor/google.golang.org/api/pubsub/v1/pubsub-gen.go +++ b/vendor/google.golang.org/api/pubsub/v1/pubsub-gen.go @@ -1,5 +1,13 @@ +// Copyright 2018 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Code generated file. DO NOT EDIT. + // Package pubsub provides access to the Cloud Pub/Sub API. // +// This package is DEPRECATED. Use package cloud.google.com/go/pubsub instead. +// // See https://cloud.google.com/pubsub/docs // // Usage example: @@ -11,18 +19,18 @@ package pubsub import ( "bytes" + "context" "encoding/json" "errors" "fmt" - context "golang.org/x/net/context" - ctxhttp "golang.org/x/net/context/ctxhttp" - gensupport "google.golang.org/api/gensupport" - googleapi "google.golang.org/api/googleapi" "io" "net/http" "net/url" "strconv" "strings" + + gensupport "google.golang.org/api/gensupport" + googleapi "google.golang.org/api/googleapi" ) // Always reference these packages, just in case the auto-generated code @@ -38,7 +46,6 @@ var _ = googleapi.Version var _ = errors.New var _ = strings.Replace var _ = context.Canceled -var _ = ctxhttp.Do const apiId = "pubsub:v1" const apiName = "pubsub" @@ -179,6 +186,15 @@ func (s *AcknowledgeRequest) MarshalJSON() ([]byte, error) { // Binding: Associates `members` with a `role`. type Binding struct { + // Condition: Unimplemented. The condition that is associated with this + // binding. + // NOTE: an unsatisfied condition will not allow user access via + // current + // binding. Different bindings, including their conditions, are + // examined + // independently. + Condition *Expr `json:"condition,omitempty"` + // Members: Specifies the identities requesting access for a Cloud // Platform resource. // `members` can have the following values: @@ -215,12 +231,10 @@ type Binding struct { Members []string `json:"members,omitempty"` // Role: Role that is assigned to `members`. - // For example, `roles/viewer`, `roles/editor`, or - // `roles/owner`. - // Required + // For example, `roles/viewer`, `roles/editor`, or `roles/owner`. Role string `json:"role,omitempty"` - // ForceSendFields is a list of field names (e.g. "Members") to + // ForceSendFields is a list of field names (e.g. "Condition") to // unconditionally include in API requests. By default, fields with // empty values are omitted from API requests. However, any non-pointer, // non-interface field appearing in ForceSendFields will be sent to the @@ -228,7 +242,7 @@ type Binding struct { // used to include empty fields in Patch requests. ForceSendFields []string `json:"-"` - // NullFields is a list of field names (e.g. "Members") to include in + // NullFields is a list of field names (e.g. "Condition") to include in // API requests with the JSON null value. By default, fields with empty // values are omitted from API requests. However, any field with an // empty value appearing in NullFields will be sent to the server as @@ -245,12 +259,17 @@ func (s *Binding) MarshalJSON() ([]byte, error) { // CreateSnapshotRequest: Request for the `CreateSnapshot` // method.

-// ALPHA: This feature is part of an alpha release. This API -// might be changed in +// BETA: This feature is part of a beta release. This API might +// be changed in // backward-incompatible ways and is not recommended for production // use. // It is not subject to any SLA or deprecation policy. type CreateSnapshotRequest struct { + // Labels: See + // Creating and + // managing labels. + Labels map[string]string `json:"labels,omitempty"` + // Subscription: The subscription whose backlog the snapshot // retains. // Specifically, the created snapshot is guaranteed to retain: @@ -265,7 +284,7 @@ type CreateSnapshotRequest struct { // Format is `projects/{project}/subscriptions/{sub}`. Subscription string `json:"subscription,omitempty"` - // ForceSendFields is a list of field names (e.g. "Subscription") to + // ForceSendFields is a list of field names (e.g. "Labels") to // unconditionally include in API requests. By default, fields with // empty values are omitted from API requests. However, any non-pointer, // non-interface field appearing in ForceSendFields will be sent to the @@ -273,10 +292,10 @@ type CreateSnapshotRequest struct { // used to include empty fields in Patch requests. ForceSendFields []string `json:"-"` - // NullFields is a list of field names (e.g. "Subscription") to include - // in API requests with the JSON null value. By default, fields with - // empty values are omitted from API requests. However, any field with - // an empty value appearing in NullFields will be sent to the server as + // NullFields is a list of field names (e.g. "Labels") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as // null. It is an error if a field in this list has a non-empty value. // This may be used to include null fields in Patch requests. NullFields []string `json:"-"` @@ -306,10 +325,104 @@ type Empty struct { googleapi.ServerResponse `json:"-"` } +// ExpirationPolicy: A policy that specifies the conditions for resource +// expiration (i.e., +// automatic resource deletion). +type ExpirationPolicy struct { + // Ttl: Specifies the "time-to-live" duration for an associated + // resource. The + // resource expires if it is not active for a period of `ttl`. The + // definition + // of "activity" depends on the type of the associated resource. The + // minimum + // and maximum allowed values for `ttl` depend on the type of the + // associated + // resource, as well. If `ttl` is not set, the associated resource + // never + // expires. + Ttl string `json:"ttl,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Ttl") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Ttl") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *ExpirationPolicy) MarshalJSON() ([]byte, error) { + type NoMethod ExpirationPolicy + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// Expr: Represents an expression text. Example: +// +// title: "User account presence" +// description: "Determines whether the request has a user account" +// expression: "size(request.user) > 0" +type Expr struct { + // Description: An optional description of the expression. This is a + // longer text which + // describes the expression, e.g. when hovered over it in a UI. + Description string `json:"description,omitempty"` + + // Expression: Textual representation of an expression in + // Common Expression Language syntax. + // + // The application context of the containing message determines + // which + // well-known feature set of CEL is supported. + Expression string `json:"expression,omitempty"` + + // Location: An optional string indicating the location of the + // expression for error + // reporting, e.g. a file name and a position in the file. + Location string `json:"location,omitempty"` + + // Title: An optional title for the expression, i.e. a short string + // describing + // its purpose. This can be used e.g. in UIs which allow to enter + // the + // expression. + Title string `json:"title,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Description") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Description") to include + // in API requests with the JSON null value. By default, fields with + // empty values are omitted from API requests. However, any field with + // an empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *Expr) MarshalJSON() ([]byte, error) { + type NoMethod Expr + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + // ListSnapshotsResponse: Response for the `ListSnapshots` // method.

-// ALPHA: This feature is part of an alpha release. This API -// might be +// BETA: This feature is part of a beta release. This API might +// be // changed in backward-incompatible ways and is not recommended for // production // use. It is not subject to any SLA or deprecation policy. @@ -391,8 +504,8 @@ func (s *ListSubscriptionsResponse) MarshalJSON() ([]byte, error) { // ListTopicSnapshotsResponse: Response for the `ListTopicSnapshots` // method.

-// ALPHA: This feature is part of an alpha release. This API -// might be +// BETA: This feature is part of a beta release. This API might +// be // changed in backward-incompatible ways and is not recommended for // production // use. It is not subject to any SLA or deprecation policy. @@ -518,9 +631,12 @@ type ModifyAckDeadlineRequest struct { // the Pub/Sub system. For example, if the value is 10, the new // ack deadline will expire 10 seconds after the `ModifyAckDeadline` // call - // was made. Specifying zero may immediately make the message available - // for - // another pull request. + // was made. Specifying zero might immediately make the message + // available for + // delivery to another subscriber client. This typically results in + // an + // increase in the rate of message redeliveries (that is, + // duplicates). // The minimum deadline you can specify is 0 seconds. // The maximum deadline you can specify is 600 seconds (10 minutes). AckDeadlineSeconds int64 `json:"ackDeadlineSeconds,omitempty"` @@ -754,15 +870,27 @@ func (s *PublishResponse) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } -// PubsubMessage: A message data and its attributes. The message payload -// must not be empty; -// it must contain either a non-empty data field, or at least one +// PubsubMessage: A message that is published by publishers and consumed +// by subscribers. The +// message must contain either a non-empty data field or at least one // attribute. +// Note that client libraries represent this object +// differently +// depending on the language. See the corresponding +// client +// +// library documentation for more information. See +// Quotas and +// limits +// for more information about message limits. type PubsubMessage struct { // Attributes: Optional attributes for this message. Attributes map[string]string `json:"attributes,omitempty"` - // Data: The message payload. + // Data: The message data field. If this field is empty, the message + // must contain + // at least one attribute. Data string `json:"data,omitempty"` // MessageId: ID of this message, assigned by the server when the @@ -819,10 +947,6 @@ type PullRequest struct { // Otherwise, the system may wait (for a bounded amount of time) until // at // least one message is available, rather than returning no messages. - // The - // client may cancel the request if it does not wish to wait any longer - // for - // the response. ReturnImmediately bool `json:"returnImmediately,omitempty"` // ForceSendFields is a list of field names (e.g. "MaxMessages") to @@ -850,13 +974,13 @@ func (s *PullRequest) MarshalJSON() ([]byte, error) { // PullResponse: Response for the `Pull` method. type PullResponse struct { - // ReceivedMessages: Received Pub/Sub messages. The Pub/Sub system will - // return zero messages if - // there are no more available in the backlog. The Pub/Sub system may - // return - // fewer than the `maxMessages` requested even if there are more - // messages - // available in the backlog. + // ReceivedMessages: Received Pub/Sub messages. The list will be empty + // if there are no more + // messages available in the backlog. For JSON, the response can be + // entirely + // empty. The Pub/Sub system may return fewer than the `maxMessages` + // requested + // even if there are more messages available in the backlog. ReceivedMessages []*ReceivedMessage `json:"receivedMessages,omitempty"` // ServerResponse contains the HTTP response code and headers from the @@ -982,9 +1106,9 @@ func (s *ReceivedMessage) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } -// SeekRequest: Request for the `Seek` method.

-// ALPHA: This feature is part of an alpha release. This API -// might be +// SeekRequest: Request for the `Seek` method.

+// BETA: This feature is part of a beta release. This API might +// be // changed in backward-incompatible ways and is not recommended for // production // use. It is not subject to any SLA or deprecation policy. @@ -1039,6 +1163,8 @@ func (s *SeekRequest) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +// SeekResponse: Response for the `Seek` method (this response is +// empty). type SeekResponse struct { // ServerResponse contains the HTTP response code and headers from the // server. @@ -1078,9 +1204,18 @@ func (s *SetIamPolicyRequest) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } -// Snapshot: A snapshot resource.

-// ALPHA: This feature is part of an alpha release. This API -// might be +// Snapshot: A snapshot resource. Snapshots are used in +// Seek +// o +// perations, which allow +// you to manage message acknowledgments in bulk. That is, you can set +// the +// acknowledgment state of messages in an existing subscription to the +// state +// captured by a snapshot.

+// BETA: This feature is part of a beta release. This API might +// be // changed in backward-incompatible ways and is not recommended for // production // use. It is not subject to any SLA or deprecation policy. @@ -1105,6 +1240,11 @@ type Snapshot struct { // snapshot that would expire in less than 1 hour after creation. ExpireTime string `json:"expireTime,omitempty"` + // Labels: See + // Creating and + // managing labels. + Labels map[string]string `json:"labels,omitempty"` + // Name: The name of the snapshot. Name string `json:"name,omitempty"` @@ -1141,15 +1281,15 @@ func (s *Snapshot) MarshalJSON() ([]byte, error) { // Subscription: A subscription resource. type Subscription struct { - // AckDeadlineSeconds: This value is the maximum time after a subscriber - // receives a message - // before the subscriber should acknowledge the message. After - // message - // delivery but before the ack deadline expires and before the message - // is - // acknowledged, it is an outstanding message and will not be - // delivered - // again during that time (on a best-effort basis). + // AckDeadlineSeconds: The approximate amount of time (on a best-effort + // basis) Pub/Sub waits for + // the subscriber to acknowledge receipt before resending the message. + // In the + // interval after the message is delivered and before it is + // acknowledged, it + // is considered to be outstanding. During that time period, + // the + // message will not be redelivered (on a best-effort basis). // // For pull subscriptions, this value is used as the initial value for // the ack @@ -1173,6 +1313,29 @@ type Subscription struct { // system will eventually redeliver the message. AckDeadlineSeconds int64 `json:"ackDeadlineSeconds,omitempty"` + // ExpirationPolicy: A policy that specifies the conditions for this + // subscription's expiration. + // A subscription is considered active as long as any connected + // subscriber is + // successfully consuming messages from the subscription or is + // issuing + // operations on the subscription. If `expiration_policy` is not set, + // a + // *default policy* with `ttl` of 31 days will be used. The minimum + // allowed + // value for `expiration_policy.ttl` is 1 day. + // BETA: This feature is part of a beta release. This API might + // be + // changed in backward-incompatible ways and is not recommended for + // production + // use. It is not subject to any SLA or deprecation policy. + ExpirationPolicy *ExpirationPolicy `json:"expirationPolicy,omitempty"` + + // Labels: See + // Creating and + // managing labels. + Labels map[string]string `json:"labels,omitempty"` + // MessageRetentionDuration: How long to retain unacknowledged messages // in the subscription's backlog, // from the moment a message is published. @@ -1183,8 +1346,8 @@ type Subscription struct { // can be done. Defaults to 7 days. Cannot be more than 7 days or less // than 10 // minutes.

- // ALPHA: This feature is part of an alpha release. This API - // might be + // BETA: This feature is part of a beta release. This API might + // be // changed in backward-incompatible ways and is not recommended for // production // use. It is not subject to any SLA or deprecation policy. @@ -1216,9 +1379,14 @@ type Subscription struct { // they are // acknowledged, until they fall out of the // `message_retention_duration` - // window.

- // ALPHA: This feature is part of an alpha release. This API - // might be + // window. This must be true if you would like to + // + // Seek to a timestamp. + //

+ // BETA: This feature is part of a beta release. This API might + // be // changed in backward-incompatible ways and is not recommended for // production // use. It is not subject to any SLA or deprecation policy. @@ -1332,6 +1500,11 @@ func (s *TestIamPermissionsResponse) MarshalJSON() ([]byte, error) { // Topic: A topic resource. type Topic struct { + // Labels: See + // Creating and + // managing labels. + Labels map[string]string `json:"labels,omitempty"` + // Name: The name of the topic. It must have the // format // "projects/{project}/topics/{topic}". `{topic}` must start with a @@ -1349,7 +1522,7 @@ type Topic struct { // server. googleapi.ServerResponse `json:"-"` - // ForceSendFields is a list of field names (e.g. "Name") to + // ForceSendFields is a list of field names (e.g. "Labels") to // unconditionally include in API requests. By default, fields with // empty values are omitted from API requests. However, any non-pointer, // non-interface field appearing in ForceSendFields will be sent to the @@ -1357,7 +1530,7 @@ type Topic struct { // used to include empty fields in Patch requests. ForceSendFields []string `json:"-"` - // NullFields is a list of field names (e.g. "Name") to include in API + // NullFields is a list of field names (e.g. "Labels") to include in API // requests with the JSON null value. By default, fields with empty // values are omitted from API requests. However, any field with an // empty value appearing in NullFields will be sent to the server as @@ -1374,8 +1547,8 @@ func (s *Topic) MarshalJSON() ([]byte, error) { // UpdateSnapshotRequest: Request for the UpdateSnapshot // method.

-// ALPHA: This feature is part of an alpha release. This API -// might be +// BETA: This feature is part of a beta release. This API might +// be // changed in backward-incompatible ways and is not recommended for // production // use. It is not subject to any SLA or deprecation policy. @@ -1444,6 +1617,46 @@ func (s *UpdateSubscriptionRequest) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } +// UpdateTopicRequest: Request for the UpdateTopic method. +type UpdateTopicRequest struct { + // Topic: The updated topic object. + Topic *Topic `json:"topic,omitempty"` + + // UpdateMask: Indicates which fields in the provided topic to update. + // Must be specified + // and non-empty. Note that if `update_mask` + // contains + // "message_storage_policy" then the new value will be determined based + // on the + // policy configured at the project or organization level. + // The + // `message_storage_policy` must not be set in the `topic` provided + // above. + UpdateMask string `json:"updateMask,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Topic") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Topic") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *UpdateTopicRequest) MarshalJSON() ([]byte, error) { + type NoMethod UpdateTopicRequest + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + // method id "pubsub.projects.snapshots.create": type ProjectsSnapshotsCreateCall struct { @@ -1455,13 +1668,23 @@ type ProjectsSnapshotsCreateCall struct { header_ http.Header } -// Create: Creates a snapshot from the requested -// subscription.

-// ALPHA: This feature is part of an alpha release. This API -// might be +// Create: Creates a snapshot from the requested subscription. Snapshots +// are used in +// Seek +// o +// perations, which allow +// you to manage message acknowledgments in bulk. That is, you can set +// the +// acknowledgment state of messages in an existing subscription to the +// state +// captured by a snapshot. +//

+// BETA: This feature is part of a beta release. This API might +// be // changed in backward-incompatible ways and is not recommended for // production -// use. It is not subject to any SLA or deprecation policy. +// use. It is not subject to any SLA or deprecation policy.

// If the snapshot already exists, returns `ALREADY_EXISTS`. // If the requested subscription doesn't exist, returns `NOT_FOUND`. // If the backlog in the subscription is too old -- and the resulting @@ -1473,12 +1696,12 @@ type ProjectsSnapshotsCreateCall struct { // the request, the server will assign a random // name for this snapshot on the same project as the subscription, // conforming -// to the [resource name +// to the +// [resource name // format](https://cloud.google.com/pubsub/docs/overview#names). -// The generated -// name is populated in the returned Snapshot object. Note that for REST -// API -// requests, you must specify a name in the request. +// The generated name is populated in the returned Snapshot object. Note +// that +// for REST API requests, you must specify a name in the request. func (r *ProjectsSnapshotsService) Create(name string, createsnapshotrequest *CreateSnapshotRequest) *ProjectsSnapshotsCreateCall { c := &ProjectsSnapshotsCreateCall{s: r.s, urlParams_: make(gensupport.URLParams)} c.name = name @@ -1524,9 +1747,13 @@ func (c *ProjectsSnapshotsCreateCall) doRequest(alt string) (*http.Response, err } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PUT", urls, body) + req, err := http.NewRequest("PUT", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "name": c.name, @@ -1572,7 +1799,7 @@ func (c *ProjectsSnapshotsCreateCall) Do(opts ...googleapi.CallOption) (*Snapsho } return ret, nil // { - // "description": "Creates a snapshot from the requested subscription.\u003cbr\u003e\u003cbr\u003e\n\u003cb\u003eALPHA:\u003c/b\u003e This feature is part of an alpha release. This API might be\nchanged in backward-incompatible ways and is not recommended for production\nuse. It is not subject to any SLA or deprecation policy.\nIf the snapshot already exists, returns `ALREADY_EXISTS`.\nIf the requested subscription doesn't exist, returns `NOT_FOUND`.\nIf the backlog in the subscription is too old -- and the resulting snapshot\nwould expire in less than 1 hour -- then `FAILED_PRECONDITION` is returned.\nSee also the `Snapshot.expire_time` field. If the name is not provided in\nthe request, the server will assign a random\nname for this snapshot on the same project as the subscription, conforming\nto the [resource name format](https://cloud.google.com/pubsub/docs/overview#names).\nThe generated\nname is populated in the returned Snapshot object. Note that for REST API\nrequests, you must specify a name in the request.", + // "description": "Creates a snapshot from the requested subscription. Snapshots are used in\n\u003ca href=\"https://cloud.google.com/pubsub/docs/replay-overview\"\u003eSeek\u003c/a\u003e\noperations, which allow\nyou to manage message acknowledgments in bulk. That is, you can set the\nacknowledgment state of messages in an existing subscription to the state\ncaptured by a snapshot.\n\u003cbr\u003e\u003cbr\u003e\n\u003cb\u003eBETA:\u003c/b\u003e This feature is part of a beta release. This API might be\nchanged in backward-incompatible ways and is not recommended for production\nuse. It is not subject to any SLA or deprecation policy.\u003cbr\u003e\u003cbr\u003e\nIf the snapshot already exists, returns `ALREADY_EXISTS`.\nIf the requested subscription doesn't exist, returns `NOT_FOUND`.\nIf the backlog in the subscription is too old -- and the resulting snapshot\nwould expire in less than 1 hour -- then `FAILED_PRECONDITION` is returned.\nSee also the `Snapshot.expire_time` field. If the name is not provided in\nthe request, the server will assign a random\nname for this snapshot on the same project as the subscription, conforming\nto the\n[resource name format](https://cloud.google.com/pubsub/docs/overview#names).\nThe generated name is populated in the returned Snapshot object. Note that\nfor REST API requests, you must specify a name in the request.", // "flatPath": "v1/projects/{projectsId}/snapshots/{snapshotsId}", // "httpMethod": "PUT", // "id": "pubsub.projects.snapshots.create", @@ -1581,7 +1808,7 @@ func (c *ProjectsSnapshotsCreateCall) Do(opts ...googleapi.CallOption) (*Snapsho // ], // "parameters": { // "name": { - // "description": "Optional user-provided name for this snapshot.\nIf the name is not provided in the request, the server will assign a random\nname for this snapshot on the same project as the subscription.\nNote that for REST API requests, you must specify a name.\nFormat is `projects/{project}/snapshots/{snap}`.", + // "description": "Optional user-provided name for this snapshot.\nIf the name is not provided in the request, the server will assign a random\nname for this snapshot on the same project as the subscription.\nNote that for REST API requests, you must specify a name. See the\n\u003ca href=\"https://cloud.google.com/pubsub/docs/admin#resource_names\"\u003e\nresource name rules\u003c/a\u003e.\nFormat is `projects/{project}/snapshots/{snap}`.", // "location": "path", // "pattern": "^projects/[^/]+/snapshots/[^/]+$", // "required": true, @@ -1613,9 +1840,18 @@ type ProjectsSnapshotsDeleteCall struct { header_ http.Header } -// Delete: Removes an existing snapshot.

-// ALPHA: This feature is part of an alpha release. This API -// might be +// Delete: Removes an existing snapshot. Snapshots are used in +// Seek +// o +// perations, which allow +// you to manage message acknowledgments in bulk. That is, you can set +// the +// acknowledgment state of messages in an existing subscription to the +// state +// captured by a snapshot.

+// BETA: This feature is part of a beta release. This API might +// be // changed in backward-incompatible ways and is not recommended for // production // use. It is not subject to any SLA or deprecation policy. @@ -1666,9 +1902,13 @@ func (c *ProjectsSnapshotsDeleteCall) doRequest(alt string) (*http.Response, err reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+snapshot}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "snapshot": c.snapshot, @@ -1714,7 +1954,7 @@ func (c *ProjectsSnapshotsDeleteCall) Do(opts ...googleapi.CallOption) (*Empty, } return ret, nil // { - // "description": "Removes an existing snapshot. \u003cbr\u003e\u003cbr\u003e\n\u003cb\u003eALPHA:\u003c/b\u003e This feature is part of an alpha release. This API might be\nchanged in backward-incompatible ways and is not recommended for production\nuse. It is not subject to any SLA or deprecation policy.\nWhen the snapshot is deleted, all messages retained in the snapshot\nare immediately dropped. After a snapshot is deleted, a new one may be\ncreated with the same name, but the new one has no association with the old\nsnapshot or its subscription, unless the same subscription is specified.", + // "description": "Removes an existing snapshot. Snapshots are used in\n\u003ca href=\"https://cloud.google.com/pubsub/docs/replay-overview\"\u003eSeek\u003c/a\u003e\noperations, which allow\nyou to manage message acknowledgments in bulk. That is, you can set the\nacknowledgment state of messages in an existing subscription to the state\ncaptured by a snapshot.\u003cbr\u003e\u003cbr\u003e\n\u003cb\u003eBETA:\u003c/b\u003e This feature is part of a beta release. This API might be\nchanged in backward-incompatible ways and is not recommended for production\nuse. It is not subject to any SLA or deprecation policy.\nWhen the snapshot is deleted, all messages retained in the snapshot\nare immediately dropped. After a snapshot is deleted, a new one may be\ncreated with the same name, but the new one has no association with the old\nsnapshot or its subscription, unless the same subscription is specified.", // "flatPath": "v1/projects/{projectsId}/snapshots/{snapshotsId}", // "httpMethod": "DELETE", // "id": "pubsub.projects.snapshots.delete", @@ -1753,10 +1993,19 @@ type ProjectsSnapshotsGetCall struct { header_ http.Header } -// Get: Gets the configuration details of a +// Get: Gets the configuration details of a snapshot. Snapshots are used +// in +// Seek +// o +// perations, which allow you to manage message acknowledgments in bulk. +// That +// is, you can set the acknowledgment state of messages in an +// existing +// subscription to the state captured by a // snapshot.

-// ALPHA: This feature is part of an alpha release. This API -// might be +// BETA: This feature is part of a beta release. This API might +// be // changed in backward-incompatible ways and is not recommended for // production // use. It is not subject to any SLA or deprecation policy. @@ -1812,9 +2061,13 @@ func (c *ProjectsSnapshotsGetCall) doRequest(alt string) (*http.Response, error) } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+snapshot}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "snapshot": c.snapshot, @@ -1860,7 +2113,7 @@ func (c *ProjectsSnapshotsGetCall) Do(opts ...googleapi.CallOption) (*Snapshot, } return ret, nil // { - // "description": "Gets the configuration details of a snapshot.\u003cbr\u003e\u003cbr\u003e\n\u003cb\u003eALPHA:\u003c/b\u003e This feature is part of an alpha release. This API might be\nchanged in backward-incompatible ways and is not recommended for production\nuse. It is not subject to any SLA or deprecation policy.", + // "description": "Gets the configuration details of a snapshot. Snapshots are used in\n\u003ca href=\"https://cloud.google.com/pubsub/docs/replay-overview\"\u003eSeek\u003c/a\u003e\noperations, which allow you to manage message acknowledgments in bulk. That\nis, you can set the acknowledgment state of messages in an existing\nsubscription to the state captured by a snapshot.\u003cbr\u003e\u003cbr\u003e\n\u003cb\u003eBETA:\u003c/b\u003e This feature is part of a beta release. This API might be\nchanged in backward-incompatible ways and is not recommended for production\nuse. It is not subject to any SLA or deprecation policy.", // "flatPath": "v1/projects/{projectsId}/snapshots/{snapshotsId}", // "httpMethod": "GET", // "id": "pubsub.projects.snapshots.get", @@ -1955,9 +2208,13 @@ func (c *ProjectsSnapshotsGetIamPolicyCall) doRequest(alt string) (*http.Respons } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+resource}:getIamPolicy") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "resource": c.resource, @@ -2042,9 +2299,18 @@ type ProjectsSnapshotsListCall struct { header_ http.Header } -// List: Lists the existing snapshots.

-// ALPHA: This feature is part of an alpha release. This API -// might be +// List: Lists the existing snapshots. Snapshots are used in +// Seek +// o +// perations, which allow +// you to manage message acknowledgments in bulk. That is, you can set +// the +// acknowledgment state of messages in an existing subscription to the +// state +// captured by a snapshot.

+// BETA: This feature is part of a beta release. This API might +// be // changed in backward-incompatible ways and is not recommended for // production // use. It is not subject to any SLA or deprecation policy. @@ -2117,9 +2383,13 @@ func (c *ProjectsSnapshotsListCall) doRequest(alt string) (*http.Response, error } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+project}/snapshots") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -2165,7 +2435,7 @@ func (c *ProjectsSnapshotsListCall) Do(opts ...googleapi.CallOption) (*ListSnaps } return ret, nil // { - // "description": "Lists the existing snapshots.\u003cbr\u003e\u003cbr\u003e\n\u003cb\u003eALPHA:\u003c/b\u003e This feature is part of an alpha release. This API might be\nchanged in backward-incompatible ways and is not recommended for production\nuse. It is not subject to any SLA or deprecation policy.", + // "description": "Lists the existing snapshots. Snapshots are used in\n\u003ca href=\"https://cloud.google.com/pubsub/docs/replay-overview\"\u003eSeek\u003c/a\u003e\noperations, which allow\nyou to manage message acknowledgments in bulk. That is, you can set the\nacknowledgment state of messages in an existing subscription to the state\ncaptured by a snapshot.\u003cbr\u003e\u003cbr\u003e\n\u003cb\u003eBETA:\u003c/b\u003e This feature is part of a beta release. This API might be\nchanged in backward-incompatible ways and is not recommended for production\nuse. It is not subject to any SLA or deprecation policy.", // "flatPath": "v1/projects/{projectsId}/snapshots", // "httpMethod": "GET", // "id": "pubsub.projects.snapshots.list", @@ -2185,7 +2455,7 @@ func (c *ProjectsSnapshotsListCall) Do(opts ...googleapi.CallOption) (*ListSnaps // "type": "string" // }, // "project": { - // "description": "The name of the cloud project that snapshots belong to.\nFormat is `projects/{project}`.", + // "description": "The name of the project in which to list snapshots.\nFormat is `projects/{project-id}`.", // "location": "path", // "pattern": "^projects/[^/]+$", // "required": true, @@ -2236,9 +2506,18 @@ type ProjectsSnapshotsPatchCall struct { header_ http.Header } -// Patch: Updates an existing snapshot.

-// ALPHA: This feature is part of an alpha release. This API -// might be +// Patch: Updates an existing snapshot. Snapshots are used in +// Seek +// o +// perations, which allow +// you to manage message acknowledgments in bulk. That is, you can set +// the +// acknowledgment state of messages in an existing subscription to the +// state +// captured by a snapshot.

+// BETA: This feature is part of a beta release. This API might +// be // changed in backward-incompatible ways and is not recommended for // production // use. It is not subject to any SLA or deprecation policy. @@ -2288,9 +2567,13 @@ func (c *ProjectsSnapshotsPatchCall) doRequest(alt string) (*http.Response, erro } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PATCH", urls, body) + req, err := http.NewRequest("PATCH", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "name": c.name, @@ -2336,7 +2619,7 @@ func (c *ProjectsSnapshotsPatchCall) Do(opts ...googleapi.CallOption) (*Snapshot } return ret, nil // { - // "description": "Updates an existing snapshot.\u003cbr\u003e\u003cbr\u003e\n\u003cb\u003eALPHA:\u003c/b\u003e This feature is part of an alpha release. This API might be\nchanged in backward-incompatible ways and is not recommended for production\nuse. It is not subject to any SLA or deprecation policy.\nNote that certain properties of a snapshot are not modifiable.", + // "description": "Updates an existing snapshot. Snapshots are used in\n\u003ca href=\"https://cloud.google.com/pubsub/docs/replay-overview\"\u003eSeek\u003c/a\u003e\noperations, which allow\nyou to manage message acknowledgments in bulk. That is, you can set the\nacknowledgment state of messages in an existing subscription to the state\ncaptured by a snapshot.\u003cbr\u003e\u003cbr\u003e\n\u003cb\u003eBETA:\u003c/b\u003e This feature is part of a beta release. This API might be\nchanged in backward-incompatible ways and is not recommended for production\nuse. It is not subject to any SLA or deprecation policy.\nNote that certain properties of a snapshot are not modifiable.", // "flatPath": "v1/projects/{projectsId}/snapshots/{snapshotsId}", // "httpMethod": "PATCH", // "id": "pubsub.projects.snapshots.patch", @@ -2426,9 +2709,13 @@ func (c *ProjectsSnapshotsSetIamPolicyCall) doRequest(alt string) (*http.Respons } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+resource}:setIamPolicy") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "resource": c.resource, @@ -2572,9 +2859,13 @@ func (c *ProjectsSnapshotsTestIamPermissionsCall) doRequest(alt string) (*http.R } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+resource}:testIamPermissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "resource": c.resource, @@ -2718,9 +3009,13 @@ func (c *ProjectsSubscriptionsAcknowledgeCall) doRequest(alt string) (*http.Resp } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+subscription}:acknowledge") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "subscription": c.subscription, @@ -2809,8 +3104,10 @@ type ProjectsSubscriptionsCreateCall struct { } // Create: Creates a subscription to a given topic. See the -// resource name -// rules. +// +// reso +// urce name rules. // If the subscription already exists, returns `ALREADY_EXISTS`. // If the corresponding topic doesn't exist, returns `NOT_FOUND`. // @@ -2870,9 +3167,13 @@ func (c *ProjectsSubscriptionsCreateCall) doRequest(alt string) (*http.Response, } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PUT", urls, body) + req, err := http.NewRequest("PUT", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "name": c.name, @@ -2918,7 +3219,7 @@ func (c *ProjectsSubscriptionsCreateCall) Do(opts ...googleapi.CallOption) (*Sub } return ret, nil // { - // "description": "Creates a subscription to a given topic. See the\n\u003ca href=\"/pubsub/docs/admin#resource_names\"\u003e resource name rules\u003c/a\u003e.\nIf the subscription already exists, returns `ALREADY_EXISTS`.\nIf the corresponding topic doesn't exist, returns `NOT_FOUND`.\n\nIf the name is not provided in the request, the server will assign a random\nname for this subscription on the same project as the topic, conforming\nto the\n[resource name format](https://cloud.google.com/pubsub/docs/overview#names).\nThe generated name is populated in the returned Subscription object.\nNote that for REST API requests, you must specify a name in the request.", + // "description": "Creates a subscription to a given topic. See the\n\u003ca href=\"https://cloud.google.com/pubsub/docs/admin#resource_names\"\u003e\nresource name rules\u003c/a\u003e.\nIf the subscription already exists, returns `ALREADY_EXISTS`.\nIf the corresponding topic doesn't exist, returns `NOT_FOUND`.\n\nIf the name is not provided in the request, the server will assign a random\nname for this subscription on the same project as the topic, conforming\nto the\n[resource name format](https://cloud.google.com/pubsub/docs/overview#names).\nThe generated name is populated in the returned Subscription object.\nNote that for REST API requests, you must specify a name in the request.", // "flatPath": "v1/projects/{projectsId}/subscriptions/{subscriptionsId}", // "httpMethod": "PUT", // "id": "pubsub.projects.subscriptions.create", @@ -3007,9 +3308,13 @@ func (c *ProjectsSubscriptionsDeleteCall) doRequest(alt string) (*http.Response, reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+subscription}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "subscription": c.subscription, @@ -3147,9 +3452,13 @@ func (c *ProjectsSubscriptionsGetCall) doRequest(alt string) (*http.Response, er } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+subscription}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "subscription": c.subscription, @@ -3290,9 +3599,13 @@ func (c *ProjectsSubscriptionsGetIamPolicyCall) doRequest(alt string) (*http.Res } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+resource}:getIamPolicy") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "resource": c.resource, @@ -3447,9 +3760,13 @@ func (c *ProjectsSubscriptionsListCall) doRequest(alt string) (*http.Response, e } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+project}/subscriptions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -3515,7 +3832,7 @@ func (c *ProjectsSubscriptionsListCall) Do(opts ...googleapi.CallOption) (*ListS // "type": "string" // }, // "project": { - // "description": "The name of the cloud project that subscriptions belong to.\nFormat is `projects/{project}`.", + // "description": "The name of the project in which to list subscriptions.\nFormat is `projects/{project-id}`.", // "location": "path", // "pattern": "^projects/[^/]+$", // "required": true, @@ -3620,9 +3937,13 @@ func (c *ProjectsSubscriptionsModifyAckDeadlineCall) doRequest(alt string) (*htt } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+subscription}:modifyAckDeadline") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "subscription": c.subscription, @@ -3766,9 +4087,13 @@ func (c *ProjectsSubscriptionsModifyPushConfigCall) doRequest(alt string) (*http } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+subscription}:modifyPushConfig") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "subscription": c.subscription, @@ -3904,9 +4229,13 @@ func (c *ProjectsSubscriptionsPatchCall) doRequest(alt string) (*http.Response, } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PATCH", urls, body) + req, err := http.NewRequest("PATCH", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "name": c.name, @@ -3994,9 +4323,7 @@ type ProjectsSubscriptionsPullCall struct { header_ http.Header } -// Pull: Pulls messages from the server. Returns an empty list if there -// are no -// messages available in the backlog. The server may return +// Pull: Pulls messages from the server. The server may return // `UNAVAILABLE` if // there are too many concurrent pull requests pending for the // given @@ -4046,9 +4373,13 @@ func (c *ProjectsSubscriptionsPullCall) doRequest(alt string) (*http.Response, e } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+subscription}:pull") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "subscription": c.subscription, @@ -4094,7 +4425,7 @@ func (c *ProjectsSubscriptionsPullCall) Do(opts ...googleapi.CallOption) (*PullR } return ret, nil // { - // "description": "Pulls messages from the server. Returns an empty list if there are no\nmessages available in the backlog. The server may return `UNAVAILABLE` if\nthere are too many concurrent pull requests pending for the given\nsubscription.", + // "description": "Pulls messages from the server. The server may return `UNAVAILABLE` if\nthere are too many concurrent pull requests pending for the given\nsubscription.", // "flatPath": "v1/projects/{projectsId}/subscriptions/{subscriptionsId}:pull", // "httpMethod": "POST", // "id": "pubsub.projects.subscriptions.pull", @@ -4138,9 +4469,20 @@ type ProjectsSubscriptionsSeekCall struct { // Seek: Seeks an existing subscription to a point in time or to a given // snapshot, -// whichever is provided in the request.

-// ALPHA: This feature is part of an alpha release. This API -// might be +// whichever is provided in the request. Snapshots are used in +// Seek +// o +// perations, which allow +// you to manage message acknowledgments in bulk. That is, you can set +// the +// acknowledgment state of messages in an existing subscription to the +// state +// captured by a snapshot. Note that both the subscription and the +// snapshot +// must be on the same topic.

+// BETA: This feature is part of a beta release. This API might +// be // changed in backward-incompatible ways and is not recommended for // production // use. It is not subject to any SLA or deprecation policy. @@ -4189,9 +4531,13 @@ func (c *ProjectsSubscriptionsSeekCall) doRequest(alt string) (*http.Response, e } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+subscription}:seek") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "subscription": c.subscription, @@ -4237,7 +4583,7 @@ func (c *ProjectsSubscriptionsSeekCall) Do(opts ...googleapi.CallOption) (*SeekR } return ret, nil // { - // "description": "Seeks an existing subscription to a point in time or to a given snapshot,\nwhichever is provided in the request.\u003cbr\u003e\u003cbr\u003e\n\u003cb\u003eALPHA:\u003c/b\u003e This feature is part of an alpha release. This API might be\nchanged in backward-incompatible ways and is not recommended for production\nuse. It is not subject to any SLA or deprecation policy.", + // "description": "Seeks an existing subscription to a point in time or to a given snapshot,\nwhichever is provided in the request. Snapshots are used in\n\u003ca href=\"https://cloud.google.com/pubsub/docs/replay-overview\"\u003eSeek\u003c/a\u003e\noperations, which allow\nyou to manage message acknowledgments in bulk. That is, you can set the\nacknowledgment state of messages in an existing subscription to the state\ncaptured by a snapshot. Note that both the subscription and the snapshot\nmust be on the same topic.\u003cbr\u003e\u003cbr\u003e\n\u003cb\u003eBETA:\u003c/b\u003e This feature is part of a beta release. This API might be\nchanged in backward-incompatible ways and is not recommended for production\nuse. It is not subject to any SLA or deprecation policy.", // "flatPath": "v1/projects/{projectsId}/subscriptions/{subscriptionsId}:seek", // "httpMethod": "POST", // "id": "pubsub.projects.subscriptions.seek", @@ -4327,9 +4673,13 @@ func (c *ProjectsSubscriptionsSetIamPolicyCall) doRequest(alt string) (*http.Res } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+resource}:setIamPolicy") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "resource": c.resource, @@ -4473,9 +4823,13 @@ func (c *ProjectsSubscriptionsTestIamPermissionsCall) doRequest(alt string) (*ht } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+resource}:testIamPermissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "resource": c.resource, @@ -4564,7 +4918,10 @@ type ProjectsTopicsCreateCall struct { } // Create: Creates the given topic with the given name. See the -// resource name rules. +// +// reso +// urce name rules. func (r *ProjectsTopicsService) Create(name string, topic *Topic) *ProjectsTopicsCreateCall { c := &ProjectsTopicsCreateCall{s: r.s, urlParams_: make(gensupport.URLParams)} c.name = name @@ -4610,9 +4967,13 @@ func (c *ProjectsTopicsCreateCall) doRequest(alt string) (*http.Response, error) } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PUT", urls, body) + req, err := http.NewRequest("PUT", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "name": c.name, @@ -4658,7 +5019,7 @@ func (c *ProjectsTopicsCreateCall) Do(opts ...googleapi.CallOption) (*Topic, err } return ret, nil // { - // "description": "Creates the given topic with the given name. See the\n\u003ca href=\"/pubsub/docs/admin#resource_names\"\u003e resource name rules\u003c/a\u003e.", + // "description": "Creates the given topic with the given name. See the\n\u003ca href=\"https://cloud.google.com/pubsub/docs/admin#resource_names\"\u003e\nresource name rules\u003c/a\u003e.", // "flatPath": "v1/projects/{projectsId}/topics/{topicsId}", // "httpMethod": "PUT", // "id": "pubsub.projects.topics.create", @@ -4747,9 +5108,13 @@ func (c *ProjectsTopicsDeleteCall) doRequest(alt string) (*http.Response, error) reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+topic}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "topic": c.topic, @@ -4887,9 +5252,13 @@ func (c *ProjectsTopicsGetCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+topic}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "topic": c.topic, @@ -5030,9 +5399,13 @@ func (c *ProjectsTopicsGetIamPolicyCall) doRequest(alt string) (*http.Response, } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+resource}:getIamPolicy") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "resource": c.resource, @@ -5187,9 +5560,13 @@ func (c *ProjectsTopicsListCall) doRequest(alt string) (*http.Response, error) { } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+project}/topics") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "project": c.project, @@ -5255,7 +5632,7 @@ func (c *ProjectsTopicsListCall) Do(opts ...googleapi.CallOption) (*ListTopicsRe // "type": "string" // }, // "project": { - // "description": "The name of the cloud project that topics belong to.\nFormat is `projects/{project}`.", + // "description": "The name of the project in which to list topics.\nFormat is `projects/{project-id}`.", // "location": "path", // "pattern": "^projects/[^/]+$", // "required": true, @@ -5295,6 +5672,148 @@ func (c *ProjectsTopicsListCall) Pages(ctx context.Context, f func(*ListTopicsRe } } +// method id "pubsub.projects.topics.patch": + +type ProjectsTopicsPatchCall struct { + s *Service + name string + updatetopicrequest *UpdateTopicRequest + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// Patch: Updates an existing topic. Note that certain properties of +// a +// topic are not modifiable. +func (r *ProjectsTopicsService) Patch(name string, updatetopicrequest *UpdateTopicRequest) *ProjectsTopicsPatchCall { + c := &ProjectsTopicsPatchCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.name = name + c.updatetopicrequest = updatetopicrequest + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *ProjectsTopicsPatchCall) Fields(s ...googleapi.Field) *ProjectsTopicsPatchCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *ProjectsTopicsPatchCall) Context(ctx context.Context) *ProjectsTopicsPatchCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *ProjectsTopicsPatchCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *ProjectsTopicsPatchCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.updatetopicrequest) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("PATCH", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "name": c.name, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "pubsub.projects.topics.patch" call. +// Exactly one of *Topic or error will be non-nil. Any non-2xx status +// code is an error. Response headers are in either +// *Topic.ServerResponse.Header or (if a response was returned at all) +// in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to +// check whether the returned error was because http.StatusNotModified +// was returned. +func (c *ProjectsTopicsPatchCall) Do(opts ...googleapi.CallOption) (*Topic, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Topic{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Updates an existing topic. Note that certain properties of a\ntopic are not modifiable.", + // "flatPath": "v1/projects/{projectsId}/topics/{topicsId}", + // "httpMethod": "PATCH", + // "id": "pubsub.projects.topics.patch", + // "parameterOrder": [ + // "name" + // ], + // "parameters": { + // "name": { + // "description": "The name of the topic. It must have the format\n`\"projects/{project}/topics/{topic}\"`. `{topic}` must start with a letter,\nand contain only letters (`[A-Za-z]`), numbers (`[0-9]`), dashes (`-`),\nunderscores (`_`), periods (`.`), tildes (`~`), plus (`+`) or percent\nsigns (`%`). It must be between 3 and 255 characters in length, and it\nmust not start with `\"goog\"`.", + // "location": "path", + // "pattern": "^projects/[^/]+/topics/[^/]+$", + // "required": true, + // "type": "string" + // } + // }, + // "path": "v1/{+name}", + // "request": { + // "$ref": "UpdateTopicRequest" + // }, + // "response": { + // "$ref": "Topic" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform", + // "https://www.googleapis.com/auth/pubsub" + // ] + // } + +} + // method id "pubsub.projects.topics.publish": type ProjectsTopicsPublishCall struct { @@ -5308,9 +5827,7 @@ type ProjectsTopicsPublishCall struct { // Publish: Adds one or more messages to the topic. Returns `NOT_FOUND` // if the topic -// does not exist. The message payload must not be empty; it must -// contain -// either a non-empty data field, or at least one attribute. +// does not exist. func (r *ProjectsTopicsService) Publish(topic string, publishrequest *PublishRequest) *ProjectsTopicsPublishCall { c := &ProjectsTopicsPublishCall{s: r.s, urlParams_: make(gensupport.URLParams)} c.topic = topic @@ -5356,9 +5873,13 @@ func (c *ProjectsTopicsPublishCall) doRequest(alt string) (*http.Response, error } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+topic}:publish") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "topic": c.topic, @@ -5404,7 +5925,7 @@ func (c *ProjectsTopicsPublishCall) Do(opts ...googleapi.CallOption) (*PublishRe } return ret, nil // { - // "description": "Adds one or more messages to the topic. Returns `NOT_FOUND` if the topic\ndoes not exist. The message payload must not be empty; it must contain\n either a non-empty data field, or at least one attribute.", + // "description": "Adds one or more messages to the topic. Returns `NOT_FOUND` if the topic\ndoes not exist.", // "flatPath": "v1/projects/{projectsId}/topics/{topicsId}:publish", // "httpMethod": "POST", // "id": "pubsub.projects.topics.publish", @@ -5494,9 +6015,13 @@ func (c *ProjectsTopicsSetIamPolicyCall) doRequest(alt string) (*http.Response, } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+resource}:setIamPolicy") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "resource": c.resource, @@ -5640,9 +6165,13 @@ func (c *ProjectsTopicsTestIamPermissionsCall) doRequest(alt string) (*http.Resp } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+resource}:testIamPermissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "resource": c.resource, @@ -5730,10 +6259,19 @@ type ProjectsTopicsSnapshotsListCall struct { header_ http.Header } -// List: Lists the names of the snapshots on this -// topic.

-// ALPHA: This feature is part of an alpha release. This API -// might be +// List: Lists the names of the snapshots on this topic. Snapshots are +// used in +// Seek +// o +// perations, which allow +// you to manage message acknowledgments in bulk. That is, you can set +// the +// acknowledgment state of messages in an existing subscription to the +// state +// captured by a snapshot.

+// BETA: This feature is part of a beta release. This API might +// be // changed in backward-incompatible ways and is not recommended for // production // use. It is not subject to any SLA or deprecation policy. @@ -5806,9 +6344,13 @@ func (c *ProjectsTopicsSnapshotsListCall) doRequest(alt string) (*http.Response, } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+topic}/snapshots") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "topic": c.topic, @@ -5854,7 +6396,7 @@ func (c *ProjectsTopicsSnapshotsListCall) Do(opts ...googleapi.CallOption) (*Lis } return ret, nil // { - // "description": "Lists the names of the snapshots on this topic.\u003cbr\u003e\u003cbr\u003e\n\u003cb\u003eALPHA:\u003c/b\u003e This feature is part of an alpha release. This API might be\nchanged in backward-incompatible ways and is not recommended for production\nuse. It is not subject to any SLA or deprecation policy.", + // "description": "Lists the names of the snapshots on this topic. Snapshots are used in\n\u003ca href=\"https://cloud.google.com/pubsub/docs/replay-overview\"\u003eSeek\u003c/a\u003e\noperations, which allow\nyou to manage message acknowledgments in bulk. That is, you can set the\nacknowledgment state of messages in an existing subscription to the state\ncaptured by a snapshot.\u003cbr\u003e\u003cbr\u003e\n\u003cb\u003eBETA:\u003c/b\u003e This feature is part of a beta release. This API might be\nchanged in backward-incompatible ways and is not recommended for production\nuse. It is not subject to any SLA or deprecation policy.", // "flatPath": "v1/projects/{projectsId}/topics/{topicsId}/snapshots", // "httpMethod": "GET", // "id": "pubsub.projects.topics.snapshots.list", @@ -5995,9 +6537,13 @@ func (c *ProjectsTopicsSubscriptionsListCall) doRequest(alt string) (*http.Respo } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+topic}/subscriptions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "topic": c.topic, diff --git a/vendor/google.golang.org/api/tpu/v1/BUILD b/vendor/google.golang.org/api/tpu/v1/BUILD index 1671565aa15..9412f84b969 100644 --- a/vendor/google.golang.org/api/tpu/v1/BUILD +++ b/vendor/google.golang.org/api/tpu/v1/BUILD @@ -7,8 +7,6 @@ go_library( importpath = "google.golang.org/api/tpu/v1", visibility = ["//visibility:public"], deps = [ - "//vendor/golang.org/x/net/context:go_default_library", - "//vendor/golang.org/x/net/context/ctxhttp:go_default_library", "//vendor/google.golang.org/api/gensupport:go_default_library", "//vendor/google.golang.org/api/googleapi:go_default_library", ], diff --git a/vendor/google.golang.org/api/tpu/v1/tpu-api.json b/vendor/google.golang.org/api/tpu/v1/tpu-api.json index 2ccfe3ac0fd..aed51d83d09 100644 --- a/vendor/google.golang.org/api/tpu/v1/tpu-api.json +++ b/vendor/google.golang.org/api/tpu/v1/tpu-api.json @@ -400,34 +400,6 @@ "https://www.googleapis.com/auth/cloud-platform" ] }, - "reset": { - "description": "Resets a node, which stops and starts the VM.", - "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/nodes/{nodesId}:reset", - "httpMethod": "POST", - "id": "tpu.projects.locations.nodes.reset", - "parameterOrder": [ - "name" - ], - "parameters": { - "name": { - "description": "The resource name.", - "location": "path", - "pattern": "^projects/[^/]+/locations/[^/]+/nodes/[^/]+$", - "required": true, - "type": "string" - } - }, - "path": "v1/{+name}:reset", - "request": { - "$ref": "ResetNodeRequest" - }, - "response": { - "$ref": "Operation" - }, - "scopes": [ - "https://www.googleapis.com/auth/cloud-platform" - ] - }, "start": { "description": "Starts a node.", "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/nodes/{nodesId}:start", @@ -686,7 +658,7 @@ } } }, - "revision": "20180601", + "revision": "20181010", "rootUrl": "https://tpu.googleapis.com/", "schemas": { "AcceleratorType": { @@ -760,6 +732,13 @@ "$ref": "Node" }, "type": "array" + }, + "unreachable": { + "description": "Locations that could not be reached.", + "items": { + "type": "string" + }, + "type": "array" } }, "type": "object" @@ -940,7 +919,9 @@ "REPAIRING", "STOPPED", "STOPPING", - "STARTING" + "STARTING", + "PREEMPTED", + "TERMINATED" ], "enumDescriptions": [ "TPU node state is not known/set.", @@ -952,7 +933,9 @@ "TPU node is being repaired and may be unusable. Details can be\nfound in the `help_description` field.", "7 - Reserved. Was SUSPENDED.\nTPU node is stopped.", "TPU node is currently stopping.", - "TPU node is currently starting." + "TPU node is currently starting.", + "TPU node has been preempted. Only applies to Preemptible TPU Nodes.", + "TPU node has been terminated due to maintenance or has reached the end of\nits life cycle (for preemptible nodes)." ], "type": "string" }, @@ -1046,12 +1029,6 @@ }, "type": "object" }, - "ResetNodeRequest": { - "description": "Request for ResetNode.", - "id": "ResetNodeRequest", - "properties": {}, - "type": "object" - }, "SchedulingConfig": { "id": "SchedulingConfig", "properties": { diff --git a/vendor/google.golang.org/api/tpu/v1/tpu-gen.go b/vendor/google.golang.org/api/tpu/v1/tpu-gen.go index 33c972edff6..0b464205cbe 100644 --- a/vendor/google.golang.org/api/tpu/v1/tpu-gen.go +++ b/vendor/google.golang.org/api/tpu/v1/tpu-gen.go @@ -1,3 +1,9 @@ +// Copyright 2018 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Code generated file. DO NOT EDIT. + // Package tpu provides access to the Cloud TPU API. // // See https://cloud.google.com/tpu/ @@ -11,18 +17,18 @@ package tpu import ( "bytes" + "context" "encoding/json" "errors" "fmt" - context "golang.org/x/net/context" - ctxhttp "golang.org/x/net/context/ctxhttp" - gensupport "google.golang.org/api/gensupport" - googleapi "google.golang.org/api/googleapi" "io" "net/http" "net/url" "strconv" "strings" + + gensupport "google.golang.org/api/gensupport" + googleapi "google.golang.org/api/googleapi" ) // Always reference these packages, just in case the auto-generated code @@ -38,7 +44,6 @@ var _ = googleapi.Version var _ = errors.New var _ = strings.Replace var _ = context.Canceled -var _ = ctxhttp.Do const apiId = "tpu:v1" const apiName = "tpu" @@ -279,6 +284,9 @@ type ListNodesResponse struct { // Nodes: The listed nodes. Nodes []*Node `json:"nodes,omitempty"` + // Unreachable: Locations that could not be reached. + Unreachable []string `json:"unreachable,omitempty"` + // ServerResponse contains the HTTP response code and headers from the // server. googleapi.ServerResponse `json:"-"` @@ -575,6 +583,11 @@ type Node struct { // TPU node is stopped. // "STOPPING" - TPU node is currently stopping. // "STARTING" - TPU node is currently starting. + // "PREEMPTED" - TPU node has been preempted. Only applies to + // Preemptible TPU Nodes. + // "TERMINATED" - TPU node has been terminated due to maintenance or + // has reached the end of + // its life cycle (for preemptible nodes). State string `json:"state,omitempty"` // TensorflowVersion: The version of Tensorflow running in the @@ -769,10 +782,6 @@ func (s *ReimageNodeRequest) MarshalJSON() ([]byte, error) { return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) } -// ResetNodeRequest: Request for ResetNode. -type ResetNodeRequest struct { -} - type SchedulingConfig struct { Preemptible bool `json:"preemptible,omitempty"` @@ -1026,9 +1035,13 @@ func (c *ProjectsLocationsGetCall) doRequest(alt string) (*http.Response, error) } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "name": c.name, @@ -1187,9 +1200,13 @@ func (c *ProjectsLocationsListCall) doRequest(alt string) (*http.Response, error } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}/locations") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "name": c.name, @@ -1363,9 +1380,13 @@ func (c *ProjectsLocationsAcceleratorTypesGetCall) doRequest(alt string) (*http. } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "name": c.name, @@ -1528,9 +1549,13 @@ func (c *ProjectsLocationsAcceleratorTypesListCall) doRequest(alt string) (*http } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+parent}/acceleratorTypes") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "parent": c.parent, @@ -1709,9 +1734,13 @@ func (c *ProjectsLocationsNodesCreateCall) doRequest(alt string) (*http.Response } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+parent}/nodes") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "parent": c.parent, @@ -1842,9 +1871,13 @@ func (c *ProjectsLocationsNodesDeleteCall) doRequest(alt string) (*http.Response reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "name": c.name, @@ -1981,9 +2014,13 @@ func (c *ProjectsLocationsNodesGetCall) doRequest(alt string) (*http.Response, e } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "name": c.name, @@ -2134,9 +2171,13 @@ func (c *ProjectsLocationsNodesListCall) doRequest(alt string) (*http.Response, } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+parent}/nodes") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "parent": c.parent, @@ -2298,9 +2339,13 @@ func (c *ProjectsLocationsNodesReimageCall) doRequest(alt string) (*http.Respons } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}:reimage") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "name": c.name, @@ -2376,141 +2421,6 @@ func (c *ProjectsLocationsNodesReimageCall) Do(opts ...googleapi.CallOption) (*O } -// method id "tpu.projects.locations.nodes.reset": - -type ProjectsLocationsNodesResetCall struct { - s *Service - name string - resetnoderequest *ResetNodeRequest - urlParams_ gensupport.URLParams - ctx_ context.Context - header_ http.Header -} - -// Reset: Resets a node, which stops and starts the VM. -func (r *ProjectsLocationsNodesService) Reset(name string, resetnoderequest *ResetNodeRequest) *ProjectsLocationsNodesResetCall { - c := &ProjectsLocationsNodesResetCall{s: r.s, urlParams_: make(gensupport.URLParams)} - c.name = name - c.resetnoderequest = resetnoderequest - return c -} - -// Fields allows partial responses to be retrieved. See -// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse -// for more information. -func (c *ProjectsLocationsNodesResetCall) Fields(s ...googleapi.Field) *ProjectsLocationsNodesResetCall { - c.urlParams_.Set("fields", googleapi.CombineFields(s)) - return c -} - -// Context sets the context to be used in this call's Do method. Any -// pending HTTP request will be aborted if the provided context is -// canceled. -func (c *ProjectsLocationsNodesResetCall) Context(ctx context.Context) *ProjectsLocationsNodesResetCall { - c.ctx_ = ctx - return c -} - -// Header returns an http.Header that can be modified by the caller to -// add HTTP headers to the request. -func (c *ProjectsLocationsNodesResetCall) Header() http.Header { - if c.header_ == nil { - c.header_ = make(http.Header) - } - return c.header_ -} - -func (c *ProjectsLocationsNodesResetCall) doRequest(alt string) (*http.Response, error) { - reqHeaders := make(http.Header) - for k, v := range c.header_ { - reqHeaders[k] = v - } - reqHeaders.Set("User-Agent", c.s.userAgent()) - var body io.Reader = nil - body, err := googleapi.WithoutDataWrapper.JSONReader(c.resetnoderequest) - if err != nil { - return nil, err - } - reqHeaders.Set("Content-Type", "application/json") - c.urlParams_.Set("alt", alt) - urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}:reset") - urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) - req.Header = reqHeaders - googleapi.Expand(req.URL, map[string]string{ - "name": c.name, - }) - return gensupport.SendRequest(c.ctx_, c.s.client, req) -} - -// Do executes the "tpu.projects.locations.nodes.reset" call. -// Exactly one of *Operation or error will be non-nil. Any non-2xx -// status code is an error. Response headers are in either -// *Operation.ServerResponse.Header or (if a response was returned at -// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified -// to check whether the returned error was because -// http.StatusNotModified was returned. -func (c *ProjectsLocationsNodesResetCall) Do(opts ...googleapi.CallOption) (*Operation, error) { - gensupport.SetOptions(c.urlParams_, opts...) - res, err := c.doRequest("json") - if res != nil && res.StatusCode == http.StatusNotModified { - if res.Body != nil { - res.Body.Close() - } - return nil, &googleapi.Error{ - Code: res.StatusCode, - Header: res.Header, - } - } - if err != nil { - return nil, err - } - defer googleapi.CloseBody(res) - if err := googleapi.CheckResponse(res); err != nil { - return nil, err - } - ret := &Operation{ - ServerResponse: googleapi.ServerResponse{ - Header: res.Header, - HTTPStatusCode: res.StatusCode, - }, - } - target := &ret - if err := gensupport.DecodeResponse(target, res); err != nil { - return nil, err - } - return ret, nil - // { - // "description": "Resets a node, which stops and starts the VM.", - // "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/nodes/{nodesId}:reset", - // "httpMethod": "POST", - // "id": "tpu.projects.locations.nodes.reset", - // "parameterOrder": [ - // "name" - // ], - // "parameters": { - // "name": { - // "description": "The resource name.", - // "location": "path", - // "pattern": "^projects/[^/]+/locations/[^/]+/nodes/[^/]+$", - // "required": true, - // "type": "string" - // } - // }, - // "path": "v1/{+name}:reset", - // "request": { - // "$ref": "ResetNodeRequest" - // }, - // "response": { - // "$ref": "Operation" - // }, - // "scopes": [ - // "https://www.googleapis.com/auth/cloud-platform" - // ] - // } - -} - // method id "tpu.projects.locations.nodes.start": type ProjectsLocationsNodesStartCall struct { @@ -2568,9 +2478,13 @@ func (c *ProjectsLocationsNodesStartCall) doRequest(alt string) (*http.Response, } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}:start") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "name": c.name, @@ -2703,9 +2617,13 @@ func (c *ProjectsLocationsNodesStopCall) doRequest(alt string) (*http.Response, } reqHeaders.Set("Content-Type", "application/json") c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}:stop") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "name": c.name, @@ -2848,9 +2766,13 @@ func (c *ProjectsLocationsOperationsCancelCall) doRequest(alt string) (*http.Res reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}:cancel") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "name": c.name, @@ -2979,9 +2901,13 @@ func (c *ProjectsLocationsOperationsDeleteCall) doRequest(alt string) (*http.Res reqHeaders.Set("User-Agent", c.s.userAgent()) var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "name": c.name, @@ -3122,9 +3048,13 @@ func (c *ProjectsLocationsOperationsGetCall) doRequest(alt string) (*http.Respon } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "name": c.name, @@ -3298,9 +3228,13 @@ func (c *ProjectsLocationsOperationsListCall) doRequest(alt string) (*http.Respo } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}/operations") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "name": c.name, @@ -3474,9 +3408,13 @@ func (c *ProjectsLocationsTensorflowVersionsGetCall) doRequest(alt string) (*htt } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "name": c.name, @@ -3639,9 +3577,13 @@ func (c *ProjectsLocationsTensorflowVersionsListCall) doRequest(alt string) (*ht } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+parent}/tensorflowVersions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "parent": c.parent, diff --git a/vendor/k8s.io/node-api b/vendor/k8s.io/node-api new file mode 120000 index 00000000000..61fba3899f4 --- /dev/null +++ b/vendor/k8s.io/node-api @@ -0,0 +1 @@ +../../staging/src/k8s.io/node-api \ No newline at end of file diff --git a/vendor/sigs.k8s.io/kustomize/LICENSE b/vendor/sigs.k8s.io/kustomize/LICENSE new file mode 100644 index 00000000000..8dada3edaf5 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/vendor/sigs.k8s.io/kustomize/pkg/commands/build/BUILD b/vendor/sigs.k8s.io/kustomize/pkg/commands/build/BUILD new file mode 100644 index 00000000000..225b86735e5 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/commands/build/BUILD @@ -0,0 +1,33 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = ["build.go"], + importmap = "k8s.io/kubernetes/vendor/sigs.k8s.io/kustomize/pkg/commands/build", + importpath = "sigs.k8s.io/kustomize/pkg/commands/build", + visibility = ["//visibility:public"], + deps = [ + "//vendor/github.com/pkg/errors:go_default_library", + "//vendor/github.com/spf13/cobra:go_default_library", + "//vendor/sigs.k8s.io/kustomize/pkg/constants:go_default_library", + "//vendor/sigs.k8s.io/kustomize/pkg/fs:go_default_library", + "//vendor/sigs.k8s.io/kustomize/pkg/ifc/transformer:go_default_library", + "//vendor/sigs.k8s.io/kustomize/pkg/loader:go_default_library", + "//vendor/sigs.k8s.io/kustomize/pkg/resmap:go_default_library", + "//vendor/sigs.k8s.io/kustomize/pkg/target:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/vendor/sigs.k8s.io/kustomize/pkg/commands/build/build.go b/vendor/sigs.k8s.io/kustomize/pkg/commands/build/build.go new file mode 100644 index 00000000000..b306e262062 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/commands/build/build.go @@ -0,0 +1,120 @@ +/* +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 build + +import ( + "io" + + "github.com/pkg/errors" + "github.com/spf13/cobra" + "sigs.k8s.io/kustomize/pkg/constants" + "sigs.k8s.io/kustomize/pkg/fs" + "sigs.k8s.io/kustomize/pkg/ifc/transformer" + "sigs.k8s.io/kustomize/pkg/loader" + "sigs.k8s.io/kustomize/pkg/resmap" + "sigs.k8s.io/kustomize/pkg/target" +) + +type buildOptions struct { + kustomizationPath string + outputPath string +} + +var examples = ` +Use the file somedir/kustomization.yaml to generate a set of api resources: + build somedir + +Use a url pointing to a remote directory/kustomization.yaml to generate a set of api resources: + build url +The url should follow hashicorp/go-getter URL format described in +https://github.com/hashicorp/go-getter#url-format + +url examples: + sigs.k8s.io/kustomize//examples/multibases?ref=v1.0.6 + github.com/Liujingfang1/mysql + github.com/Liujingfang1/kustomize//examples/helloWorld?ref=repoUrl2 +` + +// NewCmdBuild creates a new build command. +func NewCmdBuild( + out io.Writer, fs fs.FileSystem, + rf *resmap.Factory, + ptf transformer.Factory) *cobra.Command { + var o buildOptions + + cmd := &cobra.Command{ + Use: "build [path]", + Short: "Print current configuration per contents of " + constants.KustomizationFileName, + Example: examples, + SilenceUsage: true, + RunE: func(cmd *cobra.Command, args []string) error { + err := o.Validate(args) + if err != nil { + return err + } + return o.RunBuild(out, fs, rf, ptf) + }, + } + cmd.Flags().StringVarP( + &o.outputPath, + "output", "o", "", + "If specified, write the build output to this path.") + return cmd +} + +// Validate validates build command. +func (o *buildOptions) Validate(args []string) error { + if len(args) > 1 { + return errors.New("specify one path to " + constants.KustomizationFileName) + } + if len(args) == 0 { + o.kustomizationPath = "./" + } else { + o.kustomizationPath = args[0] + } + + return nil +} + +// RunBuild runs build command. +func (o *buildOptions) RunBuild( + out io.Writer, fSys fs.FileSystem, + rf *resmap.Factory, ptf transformer.Factory) error { + ldr, err := loader.NewLoader(o.kustomizationPath, fSys) + if err != nil { + return err + } + defer ldr.Cleanup() + kt, err := target.NewKustTarget(ldr, fSys, rf, ptf) + if err != nil { + return err + } + allResources, err := kt.MakeCustomizedResMap() + if err != nil { + return err + } + // Output the objects. + res, err := allResources.EncodeAsYaml() + if err != nil { + return err + } + if o.outputPath != "" { + return fSys.WriteFile(o.outputPath, res) + } + _, err = out.Write(res) + return err +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/constants/BUILD b/vendor/sigs.k8s.io/kustomize/pkg/constants/BUILD new file mode 100644 index 00000000000..c18418cef59 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/constants/BUILD @@ -0,0 +1,23 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = ["constants.go"], + importmap = "k8s.io/kubernetes/vendor/sigs.k8s.io/kustomize/pkg/constants", + importpath = "sigs.k8s.io/kustomize/pkg/constants", + visibility = ["//visibility:public"], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/vendor/sigs.k8s.io/kustomize/pkg/constants/constants.go b/vendor/sigs.k8s.io/kustomize/pkg/constants/constants.go new file mode 100644 index 00000000000..d81024afa17 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/constants/constants.go @@ -0,0 +1,31 @@ +/* +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 constants holds global constants for the kustomize tool. +package constants + +// KustomizationFileSuffix is expected suffix for KustomizationFileName. +const KustomizationFileSuffix = ".yaml" + +// SecondaryKustomizationFileSuffix is the second expected suffix when KustomizationFileSuffix is not found +const SecondaryKustomizationFileSuffix = ".yml" + +// KustomizationFileName is the Well-Known File Name for a kustomize configuration file. +const KustomizationFileName = "kustomization" + KustomizationFileSuffix + +// SecondaryKustomizationFileName is the secondary File Name for a kustomize configuration file when +// KustomizationFileName is not found +const SecondaryKustomizationFileName = "kustomization" + SecondaryKustomizationFileSuffix diff --git a/vendor/sigs.k8s.io/kustomize/pkg/expansion/BUILD b/vendor/sigs.k8s.io/kustomize/pkg/expansion/BUILD new file mode 100644 index 00000000000..bc3ecdeabb9 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/expansion/BUILD @@ -0,0 +1,23 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = ["expand.go"], + importmap = "k8s.io/kubernetes/vendor/sigs.k8s.io/kustomize/pkg/expansion", + importpath = "sigs.k8s.io/kustomize/pkg/expansion", + visibility = ["//visibility:public"], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/vendor/sigs.k8s.io/kustomize/pkg/expansion/expand.go b/vendor/sigs.k8s.io/kustomize/pkg/expansion/expand.go new file mode 100644 index 00000000000..c2a81ed6f25 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/expansion/expand.go @@ -0,0 +1,119 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package expansion provides functions find and replace $(FOO) style variables in strings. +package expansion + +import ( + "bytes" +) + +const ( + operator = '$' + referenceOpener = '(' + referenceCloser = ')' +) + +// syntaxWrap returns the input string wrapped by the expansion syntax. +func syntaxWrap(input string) string { + return string(operator) + string(referenceOpener) + input + string(referenceCloser) +} + +// MappingFuncFor returns a mapping function for use with Expand that +// implements the expansion semantics defined in the expansion spec; it +// returns the input string wrapped in the expansion syntax if no mapping +// for the input is found. +func MappingFuncFor(context ...map[string]string) func(string) string { + return func(input string) string { + for _, vars := range context { + val, ok := vars[input] + if ok { + return val + } + } + + return syntaxWrap(input) + } +} + +// Expand replaces variable references in the input string according to +// the expansion spec using the given mapping function to resolve the +// values of variables. +func Expand(input string, mapping func(string) string) string { + var buf bytes.Buffer + checkpoint := 0 + for cursor := 0; cursor < len(input); cursor++ { + if input[cursor] == operator && cursor+1 < len(input) { + // Copy the portion of the input string since the last + // checkpoint into the buffer + buf.WriteString(input[checkpoint:cursor]) + + // Attempt to read the variable name as defined by the + // syntax from the input string + read, isVar, advance := tryReadVariableName(input[cursor+1:]) + + if isVar { + // We were able to read a variable name correctly; + // apply the mapping to the variable name and copy the + // bytes into the buffer + buf.WriteString(mapping(read)) + } else { + // Not a variable name; copy the read bytes into the buffer + buf.WriteString(read) + } + + // Advance the cursor in the input string to account for + // bytes consumed to read the variable name expression + cursor += advance + + // Advance the checkpoint in the input string + checkpoint = cursor + 1 + } + } + + // Return the buffer and any remaining unwritten bytes in the + // input string. + return buf.String() + input[checkpoint:] +} + +// tryReadVariableName attempts to read a variable name from the input +// string and returns the content read from the input, whether that content +// represents a variable name to perform mapping on, and the number of bytes +// consumed in the input string. +// +// The input string is assumed not to contain the initial operator. +func tryReadVariableName(input string) (string, bool, int) { + switch input[0] { + case operator: + // Escaped operator; return it. + return input[0:1], false, 1 + case referenceOpener: + // Scan to expression closer + for i := 1; i < len(input); i++ { + if input[i] == referenceCloser { + return input[1:i], true, i + 1 + } + } + + // Incomplete reference; return it. + return string(operator) + string(referenceOpener), false, 1 + default: + // Not the beginning of an expression, ie, an operator + // that doesn't begin an expression. Return the operator + // and the first rune in the string. + return string(operator) + string(input[0]), false, 1 + } +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/factory/BUILD b/vendor/sigs.k8s.io/kustomize/pkg/factory/BUILD new file mode 100644 index 00000000000..2a2351e2d32 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/factory/BUILD @@ -0,0 +1,29 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = ["factory.go"], + importmap = "k8s.io/kubernetes/vendor/sigs.k8s.io/kustomize/pkg/factory", + importpath = "sigs.k8s.io/kustomize/pkg/factory", + visibility = ["//visibility:public"], + deps = [ + "//vendor/sigs.k8s.io/kustomize/pkg/ifc:go_default_library", + "//vendor/sigs.k8s.io/kustomize/pkg/ifc/transformer:go_default_library", + "//vendor/sigs.k8s.io/kustomize/pkg/resmap:go_default_library", + "//vendor/sigs.k8s.io/kustomize/pkg/resource:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/vendor/sigs.k8s.io/kustomize/pkg/factory/factory.go b/vendor/sigs.k8s.io/kustomize/pkg/factory/factory.go new file mode 100644 index 00000000000..e71669a8718 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/factory/factory.go @@ -0,0 +1,39 @@ +/* +Copyright 2018 The Kubernetes Authors. + Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +// Package factory provides factories for kustomize. +package factory + +import ( + "sigs.k8s.io/kustomize/pkg/ifc" + "sigs.k8s.io/kustomize/pkg/ifc/transformer" + "sigs.k8s.io/kustomize/pkg/resmap" + "sigs.k8s.io/kustomize/pkg/resource" +) + +// KustFactory provides different factories for kustomize +type KustFactory struct { + ResmapF *resmap.Factory + TransformerF transformer.Factory + ValidatorF ifc.Validator + UnstructF ifc.KunstructuredFactory +} + +// NewKustFactory creats a KustFactory instance +func NewKustFactory(u ifc.KunstructuredFactory, v ifc.Validator, t transformer.Factory) *KustFactory { + return &KustFactory{ + ResmapF: resmap.NewFactory(resource.NewFactory(u)), + TransformerF: t, + ValidatorF: v, + UnstructF: u, + } +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/fs/BUILD b/vendor/sigs.k8s.io/kustomize/pkg/fs/BUILD new file mode 100644 index 00000000000..cb38d32c683 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/fs/BUILD @@ -0,0 +1,31 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = [ + "fakefile.go", + "fakefileinfo.go", + "fakefs.go", + "fs.go", + "realfile.go", + "realfs.go", + ], + importmap = "k8s.io/kubernetes/vendor/sigs.k8s.io/kustomize/pkg/fs", + importpath = "sigs.k8s.io/kustomize/pkg/fs", + visibility = ["//visibility:public"], + deps = ["//vendor/sigs.k8s.io/kustomize/pkg/constants:go_default_library"], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/vendor/sigs.k8s.io/kustomize/pkg/fs/fakefile.go b/vendor/sigs.k8s.io/kustomize/pkg/fs/fakefile.go new file mode 100644 index 00000000000..64bc55685f1 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/fs/fakefile.go @@ -0,0 +1,69 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package fs + +import ( + "bytes" + "os" +) + +var _ File = &FakeFile{} + +// FakeFile implements File in-memory for tests. +type FakeFile struct { + name string + content []byte + dir bool + open bool +} + +// makeDir makes a fake directory. +func makeDir(name string) *FakeFile { + return &FakeFile{name: name, dir: true} +} + +// Close marks the fake file closed. +func (f *FakeFile) Close() error { + f.open = false + return nil +} + +// Read never fails, and doesn't mutate p. +func (f *FakeFile) Read(p []byte) (n int, err error) { + return len(p), nil +} + +// Write saves the contents of the argument to memory. +func (f *FakeFile) Write(p []byte) (n int, err error) { + f.content = p + return len(p), nil +} + +// ContentMatches returns true if v matches fake file's content. +func (f *FakeFile) ContentMatches(v []byte) bool { + return bytes.Equal(v, f.content) +} + +// GetContent the content of a fake file. +func (f *FakeFile) GetContent() []byte { + return f.content +} + +// Stat returns nil. +func (f *FakeFile) Stat() (os.FileInfo, error) { + return nil, nil +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/fs/fakefileinfo.go b/vendor/sigs.k8s.io/kustomize/pkg/fs/fakefileinfo.go new file mode 100644 index 00000000000..6ccca915091 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/fs/fakefileinfo.go @@ -0,0 +1,47 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package fs + +import ( + "os" + "time" +) + +var _ os.FileInfo = &Fakefileinfo{} + +// Fakefileinfo implements Fakefileinfo using a fake in-memory filesystem. +type Fakefileinfo struct { + *FakeFile +} + +// Name returns the name of the file +func (fi *Fakefileinfo) Name() string { return fi.name } + +// Size returns the size of the file +func (fi *Fakefileinfo) Size() int64 { return int64(len(fi.content)) } + +// Mode returns the file mode +func (fi *Fakefileinfo) Mode() os.FileMode { return 0777 } + +// ModTime returns the modification time +func (fi *Fakefileinfo) ModTime() time.Time { return time.Time{} } + +// IsDir returns if it is a directory +func (fi *Fakefileinfo) IsDir() bool { return fi.dir } + +// Sys should return underlying data source, but it now returns nil +func (fi *Fakefileinfo) Sys() interface{} { return nil } diff --git a/vendor/sigs.k8s.io/kustomize/pkg/fs/fakefs.go b/vendor/sigs.k8s.io/kustomize/pkg/fs/fakefs.go new file mode 100644 index 00000000000..32ef34fa1e4 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/fs/fakefs.go @@ -0,0 +1,171 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package fs + +import ( + "fmt" + "path/filepath" + "sort" + "strings" + + "sigs.k8s.io/kustomize/pkg/constants" +) + +var _ FileSystem = &fakeFs{} + +// fakeFs implements FileSystem using a fake in-memory filesystem. +type fakeFs struct { + m map[string]*FakeFile +} + +// MakeFakeFS returns an instance of fakeFs with no files in it. +func MakeFakeFS() *fakeFs { + result := &fakeFs{m: map[string]*FakeFile{}} + result.Mkdir("/") + return result +} + +// kustomizationContent is used in tests. +const kustomizationContent = `namePrefix: some-prefix +nameSuffix: some-suffix +# Labels to add to all objects and selectors. +# These labels would also be used to form the selector for apply --prune +# Named differently than “labels” to avoid confusion with metadata for this object +commonLabels: + app: helloworld +commonAnnotations: + note: This is an example annotation +resources: [] +#- service.yaml +#- ../some-dir/ +# There could also be configmaps in Base, which would make these overlays +configMapGenerator: [] +# There could be secrets in Base, if just using a fork/rebase workflow +secretGenerator: [] +` + +// Create assures a fake file appears in the in-memory file system. +func (fs *fakeFs) Create(name string) (File, error) { + f := &FakeFile{} + f.open = true + fs.m[name] = f + return fs.m[name], nil +} + +// Mkdir assures a fake directory appears in the in-memory file system. +func (fs *fakeFs) Mkdir(name string) error { + fs.m[name] = makeDir(name) + return nil +} + +// MkdirAll delegates to Mkdir +func (fs *fakeFs) MkdirAll(name string) error { + return fs.Mkdir(name) +} + +// RemoveAll presumably does rm -r on a path. +// There's no error. +func (fs *fakeFs) RemoveAll(name string) error { + var toRemove []string + for k := range fs.m { + if strings.HasPrefix(k, name) { + toRemove = append(toRemove, k) + } + } + for _, k := range toRemove { + delete(fs.m, k) + } + return nil +} + +// Open returns a fake file in the open state. +func (fs *fakeFs) Open(name string) (File, error) { + if _, found := fs.m[name]; !found { + return nil, fmt.Errorf("file %q cannot be opened", name) + } + return fs.m[name], nil +} + +// Exists returns true if file is known. +func (fs *fakeFs) Exists(name string) bool { + _, found := fs.m[name] + return found +} + +// Glob returns the list of matching files +func (fs *fakeFs) Glob(pattern string) ([]string, error) { + var result []string + for p := range fs.m { + if fs.pathMatch(p, pattern) { + result = append(result, p) + } + } + sort.Strings(result) + return result, nil +} + +// IsDir returns true if the file exists and is a directory. +func (fs *fakeFs) IsDir(name string) bool { + f, found := fs.m[name] + if found && f.dir { + return true + } + if !strings.HasSuffix(name, "/") { + name = name + "/" + } + for k := range fs.m { + if strings.HasPrefix(k, name) { + return true + } + } + return false +} + +// ReadFile always returns an empty bytes and error depending on content of m. +func (fs *fakeFs) ReadFile(name string) ([]byte, error) { + if ff, found := fs.m[name]; found { + return ff.content, nil + } + return nil, fmt.Errorf("cannot read file %q", name) +} + +func (fs *fakeFs) ReadTestKustomization() ([]byte, error) { + return fs.ReadFile(constants.KustomizationFileName) +} + +// WriteFile always succeeds and does nothing. +func (fs *fakeFs) WriteFile(name string, c []byte) error { + ff := &FakeFile{} + ff.Write(c) + fs.m[name] = ff + return nil +} + +// WriteTestKustomization writes a standard test file. +func (fs *fakeFs) WriteTestKustomization() { + fs.WriteTestKustomizationWith([]byte(kustomizationContent)) +} + +// WriteTestKustomizationWith writes a standard test file. +func (fs *fakeFs) WriteTestKustomizationWith(bytes []byte) { + fs.WriteFile(constants.KustomizationFileName, bytes) +} + +func (fs *fakeFs) pathMatch(path, pattern string) bool { + match, _ := filepath.Match(pattern, path) + return match +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/fs/fs.go b/vendor/sigs.k8s.io/kustomize/pkg/fs/fs.go new file mode 100644 index 00000000000..6d4d6d229fd --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/fs/fs.go @@ -0,0 +1,43 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package fs provides a file system abstraction layer. +package fs + +import ( + "io" + "os" +) + +// FileSystem groups basic os filesystem methods. +type FileSystem interface { + Create(name string) (File, error) + Mkdir(name string) error + MkdirAll(name string) error + RemoveAll(name string) error + Open(name string) (File, error) + IsDir(name string) bool + Exists(name string) bool + Glob(pattern string) ([]string, error) + ReadFile(name string) ([]byte, error) + WriteFile(name string, data []byte) error +} + +// File groups the basic os.File methods. +type File interface { + io.ReadWriteCloser + Stat() (os.FileInfo, error) +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/fs/realfile.go b/vendor/sigs.k8s.io/kustomize/pkg/fs/realfile.go new file mode 100644 index 00000000000..5bfec55abee --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/fs/realfile.go @@ -0,0 +1,40 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package fs + +import ( + "os" +) + +var _ File = &realFile{} + +// realFile implements File using the local filesystem. +type realFile struct { + file *os.File +} + +// Close closes a file. +func (f *realFile) Close() error { return f.file.Close() } + +// Read reads a file's content. +func (f *realFile) Read(p []byte) (n int, err error) { return f.file.Read(p) } + +// Write writes bytes to a file +func (f *realFile) Write(p []byte) (n int, err error) { return f.file.Write(p) } + +// Stat returns an interface which has all the information regarding the file. +func (f *realFile) Stat() (os.FileInfo, error) { return f.file.Stat() } diff --git a/vendor/sigs.k8s.io/kustomize/pkg/fs/realfs.go b/vendor/sigs.k8s.io/kustomize/pkg/fs/realfs.go new file mode 100644 index 00000000000..98a647d5220 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/fs/realfs.go @@ -0,0 +1,82 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package fs + +import ( + "io/ioutil" + "os" + "path/filepath" +) + +var _ FileSystem = realFS{} + +// realFS implements FileSystem using the local filesystem. +type realFS struct{} + +// MakeRealFS makes an instance of realFS. +func MakeRealFS() FileSystem { + return realFS{} +} + +// Create delegates to os.Create. +func (realFS) Create(name string) (File, error) { return os.Create(name) } + +// Mkdir delegates to os.Mkdir. +func (realFS) Mkdir(name string) error { + return os.Mkdir(name, 0777|os.ModeDir) +} + +// MkdirAll delegates to os.MkdirAll. +func (realFS) MkdirAll(name string) error { + return os.MkdirAll(name, 0777|os.ModeDir) +} + +// RemoveAll delegates to os.RemoveAll. +func (realFS) RemoveAll(name string) error { + return os.RemoveAll(name) +} + +// Open delegates to os.Open. +func (realFS) Open(name string) (File, error) { return os.Open(name) } + +// Exists returns true if os.Stat succeeds. +func (realFS) Exists(name string) bool { + _, err := os.Stat(name) + return err == nil +} + +// Glob returns the list of matching files +func (realFS) Glob(pattern string) ([]string, error) { + return filepath.Glob(pattern) +} + +// IsDir delegates to os.Stat and FileInfo.IsDir +func (realFS) IsDir(name string) bool { + info, err := os.Stat(name) + if err != nil { + return false + } + return info.IsDir() +} + +// ReadFile delegates to ioutil.ReadFile. +func (realFS) ReadFile(name string) ([]byte, error) { return ioutil.ReadFile(name) } + +// WriteFile delegates to ioutil.WriteFile with read/write permissions. +func (realFS) WriteFile(name string, c []byte) error { + return ioutil.WriteFile(name, c, 0666) +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/gvk/BUILD b/vendor/sigs.k8s.io/kustomize/pkg/gvk/BUILD new file mode 100644 index 00000000000..abc3b10ab15 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/gvk/BUILD @@ -0,0 +1,23 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = ["gvk.go"], + importmap = "k8s.io/kubernetes/vendor/sigs.k8s.io/kustomize/pkg/gvk", + importpath = "sigs.k8s.io/kustomize/pkg/gvk", + visibility = ["//visibility:public"], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/vendor/sigs.k8s.io/kustomize/pkg/gvk/gvk.go b/vendor/sigs.k8s.io/kustomize/pkg/gvk/gvk.go new file mode 100644 index 00000000000..d4cab2f035c --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/gvk/gvk.go @@ -0,0 +1,168 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package gvk + +import ( + "strings" +) + +// Gvk identifies a Kubernetes API type. +// https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md +type Gvk struct { + Group string `json:"group,omitempty" yaml:"group,omitempty"` + Version string `json:"version,omitempty" yaml:"version,omitempty"` + Kind string `json:"kind,omitempty" yaml:"kind,omitempty"` +} + +// FromKind makes a Gvk with only the kind specified. +func FromKind(k string) Gvk { + return Gvk{ + Kind: k, + } +} + +const ( + noGroup = "noGroup" + noVersion = "noVersion" + noKind = "noKind" + separator = "_" +) + +// String returns a string representation of the GVK. +func (x Gvk) String() string { + g := x.Group + if g == "" { + g = noGroup + } + v := x.Version + if v == "" { + v = noVersion + } + k := x.Kind + if k == "" { + k = noKind + } + return strings.Join([]string{g, v, k}, separator) +} + +// Equals returns true if the Gvk's have equal fields. +func (x Gvk) Equals(o Gvk) bool { + return x.Group == o.Group && x.Version == o.Version && x.Kind == o.Kind +} + +// An attempt to order things to help k8s, e.g. +// a Service should come before things that refer to it. +// Namespace should be first. +// In some cases order just specified to provide determinism. +var order = []string{ + "Namespace", + "StorageClass", + "CustomResourceDefinition", + "ServiceAccount", + "Role", + "ClusterRole", + "RoleBinding", + "ClusterRoleBinding", + "ConfigMap", + "Secret", + "Service", + "Deployment", + "StatefulSet", + "CronJob", + "PodDisruptionBudget", +} +var typeOrders = func() map[string]int { + m := map[string]int{} + for i, n := range order { + m[n] = i + } + return m +}() + +// IsLessThan returns true if self is less than the argument. +func (x Gvk) IsLessThan(o Gvk) bool { + indexI, foundI := typeOrders[x.Kind] + indexJ, foundJ := typeOrders[o.Kind] + if foundI && foundJ { + if indexI != indexJ { + return indexI < indexJ + } + } + if foundI && !foundJ { + return true + } + if !foundI && foundJ { + return false + } + return x.String() < o.String() +} + +// IsSelected returns true if `selector` selects `x`; otherwise, false. +// If `selector` and `x` are the same, return true. +// If `selector` is nil, it is considered as a wildcard and always return true. +// e.g. selector CAN select +// . +// selector CANNOT select +// . +func (x Gvk) IsSelected(selector *Gvk) bool { + if selector == nil { + return true + } + if len(selector.Group) > 0 { + if x.Group != selector.Group { + return false + } + } + if len(selector.Version) > 0 { + if x.Version != selector.Version { + return false + } + } + if len(selector.Kind) > 0 { + if x.Kind != selector.Kind { + return false + } + } + return true +} + +var clusterLevelKinds = []string{ + "ClusterRoleBinding", + "ClusterRole", + "CustomResourceDefinition", + "Namespace", + "PersistentVolume", +} + +// IsClusterKind returns true if x is a cluster-level Gvk +func (x Gvk) IsClusterKind() bool { + for _, k := range clusterLevelKinds { + if k == x.Kind { + return true + } + } + return false +} + +// ClusterLevelGvks returns a slice of cluster-level Gvks +func ClusterLevelGvks() []Gvk { + var result []Gvk + for _, k := range clusterLevelKinds { + result = append(result, Gvk{Kind: k}) + } + return result +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/ifc/BUILD b/vendor/sigs.k8s.io/kustomize/pkg/ifc/BUILD new file mode 100644 index 00000000000..2ac806a1442 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/ifc/BUILD @@ -0,0 +1,34 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = [ + "generationbehavior.go", + "ifc.go", + ], + importmap = "k8s.io/kubernetes/vendor/sigs.k8s.io/kustomize/pkg/ifc", + importpath = "sigs.k8s.io/kustomize/pkg/ifc", + visibility = ["//visibility:public"], + deps = [ + "//vendor/sigs.k8s.io/kustomize/pkg/fs:go_default_library", + "//vendor/sigs.k8s.io/kustomize/pkg/gvk:go_default_library", + "//vendor/sigs.k8s.io/kustomize/pkg/types:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [ + ":package-srcs", + "//vendor/sigs.k8s.io/kustomize/pkg/ifc/transformer:all-srcs", + ], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/vendor/sigs.k8s.io/kustomize/pkg/ifc/generationbehavior.go b/vendor/sigs.k8s.io/kustomize/pkg/ifc/generationbehavior.go new file mode 100644 index 00000000000..e798ca33ea2 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/ifc/generationbehavior.go @@ -0,0 +1,59 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package ifc + +// GenerationBehavior specifies generation behavior of configmaps, secrets and maybe other resources. +type GenerationBehavior int + +const ( + // BehaviorUnspecified is an Unspecified behavior; typically treated as a Create. + BehaviorUnspecified GenerationBehavior = iota + // BehaviorCreate makes a new resource. + BehaviorCreate + // BehaviorReplace replaces a resource. + BehaviorReplace + // BehaviorMerge attempts to merge a new resource with an existing resource. + BehaviorMerge +) + +// String converts a GenerationBehavior to a string. +func (b GenerationBehavior) String() string { + switch b { + case BehaviorReplace: + return "replace" + case BehaviorMerge: + return "merge" + case BehaviorCreate: + return "create" + default: + return "unspecified" + } +} + +// NewGenerationBehavior converts a string to a GenerationBehavior. +func NewGenerationBehavior(s string) GenerationBehavior { + switch s { + case "replace": + return BehaviorReplace + case "merge": + return BehaviorMerge + case "create": + return BehaviorCreate + default: + return BehaviorUnspecified + } +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/ifc/ifc.go b/vendor/sigs.k8s.io/kustomize/pkg/ifc/ifc.go new file mode 100644 index 00000000000..c4f3dbb26fb --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/ifc/ifc.go @@ -0,0 +1,74 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package ifc holds miscellaneous interfaces used by kustomize. +package ifc + +import ( + "sigs.k8s.io/kustomize/pkg/fs" + "sigs.k8s.io/kustomize/pkg/gvk" + "sigs.k8s.io/kustomize/pkg/types" +) + +// Validator provides functions to validate annotations and labels +type Validator interface { + MakeAnnotationValidator() func(map[string]string) error + MakeLabelValidator() func(map[string]string) error + ValidateNamespace(string) []string +} + +// Loader interface exposes methods to read bytes. +type Loader interface { + // Root returns the root location for this Loader. + Root() string + // New returns Loader located at newRoot. + New(newRoot string) (Loader, error) + // Load returns the bytes read from the location or an error. + Load(location string) ([]byte, error) + // Cleanup cleans the loader + Cleanup() error +} + +// Kunstructured allows manipulation of k8s objects +// that do not have Golang structs. +type Kunstructured interface { + Map() map[string]interface{} + SetMap(map[string]interface{}) + Copy() Kunstructured + GetFieldValue(string) (string, error) + MarshalJSON() ([]byte, error) + UnmarshalJSON([]byte) error + GetGvk() gvk.Gvk + GetKind() string + GetName() string + SetName(string) + GetLabels() map[string]string + SetLabels(map[string]string) + GetAnnotations() map[string]string + SetAnnotations(map[string]string) +} + +// KunstructuredFactory makes instances of Kunstructured. +type KunstructuredFactory interface { + SliceFromBytes([]byte) ([]Kunstructured, error) + FromMap(m map[string]interface{}) Kunstructured + MakeConfigMap(args *types.ConfigMapArgs, options *types.GeneratorOptions) (Kunstructured, error) + MakeSecret(args *types.SecretArgs, options *types.GeneratorOptions) (Kunstructured, error) + Set(fs fs.FileSystem, ldr Loader) +} + +// See core.v1.SecretTypeOpaque +const SecretTypeOpaque = "Opaque" diff --git a/vendor/sigs.k8s.io/kustomize/pkg/ifc/transformer/BUILD b/vendor/sigs.k8s.io/kustomize/pkg/ifc/transformer/BUILD new file mode 100644 index 00000000000..624dc8925f6 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/ifc/transformer/BUILD @@ -0,0 +1,27 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = ["factory.go"], + importmap = "k8s.io/kubernetes/vendor/sigs.k8s.io/kustomize/pkg/ifc/transformer", + importpath = "sigs.k8s.io/kustomize/pkg/ifc/transformer", + visibility = ["//visibility:public"], + deps = [ + "//vendor/sigs.k8s.io/kustomize/pkg/resource:go_default_library", + "//vendor/sigs.k8s.io/kustomize/pkg/transformers:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/vendor/sigs.k8s.io/kustomize/pkg/ifc/transformer/factory.go b/vendor/sigs.k8s.io/kustomize/pkg/ifc/transformer/factory.go new file mode 100644 index 00000000000..0a74c280930 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/ifc/transformer/factory.go @@ -0,0 +1,29 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package patch holds miscellaneous interfaces used by kustomize. +package transformer + +import ( + "sigs.k8s.io/kustomize/pkg/resource" + "sigs.k8s.io/kustomize/pkg/transformers" +) + +// Factory makes transformers +type Factory interface { + MakePatchTransformer(slice []*resource.Resource, rf *resource.Factory) (transformers.Transformer, error) + MakeHashTransformer() transformers.Transformer +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/internal/error/BUILD b/vendor/sigs.k8s.io/kustomize/pkg/internal/error/BUILD new file mode 100644 index 00000000000..f46e6424f6f --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/internal/error/BUILD @@ -0,0 +1,30 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = [ + "configmaperror.go", + "kustomizationerror.go", + "patcherror.go", + "resourceerror.go", + "secreterror.go", + "yamlformaterror.go", + ], + importmap = "k8s.io/kubernetes/vendor/sigs.k8s.io/kustomize/pkg/internal/error", + importpath = "sigs.k8s.io/kustomize/pkg/internal/error", + visibility = ["//vendor/sigs.k8s.io/kustomize/pkg:__subpackages__"], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/vendor/sigs.k8s.io/kustomize/pkg/internal/error/configmaperror.go b/vendor/sigs.k8s.io/kustomize/pkg/internal/error/configmaperror.go new file mode 100644 index 00000000000..1d60d78a231 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/internal/error/configmaperror.go @@ -0,0 +1,30 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package error has contextual error types. +package error + +import "fmt" + +// ConfigmapError represents error with a configmap. +type ConfigmapError struct { + Path string + ErrorMsg string +} + +func (e ConfigmapError) Error() string { + return fmt.Sprintf("Kustomization file [%s] encounters a configmap error: %s\n", e.Path, e.ErrorMsg) +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/internal/error/kustomizationerror.go b/vendor/sigs.k8s.io/kustomize/pkg/internal/error/kustomizationerror.go new file mode 100644 index 00000000000..0d53ca9b89e --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/internal/error/kustomizationerror.go @@ -0,0 +1,61 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package error + +import ( + "fmt" +) + +// KustomizationError represents an error with a kustomization. +type KustomizationError struct { + KustomizationPath string + ErrorMsg string +} + +func (ke KustomizationError) Error() string { + return fmt.Sprintf("Kustomization File [%s]: %s\n", ke.KustomizationPath, ke.ErrorMsg) +} + +// KustomizationErrors collects all errors. +type KustomizationErrors struct { + kErrors []error +} + +func (ke *KustomizationErrors) Error() string { + errormsg := "" + for _, e := range ke.kErrors { + errormsg += e.Error() + "\n" + } + return errormsg +} + +// Append adds error to a collection of errors. +func (ke *KustomizationErrors) Append(e error) { + ke.kErrors = append(ke.kErrors, e) +} + +// Get returns all collected errors. +func (ke *KustomizationErrors) Get() []error { + return ke.kErrors +} + +// BatchAppend adds all errors from another KustomizationErrors +func (ke *KustomizationErrors) BatchAppend(e KustomizationErrors) { + for _, err := range e.Get() { + ke.kErrors = append(ke.kErrors, err) + } +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/internal/error/patcherror.go b/vendor/sigs.k8s.io/kustomize/pkg/internal/error/patcherror.go new file mode 100644 index 00000000000..60c9f80e5b5 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/internal/error/patcherror.go @@ -0,0 +1,32 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package error + +import ( + "fmt" +) + +// PatchError represents error during Patch. +type PatchError struct { + KustomizationPath string + PatchFilepath string + ErrorMsg string +} + +func (e PatchError) Error() string { + return fmt.Sprintf("Kustomization file [%s] encounters a patch error for [%s]: %s\n", e.KustomizationPath, e.PatchFilepath, e.ErrorMsg) +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/internal/error/resourceerror.go b/vendor/sigs.k8s.io/kustomize/pkg/internal/error/resourceerror.go new file mode 100644 index 00000000000..ef3566dd1f7 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/internal/error/resourceerror.go @@ -0,0 +1,30 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package error + +import "fmt" + +// ResourceError represents error in a resource. +type ResourceError struct { + KustomizationPath string + ResourceFilepath string + ErrorMsg string +} + +func (e ResourceError) Error() string { + return fmt.Sprintf("Kustomization file [%s] encounters a resource error for [%s]: %s\n", e.KustomizationPath, e.ResourceFilepath, e.ErrorMsg) +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/internal/error/secreterror.go b/vendor/sigs.k8s.io/kustomize/pkg/internal/error/secreterror.go new file mode 100644 index 00000000000..cd72759ce6c --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/internal/error/secreterror.go @@ -0,0 +1,30 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package error + +import "fmt" + +// SecretError represents error with a secret. +type SecretError struct { + KustomizationPath string + // ErrorMsg is an error message + ErrorMsg string +} + +func (e SecretError) Error() string { + return fmt.Sprintf("Kustomization file [%s] encounters a secret error: %s\n", e.KustomizationPath, e.ErrorMsg) +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/internal/error/yamlformaterror.go b/vendor/sigs.k8s.io/kustomize/pkg/internal/error/yamlformaterror.go new file mode 100644 index 00000000000..4c27d30d717 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/internal/error/yamlformaterror.go @@ -0,0 +1,48 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package error has contextual error types. +package error + +import ( + "fmt" + "strings" +) + +// YamlFormatError represents error with yaml file name where json/yaml format error happens. +type YamlFormatError struct { + Path string + ErrorMsg string +} + +func (e YamlFormatError) Error() string { + return fmt.Sprintf("YAML file [%s] encounters a format error.\n%s\n", e.Path, e.ErrorMsg) +} + +// Handler handles YamlFormatError +func Handler(e error, path string) error { + if isYAMLSyntaxError(e) { + return YamlFormatError{ + Path: path, + ErrorMsg: e.Error(), + } + } + return e +} + +func isYAMLSyntaxError(e error) bool { + return strings.Contains(e.Error(), "error converting YAML to JSON") || strings.Contains(e.Error(), "error unmarshaling JSON") +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/loader/BUILD b/vendor/sigs.k8s.io/kustomize/pkg/loader/BUILD new file mode 100644 index 00000000000..6136540d6b6 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/loader/BUILD @@ -0,0 +1,32 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = [ + "fileloader.go", + "gitcloner.go", + "loader.go", + ], + importmap = "k8s.io/kubernetes/vendor/sigs.k8s.io/kustomize/pkg/loader", + importpath = "sigs.k8s.io/kustomize/pkg/loader", + visibility = ["//visibility:public"], + deps = [ + "//vendor/github.com/pkg/errors:go_default_library", + "//vendor/sigs.k8s.io/kustomize/pkg/fs:go_default_library", + "//vendor/sigs.k8s.io/kustomize/pkg/ifc:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/vendor/sigs.k8s.io/kustomize/pkg/loader/fileloader.go b/vendor/sigs.k8s.io/kustomize/pkg/loader/fileloader.go new file mode 100644 index 00000000000..fcf3dc8c3b0 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/loader/fileloader.go @@ -0,0 +1,224 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package loader + +import ( + "fmt" + "log" + "path/filepath" + "strings" + + "sigs.k8s.io/kustomize/pkg/fs" + "sigs.k8s.io/kustomize/pkg/ifc" +) + +// TODO: 2018/Nov/20 remove this before next release. +// Leave only the true path. Retaining only for +// quick revert. +const enforceRelocatable = true + +// fileLoader loads files, returning an array of bytes. +// It also enforces two kustomization requirements: +// +// 1) relocatable +// +// A kustomization and the resources, bases, +// patches, etc. that it depends on should be +// relocatable, so all path specifications +// must be relative, not absolute. The paths +// are taken relative to the location of the +// kusttomization file. +// +// 2) acyclic +// +// There should be no cycles in overlay to base +// relationships, including no cycles between +// git repositories. +// +// The loader has a notion of a current working directory +// (CWD), called 'root', that is independent of the CWD +// of the process. When `Load` is called with a file path +// argument, the load is done relative to this root, +// not relative to the process CWD. +// +// The loader offers a `New` method returning a new loader +// with a new root. The new root can be one of two things, +// a remote git repo URL, or a directory specified relative +// to the current root. In the former case, the remote +// repository is locally cloned, and the new loader is +// rooted on a path in that clone. +// +// Crucially, a root history is used to so that New fails +// if its argument either matches or is a parent of the +// current or any previously used root. +// +// This disallows: +// +// * A base that is a git repository that, in turn, +// specifies a base repository seen previously +// in the loading process (a cycle). +// +// * An overlay depending on a base positioned at or +// above it. I.e. '../foo' is OK, but '.', '..', +// '../..', etc. are disallowed. Allowing such a +// base has no advantages and encourage cycles, +// particularly if some future change were to +// introduce globbing to file specifications in +// the kustomization file. +// +type fileLoader struct { + // Previously visited directories, tracked to + // avoid cycles. The last entry is the current root. + roots []string + // File system utilities. + fSys fs.FileSystem + // Used to clone repositories. + cloner gitCloner + // Used to clean up, as needed. + cleaner func() error +} + +// NewFileLoaderAtCwd returns a loader that loads from ".". +func NewFileLoaderAtCwd(fSys fs.FileSystem) *fileLoader { + return newLoaderOrDie(fSys, ".") +} + +// NewFileLoaderAtRoot returns a loader that loads from "/". +func NewFileLoaderAtRoot(fSys fs.FileSystem) *fileLoader { + return newLoaderOrDie(fSys, "/") +} + +// Root returns the absolute path that is prepended to any +// relative paths used in Load. +func (l *fileLoader) Root() string { + return l.roots[len(l.roots)-1] +} + +func newLoaderOrDie(fSys fs.FileSystem, path string) *fileLoader { + l, err := newFileLoaderAt( + path, fSys, []string{}, simpleGitCloner) + if err != nil { + log.Fatalf("unable to make loader at '%s'; %v", path, err) + } + return l +} + +// newFileLoaderAt returns a new fileLoader with given root. +func newFileLoaderAt( + root string, fSys fs.FileSystem, + roots []string, cloner gitCloner) (*fileLoader, error) { + if root == "" { + return nil, fmt.Errorf( + "loader root cannot be empty") + } + root, err := filepath.Abs(root) + if err != nil { + return nil, fmt.Errorf( + "absolute path error in '%s' : %v", root, err) + } + if !fSys.IsDir(root) { + return nil, fmt.Errorf("absolute root dir '%s' does not exist", root) + } + return &fileLoader{ + roots: append(roots, root), + fSys: fSys, + cloner: cloner, + cleaner: func() error { return nil }, + }, nil +} + +// New returns a new Loader, rooted relative to current loader, +// or rooted in a temp directory holding a git repo clone. +func (l *fileLoader) New(root string) (ifc.Loader, error) { + if root == "" { + return nil, fmt.Errorf("new root cannot be empty") + } + if isRepoUrl(root) { + if err := l.seenBefore(root); err != nil { + return nil, err + } + return newGitLoader(root, l.fSys, l.roots, l.cloner) + } + if enforceRelocatable && filepath.IsAbs(root) { + return nil, fmt.Errorf("new root '%s' cannot be absolute", root) + } + // Get absolute path to squeeze out "..", ".", etc. + // to facilitate the seenBefore test. + absRoot, err := filepath.Abs(filepath.Join(l.Root(), root)) + if err != nil { + return nil, fmt.Errorf( + "problem joining '%s' to '%s': %v", l.Root(), root, err) + } + if err := l.seenBefore(absRoot); err != nil { + return nil, err + } + return newFileLoaderAt(absRoot, l.fSys, l.roots, l.cloner) +} + +// newGitLoader returns a new Loader pinned to a temporary +// directory holding a cloned git repo. +func newGitLoader( + root string, fSys fs.FileSystem, + roots []string, cloner gitCloner) (ifc.Loader, error) { + tmpDirForRepo, pathInRepo, err := cloner(root) + if err != nil { + return nil, err + } + trueRoot := filepath.Join(tmpDirForRepo, pathInRepo) + if !fSys.IsDir(trueRoot) { + return nil, fmt.Errorf( + "something wrong cloning '%s'; unable to find '%s'", + root, trueRoot) + } + return &fileLoader{ + roots: append(roots, root, trueRoot), + fSys: fSys, + cloner: cloner, + cleaner: func() error { return fSys.RemoveAll(tmpDirForRepo) }, + }, nil +} + +// seenBefore tests whether the current or any previously +// visited root begins with the given path. +func (l *fileLoader) seenBefore(path string) error { + for _, r := range l.roots { + if strings.HasPrefix(r, path) { + return fmt.Errorf( + "cycle detected: new root '%s' contains previous root '%s'", + path, r) + } + } + return nil +} + +// Load returns content of file at the given relative path. +func (l *fileLoader) Load(path string) ([]byte, error) { + if filepath.IsAbs(path) { + if enforceRelocatable { + return nil, fmt.Errorf( + "must use relative path; '%s' is absolute", path) + } + } else { + path = filepath.Join(l.Root(), path) + } + return l.fSys.ReadFile(path) +} + +// Cleanup runs the cleaner. +func (l *fileLoader) Cleanup() error { + return l.cleaner() +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/loader/gitcloner.go b/vendor/sigs.k8s.io/kustomize/pkg/loader/gitcloner.go new file mode 100644 index 00000000000..6171aedb1ae --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/loader/gitcloner.go @@ -0,0 +1,133 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package loader + +import ( + "bytes" + "io/ioutil" + "os/exec" + "path/filepath" + "strings" + + "github.com/pkg/errors" +) + +// gitCloner is a function that can clone a git repo. +type gitCloner func(url string) ( + // Directory where the repo is cloned to. + checkoutDir string, + // Relative path in the checkoutDir to location + // of kustomization file. + pathInCoDir string, + // Any error encountered when cloning. + err error) + +// isRepoUrl checks if a string is likely a github repo Url. +func isRepoUrl(arg string) bool { + arg = strings.ToLower(arg) + return !filepath.IsAbs(arg) && + (strings.HasPrefix(arg, "git::") || + strings.HasPrefix(arg, "gh:") || + strings.HasPrefix(arg, "github.com") || + strings.HasPrefix(arg, "git@github.com:") || + strings.Index(arg, "github.com/") > -1) +} + +func makeTmpDir() (string, error) { + return ioutil.TempDir("", "kustomize-") +} + +func simpleGitCloner(spec string) ( + checkoutDir string, pathInCoDir string, err error) { + gitProgram, err := exec.LookPath("git") + if err != nil { + return "", "", errors.Wrap(err, "no 'git' program on path") + } + checkoutDir, err = makeTmpDir() + if err != nil { + return + } + repo, pathInCoDir, gitRef, err := parseGithubUrl(spec) + if err != nil { + return + } + cmd := exec.Command( + gitProgram, + "clone", + "https://github.com/"+repo+".git", + checkoutDir) + var out bytes.Buffer + cmd.Stdout = &out + err = cmd.Run() + if err != nil { + return "", "", + errors.Wrapf(err, "trouble cloning %s", spec) + } + if gitRef == "" { + return + } + cmd = exec.Command(gitProgram, "checkout", gitRef) + cmd.Dir = checkoutDir + err = cmd.Run() + if err != nil { + return "", "", + errors.Wrapf(err, "trouble checking out href %s", gitRef) + } + return checkoutDir, pathInCoDir, nil +} + +const refQuery = "?ref=" + +// From strings like git@github.com:someOrg/someRepo.git or +// https://github.com/someOrg/someRepo?ref=someHash, extract +// the parts. +func parseGithubUrl(n string) ( + repo string, path string, gitRef string, err error) { + for _, p := range []string{ + // Order matters here. + "git::", "gh:", "https://", "http://", + "git@", "github.com:", "github.com/", "gitlab.com/"} { + if strings.ToLower(n[:len(p)]) == p { + n = n[len(p):] + } + } + if strings.HasSuffix(n, ".git") { + n = n[0 : len(n)-len(".git")] + } + i := strings.Index(n, string(filepath.Separator)) + if i < 1 { + return "", "", "", errors.New("no separator") + } + j := strings.Index(n[i+1:], string(filepath.Separator)) + if j >= 0 { + j += i + 1 + repo = n[:j] + path, gitRef = peelQuery(n[j+1:]) + } else { + path = "" + repo, gitRef = peelQuery(n) + } + return +} + +func peelQuery(arg string) (string, string) { + j := strings.Index(arg, refQuery) + if j >= 0 { + return arg[:j], arg[j+len(refQuery):] + } + return arg, "" +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/loader/loader.go b/vendor/sigs.k8s.io/kustomize/pkg/loader/loader.go new file mode 100644 index 00000000000..5e954095dfc --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/loader/loader.go @@ -0,0 +1,33 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package loader has a data loading interface and various implementations. +package loader + +import ( + "sigs.k8s.io/kustomize/pkg/fs" + "sigs.k8s.io/kustomize/pkg/ifc" +) + +// NewLoader returns a Loader. +func NewLoader(root string, fSys fs.FileSystem) (ifc.Loader, error) { + if isRepoUrl(root) { + return newGitLoader( + root, fSys, []string{}, simpleGitCloner) + } + return newFileLoaderAt( + root, fSys, []string{}, simpleGitCloner) +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/patch/BUILD b/vendor/sigs.k8s.io/kustomize/pkg/patch/BUILD new file mode 100644 index 00000000000..d0e41faf46c --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/patch/BUILD @@ -0,0 +1,30 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = [ + "json6902.go", + "strategicmerge.go", + ], + importmap = "k8s.io/kubernetes/vendor/sigs.k8s.io/kustomize/pkg/patch", + importpath = "sigs.k8s.io/kustomize/pkg/patch", + visibility = ["//visibility:public"], + deps = ["//vendor/sigs.k8s.io/kustomize/pkg/gvk:go_default_library"], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [ + ":package-srcs", + "//vendor/sigs.k8s.io/kustomize/pkg/patch/transformer:all-srcs", + ], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/vendor/sigs.k8s.io/kustomize/pkg/patch/json6902.go b/vendor/sigs.k8s.io/kustomize/pkg/patch/json6902.go new file mode 100644 index 00000000000..30912e587df --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/patch/json6902.go @@ -0,0 +1,40 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package patch + +import "sigs.k8s.io/kustomize/pkg/gvk" + +// Json6902 represents a json patch for an object +// with format documented https://tools.ietf.org/html/rfc6902. +type Json6902 struct { + // Target refers to a Kubernetes object that the json patch will be + // applied to. It must refer to a Kubernetes resource under the + // purview of this kustomization. Target should use the + // raw name of the object (the name specified in its YAML, + // before addition of a namePrefix). + Target *Target `json:"target" yaml:"target"` + + // relative file path for a json patch file inside a kustomization + Path string `json:"path,omitempty" yaml:"path,omitempty"` +} + +// Target represents the kubernetes object that the patch is applied to +type Target struct { + gvk.Gvk `json:",inline,omitempty" yaml:",inline,omitempty"` + Namespace string `json:"namespace,omitempty" yaml:"namespace,omitempty"` + Name string `json:"name" yaml:"name"` +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/patch/strategicmerge.go b/vendor/sigs.k8s.io/kustomize/pkg/patch/strategicmerge.go new file mode 100644 index 00000000000..596cc346de1 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/patch/strategicmerge.go @@ -0,0 +1,40 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package patch + +// StrategicMerge represents a relative path to a +// stategic merge patch with the format +// https://github.com/kubernetes/community/blob/master/contributors/devel/strategic-merge-patch.md +type StrategicMerge string + +// Append appends a slice of patch paths to a StrategicMerge slice +func Append(patches []StrategicMerge, paths ...string) []StrategicMerge { + for _, p := range paths { + patches = append(patches, StrategicMerge(p)) + } + return patches +} + +// Exist determines if a patch path exists in a slice of StrategicMerge +func Exist(patches []StrategicMerge, path string) bool { + for _, p := range patches { + if p == StrategicMerge(path) { + return true + } + } + return false +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/patch/transformer/BUILD b/vendor/sigs.k8s.io/kustomize/pkg/patch/transformer/BUILD new file mode 100644 index 00000000000..757567bfa2a --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/patch/transformer/BUILD @@ -0,0 +1,38 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = [ + "factory.go", + "patchjson6902json.go", + "util.go", + ], + importmap = "k8s.io/kubernetes/vendor/sigs.k8s.io/kustomize/pkg/patch/transformer", + importpath = "sigs.k8s.io/kustomize/pkg/patch/transformer", + visibility = ["//visibility:public"], + deps = [ + "//vendor/github.com/evanphx/json-patch:go_default_library", + "//vendor/github.com/ghodss/yaml:go_default_library", + "//vendor/sigs.k8s.io/kustomize/pkg/gvk:go_default_library", + "//vendor/sigs.k8s.io/kustomize/pkg/ifc:go_default_library", + "//vendor/sigs.k8s.io/kustomize/pkg/patch:go_default_library", + "//vendor/sigs.k8s.io/kustomize/pkg/resid:go_default_library", + "//vendor/sigs.k8s.io/kustomize/pkg/resmap:go_default_library", + "//vendor/sigs.k8s.io/kustomize/pkg/resource:go_default_library", + "//vendor/sigs.k8s.io/kustomize/pkg/transformers:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/vendor/sigs.k8s.io/kustomize/pkg/patch/transformer/factory.go b/vendor/sigs.k8s.io/kustomize/pkg/patch/transformer/factory.go new file mode 100644 index 00000000000..b7eb2583911 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/patch/transformer/factory.go @@ -0,0 +1,97 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package transformer + +import ( + "fmt" + "sigs.k8s.io/kustomize/pkg/ifc" + "sigs.k8s.io/kustomize/pkg/resid" + + "github.com/evanphx/json-patch" + "github.com/ghodss/yaml" + "sigs.k8s.io/kustomize/pkg/gvk" + "sigs.k8s.io/kustomize/pkg/patch" + "sigs.k8s.io/kustomize/pkg/transformers" +) + +// PatchJson6902Factory makes Json6902 transformers +type PatchJson6902Factory struct { + loader ifc.Loader +} + +// NewPatchJson6902Factory returns a new PatchJson6902Factory. +func NewPatchJson6902Factory(l ifc.Loader) PatchJson6902Factory { + return PatchJson6902Factory{loader: l} +} + +// MakePatchJson6902Transformer returns a transformer for applying Json6902 patch +func (f PatchJson6902Factory) MakePatchJson6902Transformer(patches []patch.Json6902) (transformers.Transformer, error) { + var ts []transformers.Transformer + for _, p := range patches { + t, err := f.makeOnePatchJson6902Transformer(p) + if err != nil { + return nil, err + } + if t != nil { + ts = append(ts, t) + } + } + return transformers.NewMultiTransformerWithConflictCheck(ts), nil +} + +func (f PatchJson6902Factory) makeOnePatchJson6902Transformer(p patch.Json6902) (transformers.Transformer, error) { + if p.Target == nil { + return nil, fmt.Errorf("must specify the target field in patchesJson6902") + } + if p.Path == "" { + return nil, fmt.Errorf("must specify the path for a json patch file") + } + + targetId := resid.NewResIdWithPrefixNamespace( + gvk.Gvk{ + Group: p.Target.Group, + Version: p.Target.Version, + Kind: p.Target.Kind, + }, + p.Target.Name, + "", + p.Target.Namespace, + ) + + rawOp, err := f.loader.Load(p.Path) + if err != nil { + return nil, err + } + + if !isJsonFormat(rawOp) { + // if it isn't JSON, try to parse it as YAML + rawOp, err = yaml.YAMLToJSON(rawOp) + if err != nil { + return nil, err + } + } + + decodedPatch, err := jsonpatch.DecodePatch(rawOp) + if err != nil { + return nil, err + } + return newPatchJson6902JSONTransformer(targetId, decodedPatch) +} + +func isJsonFormat(data []byte) bool { + return data[0] == '[' +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/patch/transformer/patchjson6902json.go b/vendor/sigs.k8s.io/kustomize/pkg/patch/transformer/patchjson6902json.go new file mode 100644 index 00000000000..6737b959c79 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/patch/transformer/patchjson6902json.go @@ -0,0 +1,61 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package transformer + +import ( + "github.com/evanphx/json-patch" + "sigs.k8s.io/kustomize/pkg/resid" + "sigs.k8s.io/kustomize/pkg/resmap" + "sigs.k8s.io/kustomize/pkg/transformers" +) + +// patchJson6902JSONTransformer applies patches. +type patchJson6902JSONTransformer struct { + target resid.ResId + patch jsonpatch.Patch +} + +var _ transformers.Transformer = &patchJson6902JSONTransformer{} + +// newPatchJson6902JSONTransformer constructs a PatchJson6902 transformer. +func newPatchJson6902JSONTransformer(t resid.ResId, p jsonpatch.Patch) (transformers.Transformer, error) { + if len(p) == 0 { + return transformers.NewNoOpTransformer(), nil + } + return &patchJson6902JSONTransformer{target: t, patch: p}, nil +} + +// Transform apply the json patches on top of the base resources. +func (t *patchJson6902JSONTransformer) Transform(baseResourceMap resmap.ResMap) error { + obj, err := findTargetObj(baseResourceMap, t.target) + if obj == nil { + return err + } + rawObj, err := obj.MarshalJSON() + if err != nil { + return err + } + modifiedObj, err := t.patch.Apply(rawObj) + if err != nil { + return err + } + err = obj.UnmarshalJSON(modifiedObj) + if err != nil { + return err + } + return nil +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/patch/transformer/util.go b/vendor/sigs.k8s.io/kustomize/pkg/patch/transformer/util.go new file mode 100644 index 00000000000..aaed1e1cc62 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/patch/transformer/util.go @@ -0,0 +1,46 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package transformer + +import ( + "fmt" + + "sigs.k8s.io/kustomize/pkg/resid" + "sigs.k8s.io/kustomize/pkg/resmap" + "sigs.k8s.io/kustomize/pkg/resource" +) + +func findTargetObj(m resmap.ResMap, targetId resid.ResId) (*resource.Resource, error) { + matchedIds := m.FindByGVKN(targetId) + if targetId.Namespace() != "" { + var ids []resid.ResId + for _, id := range matchedIds { + if id.Namespace() == targetId.Namespace() { + ids = append(ids, id) + } + } + matchedIds = ids + } + + if len(matchedIds) == 0 { + return nil, fmt.Errorf("couldn't find any object to apply the json patch %v", targetId) + } + if len(matchedIds) > 1 { + return nil, fmt.Errorf("found multiple objects that the patch can apply %v", matchedIds) + } + return m[matchedIds[0]], nil +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/resid/BUILD b/vendor/sigs.k8s.io/kustomize/pkg/resid/BUILD new file mode 100644 index 00000000000..f8f9f627e92 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/resid/BUILD @@ -0,0 +1,24 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = ["resid.go"], + importmap = "k8s.io/kubernetes/vendor/sigs.k8s.io/kustomize/pkg/resid", + importpath = "sigs.k8s.io/kustomize/pkg/resid", + visibility = ["//visibility:public"], + deps = ["//vendor/sigs.k8s.io/kustomize/pkg/gvk:go_default_library"], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/vendor/sigs.k8s.io/kustomize/pkg/resid/resid.go b/vendor/sigs.k8s.io/kustomize/pkg/resid/resid.go new file mode 100644 index 00000000000..47df4efc66e --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/resid/resid.go @@ -0,0 +1,220 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package resid + +import ( + "fmt" + "strings" + + "sigs.k8s.io/kustomize/pkg/gvk" +) + +// ResId conflates GroupVersionKind with a textual name to uniquely identify a kubernetes resource (object). +type ResId struct { + // Gvk of the resource. + gvKind gvk.Gvk + // original name of the resource before transformation. + name string + // namePrefix of the resource + // an untransformed resource has no prefix, fully transformed resource has an arbitrary number of prefixes + // concatenated together. + prefix string + // nameSuffix of the resource + // an untransformed resource has no suffix, fully transformed resource has an arbitrary number of suffixes + // concatenated together. + suffix string + // namespace the resource belongs to + // an untransformed resource has no namespace, fully transformed resource has the namespace from + // the top most overlay + namespace string +} + +// NewResIdWithPrefixSuffixNamespace creates new resource identifier with a prefix, suffix and a namespace +func NewResIdWithPrefixSuffixNamespace(k gvk.Gvk, n, p, s, ns string) ResId { + return ResId{gvKind: k, name: n, prefix: p, suffix: s, namespace: ns} +} + +// NewResIdWithPrefixNamespace creates new resource identifier with a prefix and a namespace +func NewResIdWithPrefixNamespace(k gvk.Gvk, n, p, ns string) ResId { + return ResId{gvKind: k, name: n, prefix: p, namespace: ns} +} + +// NewResIdWithSuffixNamespace creates new resource identifier with a suffix and a namespace +func NewResIdWithSuffixNamespace(k gvk.Gvk, n, s, ns string) ResId { + return ResId{gvKind: k, name: n, suffix: s, namespace: ns} +} + +// NewResIdWithPrefixSuffix creates new resource identifier with a prefix and suffix +func NewResIdWithPrefixSuffix(k gvk.Gvk, n, p, s string) ResId { + return ResId{gvKind: k, name: n, prefix: p, suffix: s} +} + +// NewResIdWithPrefix creates new resource identifier with a prefix +func NewResIdWithPrefix(k gvk.Gvk, n, p string) ResId { + return ResId{gvKind: k, name: n, prefix: p} +} + +// NewResIdWithSuffix creates new resource identifier with a suffix +func NewResIdWithSuffix(k gvk.Gvk, n, s string) ResId { + return ResId{gvKind: k, name: n, suffix: s} +} + +// NewResId creates new resource identifier +func NewResId(k gvk.Gvk, n string) ResId { + return ResId{gvKind: k, name: n} +} + +// NewResIdKindOnly creates new resource identifier +func NewResIdKindOnly(k string, n string) ResId { + return ResId{gvKind: gvk.FromKind(k), name: n} +} + +const ( + noNamespace = "noNamespace" + noPrefix = "noPrefix" + noName = "noName" + noSuffix = "noSuffix" + separator = "|" +) + +// String of ResId based on GVK, name and prefix +func (n ResId) String() string { + ns := n.namespace + if ns == "" { + ns = noNamespace + } + p := n.prefix + if p == "" { + p = noPrefix + } + nm := n.name + if nm == "" { + nm = noName + } + s := n.suffix + if s == "" { + s = noSuffix + } + + return strings.Join( + []string{n.gvKind.String(), ns, p, nm, s}, separator) +} + +// GvknString of ResId based on GVK and name +func (n ResId) GvknString() string { + return n.gvKind.String() + separator + n.name +} + +// GvknEquals return if two ResId have the same Group/Version/Kind and name +// The comparison excludes prefix and suffix +func (n ResId) GvknEquals(id ResId) bool { + return n.gvKind.Equals(id.gvKind) && n.name == id.name +} + +// Gvk returns Group/Version/Kind of the resource. +func (n ResId) Gvk() gvk.Gvk { + return n.gvKind +} + +// Name returns resource name. +func (n ResId) Name() string { + return n.name +} + +// NameWithPrefixSuffix returns resource name with prefix and suffix. +func (n ResId) NameWithPrefixSuffix() string { + prefix := strings.Join(n.prefixList(), "") + suffix := strings.Join(n.suffixList(), "") + return fmt.Sprintf("%s%s%s", prefix, n.name, suffix) +} + +// Prefix returns name prefix. +func (n ResId) Prefix() string { + return n.prefix +} + +// Suffix returns name suffix. +func (n ResId) Suffix() string { + return n.suffix +} + +// Namespace returns resource namespace. +func (n ResId) Namespace() string { + return n.namespace +} + +// CopyWithNewPrefixSuffix make a new copy from current ResId and append a new prefix and suffix +func (n ResId) CopyWithNewPrefixSuffix(p, s string) ResId { + prefix := n.prefix + if p != "" { + prefix = n.concatPrefix(p) + } + suffix := n.suffix + if s != "" { + suffix = n.concatSuffix(s) + } + return ResId{gvKind: n.gvKind, name: n.name, prefix: prefix, suffix: suffix, namespace: n.namespace} +} + +// CopyWithNewNamespace make a new copy from current ResId and set a new namespace +func (n ResId) CopyWithNewNamespace(ns string) ResId { + return ResId{gvKind: n.gvKind, name: n.name, prefix: n.prefix, suffix: n.suffix, namespace: ns} +} + +// HasSameLeftmostPrefix check if two ResIds have the same +// left most prefix. +func (n ResId) HasSameLeftmostPrefix(id ResId) bool { + prefixes1 := n.prefixList() + prefixes2 := id.prefixList() + return prefixes1[0] == prefixes2[0] +} + +// HasSameRightmostSuffix check if two ResIds have the same +// right most suffix. +func (n ResId) HasSameRightmostSuffix(id ResId) bool { + suffixes1 := n.suffixList() + suffixes2 := id.suffixList() + return suffixes1[len(suffixes1)-1] == suffixes2[len(suffixes2)-1] +} + +func (n ResId) concatPrefix(p string) string { + if p == "" { + return n.prefix + } + if n.prefix == "" { + return p + } + return p + ":" + n.prefix +} + +func (n ResId) concatSuffix(s string) string { + if s == "" { + return n.suffix + } + if n.suffix == "" { + return s + } + return n.suffix + ":" + s +} + +func (n ResId) prefixList() []string { + return strings.Split(n.prefix, ":") +} + +func (n ResId) suffixList() []string { + return strings.Split(n.suffix, ":") +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/resmap/BUILD b/vendor/sigs.k8s.io/kustomize/pkg/resmap/BUILD new file mode 100644 index 00000000000..3252dd666fa --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/resmap/BUILD @@ -0,0 +1,37 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = [ + "factory.go", + "idslice.go", + "resmap.go", + ], + importmap = "k8s.io/kubernetes/vendor/sigs.k8s.io/kustomize/pkg/resmap", + importpath = "sigs.k8s.io/kustomize/pkg/resmap", + visibility = ["//visibility:public"], + deps = [ + "//vendor/github.com/ghodss/yaml:go_default_library", + "//vendor/github.com/pkg/errors:go_default_library", + "//vendor/sigs.k8s.io/kustomize/pkg/fs:go_default_library", + "//vendor/sigs.k8s.io/kustomize/pkg/ifc:go_default_library", + "//vendor/sigs.k8s.io/kustomize/pkg/internal/error:go_default_library", + "//vendor/sigs.k8s.io/kustomize/pkg/resid:go_default_library", + "//vendor/sigs.k8s.io/kustomize/pkg/resource:go_default_library", + "//vendor/sigs.k8s.io/kustomize/pkg/types:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/vendor/sigs.k8s.io/kustomize/pkg/resmap/factory.go b/vendor/sigs.k8s.io/kustomize/pkg/resmap/factory.go new file mode 100644 index 00000000000..9083a37eac5 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/resmap/factory.go @@ -0,0 +1,124 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package resmap + +import ( + "fmt" + + "github.com/pkg/errors" + "sigs.k8s.io/kustomize/pkg/fs" + "sigs.k8s.io/kustomize/pkg/ifc" + internal "sigs.k8s.io/kustomize/pkg/internal/error" + "sigs.k8s.io/kustomize/pkg/resource" + "sigs.k8s.io/kustomize/pkg/types" +) + +// Factory makes instances of ResMap. +type Factory struct { + resF *resource.Factory +} + +// NewFactory returns a new resmap.Factory. +func NewFactory(rf *resource.Factory) *Factory { + return &Factory{resF: rf} +} + +// RF returns a resource.Factory. +func (rmF *Factory) RF() *resource.Factory { + return rmF.resF +} + +// FromFiles returns a ResMap given a resource path slice. +func (rmF *Factory) FromFiles( + loader ifc.Loader, paths []string) (ResMap, error) { + var result []ResMap + for _, path := range paths { + content, err := loader.Load(path) + if err != nil { + return nil, errors.Wrap(err, "Load from path "+path+" failed") + } + res, err := rmF.newResMapFromBytes(content) + if err != nil { + return nil, internal.Handler(err, path) + } + result = append(result, res) + } + return MergeWithoutOverride(result...) +} + +// newResMapFromBytes decodes a list of objects in byte array format. +func (rmF *Factory) newResMapFromBytes(b []byte) (ResMap, error) { + resources, err := rmF.resF.SliceFromBytes(b) + if err != nil { + return nil, err + } + + result := ResMap{} + for _, res := range resources { + id := res.Id() + if _, found := result[id]; found { + return result, fmt.Errorf("GroupVersionKindName: %#v already exists b the map", id) + } + result[id] = res + } + return result, nil +} + +// NewResMapFromConfigMapArgs returns a Resource slice given +// a configmap metadata slice from kustomization file. +func (rmF *Factory) NewResMapFromConfigMapArgs(argList []types.ConfigMapArgs, options *types.GeneratorOptions) (ResMap, error) { + var resources []*resource.Resource + for _, args := range argList { + res, err := rmF.resF.MakeConfigMap(&args, options) + if err != nil { + return nil, errors.Wrap(err, "NewResMapFromConfigMapArgs") + } + resources = append(resources, res) + } + return newResMapFromResourceSlice(resources) +} + +// NewResMapFromSecretArgs takes a SecretArgs slice, generates +// secrets from each entry, and accumulates them in a ResMap. +func (rmF *Factory) NewResMapFromSecretArgs(argsList []types.SecretArgs, options *types.GeneratorOptions) (ResMap, error) { + var resources []*resource.Resource + for _, args := range argsList { + res, err := rmF.resF.MakeSecret(&args, options) + if err != nil { + return nil, errors.Wrap(err, "NewResMapFromSecretArgs") + } + resources = append(resources, res) + } + return newResMapFromResourceSlice(resources) +} + +// Set sets the filesystem and loader for the underlying factory +func (rmF *Factory) Set(fs fs.FileSystem, ldr ifc.Loader) { + rmF.resF.Set(fs, ldr) +} + +func newResMapFromResourceSlice(resources []*resource.Resource) (ResMap, error) { + result := ResMap{} + for _, res := range resources { + id := res.Id() + if _, found := result[id]; found { + return nil, fmt.Errorf("duplicated %#v is not allowed", id) + } + result[id] = res + } + return result, nil +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/resmap/idslice.go b/vendor/sigs.k8s.io/kustomize/pkg/resmap/idslice.go new file mode 100644 index 00000000000..cdf759203bd --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/resmap/idslice.go @@ -0,0 +1,37 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package resmap + +import ( + "sort" + + "sigs.k8s.io/kustomize/pkg/resid" +) + +// IdSlice implements the sort interface. +type IdSlice []resid.ResId + +var _ sort.Interface = IdSlice{} + +func (a IdSlice) Len() int { return len(a) } +func (a IdSlice) Swap(i, j int) { a[i], a[j] = a[j], a[i] } +func (a IdSlice) Less(i, j int) bool { + if !a[i].Gvk().Equals(a[j].Gvk()) { + return a[i].Gvk().IsLessThan(a[j].Gvk()) + } + return a[i].String() < a[j].String() +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/resmap/resmap.go b/vendor/sigs.k8s.io/kustomize/pkg/resmap/resmap.go new file mode 100644 index 00000000000..68c409063d9 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/resmap/resmap.go @@ -0,0 +1,213 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package resmap implements a map from ResId to Resource that tracks all resources in a kustomization. +package resmap + +import ( + "bytes" + "fmt" + "log" + "reflect" + "sort" + + "github.com/ghodss/yaml" + "sigs.k8s.io/kustomize/pkg/ifc" + "sigs.k8s.io/kustomize/pkg/resid" + "sigs.k8s.io/kustomize/pkg/resource" +) + +// ResMap is a map from ResId to Resource. +type ResMap map[resid.ResId]*resource.Resource + +// FindByGVKN find the matched ResIds by Group/Version/Kind and Name +func (m ResMap) FindByGVKN(inputId resid.ResId) []resid.ResId { + var result []resid.ResId + for id := range m { + if id.GvknEquals(inputId) { + result = append(result, id) + } + } + return result +} + +// DemandOneMatchForId find the matched resource by Group/Version/Kind and Name +func (m ResMap) DemandOneMatchForId(inputId resid.ResId) (*resource.Resource, bool) { + result := m.FindByGVKN(inputId) + if len(result) == 1 { + return m[result[0]], true + } + return nil, false +} + +// EncodeAsYaml encodes a ResMap to YAML; encoded objects separated by `---`. +func (m ResMap) EncodeAsYaml() ([]byte, error) { + var ids []resid.ResId + for id := range m { + ids = append(ids, id) + } + sort.Sort(IdSlice(ids)) + + firstObj := true + var b []byte + buf := bytes.NewBuffer(b) + for _, id := range ids { + obj := m[id] + out, err := yaml.Marshal(obj.Map()) + if err != nil { + return nil, err + } + if firstObj { + firstObj = false + } else { + _, err = buf.WriteString("---\n") + if err != nil { + return nil, err + } + } + _, err = buf.Write(out) + if err != nil { + return nil, err + } + } + return buf.Bytes(), nil +} + +// ErrorIfNotEqual returns error if maps are not equal. +func (m ResMap) ErrorIfNotEqual(m2 ResMap) error { + if len(m) != len(m2) { + var keySet1 []resid.ResId + var keySet2 []resid.ResId + for id := range m { + keySet1 = append(keySet1, id) + } + for id := range m2 { + keySet2 = append(keySet2, id) + } + return fmt.Errorf("maps has different number of entries: %#v doesn't equals %#v", keySet1, keySet2) + } + for id, obj1 := range m { + obj2, found := m2[id] + if !found { + return fmt.Errorf("%#v doesn't exist in %#v", id, m2) + } + if !reflect.DeepEqual(obj1, obj2) { + return fmt.Errorf("%#v doesn't deep equal %#v", obj1, obj2) + } + } + return nil +} + +// DeepCopy clone the resmap into a new one +func (m ResMap) DeepCopy(rf *resource.Factory) ResMap { + mcopy := make(ResMap) + for id, obj := range m { + mcopy[id] = rf.FromKunstructured(obj.Copy()) + mcopy[id].SetBehavior(obj.Behavior()) + } + return mcopy +} + +// FilterBy returns a subset ResMap containing ResIds with +// the same namespace and leftmost name prefix and rightmost name +// as the inputId. If inputId is a cluster level resource, this +// returns the original ResMap. +func (m ResMap) FilterBy(inputId resid.ResId) ResMap { + if inputId.Gvk().IsClusterKind() { + return m + } + result := ResMap{} + for id, res := range m { + if id.Namespace() == inputId.Namespace() && id.HasSameLeftmostPrefix(inputId) && id.HasSameRightmostSuffix(inputId) { + result[id] = res + } + } + return result +} + +// MergeWithoutOverride combines multiple ResMap instances, failing on key collision +// and skipping nil maps. In case if all of the maps are nil, an empty ResMap is returned. +func MergeWithoutOverride(maps ...ResMap) (ResMap, error) { + result := ResMap{} + for _, m := range maps { + if m == nil { + continue + } + for id, res := range m { + if _, found := result[id]; found { + return nil, fmt.Errorf("id '%q' already used", id) + } + result[id] = res + } + } + return result, nil +} + +// MergeWithOverride combines multiple ResMap instances, allowing and sometimes +// demanding certain collisions and skipping nil maps. +// A collision would be demanded, say, when a generated ConfigMap has the +// "replace" option in its generation instructions, meaning it is supposed +// to replace something from the raw resources list. +// If all of the maps are nil, an empty ResMap is returned. +// When looping over the instances to combine them, if a resource id for resource X +// is found to be already in the combined map, then the behavior field for X +// must be BehaviorMerge or BehaviorReplace. If X is not in the map, then it's +// behavior cannot be merge or replace. +func MergeWithOverride(maps ...ResMap) (ResMap, error) { + result := maps[0] + if result == nil { + result = ResMap{} + } + for _, m := range maps[1:] { + if m == nil { + continue + } + for id, r := range m { + matchedId := result.FindByGVKN(id) + if len(matchedId) == 1 { + id = matchedId[0] + switch r.Behavior() { + case ifc.BehaviorReplace: + log.Printf( + "Replace %v with %v", result[id].Map(), r.Map()) + r.Replace(result[id]) + result[id] = r + result[id].SetBehavior(ifc.BehaviorCreate) + case ifc.BehaviorMerge: + log.Printf( + "Merging %v with %v", result[id].Map(), r.Map()) + r.Merge(result[id]) + result[id] = r + log.Printf( + "Merged object is %v", result[id].Map()) + result[id].SetBehavior(ifc.BehaviorCreate) + default: + return nil, fmt.Errorf("id %#v exists; must merge or replace", id) + } + } else if len(matchedId) == 0 { + switch r.Behavior() { + case ifc.BehaviorMerge, ifc.BehaviorReplace: + return nil, fmt.Errorf("id %#v does not exist; cannot merge or replace", id) + default: + result[id] = r + } + } else { + return nil, fmt.Errorf("merge conflict, found multiple objects %v the Resmap %v can merge into", matchedId, id) + } + } + } + return result, nil +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/resource/BUILD b/vendor/sigs.k8s.io/kustomize/pkg/resource/BUILD new file mode 100644 index 00000000000..72e402f6b70 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/resource/BUILD @@ -0,0 +1,34 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = [ + "factory.go", + "resource.go", + ], + importmap = "k8s.io/kubernetes/vendor/sigs.k8s.io/kustomize/pkg/resource", + importpath = "sigs.k8s.io/kustomize/pkg/resource", + visibility = ["//visibility:public"], + deps = [ + "//vendor/sigs.k8s.io/kustomize/pkg/fs:go_default_library", + "//vendor/sigs.k8s.io/kustomize/pkg/ifc:go_default_library", + "//vendor/sigs.k8s.io/kustomize/pkg/internal/error:go_default_library", + "//vendor/sigs.k8s.io/kustomize/pkg/patch:go_default_library", + "//vendor/sigs.k8s.io/kustomize/pkg/resid:go_default_library", + "//vendor/sigs.k8s.io/kustomize/pkg/types:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/vendor/sigs.k8s.io/kustomize/pkg/resource/factory.go b/vendor/sigs.k8s.io/kustomize/pkg/resource/factory.go new file mode 100644 index 00000000000..2d9da9c66ba --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/resource/factory.go @@ -0,0 +1,116 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package resource + +import ( + "log" + + "sigs.k8s.io/kustomize/pkg/fs" + "sigs.k8s.io/kustomize/pkg/ifc" + internal "sigs.k8s.io/kustomize/pkg/internal/error" + "sigs.k8s.io/kustomize/pkg/patch" + "sigs.k8s.io/kustomize/pkg/types" +) + +// Factory makes instances of Resource. +type Factory struct { + kf ifc.KunstructuredFactory +} + +// NewFactory makes an instance of Factory. +func NewFactory(kf ifc.KunstructuredFactory) *Factory { + return &Factory{kf: kf} +} + +// FromMap returns a new instance of Resource. +func (rf *Factory) FromMap(m map[string]interface{}) *Resource { + return &Resource{ + Kunstructured: rf.kf.FromMap(m), + b: ifc.BehaviorUnspecified} +} + +// FromKunstructured returns a new instance of Resource. +func (rf *Factory) FromKunstructured( + u ifc.Kunstructured) *Resource { + if u == nil { + log.Fatal("unstruct ifc must not be null") + } + return &Resource{Kunstructured: u, b: ifc.BehaviorUnspecified} +} + +// SliceFromPatches returns a slice of resources given a patch path +// slice from a kustomization file. +func (rf *Factory) SliceFromPatches( + ldr ifc.Loader, paths []patch.StrategicMerge) ([]*Resource, error) { + var result []*Resource + for _, path := range paths { + content, err := ldr.Load(string(path)) + if err != nil { + return nil, err + } + res, err := rf.SliceFromBytes(content) + if err != nil { + return nil, internal.Handler(err, string(path)) + } + result = append(result, res...) + } + return result, nil +} + +// SliceFromBytes unmarshalls bytes into a Resource slice. +func (rf *Factory) SliceFromBytes(in []byte) ([]*Resource, error) { + kunStructs, err := rf.kf.SliceFromBytes(in) + if err != nil { + return nil, err + } + var result []*Resource + for _, u := range kunStructs { + result = append(result, rf.FromKunstructured(u)) + } + return result, nil +} + +// Set sets the filesystem and loader for the underlying factory +func (rf *Factory) Set(fs fs.FileSystem, ldr ifc.Loader) { + rf.kf.Set(fs, ldr) +} + +// MakeConfigMap makes an instance of Resource for ConfigMap +func (rf *Factory) MakeConfigMap(args *types.ConfigMapArgs, options *types.GeneratorOptions) (*Resource, error) { + u, err := rf.kf.MakeConfigMap(args, options) + if err != nil { + return nil, err + } + return &Resource{Kunstructured: u, b: fixBehavior(args.Behavior)}, nil +} + +// MakeSecret makes an instance of Resource for Secret +func (rf *Factory) MakeSecret(args *types.SecretArgs, options *types.GeneratorOptions) (*Resource, error) { + u, err := rf.kf.MakeSecret(args, options) + if err != nil { + return nil, err + } + return &Resource{Kunstructured: u, b: fixBehavior(args.Behavior)}, nil +} + +func fixBehavior(s string) ifc.GenerationBehavior { + b := ifc.NewGenerationBehavior(s) + if b == ifc.BehaviorUnspecified { + return ifc.BehaviorCreate + } + return b +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/resource/resource.go b/vendor/sigs.k8s.io/kustomize/pkg/resource/resource.go new file mode 100644 index 00000000000..e952312b803 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/resource/resource.go @@ -0,0 +1,103 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package resource implements representations of k8s API resources as "unstructured" objects. +package resource + +import ( + "strings" + + "sigs.k8s.io/kustomize/pkg/ifc" + "sigs.k8s.io/kustomize/pkg/resid" +) + +// Resource is map representation of a Kubernetes API resource object +// paired with a GenerationBehavior. +type Resource struct { + ifc.Kunstructured + b ifc.GenerationBehavior +} + +// String returns resource as JSON. +func (r *Resource) String() string { + bs, err := r.MarshalJSON() + if err != nil { + return "<" + err.Error() + ">" + } + return r.b.String() + ":" + strings.TrimSpace(string(bs)) +} + +// Behavior returns the behavior for the resource. +func (r *Resource) Behavior() ifc.GenerationBehavior { + return r.b +} + +// SetBehavior changes the resource to the new behavior +func (r *Resource) SetBehavior(b ifc.GenerationBehavior) *Resource { + r.b = b + return r +} + +// IsGenerated checks if the resource is generated from a generator +func (r *Resource) IsGenerated() bool { + return r.b != ifc.BehaviorUnspecified +} + +// Id returns the ResId for the resource. +func (r *Resource) Id() resid.ResId { + namespace, _ := r.GetFieldValue("metadata.namespace") + return resid.NewResIdWithPrefixNamespace(r.GetGvk(), r.GetName(), "", namespace) +} + +// Merge performs merge with other resource. +func (r *Resource) Merge(other *Resource) { + r.Replace(other) + mergeConfigmap(r.Map(), other.Map(), r.Map()) +} + +// Replace performs replace with other resource. +func (r *Resource) Replace(other *Resource) { + r.SetLabels(mergeStringMaps(other.GetLabels(), r.GetLabels())) + r.SetAnnotations( + mergeStringMaps(other.GetAnnotations(), r.GetAnnotations())) + r.SetName(other.GetName()) +} + +// TODO: Add BinaryData once we sync to new k8s.io/api +func mergeConfigmap( + mergedTo map[string]interface{}, + maps ...map[string]interface{}) { + mergedMap := map[string]interface{}{} + for _, m := range maps { + datamap, ok := m["data"].(map[string]interface{}) + if ok { + for key, value := range datamap { + mergedMap[key] = value + } + } + } + mergedTo["data"] = mergedMap +} + +func mergeStringMaps(maps ...map[string]string) map[string]string { + result := map[string]string{} + for _, m := range maps { + for key, value := range m { + result[key] = value + } + } + return result +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/target/BUILD b/vendor/sigs.k8s.io/kustomize/pkg/target/BUILD new file mode 100644 index 00000000000..d7eeec3afa5 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/target/BUILD @@ -0,0 +1,39 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = ["kusttarget.go"], + importmap = "k8s.io/kubernetes/vendor/sigs.k8s.io/kustomize/pkg/target", + importpath = "sigs.k8s.io/kustomize/pkg/target", + visibility = ["//visibility:public"], + deps = [ + "//vendor/github.com/ghodss/yaml:go_default_library", + "//vendor/github.com/pkg/errors:go_default_library", + "//vendor/sigs.k8s.io/kustomize/pkg/constants:go_default_library", + "//vendor/sigs.k8s.io/kustomize/pkg/fs:go_default_library", + "//vendor/sigs.k8s.io/kustomize/pkg/ifc:go_default_library", + "//vendor/sigs.k8s.io/kustomize/pkg/ifc/transformer:go_default_library", + "//vendor/sigs.k8s.io/kustomize/pkg/internal/error:go_default_library", + "//vendor/sigs.k8s.io/kustomize/pkg/patch/transformer:go_default_library", + "//vendor/sigs.k8s.io/kustomize/pkg/resid:go_default_library", + "//vendor/sigs.k8s.io/kustomize/pkg/resmap:go_default_library", + "//vendor/sigs.k8s.io/kustomize/pkg/resource:go_default_library", + "//vendor/sigs.k8s.io/kustomize/pkg/transformers:go_default_library", + "//vendor/sigs.k8s.io/kustomize/pkg/transformers/config:go_default_library", + "//vendor/sigs.k8s.io/kustomize/pkg/types:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/vendor/sigs.k8s.io/kustomize/pkg/target/kusttarget.go b/vendor/sigs.k8s.io/kustomize/pkg/target/kusttarget.go new file mode 100644 index 00000000000..6219581ca82 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/target/kusttarget.go @@ -0,0 +1,383 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package target implements state for the set of all resources being customized. +package target + +import ( + "bytes" + "encoding/json" + "fmt" + "log" + "strings" + + "github.com/ghodss/yaml" + "github.com/pkg/errors" + "sigs.k8s.io/kustomize/pkg/constants" + "sigs.k8s.io/kustomize/pkg/fs" + "sigs.k8s.io/kustomize/pkg/ifc" + "sigs.k8s.io/kustomize/pkg/ifc/transformer" + interror "sigs.k8s.io/kustomize/pkg/internal/error" + patchtransformer "sigs.k8s.io/kustomize/pkg/patch/transformer" + "sigs.k8s.io/kustomize/pkg/resid" + "sigs.k8s.io/kustomize/pkg/resmap" + "sigs.k8s.io/kustomize/pkg/resource" + "sigs.k8s.io/kustomize/pkg/transformers" + "sigs.k8s.io/kustomize/pkg/transformers/config" + "sigs.k8s.io/kustomize/pkg/types" +) + +// KustTarget encapsulates the entirety of a kustomization build. +type KustTarget struct { + kustomization *types.Kustomization + ldr ifc.Loader + fSys fs.FileSystem + rFactory *resmap.Factory + tConfig *config.TransformerConfig + tFactory transformer.Factory +} + +// NewKustTarget returns a new instance of KustTarget primed with a Loader. +func NewKustTarget( + ldr ifc.Loader, fSys fs.FileSystem, + rFactory *resmap.Factory, + tFactory transformer.Factory) (*KustTarget, error) { + content, err := loadKustFile(ldr) + if err != nil { + return nil, err + } + + var k types.Kustomization + err = unmarshal(content, &k) + if err != nil { + return nil, err + } + k.DealWithDeprecatedFields() + tConfig, err := makeTransformerConfig(ldr, k.Configurations) + if err != nil { + return nil, err + } + return &KustTarget{ + kustomization: &k, + ldr: ldr, + fSys: fSys, + rFactory: rFactory, + tConfig: tConfig, + tFactory: tFactory, + }, nil +} + +func unmarshal(y []byte, o interface{}) error { + j, err := yaml.YAMLToJSON(y) + if err != nil { + return err + } + dec := json.NewDecoder(bytes.NewReader(j)) + dec.DisallowUnknownFields() + return dec.Decode(o) +} + +// makeTransformerConfig returns a complete TransformerConfig object from either files +// or the default configs +func makeTransformerConfig(ldr ifc.Loader, paths []string) (*config.TransformerConfig, error) { + if paths == nil || len(paths) == 0 { + return config.NewFactory(nil).DefaultConfig(), nil + } + return config.NewFactory(ldr).FromFiles(paths) +} + +// MakeCustomizedResMap creates a ResMap per kustomization instructions. +// The Resources in the returned ResMap are fully customized. +func (kt *KustTarget) MakeCustomizedResMap() (resmap.ResMap, error) { + m, err := kt.loadCustomizedResMap() + if err != nil { + return nil, err + } + return kt.resolveRefsToGeneratedResources(m) +} + +// resolveRefsToGeneratedResources fixes all name references. +func (kt *KustTarget) resolveRefsToGeneratedResources(m resmap.ResMap) (resmap.ResMap, error) { + if kt.kustomization.GeneratorOptions == nil || + !kt.kustomization.GeneratorOptions.DisableNameSuffixHash { + // This effects only generated resources. + // It changes only the Name field in the + // resource held in the ResMap's value, not + // the Name in the key in the ResMap. + err := kt.tFactory.MakeHashTransformer().Transform(m) + if err != nil { + return nil, err + } + } + var r []transformers.Transformer + t, err := transformers.NewNameReferenceTransformer(kt.tConfig.NameReference) + if err != nil { + return nil, err + } + r = append(r, t) + + refVars, err := kt.resolveRefVars(m) + if err != nil { + return nil, err + } + t = transformers.NewRefVarTransformer(refVars, kt.tConfig.VarReference) + r = append(r, t) + + err = transformers.NewMultiTransformer(r).Transform(m) + if err != nil { + return nil, err + } + return m, nil +} + +// loadCustomizedResMap loads and customizes resources to build a ResMap. +func (kt *KustTarget) loadCustomizedResMap() (resmap.ResMap, error) { + errs := &interror.KustomizationErrors{} + result, err := kt.loadResMapFromBasesAndResources() + if err != nil { + errs.Append(errors.Wrap(err, "loadResMapFromBasesAndResources")) + } + crdTc, err := config.NewFactory(kt.ldr).LoadCRDs(kt.kustomization.Crds) + kt.tConfig = kt.tConfig.Merge(crdTc) + if err != nil { + errs.Append(errors.Wrap(err, "LoadCRDs")) + } + resMap, err := kt.generateConfigMapsAndSecrets(errs) + if err != nil { + errs.Append(errors.Wrap(err, "generateConfigMapsAndSecrets")) + } + result, err = resmap.MergeWithOverride(result, resMap) + if err != nil { + return nil, err + } + + patches, err := kt.rFactory.RF().SliceFromPatches( + kt.ldr, kt.kustomization.PatchesStrategicMerge) + if err != nil { + errs.Append(errors.Wrap(err, "SliceFromPatches")) + } + if len(errs.Get()) > 0 { + return nil, errs + } + + var r []transformers.Transformer + t, err := kt.newTransformer(patches) + if err != nil { + return nil, err + } + r = append(r, t) + t, err = patchtransformer.NewPatchJson6902Factory(kt.ldr). + MakePatchJson6902Transformer(kt.kustomization.PatchesJson6902) + if err != nil { + return nil, err + } + r = append(r, t) + t, err = transformers.NewImageTagTransformer(kt.kustomization.ImageTags) + if err != nil { + return nil, err + } + r = append(r, t) + + err = transformers.NewMultiTransformer(r).Transform(result) + if err != nil { + return nil, err + } + return result, nil +} + +func (kt *KustTarget) generateConfigMapsAndSecrets( + errs *interror.KustomizationErrors) (resmap.ResMap, error) { + kt.rFactory.Set(kt.fSys, kt.ldr) + cms, err := kt.rFactory.NewResMapFromConfigMapArgs( + kt.kustomization.ConfigMapGenerator, kt.kustomization.GeneratorOptions) + if err != nil { + errs.Append(errors.Wrap(err, "NewResMapFromConfigMapArgs")) + } + secrets, err := kt.rFactory.NewResMapFromSecretArgs( + kt.kustomization.SecretGenerator, kt.kustomization.GeneratorOptions) + if err != nil { + errs.Append(errors.Wrap(err, "NewResMapFromSecretArgs")) + } + return resmap.MergeWithoutOverride(cms, secrets) +} + +// Gets Bases and Resources as advertised. +func (kt *KustTarget) loadResMapFromBasesAndResources() (resmap.ResMap, error) { + bases, errs := kt.loadCustomizedBases() + resources, err := kt.rFactory.FromFiles( + kt.ldr, kt.kustomization.Resources) + if err != nil { + errs.Append(errors.Wrap(err, "rawResources failed to read Resources")) + } + if len(errs.Get()) > 0 { + return nil, errs + } + return resmap.MergeWithoutOverride(resources, bases) +} + +// Loop through the Bases of this kustomization recursively loading resources. +// Combine into one ResMap, demanding unique Ids for each resource. +func (kt *KustTarget) loadCustomizedBases() (resmap.ResMap, *interror.KustomizationErrors) { + var list []resmap.ResMap + errs := &interror.KustomizationErrors{} + for _, path := range kt.kustomization.Bases { + ldr, err := kt.ldr.New(path) + if err != nil { + errs.Append(errors.Wrap(err, "couldn't make ldr for "+path)) + continue + } + target, err := NewKustTarget( + ldr, kt.fSys, + kt.rFactory, kt.tFactory) + if err != nil { + errs.Append(errors.Wrap(err, "couldn't make target for "+path)) + continue + } + resMap, err := target.loadCustomizedResMap() + if err != nil { + errs.Append(errors.Wrap(err, "SemiResources")) + continue + } + ldr.Cleanup() + list = append(list, resMap) + } + result, err := resmap.MergeWithoutOverride(list...) + if err != nil { + errs.Append(errors.Wrap(err, "Merge failed")) + } + return result, errs +} + +func (kt *KustTarget) loadBasesAsFlatList() ([]*KustTarget, error) { + var result []*KustTarget + errs := &interror.KustomizationErrors{} + for _, path := range kt.kustomization.Bases { + ldr, err := kt.ldr.New(path) + if err != nil { + errs.Append(err) + continue + } + target, err := NewKustTarget( + ldr, kt.fSys, kt.rFactory, kt.tFactory) + if err != nil { + errs.Append(err) + continue + } + result = append(result, target) + } + if len(errs.Get()) > 0 { + return nil, errs + } + return result, nil +} + +// newTransformer makes a Transformer that does everything except resolve generated names. +func (kt *KustTarget) newTransformer(patches []*resource.Resource) (transformers.Transformer, error) { + var r []transformers.Transformer + t, err := kt.tFactory.MakePatchTransformer(patches, kt.rFactory.RF()) + if err != nil { + return nil, err + } + r = append(r, t) + r = append(r, transformers.NewNamespaceTransformer( + string(kt.kustomization.Namespace), kt.tConfig.NameSpace)) + t, err = transformers.NewNamePrefixSuffixTransformer( + string(kt.kustomization.NamePrefix), + string(kt.kustomization.NameSuffix), + kt.tConfig.NamePrefix, + ) + if err != nil { + return nil, err + } + r = append(r, t) + t, err = transformers.NewLabelsMapTransformer( + kt.kustomization.CommonLabels, kt.tConfig.CommonLabels) + if err != nil { + return nil, err + } + r = append(r, t) + t, err = transformers.NewAnnotationsMapTransformer( + kt.kustomization.CommonAnnotations, kt.tConfig.CommonAnnotations) + if err != nil { + return nil, err + } + r = append(r, t) + return transformers.NewMultiTransformer(r), nil +} + +func (kt *KustTarget) resolveRefVars(m resmap.ResMap) (map[string]string, error) { + result := map[string]string{} + vars, err := kt.getAllVars() + if err != nil { + return result, err + } + for _, v := range vars { + id := resid.NewResId(v.ObjRef.GVK(), v.ObjRef.Name) + if r, found := m.DemandOneMatchForId(id); found { + s, err := r.GetFieldValue(v.FieldRef.FieldPath) + if err != nil { + return nil, fmt.Errorf("failed to resolve referred var: %+v", v) + } + result[v.Name] = s + } else { + log.Printf("couldn't resolve v: %v", v) + } + } + return result, nil +} + +// getAllVars returns all the "environment" style Var instances defined in the app. +func (kt *KustTarget) getAllVars() ([]types.Var, error) { + var result []types.Var + errs := &interror.KustomizationErrors{} + + bases, err := kt.loadBasesAsFlatList() + if err != nil { + return nil, err + } + + // TODO: computing vars and resources for bases can be combined + for _, b := range bases { + vars, err := b.getAllVars() + if err != nil { + errs.Append(err) + continue + } + b.ldr.Cleanup() + result = append(result, vars...) + } + for _, v := range kt.kustomization.Vars { + v.Defaulting() + result = append(result, v) + } + if len(errs.Get()) > 0 { + return nil, errs + } + return result, nil +} + +func loadKustFile(ldr ifc.Loader) ([]byte, error) { + for _, kf := range []string{constants.KustomizationFileName, constants.SecondaryKustomizationFileName} { + content, err := ldr.Load(kf) + if err == nil { + return content, nil + } + if !strings.Contains(err.Error(), "no such file or directory") { + return nil, err + } + } + return nil, fmt.Errorf("no kustomization.yaml file under %s", ldr.Root()) +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/transformers/BUILD b/vendor/sigs.k8s.io/kustomize/pkg/transformers/BUILD new file mode 100644 index 00000000000..2ac02fcd0e1 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/transformers/BUILD @@ -0,0 +1,45 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = [ + "imagetag.go", + "labelsandannotations.go", + "multitransformer.go", + "namereference.go", + "namespace.go", + "nooptransformer.go", + "prefixsuffixname.go", + "refvars.go", + "transformer.go", + "util.go", + ], + importmap = "k8s.io/kubernetes/vendor/sigs.k8s.io/kustomize/pkg/transformers", + importpath = "sigs.k8s.io/kustomize/pkg/transformers", + visibility = ["//visibility:public"], + deps = [ + "//vendor/sigs.k8s.io/kustomize/pkg/expansion:go_default_library", + "//vendor/sigs.k8s.io/kustomize/pkg/gvk:go_default_library", + "//vendor/sigs.k8s.io/kustomize/pkg/resmap:go_default_library", + "//vendor/sigs.k8s.io/kustomize/pkg/resource:go_default_library", + "//vendor/sigs.k8s.io/kustomize/pkg/transformers/config:go_default_library", + "//vendor/sigs.k8s.io/kustomize/pkg/types:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [ + ":package-srcs", + "//vendor/sigs.k8s.io/kustomize/pkg/transformers/config:all-srcs", + ], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/vendor/sigs.k8s.io/kustomize/pkg/transformers/config/BUILD b/vendor/sigs.k8s.io/kustomize/pkg/transformers/config/BUILD new file mode 100644 index 00000000000..f4dae0eec80 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/transformers/config/BUILD @@ -0,0 +1,40 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = [ + "constants.go", + "factory.go", + "factorycrd.go", + "fieldspec.go", + "namebackreferences.go", + "transformerconfig.go", + ], + importmap = "k8s.io/kubernetes/vendor/sigs.k8s.io/kustomize/pkg/transformers/config", + importpath = "sigs.k8s.io/kustomize/pkg/transformers/config", + visibility = ["//visibility:public"], + deps = [ + "//vendor/github.com/ghodss/yaml:go_default_library", + "//vendor/k8s.io/kube-openapi/pkg/common:go_default_library", + "//vendor/sigs.k8s.io/kustomize/pkg/gvk:go_default_library", + "//vendor/sigs.k8s.io/kustomize/pkg/ifc:go_default_library", + "//vendor/sigs.k8s.io/kustomize/pkg/transformers/config/defaultconfig:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [ + ":package-srcs", + "//vendor/sigs.k8s.io/kustomize/pkg/transformers/config/defaultconfig:all-srcs", + ], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/vendor/sigs.k8s.io/kustomize/pkg/transformers/config/constants.go b/vendor/sigs.k8s.io/kustomize/pkg/transformers/config/constants.go new file mode 100644 index 00000000000..357b8950fd6 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/transformers/config/constants.go @@ -0,0 +1,42 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package config + +// Annotation is to mark a field as annotations. +// "x-kubernetes-annotation": "" +const Annotation = "x-kubernetes-annotation" + +// LabelSelector is to mark a field as LabelSelector +// "x-kubernetes-label-selector": "" +const LabelSelector = "x-kubernetes-label-selector" + +// Identity is to mark a field as Identity +// "x-kubernetes-identity": "" +const Identity = "x-kubernetes-identity" + +// Version marks the type version of an object ref field +// "x-kubernetes-object-ref-api-version": +const Version = "x-kubernetes-object-ref-api-version" + +// Kind marks the type name of an object ref field +// "x-kubernetes-object-ref-kind": +const Kind = "x-kubernetes-object-ref-kind" + +// NameKey marks the field key that refers to an object of an object ref field +// "x-kubernetes-object-ref-name-key": "name" +// default is "name" +const NameKey = "x-kubernetes-object-ref-name-key" diff --git a/vendor/sigs.k8s.io/kustomize/pkg/transformers/config/defaultconfig/BUILD b/vendor/sigs.k8s.io/kustomize/pkg/transformers/config/defaultconfig/BUILD new file mode 100644 index 00000000000..380e4cd07cb --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/transformers/config/defaultconfig/BUILD @@ -0,0 +1,31 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = [ + "commonannotations.go", + "commonlabels.go", + "defaultconfig.go", + "nameprefix.go", + "namereference.go", + "namespace.go", + "varreference.go", + ], + importmap = "k8s.io/kubernetes/vendor/sigs.k8s.io/kustomize/pkg/transformers/config/defaultconfig", + importpath = "sigs.k8s.io/kustomize/pkg/transformers/config/defaultconfig", + visibility = ["//visibility:public"], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/vendor/sigs.k8s.io/kustomize/pkg/transformers/config/defaultconfig/commonannotations.go b/vendor/sigs.k8s.io/kustomize/pkg/transformers/config/defaultconfig/commonannotations.go new file mode 100644 index 00000000000..2754559042d --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/transformers/config/defaultconfig/commonannotations.go @@ -0,0 +1,60 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package defaultconfig + +const commonAnnotationFieldSpecs = ` +commonAnnotations: +- path: metadata/annotations + create: true + +- path: spec/template/metadata/annotations + create: true + version: v1 + kind: ReplicationController + +- path: spec/template/metadata/annotations + create: true + kind: Deployment + +- path: spec/template/metadata/annotations + create: true + kind: ReplicaSet + +- path: spec/template/metadata/annotations + create: true + kind: DaemonSet + +- path: spec/template/metadata/annotations + create: true + kind: StatefulSet + +- path: spec/template/metadata/annotations + create: true + group: batch + kind: Job + +- path: spec/jobTemplate/metadata/annotations + create: true + group: batch + kind: CronJob + +- path: spec/jobTemplate/spec/template/metadata/annotations + create: true + group: batch + kind: CronJob + +` diff --git a/vendor/sigs.k8s.io/kustomize/pkg/transformers/config/defaultconfig/commonlabels.go b/vendor/sigs.k8s.io/kustomize/pkg/transformers/config/defaultconfig/commonlabels.go new file mode 100644 index 00000000000..7efd6a54d4f --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/transformers/config/defaultconfig/commonlabels.go @@ -0,0 +1,157 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package defaultconfig + +const commonLabelFieldSpecs = ` +commonLabels: +- path: metadata/labels + create: true + +- path: spec/selector + create: true + version: v1 + kind: Service + +- path: spec/selector + create: true + version: v1 + kind: ReplicationController + +- path: spec/template/metadata/labels + create: true + version: v1 + kind: ReplicationController + +- path: spec/selector/matchLabels + create: true + kind: Deployment + +- path: spec/template/metadata/labels + create: true + kind: Deployment + +- path: spec/template/spec/affinity/podAffinity/preferredDuringSchedulingIgnoredDuringExecution/podAffinityTerm/labelSelector/matchLabels + create: false + group: apps + kind: Deployment + +- path: spec/template/spec/affinity/podAffinity/requiredDuringSchedulingIgnoredDuringExecution/labelSelector/matchLabels + create: false + group: apps + kind: Deployment + +- path: spec/template/spec/affinity/podAntiAffinity/preferredDuringSchedulingIgnoredDuringExecution/podAffinityTerm/labelSelector/matchLabels + create: false + group: apps + kind: Deployment + +- path: spec/template/spec/affinity/podAntiAffinity/requiredDuringSchedulingIgnoredDuringExecution/labelSelector/matchLabels + create: false + group: apps + kind: Deployment + +- path: spec/selector/matchLabels + create: true + kind: ReplicaSet + +- path: spec/template/metadata/labels + create: true + kind: ReplicaSet + +- path: spec/selector/matchLabels + create: true + kind: DaemonSet + +- path: spec/template/metadata/labels + create: true + kind: DaemonSet + +- path: spec/selector/matchLabels + create: true + group: apps + kind: StatefulSet + +- path: spec/template/metadata/labels + create: true + group: apps + kind: StatefulSet + +- path: spec/template/spec/affinity/podAffinity/preferredDuringSchedulingIgnoredDuringExecution/podAffinityTerm/labelSelector/matchLabels + create: false + group: apps + kind: StatefulSet + +- path: spec/template/spec/affinity/podAffinity/requiredDuringSchedulingIgnoredDuringExecution/labelSelector/matchLabels + create: false + group: apps + kind: StatefulSet + +- path: spec/template/spec/affinity/podAntiAffinity/preferredDuringSchedulingIgnoredDuringExecution/podAffinityTerm/labelSelector/matchLabels + create: false + group: apps + kind: StatefulSet + +- path: spec/template/spec/affinity/podAntiAffinity/requiredDuringSchedulingIgnoredDuringExecution/labelSelector/matchLabels + create: false + group: apps + kind: StatefulSet + +- path: spec/volumeClaimTemplates/metadata/labels + create: true + group: apps + kind: StatefulSet + +- path: spec/selector/matchLabels + create: false + group: batch + kind: Job + +- path: spec/template/metadata/labels + create: true + group: batch + kind: Job + +- path: spec/jobTemplate/spec/selector/matchLabels + create: false + group: batch + kind: CronJob + +- path: spec/jobTemplate/spec/template/metadata/labels + create: true + group: batch + kind: CronJob + +- path: spec/selector/matchLabels + create: false + group: policy + kind: PodDisruptionBudget + +- path: spec/podSelector/matchLabels + create: false + group: networking.k8s.io + kind: NetworkPolicy + +- path: spec/ingress/from/podSelector/matchLabels + create: false + group: networking.k8s.io + kind: NetworkPolicy + +- path: spec/egress/to/podSelector/matchLabels + create: false + group: networking.k8s.io + kind: NetworkPolicy +` diff --git a/vendor/sigs.k8s.io/kustomize/pkg/transformers/config/defaultconfig/defaultconfig.go b/vendor/sigs.k8s.io/kustomize/pkg/transformers/config/defaultconfig/defaultconfig.go new file mode 100644 index 00000000000..d96639a8ab0 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/transformers/config/defaultconfig/defaultconfig.go @@ -0,0 +1,49 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package defaultconfig provides the default +// transformer configurations +package defaultconfig + +import ( + "bytes" +) + +// GetDefaultFieldSpecs returns default fieldSpecs. +func GetDefaultFieldSpecs() []byte { + configData := [][]byte{ + []byte(namePrefixFieldSpecs), + []byte(commonLabelFieldSpecs), + []byte(commonAnnotationFieldSpecs), + []byte(namespaceFieldSpecs), + []byte(varReferenceFieldSpecs), + []byte(nameReferenceFieldSpecs), + } + return bytes.Join(configData, []byte("\n")) +} + +// GetDefaultFieldSpecsAsMap returns default fieldSpecs +// as a string->string map. +func GetDefaultFieldSpecsAsMap() map[string]string { + result := make(map[string]string) + result["nameprefix"] = namePrefixFieldSpecs + result["commonlabels"] = commonLabelFieldSpecs + result["commonannotations"] = commonAnnotationFieldSpecs + result["namespace"] = namespaceFieldSpecs + result["varreference"] = varReferenceFieldSpecs + result["namereference"] = nameReferenceFieldSpecs + return result +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/transformers/config/defaultconfig/nameprefix.go b/vendor/sigs.k8s.io/kustomize/pkg/transformers/config/defaultconfig/nameprefix.go new file mode 100644 index 00000000000..94fe07a4859 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/transformers/config/defaultconfig/nameprefix.go @@ -0,0 +1,24 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package defaultconfig + +const ( + namePrefixFieldSpecs = ` +namePrefix: +- path: metadata/name +` +) diff --git a/vendor/sigs.k8s.io/kustomize/pkg/transformers/config/defaultconfig/namereference.go b/vendor/sigs.k8s.io/kustomize/pkg/transformers/config/defaultconfig/namereference.go new file mode 100644 index 00000000000..a0d81db5b09 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/transformers/config/defaultconfig/namereference.go @@ -0,0 +1,306 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package defaultconfig + +const ( + nameReferenceFieldSpecs = ` +nameReference: +- kind: Deployment + fieldSpecs: + - path: spec/scaleTargetRef/name + kind: HorizontalPodAutoscaler + +- kind: ReplicationController + fieldSpecs: + - path: spec/scaleTargetRef/name + kind: HorizontalPodAutoscaler + +- kind: ReplicaSet + fieldSpecs: + - path: spec/scaleTargetRef/name + kind: HorizontalPodAutoscaler + +- kind: ConfigMap + version: v1 + fieldSpecs: + - path: spec/volumes/configMap/name + version: v1 + kind: Pod + - path: spec/containers/env/valueFrom/configMapKeyRef/name + version: v1 + kind: Pod + - path: spec/initContainers/env/valueFrom/configMapKeyRef/name + version: v1 + kind: Pod + - path: spec/containers/envFrom/configMapRef/name + version: v1 + kind: Pod + - path: spec/initContainers/envFrom/configMapRef/name + version: v1 + kind: Pod + - path: spec/template/spec/volumes/configMap/name + kind: Deployment + - path: spec/template/spec/containers/env/valueFrom/configMapKeyRef/name + kind: Deployment + - path: spec/template/spec/initContainers/env/valueFrom/configMapKeyRef/name + kind: Deployment + - path: spec/template/spec/containers/envFrom/configMapRef/name + kind: Deployment + - path: spec/template/spec/initContainers/envFrom/configMapRef/name + kind: Deployment + - path: spec/template/spec/volumes/projected/sources/configMap/name + kind: Deployment + - path: spec/template/spec/volumes/configMap/name + kind: ReplicaSet + - path: spec/template/spec/containers/env/valueFrom/configMapKeyRef/name + kind: ReplicaSet + - path: spec/template/spec/initContainers/env/valueFrom/configMapKeyRef/name + kind: ReplicaSet + - path: spec/template/spec/containers/envFrom/configMapRef/name + kind: ReplicaSet + - path: spec/template/spec/initContainers/envFrom/configMapRef/name + kind: ReplicaSet + - path: spec/template/spec/volumes/configMap/name + kind: DaemonSet + - path: spec/template/spec/containers/env/valueFrom/configMapKeyRef/name + kind: DaemonSet + - path: spec/template/spec/initContainers/env/valueFrom/configMapKeyRef/name + kind: DaemonSet + - path: spec/template/spec/containers/envFrom/configMapRef/name + kind: DaemonSet + - path: spec/template/spec/initContainers/envFrom/configMapRef/name + kind: DaemonSet + - path: spec/template/spec/volumes/configMap/name + kind: StatefulSet + - path: spec/template/spec/containers/env/valueFrom/configMapKeyRef/name + kind: StatefulSet + - path: spec/template/spec/initContainers/env/valueFrom/configMapKeyRef/name + kind: StatefulSet + - path: spec/template/spec/containers/envFrom/configMapRef/name + kind: StatefulSet + - path: spec/template/spec/initContainers/envFrom/configMapRef/name + kind: StatefulSet + - path: spec/template/spec/volumes/projected/sources/configMap/name + kind: StatefulSet + - path: spec/template/spec/volumes/configMap/name + kind: Job + - path: spec/template/spec/containers/env/valueFrom/configMapKeyRef/name + kind: Job + - path: spec/template/spec/initContainers/env/valueFrom/configMapKeyRef/name + kind: Job + - path: spec/template/spec/containers/envFrom/configMapRef/name + kind: Job + - path: spec/template/spec/initContainers/envFrom/configMapRef/name + kind: Job + - path: spec/jobTemplate/spec/template/spec/volumes/configMap/name + kind: CronJob + - path: spec/jobTemplate/spec/template/spec/containers/env/valueFrom/configMapKeyRef/name + kind: CronJob + - path: spec/jobTemplate/spec/template/spec/initContainers/env/valueFrom/configMapKeyRef/name + kind: CronJob + - path: spec/jobTemplate/spec/template/spec/containers/envFrom/configMapRef/name + kind: CronJob + - path: spec/jobTemplate/spec/template/spec/initContainers/envFrom/configmapRef/name + kind: CronJob + +- kind: Secret + version: v1 + fieldSpecs: + - path: spec/volumes/secret/secretName + version: v1 + kind: Pod + - path: spec/containers/env/valueFrom/secretKeyRef/name + version: v1 + kind: Pod + - path: spec/initContainers/env/valueFrom/secretKeyRef/name + version: v1 + kind: Pod + - path: spec/containers/envFrom/secretRef/name + version: v1 + kind: Pod + - path: spec/initContainers/envFrom/secretRef/name + version: v1 + kind: Pod + - path: spec/imagePullSecrets/name + version: v1 + kind: Pod + - path: spec/template/spec/volumes/secret/secretName + kind: Deployment + - path: spec/template/spec/containers/env/valueFrom/secretKeyRef/name + kind: Deployment + - path: spec/template/spec/initContainers/env/valueFrom/secretKeyRef/name + kind: Deployment + - path: spec/template/spec/containers/envFrom/secretRef/name + kind: Deployment + - path: spec/template/spec/initContainers/envFrom/secretRef/name + kind: Deployment + - path: spec/template/spec/imagePullSecrets/name + kind: Deployment + - path: spec/template/spec/volumes/secret/secretName + kind: ReplicaSet + - path: spec/template/spec/containers/env/valueFrom/secretKeyRef/name + kind: ReplicaSet + - path: spec/template/spec/initContainers/env/valueFrom/secretKeyRef/name + kind: ReplicaSet + - path: spec/template/spec/containers/envFrom/secretRef/name + kind: ReplicaSet + - path: spec/template/spec/initContainers/envFrom/secretRef/name + kind: ReplicaSet + - path: spec/template/spec/imagePullSecrets/name + kind: ReplicaSet + - path: spec/template/spec/volumes/secret/secretName + kind: DaemonSet + - path: spec/template/spec/containers/env/valueFrom/secretKeyRef/name + kind: DaemonSet + - path: spec/template/spec/initContainers/env/valueFrom/secretKeyRef/name + kind: DaemonSet + - path: spec/template/spec/containers/envFrom/secretRef/name + kind: DaemonSet + - path: spec/template/spec/initContainers/envFrom/secretRef/name + kind: DaemonSet + - path: spec/template/spec/imagePullSecrets/name + kind: DaemonSet + - path: spec/template/spec/volumes/secret/secretName + kind: StatefulSet + - path: spec/template/spec/containers/env/valueFrom/secretKeyRef/name + kind: StatefulSet + - path: spec/template/spec/initContainers/env/valueFrom/secretKeyRef/name + kind: StatefulSet + - path: spec/template/spec/containers/envFrom/secretRef/name + kind: StatefulSet + - path: spec/template/spec/initContainers/envFrom/secretRef/name + kind: StatefulSet + - path: spec/template/spec/imagePullSecrets/name + kind: StatefulSet + - path: spec/template/spec/volumes/secret/secretName + kind: Job + - path: spec/template/spec/containers/env/valueFrom/secretKeyRef/name + kind: Job + - path: spec/template/spec/initContainers/env/valueFrom/secretKeyRef/name + kind: Job + - path: spec/template/spec/containers/envFrom/secretRef/name + kind: Job + - path: spec/template/spec/initContainers/envFrom/secretRef/name + kind: Job + - path: spec/template/spec/imagePullSecrets/name + kind: Job + - path: spec/jobTemplate/spec/template/spec/volumes/secret/secretName + kind: CronJob + - path: spec/jobTemplate/spec/template/spec/containers/env/valueFrom/secretKeyRef/name + kind: CronJob + - path: spec/jobTemplate/spec/template/spec/initContainers/env/valueFrom/secretKeyRef/name + kind: CronJob + - path: spec/jobTemplate/spec/template/spec/containers/envFrom/secretRef/name + kind: CronJob + - path: spec/jobTemplate/spec/template/spec/initContainers/envFrom/secretRef/name + kind: CronJob + - path: spec/jobTemplate/spec/template/spec/imagePullSecrets/name + kind: CronJob + - path: spec/tls/secretName + kind: Ingress + - path: metadata/annotations/ingress.kubernetes.io\/auth-secret + kind: Ingress + - path: metadata/annotations/nginx.ingress.kubernetes.io\/auth-secret + kind: Ingress + - path: imagePullSecrets/name + kind: ServiceAccount + - path: parameters/secretName + kind: StorageClass + - path: parameters/adminSecretName + kind: StorageClass + - path: parameters/userSecretName + kind: StorageClass + - path: parameters/secretRef + kind: StorageClass + +- kind: Service + version: v1 + fieldSpecs: + - path: spec/serviceName + kind: StatefulSet + group: apps + - path: spec/rules/http/paths/backend/serviceName + kind: Ingress + - path: spec/backend/serviceName + kind: Ingress + +- kind: Role + group: rbac.authorization.k8s.io + fieldSpecs: + - path: roleRef/name + kind: RoleBinding + group: rbac.authorization.k8s.io + +- kind: ClusterRole + group: rbac.authorization.k8s.io + fieldSpecs: + - path: roleRef/name + kind: RoleBinding + group: rbac.authorization.k8s.io + - path: roleRef/name + kind: ClusterRoleBinding + group: rbac.authorization.k8s.io + +- kind: ServiceAccount + version: v1 + fieldSpecs: + - path: subjects/name + kind: RoleBinding + group: rbac.authorization.k8s.io + - path: subjects/name + kind: ClusterRoleBinding + group: rbac.authorization.k8s.io + - path: spec/serviceAccountName + kind: Pod + - path: spec/template/spec/serviceAccountName + kind: StatefulSet + - path: spec/template/spec/serviceAccountName + kind: Deployment + - path: spec/template/spec/serviceAccountName + kind: ReplicationController + - path: spec/jobTemplate/spec/template/spec/serviceAccountName + kind: CronJob + - path: spec/template/spec/serviceAccountName + kind: job + - path: spec/template/spec/serviceAccountName + kind: DaemonSet + +- kind: PersistentVolumeClaim + version: v1 + fieldSpecs: + - path: spec/volumes/persistentVolumeClaim/claimName + kind: Pod + - path: spec/template/spec/volumes/persistentVolumeClaim/claimName + kind: StatefulSet + - path: spec/template/spec/volumes/persistentVolumeClaim/claimName + kind: Deployment + - path: spec/template/spec/volumes/persistentVolumeClaim/claimName + kind: ReplicationController + - path: spec/jobTemplate/spec/template/spec/volumes/persistentVolumeClaim/claimName + kind: CronJob + - path: spec/template/spec/volumes/persistentVolumeClaim/claimName + kind: Job + - path: spec/template/spec/volumes/persistentVolumeClaim/claimName + kind: DaemonSet + +- kind: PersistentVolume + version: v1 + fieldSpecs: + - path: spec/volumeName + kind: PersistentVolumeClaim +` +) diff --git a/vendor/sigs.k8s.io/kustomize/pkg/transformers/config/defaultconfig/namespace.go b/vendor/sigs.k8s.io/kustomize/pkg/transformers/config/defaultconfig/namespace.go new file mode 100644 index 00000000000..431eb07699e --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/transformers/config/defaultconfig/namespace.go @@ -0,0 +1,25 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package defaultconfig + +const ( + namespaceFieldSpecs = ` +namespace: +- path: metadata/namespace + create: true +` +) diff --git a/vendor/sigs.k8s.io/kustomize/pkg/transformers/config/defaultconfig/varreference.go b/vendor/sigs.k8s.io/kustomize/pkg/transformers/config/defaultconfig/varreference.go new file mode 100644 index 00000000000..90a6de93394 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/transformers/config/defaultconfig/varreference.go @@ -0,0 +1,85 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package defaultconfig + +const ( + varReferenceFieldSpecs = ` +varReference: +- path: spec/template/spec/initContainers/command + kind: StatefulSet + +- path: spec/template/spec/containers/command + kind: StatefulSet + +- path: spec/template/spec/initContainers/command + kind: Deployment + +- path: spec/template/spec/containers/command + kind: Deployment + +- path: spec/template/spec/containers/command + kind: Job + +- path: spec/jobTemplate/spec/template/spec/containers/command + kind: CronJob + +- path: spec/template/spec/initContainers/args + kind: StatefulSet + +- path: spec/template/spec/containers/args + kind: StatefulSet + +- path: spec/template/spec/initContainers/args + kind: Deployment + +- path: spec/template/spec/containers/args + kind: Deployment + +- path: spec/template/spec/containers/args + kind: Job + +- path: spec/jobTemplate/spec/template/spec/containers/args + kind: CronJob + +- path: spec/template/spec/initContainers/env/value + kind: StatefulSet + +- path: spec/template/spec/containers/env/value + kind: StatefulSet + +- path: spec/template/spec/initContainers/env/value + kind: Deployment + +- path: spec/template/spec/containers/env/value + kind: Deployment + +- path: spec/template/spec/containers/env/value + kind: Job + +- path: spec/jobTemplate/spec/template/spec/containers/env/value + kind: CronJob + +- path: spec/containers/command + kind: Pod + +- path: spec/containers/args + kind: Pod + +- path: spec/containers/env/value + kind: Pod +` +) diff --git a/vendor/sigs.k8s.io/kustomize/pkg/transformers/config/factory.go b/vendor/sigs.k8s.io/kustomize/pkg/transformers/config/factory.go new file mode 100644 index 00000000000..0bf842c64d9 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/transformers/config/factory.go @@ -0,0 +1,86 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package config + +import ( + "log" + + "github.com/ghodss/yaml" + "sigs.k8s.io/kustomize/pkg/ifc" + "sigs.k8s.io/kustomize/pkg/transformers/config/defaultconfig" +) + +// Factory makes instances of TransformerConfig. +type Factory struct { + ldr ifc.Loader +} + +func NewFactory(l ifc.Loader) *Factory { + return &Factory{ldr: l} +} + +func (tf *Factory) loader() ifc.Loader { + if tf.ldr.(ifc.Loader) == nil { + log.Fatal("no loader") + } + return tf.ldr +} + +// FromFiles returns a TranformerConfig object from a list of files +func (tf *Factory) FromFiles( + paths []string) (*TransformerConfig, error) { + result := &TransformerConfig{} + for _, path := range paths { + data, err := tf.loader().Load(path) + if err != nil { + return nil, err + } + t, err := makeTransformerConfigFromBytes(data) + if err != nil { + return nil, err + } + result = result.Merge(t) + } + return result, nil +} + +// makeTransformerConfigFromBytes returns a TransformerConfig object from bytes +func makeTransformerConfigFromBytes(data []byte) (*TransformerConfig, error) { + var t TransformerConfig + err := yaml.Unmarshal(data, &t) + if err != nil { + return nil, err + } + t.sortFields() + return &t, nil +} + +// EmptyConfig returns an empty TransformerConfig object +func (tf *Factory) EmptyConfig() *TransformerConfig { + return &TransformerConfig{} +} + +// DefaultConfig returns a default TransformerConfig. +// This should never fail, hence the Fatal panic. +func (tf *Factory) DefaultConfig() *TransformerConfig { + c, err := makeTransformerConfigFromBytes( + defaultconfig.GetDefaultFieldSpecs()) + if err != nil { + log.Fatalf("Unable to make default transformconfig: %v", err) + } + return c +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/transformers/config/factorycrd.go b/vendor/sigs.k8s.io/kustomize/pkg/transformers/config/factorycrd.go new file mode 100644 index 00000000000..0742ab5dbfd --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/transformers/config/factorycrd.go @@ -0,0 +1,159 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package config + +import ( + "encoding/json" + "strings" + + "github.com/ghodss/yaml" + "k8s.io/kube-openapi/pkg/common" + "sigs.k8s.io/kustomize/pkg/gvk" +) + +// LoadCRDs parse CRD schemas from paths into a TransformerConfig +func (tf *Factory) LoadCRDs(paths []string) (*TransformerConfig, error) { + tc := tf.EmptyConfig() + for _, path := range paths { + otherTc, err := tf.loadCRD(path) + if err != nil { + return nil, err + } + tc = tc.Merge(otherTc) + } + return tc, nil +} + +func (tf *Factory) loadCRD(path string) (*TransformerConfig, error) { + result := tf.EmptyConfig() + content, err := tf.loader().Load(path) + if err != nil { + return result, err + } + + var types map[string]common.OpenAPIDefinition + if content[0] == '{' { + err = json.Unmarshal(content, &types) + } else { + err = yaml.Unmarshal(content, &types) + } + if err != nil { + return nil, err + } + + crds := getCRDs(types) + for crd, k := range crds { + tc := tf.EmptyConfig() + err = loadCrdIntoConfig( + types, crd, crd, k, []string{}, tc) + if err != nil { + return result, err + } + result = result.Merge(tc) + } + + return result, nil +} + +// getCRDs get all CRD types +func getCRDs(types map[string]common.OpenAPIDefinition) map[string]gvk.Gvk { + crds := map[string]gvk.Gvk{} + + for typename, t := range types { + properties := t.Schema.SchemaProps.Properties + _, foundKind := properties["kind"] + _, foundAPIVersion := properties["apiVersion"] + _, foundMetadata := properties["metadata"] + if foundKind && foundAPIVersion && foundMetadata { + // TODO: Get Group and Version for CRD from the openAPI definition once + // "x-kubernetes-group-version-kind" is available in CRD + kind := strings.Split(typename, ".")[len(strings.Split(typename, "."))-1] + crds[typename] = gvk.Gvk{Kind: kind} + } + } + return crds +} + +// loadCrdIntoConfig loads a CRD spec into a TransformerConfig +func loadCrdIntoConfig( + types map[string]common.OpenAPIDefinition, + atype string, crd string, in gvk.Gvk, + path []string, config *TransformerConfig) error { + if _, ok := types[crd]; !ok { + return nil + } + + for propname, property := range types[atype].Schema.SchemaProps.Properties { + _, annotate := property.Extensions.GetString(Annotation) + if annotate { + config.AddAnnotationFieldSpec( + FieldSpec{ + CreateIfNotPresent: false, + Gvk: in, + Path: strings.Join(append(path, propname), "/"), + }, + ) + } + _, label := property.Extensions.GetString(LabelSelector) + if label { + config.AddLabelFieldSpec( + FieldSpec{ + CreateIfNotPresent: false, + Gvk: in, + Path: strings.Join(append(path, propname), "/"), + }, + ) + } + _, identity := property.Extensions.GetString(Identity) + if identity { + config.AddPrefixFieldSpec( + FieldSpec{ + CreateIfNotPresent: false, + Gvk: in, + Path: strings.Join(append(path, propname), "/"), + }, + ) + } + version, ok := property.Extensions.GetString(Version) + if ok { + kind, ok := property.Extensions.GetString(Kind) + if ok { + nameKey, ok := property.Extensions.GetString(NameKey) + if !ok { + nameKey = "name" + } + config.AddNamereferenceFieldSpec(NameBackReferences{ + Gvk: gvk.Gvk{Kind: kind, Version: version}, + FieldSpecs: []FieldSpec{ + { + CreateIfNotPresent: false, + Gvk: in, + Path: strings.Join(append(path, propname, nameKey), "/"), + }, + }, + }) + } + } + + if property.Ref.GetURL() != nil { + loadCrdIntoConfig( + types, property.Ref.String(), crd, in, + append(path, propname), config) + } + } + return nil +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/transformers/config/fieldspec.go b/vendor/sigs.k8s.io/kustomize/pkg/transformers/config/fieldspec.go new file mode 100644 index 00000000000..7f759d2a095 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/transformers/config/fieldspec.go @@ -0,0 +1,95 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package config + +import ( + "fmt" + "strings" + + "sigs.k8s.io/kustomize/pkg/gvk" +) + +// FieldSpec completely specifies a kustomizable field in +// an unstructured representation of a k8s API object. +// It helps define the operands of transformations. +// +// For example, a directive to add a common label to objects +// will need to know that a 'Deployment' object (in API group +// 'apps', any version) can have labels at field path +// 'spec/template/metadata/labels', and further that it is OK +// (or not OK) to add that field path to the object if the +// field path doesn't exist already. +// +// This would look like +// { +// group: apps +// kind: Deployment +// path: spec/template/metadata/labels +// create: true +// } +type FieldSpec struct { + gvk.Gvk `json:",inline,omitempty" yaml:",inline,omitempty"` + Path string `json:"path,omitempty" yaml:"path,omitempty"` + CreateIfNotPresent bool `json:"create,omitempty" yaml:"create,omitempty"` +} + +const ( + escapedForwardSlash = "\\/" + tempSlashReplacement = "???" +) + +func (fs FieldSpec) String() string { + return fmt.Sprintf( + "%s:%v:%s", fs.Gvk.String(), fs.CreateIfNotPresent, fs.Path) +} + +// PathSlice converts the path string to a slice of strings, +// separated by a '/'. Forward slash can be contained in a +// fieldname. such as ingress.kubernetes.io/auth-secret in +// Ingress annotations. To deal with this special case, the +// path to this field should be formatted as +// +// metadata/annotations/ingress.kubernetes.io\/auth-secret +// +// Then PathSlice will return +// +// []string{ +// "metadata", +// "annotations", +// "ingress.auth-secretkubernetes.io/auth-secret" +// } +func (fs FieldSpec) PathSlice() []string { + if !strings.Contains(fs.Path, escapedForwardSlash) { + return strings.Split(fs.Path, "/") + } + + s := strings.Replace(fs.Path, escapedForwardSlash, tempSlashReplacement, -1) + paths := strings.Split(s, "/") + var result []string + for _, path := range paths { + result = append(result, strings.Replace(path, tempSlashReplacement, "/", -1)) + } + return result +} + +type fsSlice []FieldSpec + +func (s fsSlice) Len() int { return len(s) } +func (s fsSlice) Swap(i, j int) { s[i], s[j] = s[j], s[i] } +func (s fsSlice) Less(i, j int) bool { + return s[i].Gvk.IsLessThan(s[j].Gvk) +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/transformers/config/namebackreferences.go b/vendor/sigs.k8s.io/kustomize/pkg/transformers/config/namebackreferences.go new file mode 100644 index 00000000000..d0a6e8d1eb7 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/transformers/config/namebackreferences.go @@ -0,0 +1,98 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package config + +import ( + "strings" + + "sigs.k8s.io/kustomize/pkg/gvk" +) + +// NameBackReferences is an association between a gvk.GVK and a list +// of FieldSpec instances that could refer to it. +// +// It is used to handle name changes, and can be thought of as a +// a contact list. If you change your own contact info (name, +// phone number, etc.), you must tell your contacts or they won't +// know about the change. +// +// For example, ConfigMaps can be used by Pods and everything that +// contains a Pod; Deployment, Job, StatefulSet, etc. To change +// the name of a ConfigMap instance from 'alice' to 'bob', one +// must visit all objects that could refer to the ConfigMap, see if +// they mention 'alice', and if so, change the reference to 'bob'. +// +// The NameBackReferences instance to aid in this could look like +// { +// kind: ConfigMap +// version: v1 +// FieldSpecs: +// - kind: Pod +// version: v1 +// path: spec/volumes/configMap/name +// - kind: Deployment +// path: spec/template/spec/volumes/configMap/name +// - kind: Job +// path: spec/template/spec/volumes/configMap/name +// (etc.) +// } +type NameBackReferences struct { + gvk.Gvk `json:",inline,omitempty" yaml:",inline,omitempty"` + FieldSpecs []FieldSpec `json:"FieldSpecs,omitempty" yaml:"FieldSpecs,omitempty"` +} + +func (n NameBackReferences) String() string { + var r []string + for _, f := range n.FieldSpecs { + r = append(r, f.String()) + } + return n.Gvk.String() + ": (\n" + + strings.Join(r, "\n") + "\n)" +} + +type nbrSlice []NameBackReferences + +func (s nbrSlice) Len() int { return len(s) } +func (s nbrSlice) Swap(i, j int) { s[i], s[j] = s[j], s[i] } +func (s nbrSlice) Less(i, j int) bool { + return s[i].Gvk.IsLessThan(s[j].Gvk) +} + +func (s nbrSlice) mergeAll(o nbrSlice) nbrSlice { + result := s + for _, r := range o { + result = result.mergeOne(r) + } + return result +} + +func (s nbrSlice) mergeOne(other NameBackReferences) nbrSlice { + var result nbrSlice + found := false + for _, c := range s { + if c.Gvk.Equals(other.Gvk) { + c.FieldSpecs = append(c.FieldSpecs, other.FieldSpecs...) + found = true + } + result = append(result, c) + } + + if !found { + result = append(result, other) + } + return result +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/transformers/config/transformerconfig.go b/vendor/sigs.k8s.io/kustomize/pkg/transformers/config/transformerconfig.go new file mode 100644 index 00000000000..5de589e198b --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/transformers/config/transformerconfig.go @@ -0,0 +1,86 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package config provides the functions to load default or user provided configurations +// for different transformers +package config + +import ( + "sort" +) + +// TransformerConfig holds the data needed to perform transformations. +type TransformerConfig struct { + NamePrefix fsSlice `json:"namePrefix,omitempty" yaml:"namePrefix,omitempty"` + NameSuffix fsSlice `json:"nameSuffix,omitempty" yaml:"nameSuffix,omitempty"` + NameSpace fsSlice `json:"namespace,omitempty" yaml:"namespace,omitempty"` + CommonLabels fsSlice `json:"commonLabels,omitempty" yaml:"commonLabels,omitempty"` + CommonAnnotations fsSlice `json:"commonAnnotations,omitempty" yaml:"commonAnnotations,omitempty"` + NameReference nbrSlice `json:"nameReference,omitempty" yaml:"nameReference,omitempty"` + VarReference fsSlice `json:"varReference,omitempty" yaml:"varReference,omitempty"` +} + +// sortFields provides determinism in logging, tests, etc. +func (t *TransformerConfig) sortFields() { + sort.Sort(t.NamePrefix) + sort.Sort(t.NameSpace) + sort.Sort(t.CommonLabels) + sort.Sort(t.CommonAnnotations) + sort.Sort(t.NameReference) + sort.Sort(t.VarReference) +} + +// AddPrefixFieldSpec adds a FieldSpec to NamePrefix +func (t *TransformerConfig) AddPrefixFieldSpec(fs FieldSpec) { + t.NamePrefix = append(t.NamePrefix, fs) +} + +// AddSuffixFieldSpec adds a FieldSpec to NameSuffix +func (t *TransformerConfig) AddSuffixFieldSpec(fs FieldSpec) { + t.NameSuffix = append([]FieldSpec{fs}, t.NameSuffix...) +} + +// AddLabelFieldSpec adds a FieldSpec to CommonLabels +func (t *TransformerConfig) AddLabelFieldSpec(fs FieldSpec) { + t.CommonLabels = append(t.CommonLabels, fs) +} + +// AddAnnotationFieldSpec adds a FieldSpec to CommonAnnotations +func (t *TransformerConfig) AddAnnotationFieldSpec(fs FieldSpec) { + t.CommonAnnotations = append(t.CommonAnnotations, fs) +} + +// AddNamereferenceFieldSpec adds a NameBackReferences to NameReference +func (t *TransformerConfig) AddNamereferenceFieldSpec(nbrs NameBackReferences) { + t.NameReference = t.NameReference.mergeOne(nbrs) +} + +// Merge merges two TransformerConfigs objects into a new TransformerConfig object +func (t *TransformerConfig) Merge(input *TransformerConfig) *TransformerConfig { + if input == nil { + return t + } + merged := &TransformerConfig{} + merged.NamePrefix = append(t.NamePrefix, input.NamePrefix...) + merged.NameSuffix = append(input.NameSuffix, t.NameSuffix...) + merged.NameSpace = append(t.NameSpace, input.NameSpace...) + merged.CommonAnnotations = append(t.CommonAnnotations, input.CommonAnnotations...) + merged.CommonLabels = append(t.CommonLabels, input.CommonLabels...) + merged.VarReference = append(t.VarReference, input.VarReference...) + merged.NameReference = t.NameReference.mergeAll(input.NameReference) + merged.sortFields() + return merged +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/transformers/imagetag.go b/vendor/sigs.k8s.io/kustomize/pkg/transformers/imagetag.go new file mode 100644 index 00000000000..ef1f7c2792a --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/transformers/imagetag.go @@ -0,0 +1,126 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package transformers + +import ( + "regexp" + + "sigs.k8s.io/kustomize/pkg/resmap" + "sigs.k8s.io/kustomize/pkg/types" +) + +// imageTagTransformer replace image tags +type imageTagTransformer struct { + imageTags []types.ImageTag +} + +var _ Transformer = &imageTagTransformer{} + +// NewImageTagTransformer constructs a imageTagTransformer. +func NewImageTagTransformer(slice []types.ImageTag) (Transformer, error) { + return &imageTagTransformer{slice}, nil +} + +// Transform finds the matching images and replace the tag +func (pt *imageTagTransformer) Transform(resources resmap.ResMap) error { + if len(pt.imageTags) == 0 { + return nil + } + for _, res := range resources { + err := pt.findAndReplaceTag(res.Map()) + if err != nil { + return err + } + } + return nil +} + +/* + findAndReplaceTag replaces the image tags inside one object + It searches the object for container session + then loops though all images inside containers session, finds matched ones and update the tag name +*/ +func (pt *imageTagTransformer) findAndReplaceTag(obj map[string]interface{}) error { + paths := []string{"containers", "initContainers"} + found := false + for _, path := range paths { + _, found = obj[path] + if found { + err := pt.updateContainers(obj, path) + if err != nil { + return err + } + } + } + if !found { + return pt.findContainers(obj) + } + return nil +} + +func (pt *imageTagTransformer) updateContainers(obj map[string]interface{}, path string) error { + containers := obj[path].([]interface{}) + for i := range containers { + container := containers[i].(map[string]interface{}) + image, found := container["image"] + if !found { + continue + } + for _, imagetag := range pt.imageTags { + if isImageMatched(image.(string), imagetag.Name) { + container["image"] = imagetag.Name + ":" + imagetag.NewTag + + if imagetag.Digest != "" { + container["image"] = imagetag.Name + "@" + imagetag.Digest + } + + break + } + } + } + return nil +} + +func (pt *imageTagTransformer) findContainers(obj map[string]interface{}) error { + for key := range obj { + switch typedV := obj[key].(type) { + case map[string]interface{}: + err := pt.findAndReplaceTag(typedV) + if err != nil { + return err + } + case []interface{}: + for i := range typedV { + item := typedV[i] + typedItem, ok := item.(map[string]interface{}) + if ok { + err := pt.findAndReplaceTag(typedItem) + if err != nil { + return err + } + } + } + } + } + return nil +} + +func isImageMatched(s, t string) bool { + // Tag values are limited to [a-zA-Z0-9_.-]. + pattern, _ := regexp.Compile("^" + t + "(:[a-zA-Z0-9_.-]*)?$") + return pattern.MatchString(s) +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/transformers/labelsandannotations.go b/vendor/sigs.k8s.io/kustomize/pkg/transformers/labelsandannotations.go new file mode 100644 index 00000000000..836abcaa488 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/transformers/labelsandannotations.go @@ -0,0 +1,86 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package transformers + +import ( + "errors" + "fmt" + + "sigs.k8s.io/kustomize/pkg/resmap" + "sigs.k8s.io/kustomize/pkg/transformers/config" +) + +// mapTransformer applies a string->string map to fieldSpecs. +type mapTransformer struct { + m map[string]string + fieldSpecs []config.FieldSpec +} + +var _ Transformer = &mapTransformer{} + +// NewLabelsMapTransformer constructs a mapTransformer. +func NewLabelsMapTransformer( + m map[string]string, fs []config.FieldSpec) (Transformer, error) { + return NewMapTransformer(fs, m) +} + +// NewAnnotationsMapTransformer construct a mapTransformer. +func NewAnnotationsMapTransformer( + m map[string]string, fs []config.FieldSpec) (Transformer, error) { + return NewMapTransformer(fs, m) +} + +// NewMapTransformer construct a mapTransformer. +func NewMapTransformer( + pc []config.FieldSpec, m map[string]string) (Transformer, error) { + if m == nil { + return NewNoOpTransformer(), nil + } + if pc == nil { + return nil, errors.New("fieldSpecs is not expected to be nil") + } + return &mapTransformer{fieldSpecs: pc, m: m}, nil +} + +// Transform apply each pair in the mapTransformer to the +// fields specified in mapTransformer. +func (o *mapTransformer) Transform(m resmap.ResMap) error { + for id := range m { + objMap := m[id].Map() + for _, path := range o.fieldSpecs { + if !id.Gvk().IsSelected(&path.Gvk) { + continue + } + err := mutateField(objMap, path.PathSlice(), path.CreateIfNotPresent, o.addMap) + if err != nil { + return err + } + } + } + return nil +} + +func (o *mapTransformer) addMap(in interface{}) (interface{}, error) { + m, ok := in.(map[string]interface{}) + if !ok { + return nil, fmt.Errorf("%#v is expected to be %T", in, m) + } + for k, v := range o.m { + m[k] = v + } + return m, nil +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/transformers/multitransformer.go b/vendor/sigs.k8s.io/kustomize/pkg/transformers/multitransformer.go new file mode 100644 index 00000000000..d5921d1a92e --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/transformers/multitransformer.go @@ -0,0 +1,95 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package transformers + +import ( + "fmt" + "sigs.k8s.io/kustomize/pkg/resource" + + "sigs.k8s.io/kustomize/pkg/resmap" +) + +// multiTransformer contains a list of transformers. +type multiTransformer struct { + transformers []Transformer + checkConflictEnabled bool + rf *resource.Factory +} + +var _ Transformer = &multiTransformer{} + +// NewMultiTransformer constructs a multiTransformer. +func NewMultiTransformer(t []Transformer) Transformer { + r := &multiTransformer{ + transformers: make([]Transformer, len(t)), + checkConflictEnabled: false} + copy(r.transformers, t) + return r +} + +// NewMultiTransformerWithConflictCheck constructs a multiTransformer with checking of conflicts. +func NewMultiTransformerWithConflictCheck(t []Transformer) Transformer { + r := &multiTransformer{ + transformers: make([]Transformer, len(t)), + checkConflictEnabled: true} + copy(r.transformers, t) + return r +} + +// Transform prepends the name prefix. +func (o *multiTransformer) Transform(m resmap.ResMap) error { + if o.checkConflictEnabled { + return o.transformWithCheckConflict(m) + } + return o.transform(m) +} +func (o *multiTransformer) transform(m resmap.ResMap) error { + for _, t := range o.transformers { + err := t.Transform(m) + if err != nil { + return err + } + } + return nil +} + +// Of the len(o.transformers)! possible transformer orderings, compare to a reversed order. +// A spot check to perform when the transformations are supposed to be commutative. +// Fail if there's a difference in the result. +func (o *multiTransformer) transformWithCheckConflict(m resmap.ResMap) error { + mcopy := m.DeepCopy(o.rf) + err := o.transform(m) + if err != nil { + return err + } + o.reverseTransformers() + err = o.transform(mcopy) + if err != nil { + return err + } + err = m.ErrorIfNotEqual(mcopy) + if err != nil { + return fmt.Errorf("found conflict between different patches\n%v", err) + } + return nil +} + +func (o *multiTransformer) reverseTransformers() { + for i, j := 0, len(o.transformers)-1; i < j; i, j = i+1, j-1 { + o.transformers[i], o.transformers[j] = o.transformers[j], o.transformers[i] + } +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/transformers/namereference.go b/vendor/sigs.k8s.io/kustomize/pkg/transformers/namereference.go new file mode 100644 index 00000000000..134bac71682 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/transformers/namereference.go @@ -0,0 +1,94 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package transformers + +import ( + "errors" + "fmt" + + "sigs.k8s.io/kustomize/pkg/gvk" + "sigs.k8s.io/kustomize/pkg/resmap" + "sigs.k8s.io/kustomize/pkg/transformers/config" +) + +type nameReferenceTransformer struct { + backRefs []config.NameBackReferences +} + +var _ Transformer = &nameReferenceTransformer{} + +// NewNameReferenceTransformer constructs a nameReferenceTransformer +// with a given slice of NameBackReferences. +func NewNameReferenceTransformer( + br []config.NameBackReferences) (Transformer, error) { + if br == nil { + return nil, errors.New("backrefs not expected to be nil") + } + return &nameReferenceTransformer{backRefs: br}, nil +} + +// Transform does the field update according to fieldSpecs. +// The old name is in the key in the map and the new name is in the object +// associated with the key. e.g. if is one of the key-value pair in the map, +// then the old name is k.Name and the new name is v.GetName() +func (o *nameReferenceTransformer) Transform(m resmap.ResMap) error { + // TODO: Too much looping. + // Even more hidden loops in FilterBy, + // updateNameReference and FindByGVKN. + for id := range m { + for _, backRef := range o.backRefs { + for _, fSpec := range backRef.FieldSpecs { + if id.Gvk().IsSelected(&fSpec.Gvk) { + err := mutateField( + m[id].Map(), fSpec.PathSlice(), + fSpec.CreateIfNotPresent, + o.updateNameReference( + backRef.Gvk, m.FilterBy(id))) + if err != nil { + return err + } + } + } + } + } + return nil +} + +func (o *nameReferenceTransformer) updateNameReference( + backRef gvk.Gvk, m resmap.ResMap) func(in interface{}) (interface{}, error) { + return func(in interface{}) (interface{}, error) { + s, ok := in.(string) + if !ok { + return nil, fmt.Errorf("%#v is expected to be %T", in, s) + } + for id, res := range m { + if id.Gvk().IsSelected(&backRef) && id.Name() == s { + matchedIds := m.FindByGVKN(id) + // If there's more than one match, there's no way + // to know which one to pick, so emit error. + if len(matchedIds) > 1 { + return nil, fmt.Errorf( + "Multiple matches for name %s:\n %v", id, matchedIds) + } + // Return transformed name of the object, + // complete with prefixes, hashes, etc. + return res.GetName(), nil + } + } + return in, nil + } +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/transformers/namespace.go b/vendor/sigs.k8s.io/kustomize/pkg/transformers/namespace.go new file mode 100644 index 00000000000..5f0c0648207 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/transformers/namespace.go @@ -0,0 +1,121 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package transformers + +import ( + "sigs.k8s.io/kustomize/pkg/gvk" + "sigs.k8s.io/kustomize/pkg/resmap" + "sigs.k8s.io/kustomize/pkg/transformers/config" +) + +type namespaceTransformer struct { + namespace string + fieldSpecsToUse []config.FieldSpec + fieldSpecsToSkip []config.FieldSpec +} + +var _ Transformer = &namespaceTransformer{} + +// NewNamespaceTransformer construct a namespaceTransformer. +func NewNamespaceTransformer(ns string, cf []config.FieldSpec) Transformer { + if len(ns) == 0 { + return NewNoOpTransformer() + } + var skip []config.FieldSpec + for _, g := range gvk.ClusterLevelGvks() { + skip = append(skip, config.FieldSpec{Gvk: g}) + } + return &namespaceTransformer{ + namespace: ns, + fieldSpecsToUse: cf, + fieldSpecsToSkip: skip, + } +} + +// Transform adds the namespace. +func (o *namespaceTransformer) Transform(m resmap.ResMap) error { + mf := resmap.ResMap{} + + for id := range m { + found := false + for _, path := range o.fieldSpecsToSkip { + if id.Gvk().IsSelected(&path.Gvk) { + found = true + break + } + } + if !found { + mf[id] = m[id] + delete(m, id) + } + } + + for id := range mf { + objMap := mf[id].Map() + for _, path := range o.fieldSpecsToUse { + if !id.Gvk().IsSelected(&path.Gvk) { + continue + } + + err := mutateField(objMap, path.PathSlice(), path.CreateIfNotPresent, func(_ interface{}) (interface{}, error) { + return o.namespace, nil + }) + if err != nil { + return err + } + newid := id.CopyWithNewNamespace(o.namespace) + m[newid] = mf[id] + } + + } + o.updateClusterRoleBinding(m) + return nil +} + +func (o *namespaceTransformer) updateClusterRoleBinding(m resmap.ResMap) { + saMap := map[string]bool{} + for id := range m { + if id.Gvk().Equals(gvk.Gvk{Version: "v1", Kind: "ServiceAccount"}) { + saMap[id.Name()] = true + } + } + + for id := range m { + if id.Gvk().Kind != "ClusterRoleBinding" && id.Gvk().Kind != "RoleBinding" { + continue + } + objMap := m[id].Map() + subjects := objMap["subjects"].([]interface{}) + for i := range subjects { + subject := subjects[i].(map[string]interface{}) + kind, foundk := subject["kind"] + name, foundn := subject["name"] + if !foundk || !foundn || kind.(string) != "ServiceAccount" { + continue + } + // a ServiceAccount named “default” exists in every active namespace + if name.(string) == "default" || saMap[name.(string)] { + subject := subjects[i].(map[string]interface{}) + mutateField(subject, []string{"namespace"}, true, func(_ interface{}) (interface{}, error) { + return o.namespace, nil + }) + subjects[i] = subject + } + } + objMap["subjects"] = subjects + } +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/transformers/nooptransformer.go b/vendor/sigs.k8s.io/kustomize/pkg/transformers/nooptransformer.go new file mode 100644 index 00000000000..c07389b31d5 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/transformers/nooptransformer.go @@ -0,0 +1,34 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package transformers + +import "sigs.k8s.io/kustomize/pkg/resmap" + +// noOpTransformer contains a no-op transformer. +type noOpTransformer struct{} + +var _ Transformer = &noOpTransformer{} + +// NewNoOpTransformer constructs a noOpTransformer. +func NewNoOpTransformer() Transformer { + return &noOpTransformer{} +} + +// Transform does nothing. +func (o *noOpTransformer) Transform(_ resmap.ResMap) error { + return nil +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/transformers/prefixsuffixname.go b/vendor/sigs.k8s.io/kustomize/pkg/transformers/prefixsuffixname.go new file mode 100644 index 00000000000..4dc97aba678 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/transformers/prefixsuffixname.go @@ -0,0 +1,108 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package transformers + +import ( + "errors" + "fmt" + "log" + + "sigs.k8s.io/kustomize/pkg/gvk" + "sigs.k8s.io/kustomize/pkg/resmap" + "sigs.k8s.io/kustomize/pkg/transformers/config" +) + +// namePrefixSuffixTransformer contains the prefix, suffix, and the FieldSpecs +// for each field needing a name prefix and suffix. +type namePrefixSuffixTransformer struct { + prefix string + suffix string + fieldSpecsToUse []config.FieldSpec + fieldSpecsToSkip []config.FieldSpec +} + +var _ Transformer = &namePrefixSuffixTransformer{} + +var prefixSuffixFieldSpecsToSkip = []config.FieldSpec{ + { + Gvk: gvk.Gvk{Kind: "CustomResourceDefinition"}, + }, +} + +// deprecateNamePrefixSuffixFieldSpec will be moved into prefixSuffixFieldSpecsToSkip in next release +var deprecateNamePrefixSuffixFieldSpec = config.FieldSpec{ + Gvk: gvk.Gvk{Kind: "Namespace"}, +} + +// NewNamePrefixSuffixTransformer construct a namePrefixSuffixTransformer. +func NewNamePrefixSuffixTransformer(np, ns string, pc []config.FieldSpec) (Transformer, error) { + if len(np) == 0 && len(ns) == 0 { + return NewNoOpTransformer(), nil + } + if pc == nil { + return nil, errors.New("fieldSpecs is not expected to be nil") + } + return &namePrefixSuffixTransformer{fieldSpecsToUse: pc, prefix: np, suffix: ns, fieldSpecsToSkip: prefixSuffixFieldSpecsToSkip}, nil +} + +// Transform prepends the name prefix and appends the name suffix. +func (o *namePrefixSuffixTransformer) Transform(m resmap.ResMap) error { + // Fill map "mf" with entries subject to name modification, and + // delete these entries from "m", so that for now m retains only + // the entries whose names will not be modified. + mf := resmap.ResMap{} + for id := range m { + found := false + for _, path := range o.fieldSpecsToSkip { + if id.Gvk().IsSelected(&path.Gvk) { + found = true + break + } + } + if !found { + mf[id] = m[id] + delete(m, id) + } + } + + for id := range mf { + if id.Gvk().IsSelected(&deprecateNamePrefixSuffixFieldSpec.Gvk) { + log.Println("Adding nameprefix and namesuffix to Namespace resource will be deprecated in next release.") + } + objMap := mf[id].Map() + for _, path := range o.fieldSpecsToUse { + if !id.Gvk().IsSelected(&path.Gvk) { + continue + } + err := mutateField(objMap, path.PathSlice(), path.CreateIfNotPresent, o.addPrefixSuffix) + if err != nil { + return err + } + newId := id.CopyWithNewPrefixSuffix(o.prefix, o.suffix) + m[newId] = mf[id] + } + } + return nil +} + +func (o *namePrefixSuffixTransformer) addPrefixSuffix(in interface{}) (interface{}, error) { + s, ok := in.(string) + if !ok { + return nil, fmt.Errorf("%#v is expected to be %T", in, s) + } + return fmt.Sprintf("%s%s%s", o.prefix, s, o.suffix), nil +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/transformers/refvars.go b/vendor/sigs.k8s.io/kustomize/pkg/transformers/refvars.go new file mode 100644 index 00000000000..fef731a4ce7 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/transformers/refvars.go @@ -0,0 +1,68 @@ +package transformers + +import ( + "fmt" + + "sigs.k8s.io/kustomize/pkg/expansion" + "sigs.k8s.io/kustomize/pkg/resmap" + "sigs.k8s.io/kustomize/pkg/transformers/config" +) + +type refvarTransformer struct { + fieldSpecs []config.FieldSpec + vars map[string]string +} + +// NewRefVarTransformer returns a Trasformer that replaces $(VAR) style variables with values. +func NewRefVarTransformer(vars map[string]string, p []config.FieldSpec) Transformer { + return &refvarTransformer{ + vars: vars, + fieldSpecs: p, + } +} + +// Transform determines the final values of variables: +// +// 1. Determine the final value of each variable: +// a. If the variable's Value is set, expand the `$(var)` references to other +// variables in the .Value field; the sources of variables are the declared +// variables of the container and the service environment variables +// b. If a source is defined for an environment variable, resolve the source +// 2. Create the container's environment in the order variables are declared +// 3. Add remaining service environment vars +func (rv *refvarTransformer) Transform(resources resmap.ResMap) error { + for resId := range resources { + objMap := resources[resId].Map() + for _, pc := range rv.fieldSpecs { + if !resId.Gvk().IsSelected(&pc.Gvk) { + continue + } + err := mutateField(objMap, pc.PathSlice(), false, func(in interface{}) (interface{}, error) { + var ( + mappingFunc = expansion.MappingFuncFor(rv.vars) + ) + switch vt := in.(type) { + case []interface{}: + var xs []string + for _, a := range in.([]interface{}) { + xs = append(xs, expansion.Expand(a.(string), mappingFunc)) + } + return xs, nil + case interface{}: + s, ok := in.(string) + if !ok { + return nil, fmt.Errorf("%#v is expected to be %T", in, s) + } + runtimeVal := expansion.Expand(s, mappingFunc) + return runtimeVal, nil + default: + return "", fmt.Errorf("invalid type encountered %T", vt) + } + }) + if err != nil { + return err + } + } + } + return nil +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/transformers/transformer.go b/vendor/sigs.k8s.io/kustomize/pkg/transformers/transformer.go new file mode 100644 index 00000000000..dc6f8807c3b --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/transformers/transformer.go @@ -0,0 +1,26 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package transformers has implementations of resmap.ResMap transformers. +package transformers + +import "sigs.k8s.io/kustomize/pkg/resmap" + +// A Transformer modifies an instance of resmap.ResMap. +type Transformer interface { + // Transform modifies data in the argument, e.g. adding labels to resources that can be labelled. + Transform(m resmap.ResMap) error +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/transformers/util.go b/vendor/sigs.k8s.io/kustomize/pkg/transformers/util.go new file mode 100644 index 00000000000..b90ccb60ae0 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/transformers/util.go @@ -0,0 +1,74 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package transformers + +import ( + "fmt" +) + +type mutateFunc func(interface{}) (interface{}, error) + +func mutateField( + m map[string]interface{}, + pathToField []string, + createIfNotPresent bool, + fns ...mutateFunc) error { + if len(pathToField) == 0 { + return nil + } + + _, found := m[pathToField[0]] + if !found { + if !createIfNotPresent { + return nil + } + m[pathToField[0]] = map[string]interface{}{} + } + + if len(pathToField) == 1 { + var err error + for _, fn := range fns { + m[pathToField[0]], err = fn(m[pathToField[0]]) + if err != nil { + return err + } + } + return nil + } + + v := m[pathToField[0]] + newPathToField := pathToField[1:] + switch typedV := v.(type) { + case map[string]interface{}: + return mutateField(typedV, newPathToField, createIfNotPresent, fns...) + case []interface{}: + for i := range typedV { + item := typedV[i] + typedItem, ok := item.(map[string]interface{}) + if !ok { + return fmt.Errorf("%#v is expected to be %T", item, typedItem) + } + err := mutateField(typedItem, newPathToField, createIfNotPresent, fns...) + if err != nil { + return err + } + } + return nil + default: + return fmt.Errorf("%#v is not expected to be a primitive type", typedV) + } +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/types/BUILD b/vendor/sigs.k8s.io/kustomize/pkg/types/BUILD new file mode 100644 index 00000000000..e614dd9bb0a --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/types/BUILD @@ -0,0 +1,30 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = [ + "kustomization.go", + "var.go", + ], + importmap = "k8s.io/kubernetes/vendor/sigs.k8s.io/kustomize/pkg/types", + importpath = "sigs.k8s.io/kustomize/pkg/types", + visibility = ["//visibility:public"], + deps = [ + "//vendor/sigs.k8s.io/kustomize/pkg/gvk:go_default_library", + "//vendor/sigs.k8s.io/kustomize/pkg/patch:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/vendor/sigs.k8s.io/kustomize/pkg/types/kustomization.go b/vendor/sigs.k8s.io/kustomize/pkg/types/kustomization.go new file mode 100644 index 00000000000..945e2d5bdaa --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/types/kustomization.go @@ -0,0 +1,263 @@ +/* +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 types holds struct definitions that should find a better home. +package types + +import ( + "sigs.k8s.io/kustomize/pkg/patch" +) + +// TypeMeta copies apimachinery/pkg/apis/meta/v1.TypeMeta +type TypeMeta struct { + // Kind copies apimachinery/pkg/apis/meta/v1.Typemeta.Kind + Kind string `json:"kind,omitempty" protobuf:"bytes,1,opt,name=kind"` + + // APIVersion copies apimachinery/pkg/apis/meta/v1.Typemeta.APIVersion + APIVersion string `json:"apiVersion,omitempty" protobuf:"bytes,2,opt,name=apiVersion"` +} + +// Kustomization holds the information needed to generate customized k8s api resources. +type Kustomization struct { + TypeMeta `json:",inline" yaml:",inline"` + + // + // Operators - what kustomize can do. + // + + // NamePrefix will prefix the names of all resources mentioned in the kustomization + // file including generated configmaps and secrets. + NamePrefix string `json:"namePrefix,omitempty" yaml:"namePrefix,omitempty"` + + // NameSuffix will suffix the names of all resources mentioned in the kustomization + // file including generated configmaps and secrets. + NameSuffix string `json:"nameSuffix,omitempty" yaml:"nameSuffix,omitempty"` + + // Namespace to add to all objects. + Namespace string `json:"namespace,omitempty" yaml:"namespace,omitempty"` + + // CommonLabels to add to all objects and selectors. + CommonLabels map[string]string `json:"commonLabels,omitempty" yaml:"commonLabels,omitempty"` + + // CommonAnnotations to add to all objects. + CommonAnnotations map[string]string `json:"commonAnnotations,omitempty" yaml:"commonAnnotations,omitempty"` + + // PatchesStrategicMerge specifies the relative path to a file + // containing a strategic merge patch. Format documented at + // https://github.com/kubernetes/community/blob/master/contributors/devel/strategic-merge-patch.md + // URLs and globs are not supported. + PatchesStrategicMerge []patch.StrategicMerge `json:"patchesStrategicMerge,omitempty" yaml:"patchesStrategicMerge,omitempty"` + + // JSONPatches is a list of JSONPatch for applying JSON patch. + // Format documented at https://tools.ietf.org/html/rfc6902 + // and http://jsonpatch.com + PatchesJson6902 []patch.Json6902 `json:"patchesJson6902,omitempty" yaml:"patchesJson6902,omitempty"` + + // ImageTags is a list of (image name, new tag) pairs for simply + // changing a an image tag. This can also be achieved with a + // patch, but this operator is simpler to specify. + ImageTags []ImageTag `json:"imageTags,omitempty" yaml:"imageTags,omitempty"` + + // Vars allow things modified by kustomize to be injected into a + // container specification. A var is a name (e.g. FOO) associated + // with a field in a specific resource instance. The field must + // contain a value of type string, and defaults to the name field + // of the instance. Any appearance of "$(FOO)" in the container + // spec will be replaced at kustomize build time, after the final + // value of the specified field has been determined. + Vars []Var `json:"vars,omitempty" yaml:"vars,omitempty"` + + // + // Operands - what kustomize operates on. + // + + // Resources specifies relative paths to files holding YAML representations + // of kubernetes API objects. URLs and globs not supported. + Resources []string `json:"resources,omitempty" yaml:"resources,omitempty"` + + // Crds specifies relative paths to Custom Resource Definition files. + // This allows custom resources to be recognized as operands, making + // it possible to add them to the Resources list. + // CRDs themselves are not modified. + Crds []string `json:"crds,omitempty" yaml:"crds,omitempty"` + + // Bases are relative paths or github repository URLs specifying a + // directory containing a kustomization.yaml file. + // URL format: https://github.com/hashicorp/go-getter#url-format + Bases []string `json:"bases,omitempty" yaml:"bases,omitempty"` + + // + // Generators (operators that create operands) + // + + // ConfigMapGenerator is a list of configmaps to generate from + // local data (one configMap per list item). + // The resulting resource is a normal operand, subject to + // name prefixing, patching, etc. By default, the name of + // the map will have a suffix hash generated from its contents. + ConfigMapGenerator []ConfigMapArgs `json:"configMapGenerator,omitempty" yaml:"configMapGenerator,omitempty"` + + // SecretGenerator is a list of secrets to generate from + // local data (one secret per list item). + // The resulting resource is a normal operand, subject to + // name prefixing, patching, etc. By default, the name of + // the map will have a suffix hash generated from its contents. + SecretGenerator []SecretArgs `json:"secretGenerator,omitempty" yaml:"secretGenerator,omitempty"` + + // GeneratorOptions modify behavior of all ConfigMap and Secret generators. + GeneratorOptions *GeneratorOptions `json:"generatorOptions,omitempty" yaml:"generatorOptions,omitempty"` + + // Configurations is a list of transformer configuration files + Configurations []string `json:"configurations,omitempty" yaml:"configurations,omitempty"` + + // + // Deprecated fields - See DealWithDeprecatedFields + // + + // Deprecated. + Patches []string `json:"patches,omitempty" yaml:"patches,omitempty"` +} + +// DealWithDeprecatedFields should be called immediately after +// loading from storage. +func (k *Kustomization) DealWithDeprecatedFields() { + if len(k.Patches) > 0 { + // The Patches field, meant to hold strategic merge + // patches, is deprecated. Append anything found + // there to the PatchesStrategicMerge field. + // This happened when the PatchesJson6902 field + // was introduced. + k.PatchesStrategicMerge = patch.Append( + k.PatchesStrategicMerge, k.Patches...) + k.Patches = []string{} + } +} + +// ConfigMapArgs contains the metadata of how to generate a configmap. +type ConfigMapArgs struct { + // Name of the configmap. + // The full name should be Kustomization.NamePrefix + Configmap.Name + + // hash(content of configmap). + Name string `json:"name,omitempty" yaml:"name,omitempty"` + + // behavior of configmap, must be one of create, merge and replace + // 'create': create a new one; + // 'replace': replace the existing one; + // 'merge': merge the existing one. + Behavior string `json:"behavior,omitempty" yaml:"behavior,omitempty"` + + // DataSources for configmap. + DataSources `json:",inline,omitempty" yaml:",inline,omitempty"` +} + +// SecretArgs contains the metadata of how to generate a secret. +type SecretArgs struct { + // Name of the secret. + // The full name should be Kustomization.NamePrefix + SecretGenerator.Name + + // hash(content of secret). + Name string `json:"name,omitempty" yaml:"name,omitempty"` + + // behavior of secretGenerator, must be one of create, merge and replace + // 'create': create a new one; + // 'replace': replace the existing one; + // 'merge': merge the existing one. + Behavior string `json:"behavior,omitempty" yaml:"behavior,omitempty"` + + // Type of the secret. + // + // This is the same field as the secret type field in v1/Secret: + // It can be "Opaque" (default), or "kubernetes.io/tls". + // + // If type is "kubernetes.io/tls", then "Commands" must have exactly two + // keys: "tls.key" and "tls.crt" + Type string `json:"type,omitempty" yaml:"type,omitempty"` + + // CommandSources for secret. + CommandSources `json:",inline,omitempty" yaml:",inline,omitempty"` + + // Deprecated. + // Replaced by GeneratorOptions.TimeoutSeconds + // TimeoutSeconds specifies the timeout for commands. + TimeoutSeconds *int64 `json:"timeoutSeconds,omitempty" yaml:"timeoutSeconds,omitempty"` +} + +// CommandSources contains some generic sources for secrets. +type CommandSources struct { + // Map of keys to commands to generate the values + Commands map[string]string `json:"commands,omitempty" yaml:"commands,omitempty"` + // EnvCommand to output lines of key=val pairs to create a secret. + // i.e. a Docker .env file or a .ini file. + EnvCommand string `json:"envCommand,omitempty" yaml:"envCommand,omitempty"` +} + +// DataSources contains some generic sources for configmaps. +type DataSources struct { + // LiteralSources is a list of literal sources. + // Each literal source should be a key and literal value, + // e.g. `somekey=somevalue` + // It will be similar to kubectl create configmap|secret --from-literal + LiteralSources []string `json:"literals,omitempty" yaml:"literals,omitempty"` + + // FileSources is a list of file sources. + // Each file source can be specified using its file path, in which case file + // basename will be used as configmap key, or optionally with a key and file + // path, in which case the given key will be used. + // Specifying a directory will iterate each named file in the directory + // whose basename is a valid configmap key. + // It will be similar to kubectl create configmap|secret --from-file + FileSources []string `json:"files,omitempty" yaml:"files,omitempty"` + + // EnvSource format should be a path to a file to read lines of key=val + // pairs to create a configmap. + // i.e. a Docker .env file or a .ini file. + EnvSource string `json:"env,omitempty" yaml:"env,omitempty"` +} + +// ImageTag contains an image and a new tag, which will replace the original tag. +type ImageTag struct { + // Name is a tag-less image name. + Name string `json:"name,omitempty" yaml:"name,omitempty"` + + // NewTag is the value to use in replacing the original tag. + NewTag string `json:"newTag,omitempty" yaml:"newTag,omitempty"` + + // Digest is the value used to replace the original image tag. + // If digest is present NewTag value is ignored. + Digest string `json:"digest,omitempty" yaml:"digest,omitempty"` +} + +// GeneratorOptions modify behavior of all ConfigMap and Secret generators. +type GeneratorOptions struct { + // Labels to add to all generated resources. + Labels map[string]string `json:"labels,omitempty" yaml:"labels,omitempty"` + + // Annotations to add to all generated resources. + Annotations map[string]string `json:"annotations,omitempty" yaml:"annotations,omitempty"` + + // TimeoutSeconds specifies the timeout for commands, if any, + // used in resource generation. At time of writing, the default + // was specified in configmapandsecret.defaultCommandTimeout. + TimeoutSeconds *int64 `json:"timeoutSeconds,omitempty" yaml:"timeoutSeconds,omitempty"` + + // Shell and arguments to use as a context for commands used in + // resource generation. Default at time of writing: {'sh', '-c'}. + Shell []string `json:"shell,omitempty" yaml:"shell,omitempty"` + + // DisableNameSuffixHash if true disables the default behavior of adding a + // suffix to the names of generated resources that is a hash of the + // resource contents. + DisableNameSuffixHash bool `json:"disableNameSuffixHash,omitempty" yaml:"disableNameSuffixHash,omitempty"` +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/types/var.go b/vendor/sigs.k8s.io/kustomize/pkg/types/var.go new file mode 100644 index 00000000000..4d48c96198e --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/types/var.go @@ -0,0 +1,82 @@ +/* +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 types + +import ( + "sigs.k8s.io/kustomize/pkg/gvk" + "strings" +) + +// Var represents a variable whose value will be sourced +// from a field in a Kubernetes object. +type Var struct { + // Value of identifier name e.g. FOO used in container args, annotations + // Appears in pod template as $(FOO) + Name string `json:"name" yaml:"name"` + + // ObjRef must refer to a Kubernetes resource under the + // purview of this kustomization. ObjRef should use the + // raw name of the object (the name specified in its YAML, + // before addition of a namePrefix). + ObjRef Target `json:"objref" yaml:"objref"` + + // FieldRef refers to the field of the object referred to by + // ObjRef whose value will be extracted for use in + // replacing $(FOO). + // If unspecified, this defaults to fieldPath: metadata.name + FieldRef FieldSelector `json:"fieldref,omitempty" yaml:"fieldref,omitempty"` +} + +// Target refers to a kubernetes object by Group, Version, Kind and Name +// gvk.Gvk contains Group, Version and Kind +// APIVersion is added to keep the backward compatibility of using ObjectReference +// for Var.ObjRef +type Target struct { + APIVersion string `json:"apiVersion,omitempty" yaml:"apiVersion,omitempty"` + gvk.Gvk `json:",inline,omitempty" yaml:",inline,omitempty"` + Name string `json:"name" yaml:"name"` +} + +// FieldSelector contains the fieldPath to an object field, such as metadata.name +// This struct is added to keep the backward compatibility of using ObjectFieldSelector +// for Var.FieldRef +type FieldSelector struct { + FieldPath string `json:"fieldPath,omitempty" yaml:"fieldPath,omitempty"` +} + +// Defaulting sets reference to field used by default. +func (v *Var) Defaulting() { + if v.FieldRef.FieldPath == "" { + v.FieldRef.FieldPath = "metadata.name" + } +} + +// GVK returns the Gvk object in Target +func (t *Target) GVK() gvk.Gvk { + if t.APIVersion == "" { + return t.Gvk + } + versions := strings.Split(t.APIVersion, "/") + if len(versions) == 2 { + t.Group = versions[0] + t.Version = versions[1] + } + if len(versions) == 1 { + t.Version = versions[0] + } + return t.Gvk +}